collapse Table of Contents
  1. GECL -- The Good-Enough COM Library
    1. Recent News
      1. April 19, 1999
    2. General Information
    3. QueryInterface implementation

GECL -- The Good-Enough COM Library

Recent News

April 19, 1999

General Information

Good-enough for what? Good enough for me, good enough for Nidus, and hopefully, good-enough for cross-platform C++ COM development. However, it might not reach all of these goals, especially cross-platform development (given heavy reliance on templates, which aren't supported across all platforms), but it's hoped that being compilable under the GNU egcs compiler should help...

The Good-Enough COM Library is (supposed to be) a set of template classes to facilitate the creation of COM-based components. Among its best points are its ability to be compiled with multiple compilers (MSVC 5.0 and egcs 1.1) and its QueryInterface implementation.

The current source is available.

QueryInterface implementation

What started this entire project is the following. Using other COM frameworks such as ATL and YACL, the implemented interface must be specified twice -- once in the inheritence list, and again for a table-driven QueryInterface implementation, e.g.

      /*
         Note that interfaces are first listed in the inheritance list...
       */
      class CoMyClass :
        public IDog, public ICat, public IBird
        {
        /*
          The following is used for a table-driven QueryInterface
         */
        BEGIN_INTERFACE_MAP(CoMyClass)
          /*
            Interfaces are listed a second time in the table...
           */
          IMPLEMENTS_INTERFACE(IDog)
          IMPLEMENTS_INTERFACE(ICat)
          IMPLEMENTS_INTERFACE(IBird)
        END_INTERFACE_MAP()

        /*
          Class implementation here...
         */
        };
    

My biggest problem with this is that the interfaces need to be listed more than once, duplicating code (or at least, names). It's quite possible (and likely) that one of the duplicate listings will be forgotten.

In the July, 1998 issue of Microsoft Systems Journal, Don Box lamented in his House of COM article over the current state of affairs with the C++ language mappings for COM development, and offered up his "wishlist" for what he'd like to see (on page 80):

      class DCM :
        public com_implements<IDog, ICat, IBird>
        {
        /*
          Implementation here; no map needed for QueryInterface...
        */
        };
    

This idea is what started GECL. And, for the moment, it works... kindof. Instead of DB's idea, which isn't really possible in C++ (templates need to have a finite number of "arguments", so for Don Box's original example to work, only three interfaces could be supported; it would be nice to support a variable number of interfaces, so I can't use Don Box's original idea), so this is done instead:

      class DCM :
        public CImplementsComInterfaces<
          CComInterface< IDog >, CComInterfaceContainer2<
            CComInterface< ICat >,
            CComInterface< IBird >
          >
        >,
        public CComCoClass<DCM, &CLSID_DCM>,
        public CComThreadingModel<CComFreeThreadModel>
        {
        /*
          Class implementation here; no map needed for QueryInterface...
         */

        /*
          Macro used for Registration support
         */
        DECLARE_REGISTRY("Foo.DCM.1", "Foo.DCM", "Dog/Cat/Bird")
        };
    

There are some downsides:

But in return, QueryInterface is handled in the inheritence list, thus reducing code duplication. And due to the framework, writing tear-off interfaces and Aggregation can all be handled in the inheritence list, where it makes a bit of sense. Overall, I think this is very powerful, but it'll need a little more development before I can determine how much of an overhead the framework generates, and thus if the space additions are reasonable over a pure ATL-style implementation.

The code is available under an MIT-style license, which allows you to use the code in any way you see fit; in the event my code causes the end of the known and/or unknown universe, I'm not reponsible; insert your standard disclaimor here.

Another nice bit is its inclusion of the `com_cast' template code that was illistrated in MSJ. The only sad part is that, in order for my framework and the `com_cast' template to work, a `meta_info' template specialization must exist for each interface you're going to use with `com_cast' or inherit from (in order to avoid using Microsoft's __uuidof operator, which doesn't exist on other compilers).

That, alone, is the most annoying part of the whole thing -- each interface you wish to implement must have a `meta_info' template specialization. Writing them is easy, it's just tedious. A future project will be a small program that extracts the required information for `meta_info' from the interface IDL, which should make development a lot easier and more palatable.