Last updated on 1/25/2016

Interoperability & COM
by Binh Ly

We've previously seen how COM enables applications to talk to each other using interfaces. An interesting thing about interfaces is that an interface does not dictate usage of a particular development language. What this means is that the concept of an interface is rather "abstract" and does not require that your applications use C, C++, Pascal, or BASIC in order to work with an interface.

Consider a classic example that you may have encountered in the past: you are a huge C++ shop that develops reusable components. You do all development in C++ and you have tons and tons of code written in C++. In order to use your components, clients must also develop in C++ (obviously, C++ source can't be used in Visual Basic or Delphi applications) to be able to link-in your source code. Sometime later, you realize that there's a potential market in selling your components to Visual Basic developers. What options do you have?

  1. You can rewrite (i.e. duplicate) all your C++ code into Visual Basic. Now you have to maintain 2 source code trees - perhaps not a good idea.
  2. You can create plain DLLs out of your C++ code and have Visual Basic just use exported functions from your DLL. This works except that your Visual Basic clients really don't see your components as objects, they see them instead as a huge bunch of API functions where they have to pass a lot of parameters to each function - perhaps not a good idea.
  3. You can create objects out of your source and expose them as interfaces through COM. Since Visual Basic has no problems working with COM interfaces, viola, you have just created the perfect solution!

Because interfaces are "language-neutral", COM enables us to develop a web of interconnected applications each of which can be written in any language. This provides us with some interesting advantages:

  1. If you want to create interoperable applications but you prefer to develop using a particular language, you simply develop in that language and just expose your objects through COM interfaces. Other applications who make friends with your applications couldn't care less if it was written in an age-old language.
  2. If you have invested in a big massive code base (legacy or otherwise) and want other applications to be able to use it, you can "wrap" your existing code into an extra layer of COM objects and make them accessible to the outside world. This idea has interesting consequences and has in fact been used effectively in legacy integration projects.

Interfaces and vtables

An interface's "language neutrality" is based on a standard protocol. This protocol has its roots from the C++ language and is simply described as follows. Consider an interface IFoo with 2 methods:

IFoo = interface
  procedure Bar (Param1);
  procedure FooBar (Param1, Param2);

A pointer to IFoo is nothing but a pointer to a memory structure whose layout looks like this:

Figure: IFoo pointer memory structure

As far as the protocol is concerned, IFoo is a memory structure that consists of the 2 methods: method 1 (m1) and method 2 (m2), in that order. Whenever a client calls IFoo.Bar, the protocol simply calls m1 passing it the correct parameters; whenever the client calls IFoo.FooBar, the protocol simply calls m2 passing it the correct parameters. In short, the protocol is not concerned with the names of the methods; all it cares about is the order of the methods (m1, m2, m3, ..., mx) and the parameter count and type for each method. This enables the protocol to be used to building any interface, regardless of the number of methods or the types of parameters for each method.

In COM terminology, the memory structure described above is called a vtable (short for virtual table - a term derived from C++ classes). The protocol is called vtable binding (or early binding). Here's some important things to remember about vtable binding:

  1. A client call to an interface method is translated to a call to a method at a certain position, i.e. IFoo.Bar translates to a call to a method a position 1 (m1) and IFoo.FooBar is a call to a method at position 2 (m2). More importantly, the protocol is very strict about method positions and method parameters. For example, if a client expects to make a call to m2 (FooBar) and if the methods Bar and FooBar were swapped, Bar now becomes m2 which would make the client very unhappy.
  2. In order to use vtable binding from your client applications, your development environment must know how to generate compiled code that adheres to the vtable protocol. This is not a problem since most modern Windows development environments provide this capability; Visual Basic, Visual C++, Delphi, etc. all support the vtable binding protocol. Note that I strictly emphasize "compiled code" here because vtable binding is rather grungy and requires low-level compiled code in order to work.

Where Are We?

Binary interoperability is the term that describes everything I've said here. Binary interoperability means that applications interoperate with each other in their compiled state, i.e. as EXEs and DLLs. At the source code level, there is simply no way for applications to work with each other; for instance C++ source code is useless in Visual Basic and vice-versa. By compiling C++ code into a COM server, it suddenly becomes useful to Visual Basic and a wide range of other client applications. 

Binary interoperability is one of the key advantages in using COM and one that should be understood early on.

Further Reading

  • Understanding ActiveX and OLE by David Chappell
  • Inside COM by Dale Rogerson
  • Inside DCOM by the Eddons
  • Essential COM by Don Box
Copyright (c) 1999-2011 Binh Ly. All Rights Reserved.