Reading COM struct from IDispatch
Hi,
First of all, I do not know where to post the question in subcategory.
My question is that I have C++ function which has a IDispatch input as argument.
I am trying to read the struct from IDispatch.
So basically, the struct definition is
struct MyStruct
{
void *m_pValue;
};
I can get the ITypeInfo and read the whole structure definition from it.
But I do not know how to read the struct instance value.
I am dumping all the info from ITypeInfo
TYPEATTR
========
guid {A1CB710C-8D50-3181-BB38-65CE2E98F9A6} _GUID
lcid 0x00000000 unsigned long
dwReserved 0x00000000 unsigned long
memidConstructor 0xffffffff long
memidDestructor 0xffffffff long
lpstrSchema 0x00000000 <NULL> wchar_t *
cbSizeInstance 0x00000004 unsigned long
typekind TKIND_RECORD (0x00000001) tagTYPEKIND
cFuncs 0x0000 unsigned short
cVars 0x0001 unsigned short
cImplTypes 0x0000 unsigned short
cbSizeVft 0x0000 unsigned short
cbAlignment 0x0004 unsigned short
wTypeFlags 0x0000 unsigned short
wMajorVerNum 0x0001 unsigned short
wMinorVerNum 0x0000 unsigned short
tdescAlias {lptdesc=0xbaadf00d {lptdesc=??? lpadesc=??? hreftype=??? ...} lpadesc=0xbaadf00d {tdescElem={lptdesc=...} ...} ...} tagTYPEDESC
idldescType {dwReserved=0x00000000 wIDLFlags=0x0000 } tagIDLDESC
VARDESC[0]
==========
memid 0x40000000 long
lpstrSchema 0x00000000 <NULL> wchar_t *
oInst 0x00000000 unsigned long
lpvarValue 0x00000000 <NULL> tagVARIANT *
elemdescVar tagELEMDESC
tdesc tagTYPEDESC
lptdesc 0x003e32f8 tagTYPEDESC *
lptdesc 0x00000000 <NULL> tagTYPEDESC *
lpadesc 0x00000000 <NULL> tagARRAYDESC *
hreftype 0x00000000 unsigned long
vt 0x0018 unsigned short
lpadesc 0x003e32f8 tagARRAYDESC *
hreftype 0x003e32f8 unsigned long
vt 0x001a unsigned short
idldesc {dwReserved=0x00000000 wIDLFlags=0x0000 } tagIDLDESC
paramdesc {pparamdescex=0x00000000 <NULL> wParamFlags=0x0000 } tagPARAMDESC
wVarFlags 0x0000 unsigned short
varkind VAR_PERINSTANCE (0x00000000) tagVARKIND
Any help will be highly appreciated.
Regards.
Re: Reading COM struct from IDispatch
First thing you have to learn about COM is: COM is not C++. COM world knows nothing about C++ structures. COM knows nothing about any language specific constructs. COM knows only about COM.
The only generic way to pass some structured data via COM interfaces is passing COM objects.
There is a way to pass language specific types, though with limited support, and the way is called special marshaling. But as far as I know, IDispatch is intended to operate with universal marshaling compliant types, and the easiest way is again passing COM object's dispinterface.
Bottom line: you have to turn your C++ structure to a real COM object prior to letting it to COM world.
Re: Reading COM struct from IDispatch
I totally agree with you. But i am confused over unmanaged C++ function call from C#.
Basically, I am trying to get IOleObject interface from the user control in unmanaged function. But everytime QueryInterface returns E_NOINTERFACE.
Then I walked through the ITypeInfo from IDispatch interface and found out that it is basically a intPtr structure in IDispatch routine.
Here is what I am trying to do.
C++
void MyFunc(IDispatch *pDisp)
{
IOleObject *pOleObject;
HRESULT hr = pDisp->QueryInterface(IID_IOleObject, (LPVOID *)&pOleObject );
// Always return hr = E_NOINTERFACE
}
C#
static extern void MyFunc([In, MarshalAs(UnmanagedType.IDispatch)] Object o);
void ManagedFunc()
{
UserControl uc1 = new UserControl();
IntPtr unk = Marshal.GetIUnknownForObject(uc1);
MyFunc(unk);
}
Kindly tell me how to access IOleObject from the winform control. I can't use managed code in my Unmanaged library.
Thanks for the help.
Regards.
Re: Reading COM struct from IDispatch
Quote:
Originally Posted by
Igor Vartanov
The only generic way to pass some structured data via COM interfaces is passing COM objects.
No, that's an incorrect view of things...
COM is about interfaces (functions) and you don't know what the "inside" (data) of a COM interface really is. Although it does happen, it's rare to see COM interfaces where you pass one COM 'object' into another COM 'object'. technically speaking 'COM object' isn't a right terminology, it's an instance of a COM interface.
passing data to/from COM interfaces is about using "agreed upon" data formats.
Generically this means you have:
- the elementary types like an BYTE, SHORT, INT, LONG, DATE...
- The string type BSTR
- The VARIANT
- The SAFEARRAY
Non-generically, you can technically use "any type" you want, including (pointers to) C++ structures and even C++ classes, but that means that particular member function will probably not be accessible/callable from anything but C++ or at least from any language that doesn't provide for specific memory organized data layouts.
In extreme cases, the presense of such memberfunctions might make the whole interface invalid on some platforms/languages. Part of the point of COM is about making some interface that is accessible for "any language", so using such constructs while possible, kind of makes you wonder why you went to COM in the first place if it's only accessible from C++
IDispatch is about offerring interfaces which are "interpreted" at runtime rather than "hardcoded" function calls determined at compiletime, it's what languages like VBS/VBA and JavaScript tend to use. ANd those languages will only work with the generic types.
You can call IDispatch from C++ but without some framework support for it (like ATL), it's very tedious compared to the fairly straightforward calling of interface methods.
1 Attachment(s)
Re: Reading COM struct from IDispatch
Quote:
Originally Posted by
salman83
Kindly tell me how to access IOleObject from the winform control. I can't use managed code in my Unmanaged library.
I'm not sure how I could help, as I know nothing about what you do and how you do what you do. I tried to assemble some sample that demonstrates how true COM object and native Object in C# differ from each other. Please find the sample attached here.
When you have the project built, run it with demo or xl command parameter to see how true COM object is passed via IUnknown to C++ code. You are going to get Succeeded in case you have demo scriptlet or MS Excel registered in your system (see README.TXT for scriptlet registration details.) Which means C++ is able to query IDispatch from the IUnknown.
And see the same for native C# Object when you specify no command line parameter. You get Failed, which means there's no any dispinterface behind the IUnknown.
See the difference.
Re: Reading COM struct from IDispatch
Quote:
Originally Posted by
OReubens
No, that's an incorrect view of things...
COM is about interfaces (functions) and you don't know what the "inside" (data) of a COM interface really is.
Yeah, I should be more specific about interfaces. But once some interface is registered in the system (along with its coclass) you do know "what is inside" as the type library exposes the details. The thing is that type library can talk COM language only.
1 Attachment(s)
Re: Reading COM struct from IDispatch
I've built another sample, now with winforms app. Everything seems working fine, and IOleObject is retrievable alright, at least from button object.