Inside com Reading Notes-scheduling interface and automation

Source: Internet
Author: User
Tags ipoint
1. A new communication method

Idispatch provides another communication mode for customers and components. With idispatch, the COM component can provide the services it supports through a standard interface, there is no need to provide multiple specific and service interfaces.

 

1.1 old communication methods

Communication between a customer and a component is completed through an interface, which has an array composed of function pointers. The Customer Code must contain a header file describing the interface in the form of abstract base classes. The compiler will read this header file and then assign an index to each member function in the abstract base class. This index is actually the index of the corresponding function pointer in the function pointer array.

PIX-> fxstringout (MSG );

It will be interpreted:

(* (Pix-> pvtbl [indexoffxstringout]) (pix, MSG );

Pvtbl is the pointer to the vtbl of the corresponding class, while indexoffxstringout is the index of the fxstringout pointer in the function pointer table.

In macro language development, if the macro language may obtain the index of the pointer of the function in vtbl so that it can call them? When a macro language calls a function in the COM component, three types of information can be used: the proid, function name, and parameters passed to the function. The macro runtime system must provide a simple method to execute functions with the old name of the function. This method is the idispatch interface.

 

1.2idispatch Interface

In short, idispatch will receive a function name and execute it. IDL description of idispatch

Interfaceidispatch: iunknown

{

Typedef [unique] idispatch * lpdispatch;

 

Hresult gettypeinfocount (

[Out] uint * pctinfo

);

 

Hresult gettypeinfo (

[In] uint itinfo,

[In] lcid,

[Out] itypeinfo ** pptinfo

);

 

Hresult getidsofnames (

[In] refiid riid,

[IN, size_is (cnames)] lpolestr * rgsznames,

[In] uint cnames,

[In] lcid,

[Out, size_is (cnames)] dispid * rgdispid

);

 

[Local]

Hresult invoke (

[In] dispid dispidmember,

[In] refiid riid,

[In] lcid,

[In] Word wflags,

[In, out] dispparams * pdispparams,

[Out] variant * pvarresult,

[Out] partition info * p1_info,

[Out] uint * puargerr

);

 

[Call_as (invoke)]

Hresult remoteinvoke (

[In] dispid dispidmember,

[In] refiid riid,

[In] lcid,

[In] DWORD dwflags,

[In] dispparams * pdispparams,

[Out] variant * pvarresult,

[Out] partition info * p1_info,

[Out] uint * pargerr,

[In] uint cvarref,

[IN, size_is (cvarref)] uint * rgvarrefidx,

[In, out, size_is (cvarref)] variantarg * rgvarref

);

The most interesting about idispatch is that getidsofnames and invoke. getidsofnames read the name of a function and return its scheduling ID (dispid ). Dispid is a long integer that identifies a function. The automatic control program will pass the dispid to the invoke member function. Invoke can use dispid as the index of the function pointer array.

 

  • Scheduling Interface

Idispatch: The implementation of invoke is similar to that of vtbl. Both of them can define interfaces. Idispatch: An Implementation of invoke is called a scheduling interface in the function set. The COM interface is a pointer to a function pointer array. The first three elements of this array are QueryInterface, addref, and release. The following figure shows the scheduling interface:

On the left is a traditional COM interface idispatch, which is implemented in vtbl mode, and on the right is a scheduling interface. Invoke can recognize the dispid, which is vital to the scheduling interface. Possible implementation is given. getidsofnames obtains its dispid through the function name, and invoke finds the corresponding function pointer through dispid to execute the function.

You can also use a COM interface to implement idispatch: invoke:

 

  • Dual Interface

It is not the only method to implement the scheduling interface using COM components. You can also use the following method. Let the COM component implementing idispatch: invoke inherit idispatch instead of iunknown. This is a method called a double interface. functions that can be accessed through invoke can also be accessed directly through vtbl.

 

2. Use of idispatch

Consider the following vbprogram:

Dim cmpnt as object

Set cmpnt = Createobject ("insidecom. cmpnt1 ")

Cmpnt. FX

Call FX through the idispatch interface implemented by the COM component. Let's take a look at how C ++ achieves this.

Hresult hR = oleinitialize (null );

 

Wchar_tprogid [] = l "insidecom. cmpnt1 ";

CLSID;

Clsidfromprogid (progid, & CLSID );

Idispatch * pdispach = NULL;

Cocreateinstance (CLSID,

Null, clsctx_inproc_server,

Iid_idispatch, (void **) & pdispach );

Dispid;

Olechar * name = l "FX ";

Pdispach-> getidsofnames (

Iid_null, & name,

1, getuserdefaultlcid (), & dispid );

 

Dispparams dispparamsnoargs = {

Null, null, 0, 0

}

 

Pdispach-> invoke (dispid,

Iid_null,

Getuserdefaultlcid (),

Dispatch_method,

& Dispparamsnoargs,

Null, null, null );

 

Return an idispatch pointer through cocreateinstance. You can use idispatch: getidsofnames to convert the function name into a dispid and call the corresponding function through idispatch: invoke.

 

2.1invoke function parameters

The first parameter is the dispid that controls the function to be called by the program, and the second parameter is reserved and must be iid_null. The third is the saved location information. Others are discussed below.

 

  • Methods and attributes

All the Members in the COM interface are functions, and the "set" and "get" class functions are used to simulate the access to the variable of the year-old member. For example, setvisible can be used to set the visibility of a window. Getvisible can obtain this attribute.

If (piwindows-> getvisible () = false)

Piwindows-> setvisible (true );

It is not ideal for VB to use set and get. In VB, the following calls

If window. Visible = false then

Window. Visible = true

End if

In IDL, The propget kernel propput attribute can be interpreted as a property of the COM function.

 

  • Scheduling Parameters

Idispatch: The parameter passed to the called function when the Fifth parameter of invoke contains. The structure is as follows:

Typedef
Struct tagdispparams

{

Variantarg * rgvarg;

Dispid * rgdispidnamedargs;

Uint cargs;

Uint cnamedargs;

} Dispparams;

The first parameter of the structure is a parameter array, and the cargs member is the number of elements in the array. Each parameter type is of the variantarg type. Variant is a large combination of many different types.

 

  • Obtain returned values

The sixth parameter pvarresult points to a Variant Structure pointer. Save the result of the function or propget executed by invoke.

  • Exception

Idispatch: the second-to-last parameter of invoke is the pointer to the response info result. If an exception occurs when the invoke executes a function or attribute, the structure is filled with information about the exception.

Typedef
Struct tagdetailinfo {

Word wcode;

Word wreserved;

BSTR bstrsource;

BSTR bstrdescription;

BSTR bstrhelpfile;

DWORD dwhelpcontext;

Pvoid pvreserved;

Hresult (_ stdcall * pfndeferredfillin) (struct tag1_info *);

Scode;

} Raise info, * lp1_info;

The error code (wcode) or return value (scode) must contain an identified value. The other is 0;

Raise info raise Info;

Hresult hR = pdispach-> invoke (..., & cmdinfo );

If (failed (HR ))

{

If (hR = disp_e_exception)

{

If (Response info. pfndeferredfillin (! = NULL ))

(* (Response info. pfndeferredfillin) (& Response info );

Cout <"exception information:" <Endl

<"Source:" <cmdinfo. bstrsource <Endl

<"Description:" <strong info. bstrdescription <ends;

}

}

 

3. Type Library

The Type Library provides type information about components, interfaces, methods, attributes, parameters, and structures. The Type Library is a binary file.

3.1 create a database of the type

The automated library function createtypelib can create a Type Library. This function returns an icreatetypelib interface that can fill the type library with the corresponding information. You can use IDL to generate the proxy/stub DLL code.

 

  • Library statement

The key to creating a Type Library Using IDL is the library statement. The content of square brackets after the library keyword is edge to the Type Library.

[

Object,

UUID (7aaae05f-283e-4d79-b98c-5d3dcbe733bb ),
// Iid_ipoint

Helpstring ("ipointinterface "),

Oleautomation,

Dual

]

Interface ipoint: idispatch

{

[Propget,
Helpstring ("returns and sets X coordinate")]

Hresultx ([out, retval] int * retval );

[Propput,
Helpstring ("returns and sets X coordinate")]

Hresultx ([in] intvalue );

 

[Propget,
Helpstring ("returns and sets y coordinate")]

Hresulty ([out, retval] int * retval );

[Propput,
Helpstring ("returns and sets y coordinate")]

Hresulty ([in] intvalue );

 

[Helpstring ("displaythe point.")]

Hresultdisplay ();

}

 

[

UUID (13ba7d38-8f44-4e80-9dae-6e01776bee16), // libid_point

Helpstring ("pointcomponent Type Library "),

Version (1.0)

]

Library point

{

Importlib ("stdole32.tlb ");

 

Interface ipoint;

 

[

UUID (0615ea9a-0ed9-458d-9f0d-a9e36000038ab), // clsid_point

Helpstring ("pointclass "),

Appobject

]

Coclass point

{

[Default]
Dispinterfaceipoint;

}

}

  • Distribution of Type Libraries

After a Type Library is generated, it can be released as a separate file, or it can be included as a resource in EXE or DLL.

 

3.2 use of database types

The first step to using a Type Library is to load it. loadregtypelib will try to load the specified type library from the Windows registry. If it fails, you can use loadtypelib to load the specified type library from the disk or loadtypelibfromresource to load the specified type library from the EXE/DLL.

Hresulthr;

Lptypelibptypelib = NULL;

 

HR = loadregtypelib (libid_point, 1, 0, 0, & ptypelib );

If (failed (HR ))

{

HR = loadtypelib (olestr ("point. TLB"), & ptypelib );

}

If (failed (HR ))

Return hr;

HR = ptypelib-> gettypeinfoofguid (iid_ipoint, & s_ptypeinfo );

Ptypelib-> release ();

If (failed (HR ))

Return hr;

S_ptypeinfo-> addref ();

Return hr;

 

3.3 Type Library in the Registry

Libid class table under the keyword hkey_class_root \ typelib.

 

4. Implementation of Type Libraries

Stdmethodimpcpoint: gettypeinfocount (_ RPC _ out uint * pctinfo)

{

* Pctinfo = 1;

Return s_ OK;

}

 

Stdmethodimp cpoint: gettypeinfo (uintitinfo, lcid, itypeinfo ** pptinfo)

{

Hresulthr;

 

If (itinfo! = 0)

Return type_e_elementnotfound;

If (pptinfo = NULL)

Return e_pointer;

If (s_ptypeinfo)

{

S_ptypeinfo-> addref ();

HR = s_ OK;

}

Else

{

HR = loadmytypelib ();

}

If (! HR)

* Pptinfo = s_ptypeinfo;

Return hr;

}

 

Stdmethodimp cpoint: getidsofnames (refiidriid, lpolestr * rgszname, uint cnames, lcid, dispid * rgdispid)

{

Hresulthr;

 

If (isequaliid (riid, iid_null ))

Return disp_e_unknowninterface;

If (! S_ptypeinfo)

{

HR = loadmytypelib ();

If (failed (HR ))

Return hr;

}

 

HR = s_ptypeinfo-> getidsofnames (rgszname, cnames, rgdispid );

Return hr;

}

 

Stdmethodimp cpoint: invoke (dispiddispidmember, refiid riid, lcid, word wflags, dispparams * pdispparams, variant * pvarresult, interval info * p1_info, uint * puargerr)

{

Hresulthr;

 

If (isequaliid (riid, iid_null ))

Return disp_e_unknowninterface;

If (! S_ptypeinfo)

{

HR = loadmytypelib ();

If (failed (HR ))

Return hr;

}

HR = s_ptypeinfo-> invoke (this, dispidmember, wflags, pdispparams, pvarresult, p1_info, puargerr );

Return hr;

}

 

Hresult cpoint: loadmytypelib ()

{

Hresulthr;

Lptypelibptypelib = NULL;

 

HR = loadregtypelib (libid_point, 1, 0, 0, & ptypelib );

If (failed (HR ))

{

HR = loadtypelib (olestr ("point. TLB"), & ptypelib );

}

If (failed (HR ))

Return hr;

HR = ptypelib-> gettypeinfoofguid (iid_ipoint, & s_ptypeinfo );

Ptypelib-> release ();

If (failed (HR ))

Return hr;

S_ptypeinfo-> addref ();

Return hr;

}

 

 

 

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.