CLR-COM Interop

[This is a very old article I wrote back in 2002 when I worked for a company which built MRI scanners and was subsequently bought by Oxford Instruments. With COM being once again relevant with the introduction of WinRT, I thought it might be useful to revisit some core COM and .NET concepts.]

Details

CLR-to-Native Win32

The CLR subsystem responsible for managing access to the native platform is known as P/Invoke. These services are included in an application by use of the namespace System.Runtime.InteropServices, and the [DllImport(“<DLL_NAME>”)] attribute prepended to the function prototype.

When a call goes out to a piece of Unmanaged code from Managed code (CLR), a flag is set on the application’s CLR (pseudo-) stack. This causes the GC not to collect during the duration of the Unmanaged call. The Security Subsystem responds to the flag by searching up the stack for permissions to enter Unmanaged code. The security check can be suppressed by a call to System.Security.SuppressUnmanagedCodeSecurity, which prevents stack crawling by the Security Subsystem beyond the point at which the call was made.

P/Invoke builds a second stackframe to use when calling the Unmanaged code. Some types can be blitted from the CLR stackframe to the Unmanaged frame, e.g. integers. Other types such as System.String are less easy to transfer to the new frame; instead of a reference to the string memory being passed, a char*-compatible copy is made, meaning that the intended manipulation of the character string inside the Unmanaged code does not get transferred back to the CLR string.[1]

P/Invoke performs type conversion/coercion automatically on-the-fly. The precise native (Win32) type of converted CLR types can by controlled using the MarshallAs directive.

Note that a call through P/Invoke is expensive: a minimum of 32 machine instructions is required for the Managed-to-Unmanaged transition. In practice this figure will be much larger.

CLR-to-COM

The CLR can interop with COM. CLR types appear as COM objects to COM via CCWs, and COM objects appear as CLR types to the CLR via RCWs. The tools TLBIMP.exe and TLBEXP.exe can be used to generate CCWs and RCWs.

ComImport is a compiler directive (== metadata property) that directs the CLR to create the object to which it refers using the classic COM CoCreateInstance rather than from its own GC-managed heap.

COM-to-CLR

The tool RegAsm.exe registers types found in a .NET assembly as COM objects. These COM objects are hosted in mscoree.exe as InProc servers.[2] mscoree.dll and mscorlib.dll are the CLR COM Type Libraries.

Comments

This document is based on a lecture given at DevWeek 2002.

Glossary

  • CCW……………………………………….. COM-Callable Wrapper
  • CLR………………………………………… Common Language Runtime
  • GC………………………………………….. Garbage Collector
  • P/Invoke………………………………… Platform Invoke
  • RCW……………………………………….. Runtime-Callable Wrapper

[1] N.B. System.String is immutable, i.e. should not be modified once created. Passing a string by reference to a native Win32 DLL could allow modification, and so memory corruption. Use System.StringBuilder to manipulate strings.

[2] A public key must be used to generate a GUID for CLR types marked for export as COM objects, because the standard GUID generation is not used in .NET.

Join the discussion...

This site uses Akismet to reduce spam. Learn how your comment data is processed.