The Design of Software (CLOSED)

A public forum for discussing the design of software, from the user interface to the code architecture. Now closed.

The "Design of Software" discussion group has been merged with the main Joel on Software discussion group.

The archives will remain online indefinitely.

Sharing COM interfaces between projects

This is using VC++ 6 and also 2003

We want to have multiple COM projects implement the same interface.  It doesn't have a default implementor project.

We thought to share an additional IDL file between projects, and use the import statement.  This seems to not work too well.

What is the proper procedure to do this?
Friday, September 09, 2005
That is the proper way to do this, if by "use the import statement" you're referring to the IDL import statement.

How is it not working well?

You've got basically two ways to share COM type information: share an IDL file, or share a type library. If your interfaces are all automation compatible, the typelib is easier to use in most non-C++ tool. Unfortunately, there's a lot of stuff in IDL that doesn't go into the typelib, so if you use any of that stuff you're stuck with the IDL files.
Chris Tavares Send private email
Friday, September 09, 2005
As far as "pure" COM goes, if it isn't in the type library, it doesn't exist.

If you think you might want to access any of the interfaces from another language (VB, .Net, etc.) then using a typelib is a better solution. 

Accessing COM objects from other environments is a good check that you're playing by the rules wrt apartments, etc.  Plus, it's ridiculously easy to write unit tests, etc. in VB.

OTOH, if all access MUST be from C++, why use COM?
BillT Send private email
Friday, September 09, 2005
Bill-- COM doesn't require a type library. Some COM things do (e.g. it makes IDispatch much easier).

Basic COM is is useful for sharing cross-components because it defines some very straightforward rules about object lifetimes and interfaces.
mb Send private email
Saturday, September 10, 2005
I used COM in C++ because it was the only way to reliably share C++ objects as binaries.

Straight C++ .lib files and .dlls are pretty much a failure; if they're not compiled with exactly the right options you're pretty much screwed; same compiler versions, same service pack, same debug setting, same thread setting, etc.

COM, despite its annoyances, generally just worked once you figured it out.
Chris Tavares Send private email
Saturday, September 10, 2005

Using COM to "paper over" the problems of using different libs, DLL's etc. will work, but it may not be the best solution.

Doing this through COM comes at a price -- potentially lots of cross-apartment calls w/attendant marshalling, proxy creation, etc.  Not to mention you're locked in to Windows + COM.  Effective multithreading (i.e., without coarse-grained locking done by COM itself) requires a thorough understanding of COM threading models.

It is possible to get C++ libraries working together, but it's not easy.  (I know -- this is what my co. does for a living).

You may want to look at "Large-Scale C++ Software Design" by John Lakos -- this is the bible for creating robust interoperable C++ libraries.

If you still want to use COM, go with typelibs.  COM itself can't read IDL -- only the information in the typelib makes it over to COM, so at least you'll be working with the same info that the COM libraries are using.
BillT Send private email
Monday, September 12, 2005
We found that working with the tlb actually works best.  We played around with using the .idl directly as a 1st shot but it didnt work out too well (cant remember the specifics but it was related to builds and keeping everything straight)

Here's how we do this:

Say you have an .idl file "shared.idl".

Create a project called "sharedIDL.dsp" that simply includes "shared.idl" and builds "shared.tlb"

In ProjectA (uses shared.idl).
  Create a dependency on SharedIDL.dsp, this way the tlb is always upto date. 

  In stdafx.h use the #import (with whatever declarations you want/need)
(e.g. #import "..\bin\debug\shared.tlb" raw_interfaces_only, raw_native_types, no_namespace, named_guids ).  This will allow you to use generated smart pointers

  In ProjectA.idl use importlib
    (e.g. importlib("..\bin\debug\shared.tlb"); )

We relative path to stuff/redirect our outputs to a common folder to get all related things to 1 place.  This helps us keep everything organized for this situation.  So we end up with a directory structure as follows:

  .\ProjectName\IDL\(shared.idl, shared.dsp)
  .\ProjectName\Bin\Debug\(shared.tlb, ProjectA.dll, ProjectB.dll...)
  .\ProjectName\Bin\Release\(shared.tlb, ProjectA.dll, ProjectB.dll...)

    ProjectX would have dependency on shared.dsp and send output to ..\bin\debug (or ..\bin\release)

Hope this helps.
Tuesday, September 13, 2005
Just a note to clarify:  typelibs need not be separate files -- most/all COM dll's include an embedded typelib.

You can use the "OLE View" from VC6 to open and display the tlb info.
BillT Send private email
Tuesday, September 13, 2005
After several years into COM I came with one conclusion.
At the benining was fine, IUnknown and so on, then dengenerated in IDispatch and it grown under IDispatch.
I think they done it for VB not for C++.
In C++ you really dont need it. I am pretty fine with a
plug-in dll.
Monday, September 26, 2005

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics
Powered by FogBugz