During one of my recent projects I came across a typical problem of passing user-defined types from my COM component. The problem I had was that I was using Attributed ATL (one which even Microsoft seems to have abandoned ;) ). I came up with the following way to expose UDT from COM. Beware though, passing UDT supporting IDispatch interface is a different ball-game altogether and scripting languages don't readily support UDT's.
The way to send UDT using IDispatch involves wrapping it in a VARIANT but again for scripting, its a no-no. Passing UDT as an array is slightly more complicated. I will write about these some time in the near future.
There are various good articles on the net about this, but here is a simple, to the point approach.
First Declare your type in your header file, like this
Now you will have to declare the type in your IDL file. But, because its an attributed project, here is how you do it.
Create a new idl file in you project and name it, for example structures.idl. The make an entry in the IDL file as follows:
Once this is done you have to include this IDL file in the generated IDL file. Here is how I do it. In my main .cpp file I insert the line [importidl] on top. Like this:
This takes care to compile the right Type Information.
Now to use this UDT simply do it like this, for example:
For creating a VARIANT type for the structure, I use the following function:
This can take care of wrapping structure in a variant. Of-course there are other things to talk about like passing UDT in a SAFEARRAY, but I will talk about them sometime in future.
Any suggestions/comments are welcome.
The way to send UDT using IDispatch involves wrapping it in a VARIANT but again for scripting, its a no-no. Passing UDT as an array is slightly more complicated. I will write about these some time in the near future.
There are various good articles on the net about this, but here is a simple, to the point approach.
First Declare your type in your header file, like this
[ uuid("FD27CE79-9C08-4afa-AEB0-BB5B3E2F6DEA")] struct MiscInformation { BSTR Name; BSTR Status; BSTR Source; INT Priority; };
Now you will have to declare the type in your IDL file. But, because its an attributed project, here is how you do it.
Create a new idl file in you project and name it, for example structures.idl. The make an entry in the IDL file as follows:
[ uuid("FD27CE79-9C08-4afa-AEB0-BB5B3E2F6DEA")] struct MiscInformation { BSTR Name; BSTR Status; BSTR Source; INT Priority; }
[ version(1.0), uuid(5C6ADADA-1583-4DCB-8F14-4CF9F5BC048C), helpstring("Test UDT 1.0 Type Library") ] library TestUDT { struct MiscInformation; }
Once this is done you have to include this IDL file in the generated IDL file. Here is how I do it. In my main .cpp file I insert the line [importidl] on top. Like this:
[importidl("structures.idl")]; // The module attribute causes DllMain, DllRegisterServer and DllUnregisterServer to be automatically implemented for you[ module(dll, uuid = "{5C6ADADA-1583-4DCB-8F14-4CF9F5BC048C}", name = "TestUDT", helpstring = "TestUDT 1.0 Type Library", resource_name = "IDR_TESTUDT") ] class CTestUDTModule { public: // Override CAtlDllModuleT members };
This takes care to compile the right Type Information.
Now to use this UDT simply do it like this, for example:
[id(33), helpstring("method GetMiscInformation")]
HRESULT GetMiscInformation([out,retval] MiscInformation* pMiscInfo);
For creating a VARIANT type for the structure, I use the following function:
VARIANT GetVariantForStruct(REFGUID rGuidTypeInfo, void* data) { VARIANT vnt; IRecordInfo *pRI; HRESULT hr; hr = GetRecordInfoFromGuids(LIBID_TestUDT, 1, 0, 0x409, rGuidTypeInfo, &pRI); VariantInit(&vnt); vnt.vt = VT_RECORD; vnt.pvRecord = data; vnt.pRecInfo = pRI; pRI = NULL; return vnt; }
This can take care of wrapping structure in a variant. Of-course there are other things to talk about like passing UDT in a SAFEARRAY, but I will talk about them sometime in future.
Any suggestions/comments are welcome.
2 comments:
Good article Jalal. If possible, try to put sample code. that would be great.
-Abhishek, Germany
structure using i cant get uuid . how to get from idl and then pass the value to c# . i need clear explanation . thank you .
Post a Comment