Re: hosting the runtime
- From: "Richard Grimes [MVP]" <read my sig>
- Date: Mon, 20 Jun 2005 21:03:09 +0100
Sahil Malik [MVP] wrote:
> So a COM component has a lot to be told about - more than I can
> possibly type here. I'd recommend Inside COM by Don Box.
Hmmm, Inside COM was written by Dale Rogerson, and IMO not particularly
relevant here. Don's book is Essential COM. ;-)
First, its worth pointing out that a COM interface is very much like a
C++ v-table. Imagine COM marshalling as being a mechanism to transport a
v-table from one COM object in one memory space and make it available in
another memory space.
COM itself is essentially a mechanism to manage DLLs (we'll ignore
'local servers'). Imagine that you want to create an instance of a class
class and you know the name of the DLL. The problem in Win32 is that you
first have to locate the DLL and load it - this is the DLL hell problem,
because LoadLibrary will look in various places for the DLL and may pick
up a different version of the DLL or even a totally different DLL that
has the same name. COM manages this through values in the registry, when
you install a COM server the classes it contains will be registered in
the registry and these entries will contain the full path to the DLL.
***It is vitally important that the location of a COM server DLL does
not change***. Each class has a unique name called a GUID (a 128 bit
integer) and so whenever you create an object you create it via its
GUID. Languages do have mappings to human readable names, but it is
important to realise that the real name of a class is the GUID. COM
provides APIs that when given a GUID will locate and load the DLL
containing the class.
Next you need to create an instance of the class, which means finding
some code that will create it for you. Since you don't want a memory
leak, you also have to have a mechanism to remove the instance. COM
objects are usually created by class factory objects, a class factory is
intimately intwined with an object because the class factory calls new
with whatever memory manager it wants to use, and hence when the object
is destroyed it must call the appropriate delete.
So you need to get access to a class factory object in the DLL. However,
DLLs can only export C functions. So all COM server DLLs have to export
a function called DllGetClassObject. In effect you pass the name (GUID)
of a class to this function and it will return the class factory
interface of the class factory object (remember an interface is just a
v-table pointer, so all you get back is a pointer to a table of
pointers). You can then call the IClassFactory::CreateInstance to create
an instance of the class. Note that *all* access to COM objects are via
interfaces so you need to provide an identifier about what interface you
want to have on the new object.
All COM objects must implement IUnknown which has three methods:
QueryInterface allows you to ask for a specific interface, it's
equivalent to the C++ dynamic_cast<>. Note that there is no mechanism to
get a list of the interfaces on an object, instead, you have to call
QueryInterface for the interfaces that you want to use. The other two
methods are AddRef and Release. These maintain a reference count
(usually on the object) and when you make a copy of an interface pointer
you have to call AddRef, when you no longer need the pointer you have to
call Release. Once the reference count falls to zero the object can
delete itself. (What this means is up to the object, but it usually
means calling the delete on its this pointer that corresponds to the new
that the class factory called.)
The beauty of interfaces is that it allows polymorphism, because a
method that takes an interface pointer does not care what object the
pointer points to, it just cares about the behaviour of the interface.
> Non straightforward way - do what CoCreateInstance does -
You pass the class's GUID and the indentifier (another GUID) of the
interface you want on the object to CCI, which will locate the DLL, call
the class factory, create the object and then query for the specified
interface.
>> on the other hand I never used COM interface, I have no idea on how
>> they work....
>> care writing me a veyr simple C:main() which load an exe?
When you create a COM interface you write the interface in IDL and
compile it with MIDL. MIDL will create a header file with a C++ and a C
mapping for the interface. The platform SDK contains MIDL generated
header files created for the standard interfaces. For example, here's
IUnknown C mapping from unknwn.h:
typedef struct IUnknownVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IUnknown * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
IUnknown * This);
ULONG ( STDMETHODCALLTYPE *Release )(
IUnknown * This);
END_INTERFACE
} IUnknownVtbl;
interface IUnknown
{
CONST_VTBL struct IUnknownVtbl *lpVtbl;
};
So when you call CoCreateInstance in C you will get back an IUnknown* to
call a method you need to derefernce it to get the lpVtbl, and then
dereference that to get to the function pointer that you want to call.
In C++ the interface is treated as a C++ class v-table (the language
mapping does this) so you only need to dereference it once. Also, the
first, implicit parameter of a v-table method is a this pointer. The C++
mapping masks this, but in C you have to pass it explicitly.
// C code
IUnknown* pUnk = NULL;
HRESULT hr;
CoInitialize(); // must initialize COM, this creates a single threaded
apartment
hr = CoCreateInstance(&CLSID_MyClass, NULL, CLSCTX_INPROC_SERVER,
&IID_IUnknown, &pUnk);
if (SUCCEEDED(hr)) // always check return values
{
// use the interface here...
// finished with the interface so call Release
pUnk->lpVtbl->Release(pUnk);
// in C++ this would be pUnk->Release();
}
CoUninitialize(); // must uninitialise COM
As you can see it is much easier in C++ so usually people don't bother
with C. The only book that I know off hand that shows how to program COM
in C is Brockschmidt's Inside OLE. However, I doubt if this is still in
print. Anyway if you are a proficient C programmer it should not be too
difficult to write C to access COM objects using the headers created by
MIDL.
Richard
--
www.richardgrimes.com
my email evpuneqt@xxxxxxxx is encrypted with ROT13 (www.rot13.org)
.
- Follow-Ups:
- Re: hosting the runtime
- From: Sahil Malik [MVP]
- Re: hosting the runtime
- References:
- hosting the runtime
- From: Lloyd Dupont
- Re: hosting the runtime
- From: Sahil Malik [MVP]
- Re: hosting the runtime
- From: Lloyd Dupont
- Re: hosting the runtime
- From: Sahil Malik [MVP]
- hosting the runtime
- Prev by Date: Strange behavour of Process
- Next by Date: Re: Returning interfaces from web-services and remoting servers?
- Previous by thread: Re: hosting the runtime
- Next by thread: Re: hosting the runtime
- Index(es):
Relevant Pages
|