1. Method 5 called by COM:
1. Register com first
Requirement:
1. Create mycom. dll. This COM has only one component, and the igetres interfaces -- Methods Hello (),
Igetresex -- Method helloex ()
2. Import components or type libraries into the project
# Import "component directory mycom. dll" no_namespace
Or
# Import "mycom. TLB"
Using namespace mycom;
-- Method 1 -------------------------------------------------------
Coinitialize (null );
CLSID;
Clsidfromprogid (olestr ("mycom. getres"), & CLSID );
Ccomptr <igetres> pgetres; // smart pointer
Pgetres. cocreateinstance (CLSID );
Pgetres-> Hello ();
Pgetres. Release (); // be careful !! Please refer to the last "NOTE"
Couninitialize ();
-- Method 2 ---------------------------------------------------------
Coinitialize (null );
CLSID;
Hresult hR = clsidfromprogid (olestr ("mycom. getres"), & CLSID );
Igetres * PTR;
HR = cocreateinstance (CLSID, null, clsctx_inproc_server,
_ Uuidof (igetres), (lpvoid *) & PTR );
PTR-> Hello ();
Couninitialize ();
-- Method 3 --------------------------------------------------------
Coinitialize (null );
Hresult hr;
CLSID;
HR = clsidfromprogid (olestr ("mycom. getres"), & CLSID );
Igetres * PTR;
Igetresex * ptrex;
// Use cocreateclassobject to create multiple objects of a component (especially mutilthreads)
Higher efficiency.
Iclassfactory * p_classfactory;
HR = cogetclassobject (CLSID, clsctx_inproc_server,
Null, iid_iclassfactory,
(Lpvoid *) & p_classfactory );
P_classfactory-> createinstance (null ,__ uuidof (igetres ),
(Lpvoid *) & PTR );
P_classfactory-> createinstance (null ,__ uuidof (igetresex ),
(Lpvoid *) & ptrex );
PTR-> Hello ();
Ptrex-> helloex ();
Couninitialize ();
-- Method 4 --------------------------------------------------------
Obtain the dllgetclassobject directly from the DLL, and then generate the Class Object and class instance (this method can be
Make the component do not need to be registered in the registry. This is the most primitive method, but it does not make sense to do so, at least the com
Is not recommended for user transparency.
Typedef hresult (_ stdcall * pfnhello) (refclsid, refiid, void **);
Pfnhello fnhello = NULL;
Hinstance hdllinst = loadlibrary ("mycom. dll ");
Fnhello = (pfnhello) getprocaddress (hdllinst, "dllgetclassobject ");
If (fnhello! = 0)
{
Iclassfactory * PCF = NULL;
Hresult hR = (fnhello) (clsid_getres, iid_iclassfactory, (void **) & PCF );
If (succeeded (HR) & (PCF! = NULL ))
{
Igetres * pgetres = NULL;
HR = PCF-> createinstance (null, iid_ifoo, (void **) & pgetres );
If (succeeded (HR) & (pfoo! = NULL ))
{
Pgetres-> Hello ();
Pgetres-> release ();
}
PCF-> release ();
}
}
Freelibrary (hdllinst );
-- Method 5 -------------------------------------------------------
Use classwizard to generate a packaging class using the Type Library, provided that the COM Component Interface must be
Generated from idispatch. The specific method is as follows:
Call out the Add Class Wizard (. NET), select the type library in the MFC class, open, select "file", select
"Mycom. dll" or "mycom. TLB", all interfaces in this mycom will be displayed.
After the generated interface packaging class, the wizard will automatically generate the corresponding. h file so that you can
The parameter in (createdispatch ("mycom. getres") is the one that can be queried by progid through CLSID in the registry)
Coinitialize (null );
Cgetres getrest;
If (getrest. createdispatch ("mycom. getres ")! = 0)
{
Getrest. Hello ();
Getrest. releasedispatch ();
}
Couninitialize ();
-- Note --------------------------------------------------------------
In fact, the smart pointer in COM is a class that has been overloaded->. The purpose is to simplify the reference count.
Call addref () and release (), but why are we in method 1?
Pgetres. Release (), the problem lies with that the end of our smart pointer pgetres lifecycle is in
After couninitialize (), the suite opened by coinitialize has been
Close, and pgetres sends the analysis structure at this time, causing the program to crash. Another way to solve this problem is
Coinitialize (null );
CLSID;
Clsidfromprogid (olestr ("mycom. getres"), & CLSID );
{
Ccomptr <igetres> pgetres; // smart pointer
Pgetres. cocreateinstance (CLSID );
Pgetres-> Hello ();
}
Couninitialize ();
--------------------------------------------------------------------
The above is the method in Com 5. Of course, how to use it depends on the program environment ....
II. C # Call the com DLL compiled by C ++
When C # Calls the com DLL package library compiled by C ++, two problems will occur: 1. Data type conversion problem 2. pointer or address parameter transfer problem first, data type conversion problem. Because C # Is the. NET language and uses the basic data type of. net, C ++ actually corresponds to the basic data type of. net. For example, the original function of C ++ is: int _ stdcall functionname (unsigned char param1, unsigned short param2). The parameter data type must be converted to the corresponding data type in C. For example: [dllimport ("com dll path/file")] extern static int functionname (byte param1, ushort param2) because the _ stdcall function is called, therefore, the call method of P/invoke is used. The functionname method must be declared as a static external function, that is, the extern static declaration header is added. We can see that during the call process, unsigned char is changed to byte, and unsigned short is changed to ushort. After the parameter is changed, the Data Type of the parameter remains unchanged, but the Declaration method must be changed to the. NET language specification. We can perform this conversion using the following table:
Win32 types |
CLR type |
Char, int8, sbyte, char |
System. sbyte |
Short, short int, int16, short |
System. int16 |
Int, long, long int, int32, long32, bool, int |
System. int32 |
_ Int64, int64, Longlong |
System. int64 |
Unsigned char, uint8, uchar, byte |
System. byte |
Unsigned short, uint16, ushort, word, Atom, wchar, _ wchar_t |
System. uint16 |
Unsigned, unsigned int, uint32, ulong32, dword32, ulong, DWORD, uint |
System. uint32 |
Unsigned _ int64, uint64, dwordlong, ulonglong |
System. uint64 |
Float, float |
System. Single |
Double, Long Double, double |
System. Double |
Then, convert the CLR data type representation to the C # representation. In this way, the parameter type Problem of the function can be solved. Now let's look at the next question. What if the function parameter to be called is a pointer or address variable? In this case, you can use the non-secure code provided by C # to solve the problem. However, after all, it is not a hosting code. If the garbage resource processing is not good, It is very unfavorable for the application. Therefore, it is better to use the ref and out modifiers provided by C. The same as above, we also give an example: int _ stdcall functionname (unsigned char & param1, unsigned char * param2) in the C # method to call it is: [dllimport ("com dll path/file")] extern static int functionname (ref byte param1, ref byte param2) when you see this, someone may ask, & is the address, * It is a transfer pointer. Why do I only use ref? One possible explanation is that ref is a modifier with the overload feature and will automatically identify whether to take an address or send a pointer. In actual situations, we use the parameter transfer address to transfer more addresses to the first address of the array. For example, byte [] param1 = new param1 (6); here we declare an array, and now we want to transfer its first address to it, you only need to modify the first element of the param1 array with ref. Details: [dllimport ("com dll path/file")] extern static int functionname (ref byte param1 [1], ref byte param2)