In my last post I mentioned ,
There are two ways that C# code can directly call unmanaged code:
- Directly call a function exported from DLL
- Call an interface method on a COM object
In this post lets concentrate on how to call an interface method on a COM object and how this can be implemented for managed environment.
.NET framework provides following facilities to perform COM Interop
- Creating COM objects
- Determining if a COM interface is implemented by an object
- Calling methods on COM interfaces
- Implementing objects and interfaces that can be called by COM clients.
Additionally, .NET framework also handles reference counting issues with COM Interop so there is no need to call or implement Addref and Release.
COM Interop provides access to existing COM components without requiring that the original components need to be modified and for this we can use a COM Interop utility (Tlbimp.exe). Type library importer converts the type definitions found within a COM type library into equivalent definitions in a CLR assembly.
Type library Importer performs following conversions :
- COM coclasses are converted to C# classes with a parameter less constructor
- COM structs are converted to C# structs with public fields.
Microsoft Intermediate Language Disassembler provides a great way to check out the output of Tlbimp.exe to view the result of the conversion.
In addition to this, COM Interop allows programmers to access managed objects as easily as they access other COM objects Here COM Interop provides a Assembly Registration Tool that exports the managed types into a type library and registers the managed component as a traditional COM component.
I referred MSDN for following steps and key points are as follows
Creating a COM Class Wrapper
Tlbimp converts a COM type library into .NET framework metadata- effectively creating a managed wrapper that can be called from any managed language.
- .NET framework metadata created with Tlbimp can be included in a C# build via /R compiler option.
- Using Visual Studio we need to add only COM type library and conversion is done automatically.
Important attributes in understanding COM mapping are
- ComImport
- GUID
- Interface Type
- PreserveSig
Declaring and Creating Comcoclass object
COM coclasses are represented as a classes with parameterless constructors in C#. ComImport attribute is a must for them. Creating instance of this class using the new operator is the C# equivalent of calling CoCreateInstance.
Additional restrictions are as follows
- The class must not inherit from any other class
- The class must implement no interfaces
- GUID for the class
Declaring a COM Interface
- COM interfaces are represented in C# as interfaces with COMImport and GUID attributes.
- COM Interfaces declared in C# must include declarations for all members of their base interfaces with the exception of members of IUnknown and IDispatch. These are added by .NET framework automatically.
- COM interfaces which derive from IDispatch must be marked with the InterfaceType attribute.
- When calling a COM interface method from C# code, CLR runtime must marshal the parameters and return values to/ from the COM object.
- Common way to return success or failure is to return an HRESULT and have an out paramter marked as “retval” in MIDL for the real return value of method.
Apart from this following are the links, one should must see for COM <-> .NET interoperability given on MSDN
COM Interop Part 1: C# Client Tutorial
COM Interop Part 2: C# Server Tutorial
Exposing .NET Framework Components to COM
Simplify App Deployment with ClickOnce and Registration-Free COM
I will be writing few more posts on Interops and some of the interesting aspects discovered using this. Meanwhile, do let me know your feedback and expectations from this blog.