I do whatever seems to be appropriate for the task at hand. In the case
where I use the get__This property, the objects are tightly coupled and
require access to many internal class members. Making a separate private
interface to perform these tasks just to satisfy COM is ludicrous and would
result in many more lines of code (the project is already over 65K lines as
it is). There are other projects where I do exactly as you describe and the
interfaces in question are not exported or published. Those are cases where
the builds are not integrated and the classes are only loosely coupled.
Incidentally, declaring the method as local eliminates any problems WRT COM
and marshaling as only a direct pointer will work and any attempts to use it
cross-apartment, much less cross-process or cross-machine, (through a proxy)
will fail. Thus, portability issues are irrelevant and the danger no greater
than any other C++ faux pas.
Also, on a related note, the use of dynamic_cast will return a NULL pointer
(or toss an exception if you're using a reference) if the type information
does not match. Comparing it's behavior to that of reinterpret_cast is a
misnomer -- it's actually identical to static_cast with the exception of the
run-time type verification (it will adjust the pointer value to reach the
proper frame while reinterpret_cast will not).
Ciao,
Dee
-----Original Message-----
From: BeginThread.com MSVC List [mailto:[EMAIL PROTECTED]]On Behalf
Of Ehsan Akhgari
Sent: Friday, September 12, 2003 9:08 AM
To: [EMAIL PROTECTED]
Subject: RE: [msvc] Automation, IDispatch, Class Explosing The Interface
> Easy. Obtain the interface containing the 'get__This' function via
> QueryInterface, etc. then call that method directly like so: (Note
> that 'propget' prepends "get_" -- there are 2 underscores, not one)
>
> class MyRealObject* pRealObject;
> hr = pInterface->get__This(reinterpret_cast<long*>(&pRealObject));
>
> If you call this using a proxy, you'll get an error since it's a
> local-only interface so both OCX's must be in the same apartment for
> this to work. There are ways around that as well but it can become
> quite dangerous if you're not *really* careful. Oh, also make
> absolutely sure you don't muck with heap allocations from one to the
> other. I do so myself but there's safeguards in place to make sure all
> of the DLL's share the same heap allocator -- without which things go
> downhill real fast!
What I do all the time in my projects is using standard COM code like
this: I define a private interface (by 'private' I mean not documented
and not exposed through the type library) and have my COM object expose
it. For example, if the COM object exposes IFoo, that interface will be
IFooControl. Then, I add all the methods which control the object's
behavior to that interface. Now, whenever I need this level of control,
I request this interface from the object, do my job, and release it,
like:
IFoo * pFoo = NULL;
HRESULT hr = ::CoCreateInstance( CLSID_Foo, NULL, CLSCTX_ALL, IID_IFoo,
reinterpret_cast< void ** > (&pFoo) ); if (SUCCEEDED(hr) && pFoo) {
IFooControl * pControl = NULL;
if (SUCCEEDED(pFoo->QueryInterface( IID_IFooControl,
reinterepret_cast< void ** > (&pControl) )))
{
pControl->ControlTheObjectInWhateverWay();
pControl->Release();
// now, I can pass pFoo on to the clients
}
}
Attempting to access the C++ object itself from the interface pointer is
dangerous, not portable, and not the way COM is designed to work. I
suggest you don't use it, and instead use my IFooControl method which is
not dangerous, and portable, and as easy as accessing the C++ object
itself.
BTW, using dynamic_cast to get to the C++ object itself is no better
than using reinterpret_cast.
-------------
Ehsan Akhgari
List Owner: [EMAIL PROTECTED]
[ Email: [EMAIL PROTECTED] ]
[ WWW: http://www.beginthread.com/Ehsan ]
Close your eyes, and imagine to be without what we take for granted
every time we open our eyes...
