COM Interoperability and .NET
Why We Need COM Interop
There are fundamental architecture differences, possibly the understatement of the year, that render COM and .NET objects incompatible. Key differences include, but are not limited to, the following:
- As COM objects are created and stored in memory, the clients are given a reference to a specific memory location. The objects are not expected to move throughout their lifetime, and COM has no way to deal with object references that change memory locations because the clients have reference to a specific location. In .NET, managed objects are stored in memory controlled by the common language runtime (CLR). These objects may be allocated, de-allocated, or reallocated as deemed appropriate by the CLR. All client references to these objects are updated automatically, based on whatever action the CLR takes.
- COM objects expose a set of functions used to track the number of references to an instance of the object. Clients are responsible for using these functions to manage the lifetime of object instances. In .NET, the CLR, not the client, manages the lifetime of all objects.
Companies have resources, in the form of time and money, invested in building and/or buying COM components. In many cases, it is not justifiable to simply throw away these investments. You then have no choice but to wait to until the application has outlived its lifetime and can be replaced in order to benefit from .NET. Thus, a need exists to allow organizations to leverage current COM investments and also benefit from the advantages of .NET applications by easing them into their applications. This is the role COM Interop plays and the benefit it provides.
How COM Interop Works
It stands to reason that the work required to get the .NET and COM components to interoperate is going to be on the .NET-side because it is the newer technology. If you had to change all of your COM components to operate with .NET, it would make sense to just rewrite them in .NET and you wouldn't be reading this article on COM Interop.
To allow communication between .NET and COM objects, the CLR provides wrappers to make each object think it is talking to an object from its own architecture. A .NET client calling a COM object results in the CLR using a runtime callable wrapper (RCW) to make the .NET client think it is talking to a .NET object. A COM client calling a .NET object results in the CLR using a COM callable wrapper (CCW) that makes the COM client think it is talking to another COM object. The wrappers facilitate built-in rules for marshaling data between .NET and COM, such as conversion of string to BSTR and vice versa. Typically, the generated wrappers provide adequate marshaling of types between .NET and COM. There are ways to adjust way these wrappers are generated, but that is beyond this initial look at COM Interop.