COM/ATL novice:passing object pointers through methods on a COM interface
Author |
Message |
Trond A. S. Anderse #1 / 6
|
 COM/ATL novice:passing object pointers through methods on a COM interface
Hi, Are the parameter passing capabilities of ATL/COM limited to the data types defined for MIDL? Is it not possible to pass pointers to objects as method parameters back and forward across component boundries? Lets say I define the following interfaces in an .IDL file: [ object, uuid(5D220C6F-ACE7-4933-A4E3-A588C1F2904B), dual, helpstring("IDataObject Interface"), pointer_default(unique) ] interface IDataObject : IDispatch { .. .. }; [ object, uuid(992C58D4-6188-4745-90C0-1229FD6F0999), dual, helpstring("IDataProccesingObj"), pointer_default(unique) ] interface IDataProccesingObj : IDispatch { [id(1), helpstring("method processDataObject")] HRESULT method processDataObject([in, out] IDataObject **iData); }; Having provided implementations for the IDataObject and IDataProccesingObj interfaces and built the .dll with the type library, I would (naturally) create a test client for the COM objects. Since I'm not really into the complexity of the COM architecture, I'd prefer to just obtain access to the COM objects using smart pointers provided by the type library. A snippet of client code could look something like this: .. .. #import "nameoftypeLibrary.dll" no_namespace .. .. int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { try { IDataObjectPtr pDataObject; IDataProccesingObjPtr pDataProcessingObject; HRESULT hr = pDataObject.CreateInstance(__uuidof(IDataObject)); // Do some initialization of the data object .. .. hr = pDataProccesingObj.CreateInstance(__uuidof(IDataProccesingObj)); pDataProccesingOb->method processDataObject(&IDataObjectPtr); //..or something like that } catch(_com_error &ce) { printf("Error:\n"); printf("Code = %08lx\n", ce.Error()); printf("Code meaning = %s\n", (char*) ce.ErrorMessage()); printf("Source = %s\n", (char*) ce.Source()); printf("Description = %s\n", (char*) ce.Description()); } Quote: }
My question is whether such an approach is worth considering? Being a COM novice, I accept the possibility for making some pretty far-fetched presumtions here, but I will, however, highly appreciate some advice on how to pass object pointers through methods on a COM interface. Regards, Trond
|
Sun, 03 Jul 2005 18:12:56 GMT |
|
 |
Craig Power #2 / 6
|
 COM/ATL novice:passing object pointers through methods on a COM interface
Quote: > [id(1), helpstring("method processDataObject")] > HRESULT method processDataObject([in, out] IDataObject **iData); > };
Is "method" #defined away? I don't recognize it as an MIDL keyword, although it might be something introduced in .Net? Otherwise, this is OK. Quote: > #import "nameoftypeLibrary.dll" no_namespace > .. > .. > int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) > { > try > { > IDataObjectPtr pDataObject; > IDataProccesingObjPtr pDataProcessingObject; > HRESULT hr = > pDataObject.CreateInstance(__uuidof(IDataObject));
The UUID passed to CreateInstance needs to be that of a coclass, not an interface. Also note that you can use one of the constructor overloads on _com_ptr_t<> to do this in one step, and without getting an HRESULT to check, e.g. IDataObjectPtr pDataObject(__uuidof(DataObject)); This will throw if the CoCreateInstance call fails. Quote: > // Do some initialization of the data object > .. > .. > hr = > pDataProccesingObj.CreateInstance(__uuidof(IDataProccesingObj)); > pDataProccesingOb->method > processDataObject(&IDataObjectPtr); //..or something like that
Again, I'm not sure about the presence of method. You'll want to pass pDataObject by address, rather than taking the address of IDataObjectPtr (in fact, I don't guess what you have there would compile). And you'll want to be aware that _com_ptr_t<> smart pointers erase the contained pointer when you use their address operator. How much of a problem this is depends on the implementation of processDataObject(). If it creates an instance of DataObject if passed the address of a NULL pointer, then it's not a problem (although it does make the code earlier in main() that creates a DataObject pointless). If not, you need to do the call a little bit differently, e.g. IDataObject* pRawDataObject = pDataObject; pDataProcessingObj->processDataObject(&pRawDataObject); And note that this method will cause problems of its own if processDataObject moves its argument around. Quote: > My question is whether such an approach is worth considering?
Absolutely, in fact it's pretty much the right way to do it. -- Craig Powers MVP - Visual C++
|
Sun, 03 Jul 2005 22:59:17 GMT |
|
 |
Alexander Nickolo #3 / 6
|
 COM/ATL novice:passing object pointers through methods on a COM interface
The IDataObject interface is not Automation-compatible. You can't use it when defining dual interfaces. -- ===================================== Alexander Nickolov Microsoft MVP [VC], MCSD
MVP VC FAQ: http://www.mvps.org/vcfaq =====================================
Quote: > Hi, > Are the parameter passing capabilities of ATL/COM limited to the data > types defined for MIDL? Is it not possible to pass pointers to objects > as method parameters back and forward across component boundries? > Lets say I define the following interfaces in an .IDL file: > [ > object, > uuid(5D220C6F-ACE7-4933-A4E3-A588C1F2904B), > dual, > helpstring("IDataObject Interface"), > pointer_default(unique) > ] > interface IDataObject : IDispatch > { > .. > .. > }; > [ > object, > uuid(992C58D4-6188-4745-90C0-1229FD6F0999), > dual, > helpstring("IDataProccesingObj"), > pointer_default(unique) > ] > interface IDataProccesingObj : IDispatch > { > [id(1), helpstring("method processDataObject")] > HRESULT method processDataObject([in, out] IDataObject **iData); > }; > Having provided implementations for the IDataObject and > IDataProccesingObj interfaces and built the .dll with the type library, > I would (naturally) create a test client for the COM objects. Since I'm > not really into the complexity of the COM architecture, I'd prefer to > just obtain access to the COM objects using smart pointers provided by > the type library. A snippet of client code could look something like > this: > .. > .. > #import "nameoftypeLibrary.dll" no_namespace > .. > .. > int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) > { > try > { > IDataObjectPtr pDataObject; > IDataProccesingObjPtr pDataProcessingObject; > HRESULT hr = > pDataObject.CreateInstance(__uuidof(IDataObject)); > // Do some initialization of the data object > .. > .. > hr = > pDataProccesingObj.CreateInstance(__uuidof(IDataProccesingObj)); > pDataProccesingOb->method > processDataObject(&IDataObjectPtr); //..or something like that > } > catch(_com_error &ce) > { > printf("Error:\n"); > printf("Code = %08lx\n", ce.Error()); > printf("Code meaning = %s\n", (char*) > ce.ErrorMessage()); > printf("Source = %s\n", (char*) ce.Source()); > printf("Description = %s\n", (char*) > ce.Description()); > } > } > My question is whether such an approach is worth considering? Being a > COM novice, I accept the possibility for making some pretty far-fetched > presumtions here, but I will, however, highly appreciate some advice on > how to pass object pointers through methods on a COM interface. > Regards, Trond
|
Mon, 04 Jul 2005 06:29:35 GMT |
|
 |
Simon Tre #4 / 6
|
 COM/ATL novice:passing object pointers through methods on a COM interface
Quote: > Hi, > Are the parameter passing capabilities of ATL/COM limited to the data > types defined for MIDL? Is it not possible to pass pointers to objects > as method parameters back and forward across component boundries?
You can pass a COM object to a COM method as an IUnknown or IDispatch. Your method will then have to do QueryInterface to get the specific interface you need.
|
Mon, 04 Jul 2005 17:50:08 GMT |
|
 |
Trond A. S. Anderse #5 / 6
|
 COM/ATL novice:passing object pointers through methods on a COM interface
Thanks a lot, guys! My implementation of "interface-pointer-reference-parameter-passing" back and forward through COM interface metods are running smoothly. Still being something of a COM/ATL nivice, I'm not really sure what Alexander Nickolov means means when he claims that I can't use IDataObject when defining dual interfaces. However, the impl. works great with a C++ client. Regards, Trond
Quote: > Hi, > Are the parameter passing capabilities of ATL/COM limited to the data > types defined for MIDL? Is it not possible to pass pointers to objects > as method parameters back and forward across component boundries? > Lets say I define the following interfaces in an .IDL file: > [ > object, > uuid(5D220C6F-ACE7-4933-A4E3-A588C1F2904B), > dual, > helpstring("IDataObject Interface"), > pointer_default(unique) > ] > interface IDataObject : IDispatch > { > .. > .. > }; > [ > object, > uuid(992C58D4-6188-4745-90C0-1229FD6F0999), > dual, > helpstring("IDataProccesingObj"), > pointer_default(unique) > ] > interface IDataProccesingObj : IDispatch > { > [id(1), helpstring("method processDataObject")] > HRESULT method processDataObject([in, out] IDataObject **iData); > }; > Having provided implementations for the IDataObject and > IDataProccesingObj interfaces and built the .dll with the type library, > I would (naturally) create a test client for the COM objects. Since I'm > not really into the complexity of the COM architecture, I'd prefer to > just obtain access to the COM objects using smart pointers provided by > the type library. A snippet of client code could look something like > this: > .. > .. > #import "nameoftypeLibrary.dll" no_namespace > .. > .. > int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) > { > try > { > IDataObjectPtr pDataObject; > IDataProccesingObjPtr pDataProcessingObject; > HRESULT hr = > pDataObject.CreateInstance(__uuidof(IDataObject)); > // Do some initialization of the data object > .. > .. > hr = > pDataProccesingObj.CreateInstance(__uuidof(IDataProccesingObj)); > pDataProccesingOb->method > processDataObject(&IDataObjectPtr); //..or something like that > } > catch(_com_error &ce) > { > printf("Error:\n"); > printf("Code = %08lx\n", ce.Error()); > printf("Code meaning = %s\n", (char*) > ce.ErrorMessage()); > printf("Source = %s\n", (char*) ce.Source()); > printf("Description = %s\n", (char*) > ce.Description()); > } > } > My question is whether such an approach is worth considering? Being a > COM novice, I accept the possibility for making some pretty far-fetched > presumtions here, but I will, however, highly appreciate some advice on > how to pass object pointers through methods on a COM interface. > Regards, Trond
|
Fri, 08 Jul 2005 20:57:58 GMT |
|
 |
Alexander Nickolo #6 / 6
|
 COM/ATL novice:passing object pointers through methods on a COM interface
IDataObject is not Automation-compatible, therefore a dual interface cannot use it as an argument type in any of its methods' signatures. You should be getting a warning (an error really) from MIDL that your interface is not Automation-compatible. -- ===================================== Alexander Nickolov Microsoft MVP [VC], MCSD
MVP VC FAQ: http://www.mvps.org/vcfaq =====================================
Quote: > Thanks a lot, guys! > My implementation of "interface-pointer-reference-parameter-passing" back > and forward through COM interface metods are running smoothly. Still being > something of a COM/ATL nivice, I'm not really sure what Alexander Nickolov > means means when he claims that I can't use IDataObject when defining dual > interfaces. However, the impl. works great with a C++ client. > Regards, Trond
> > Hi, > > Are the parameter passing capabilities of ATL/COM limited to the data > > types defined for MIDL? Is it not possible to pass pointers to objects > > as method parameters back and forward across component boundries? > > Lets say I define the following interfaces in an .IDL file: > > [ > > object, > > uuid(5D220C6F-ACE7-4933-A4E3-A588C1F2904B), > > dual, > > helpstring("IDataObject Interface"), > > pointer_default(unique) > > ] > > interface IDataObject : IDispatch > > { > > .. > > .. > > }; > > [ > > object, > > uuid(992C58D4-6188-4745-90C0-1229FD6F0999), > > dual, > > helpstring("IDataProccesingObj"), > > pointer_default(unique) > > ] > > interface IDataProccesingObj : IDispatch > > { > > [id(1), helpstring("method processDataObject")] > > HRESULT method processDataObject([in, out] IDataObject **iData); > > }; > > Having provided implementations for the IDataObject and > > IDataProccesingObj interfaces and built the .dll with the type library, > > I would (naturally) create a test client for the COM objects. Since I'm > > not really into the complexity of the COM architecture, I'd prefer to > > just obtain access to the COM objects using smart pointers provided by > > the type library. A snippet of client code could look something like > > this: > > .. > > .. > > #import "nameoftypeLibrary.dll" no_namespace > > .. > > .. > > int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) > > { > > try > > { > > IDataObjectPtr pDataObject; > > IDataProccesingObjPtr pDataProcessingObject; > > HRESULT hr = > > pDataObject.CreateInstance(__uuidof(IDataObject)); > > // Do some initialization of the data object > > .. > > .. > > hr = > > pDataProccesingObj.CreateInstance(__uuidof(IDataProccesingObj)); > > pDataProccesingOb->method > > processDataObject(&IDataObjectPtr); //..or something like that > > } > > catch(_com_error &ce) > > { > > printf("Error:\n"); > > printf("Code = %08lx\n", ce.Error()); > > printf("Code meaning = %s\n", (char*) > > ce.ErrorMessage()); > > printf("Source = %s\n", (char*) ce.Source()); > > printf("Description = %s\n", (char*) > > ce.Description()); > > } > > } > > My question is whether such an approach is worth considering? Being a > > COM novice, I accept the possibility for making some pretty far-fetched > > presumtions here, but I will, however, highly appreciate some advice on > > how to pass object pointers through methods on a COM interface. > > Regards, Trond
|
Sun, 10 Jul 2005 07:15:30 GMT |
|
|
|