One way the .NET Framework solves cross-language interoperability is through the use of common data types. A String object in Visual C++ .NET is the same as a String object in C# or VB .NET. With this feature, the developer doesn't have to worry about type conversions using C++ casts or implementing some sort of data-conversion routines. However, the data types used within COM are not the same as the data types in the .NET Framework.
To achieve communication between COM objects and .NET assemblies, parameters and return values have to use a process known as marshaling. Marshaling is the packaging and sending of parameters and return types to an intermediate object, sometimes called a proxy, where it is then converted and unpackaged for the receiving object. One of the nice things about the design of COM Interop within the .NET Framework is that this marshaling process can be done for the most part by the common language runtime (CLR). However, if there is a data type in which no suitable substitute exists, that data type will either be converted to a similar albeit slightly different data type or may not be marshaled at all. If the latter case occurs, you must implement a custom object that performs the necessary marshaling for you.
When a .NET object calls a COM object, the runtime creates a runtime callable wrapper (RCW). The RCW is responsible for the marshaling behavior described earlier. In other words, whenever a .NET object calls an interface method of a COM object, the method call is routed to the RCW, marshaling is performed, and the RCW then calls the appropriate interface method in the COM objects. However, when a COM object wishes to call methods within a .NET object, a COM callable wrapper (CCW) is created (see Figure 21.1).
In order for the wrappers that are created at runtime to effectively marshal data, they need to know the data types beforehand. As mentioned in earlier hours, every .NET assembly contains an assembly manifest. Within this manifest is all the necessary information about data types and the data members of that assembly. Likewise, a COM object contains a type library that performs a similar function. It would seem reasonable that to use a .NET object within a COM client, the manifest of the .NET object must be converted into a type library, and vice versa. This is, in fact, what you will do when creating the projects for this hour. After you create the .NET project, you will add a custom build step that takes the information contained within the assembly manifest and creates a type library that can then be used by a COM client. Furthermore, you will use the information within the type library of a COM object and create an assembly manifest that is used by the RCW.