Delphi is great for COM if you want to do something simple; as soon as someting a little more complex is needed, COM in Delphi can be a real headache. Here is a braindump from a recent investigation:
The LocalServer class registration function CoRegisterClassObject
is called for each Class Factory registered with the Singleton ComServer
object in TComServer.Initialize
. Class Factories are registered in the initialization
section of units in which they are defined, and TComServer.Initialize
does not get called until after Application.Initialize
has been called (using some InitProc
hackery in first ComObj
and then ComServ
). Crucially, ComServer
is a helper object to guarantee registration of all the Class Factories in the application (or DLL), so ComServer.ObjectCount refers to the number of objects it has helped to create (via Class Factories) not the number of references held (say, externally) to any particular COM object.
A post from b.p.d.activex.controls.writing by one Patrice Corteel explains further:
Now let’s go a step further in COM threading model discussion and look at local and remote servers versus in-proc servers.
A Delphi local or remote exe server has a main thread which calls CoInitialize which makes it an apartment. And as a default behaviour, every COM component based on the delphi COM framework is created in this thread and marked as apartment threaded. If you explicitly spawn new threads you can initialize them as you want but you must get a marshalled interface to call components created by your main thread.
If you want to create free threaded components it’s far more difficult since you can’t rely directly on Delphi implementation and you have to rewrite large parts of ComServ and subclass many of ComObj classes. I’m currently working on this topic and I’ll post more on this when I am over with tests.
Note that if lengthy initialisation is needed, set ComServer.StartSuspended
to True
before Application.Initialize
; this causes the class factories to be registered with the REGCLS_SUSPENDED
flag, and ComServ.InitComServer
makes the required call to CoResumeClassObjects
to activate them again.
References
- Binh Ly’s excellent COM pages at http://www.techvanguards.com/com/
- Essential COM, by Don Box, 1998, Addison-Wesley