ECOMPLUS
25 Aug 2004 - 10:31
Keywords :

I was happy when I heard of Symbian's ECOM API (see Forum Nokia) for component discovery and instantiation at the 2003 Symbian Exposium, because I always end up creating from scratch something with equivalent functionality for my own work. I believe the ECOM API takes us a step closer to getting COM-like component functionality on Symbian. Small, interchangeable COM modules are one of the (rare) ideas that have impressed me about Microsoft's system architecture.

Unfortunately, I found the ECOM API falls a bit short of giving me the kind of component framework I'd like to have. First of all, it seems to me that the idea of interface discovery is missing -- there is no root interface through which I can query a component for its capabilities. Secondly, I don't want to have to track the destructor key for an object. I'd like to create an object, be able to pass it around, and when I'm finished with it, ask the object to go away and it should take care of this on its own. Having to manage the destructor key makes it more difficult to share a component between parts of my code -- who takes care of destroying the object?

The ECOM examples distributed with the SDK's seem to view ECOM as merely a tool for DLL polymorphism. ECOM does help with this, but I believe it can do much more.

I would like to share a design idea and bit of code I have found useful several times over now. The idea is to be entirely ECOM compatible, but to add a couple of conventions which give ECOM the salient features of COM. The scheme is encapsulated in 2 mandatory interface definitions. Ideally, if we could all start using the same interfaces, we might end up with a small pool of re-usable components. I also mention 2 small optional pieces of code that make life easier.

The first mandatory interface is MUnknown which is intended to be the base interface of every interface exposed through this mechanism. Not surprisingly, MUnknown has a QueryInterfaceL method for asking what other interfaces the component supports. Interface ID's are 32 bits long, in keeping with ECOM's API's. MUnknown also has AddRef and Release methods for lifetime management. When you create a component or query for a new interface on it, the reference count is increased. When you are finished with an interface, you should call Release. Standard COM rules apply but note that you can also use Symbian tools like CleanupReleasePushL(*myUnknown) then CleanupStack::PopAndDestroy(myUnknown) to your advantage.

The second mandatory interface is MTracksOwnDestructorKey. This interface has a single method SetDestructorKey which we use to store the destructor key passed back from REComSession::CreateImplementationL. In the object's destructor, which it will take care of calling when its reference count goes to 0, it should pass the destructor key to REComSession::DestroyedImplementation as required by ECOM.

The first handy optional piece is a small static-link DLL which I've called ECOMPLUS. It has very little code, just a CreateImplementationL method which takes only a TUid aImplementationUid as in the REComSession version. There is no mention of the TUid& aDtorIDKey destructor key which appears in all the REComSession::CreateImplementationL methods, because the ECOMPLUS implementation uses ECOM to create the component, assumes what it gets back will implement MUnknown (as everything in our scheme should), and then calls QueryInterfaceL on that interface to get the MTracksOwnDestructorKey interface and set the destructor key. You don't need to use this method or the dll -- you could manually query for MTracksOwnDestructorKey and set the key yourself each time you created an instance if you wanted to, and indeed you might need to if you want to use some of the more advanced ECOM CreateImplementationL methods.

The second optional building block is a base class for a component which implements MUnknown and MTracksOwnDestructorKey. It stores its own destructor key and keeps a reference count so that when Release is called enough times to bring the reference count down to 0, the object deletes itself. Again, there's nothing stopping you from implementing your class from scratch, as long as your object implements MUnknown and MTracksOwnDestructorKey.

Note that the only mandatory requirements of the convention are that an object properly implement the MUnknown and the MTracksOwnDestructorKey interfaces and that it returns a pointer to an MUnknown (sub)interface on creation. In all aspects the component is a regular ECOM component and can be used as such.

Symbian lets us get away with being simple about threading and process issues, but there would be nothing stopping us from fleshing this convention out to a full DCOM-like cross-process or even remotely executable system. Throw in an IDispatch equivalent, and you've even got the tools to start writing automation components that could be invoked from java or a scripting language.

I hope others find this helpful and I welcome comments or suggestions.

ecomplus.zip
ecomplus.zip

Tutorial posted August 25th, 2004 by newlc4

Submitted by Marcus Groeber (not verified) on Sat, 2004-09-04 20:42.

On a more general note, there is one thing that keeps me from using ECOM at the moment, even though I could think of several places in my code where I would like to: the lack of a backport to ER6.1 - as long as there is still a sizable population of Series 60 1.x devices out there (Sendo X, N-Gage QD being among the recent additions to the family...) I can't see how I could restrict the audience for my applications for just a bit of developer convenience...

In my mind, this is going to delay widespread usage of ECOM by at least a year or two, until developers can afford to sacrifice backward compatibility to ER6.1 devices.

Or am I completely off base, and there is already such a thing?


Submitted by MichaelMaguire (not verified) on Tue, 2004-09-07 00:31.

I don't believe I'm permitted to comment on this. Perhaps someone from Nokia could fill us in on the details...

Submitted by Anonymous on Sun, 2005-02-13 22:40.

I've been working with this quite a lot lately, and found it very useful. However, after some usage, I've found that the need to pass in a pointer to a pointer (which some other platforms' implementations' do in order to allow for smart pointers) is obviated on Symbian by the use of the CleanupStack. So to make for some cleaner code, I've changed it in my own implementation to:

virtual MUnknown * QueryInterfaceL( TInt aInterfaceId /* IN */ ) = 0;

Just thought I'd share. I'll see about updating the download at some point too.

Michael Maguire


Submitted by nicholas addo (not verified) on Wed, 2004-12-08 11:25.

Hi, Finally, someone else who finds ECOM an incomplete design! I have also been keenly interested in this sort of extension. Good beginnings!

Have you considered the IPR issues with using this these interfaces and the ideas embodied in COM.


Submitted by Anonymous on Wed, 2004-12-08 14:51.

I have considered the IPR issues, but I am not a lawyer. Please see the copyright notice in the source code, where I state that the code is provided as-is, with no guarantee that it doesn't violate anyone else's IPR.

Ideas like interface querying show up all over the place and (I believe) pre-date COM, and the Mozilla open source project has analogues of IUnknown, so I can't imagine this is a problem, but again, IANAL.


Submitted by newlc4 on Mon, 2008-03-31 13:22.

The ECOMPLUS project is now being maintained on sourceforge:

http://sourceforge.net/projects/ecomplus/

Regards,
Michael Maguire