|
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?
- 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.
- 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.
- 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:
- 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.
- 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.
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);
end;
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:
- 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.
- 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
|