Managed, Unmanaged and COM

I’m wrapping a legacy lib for use in a .NET envirment. 

Usefull: An Overview of Managed/Unmanaged Code Interoperability

Firstly, I tried to wrap the lib api with COM and use that from my C# app.  With speed and efficiecency a priority, this was unacceptable.  It involves callbacks (legacy lib) or events (COM) – the big slowdown happened in the call from the COM to it’s connection point (C#).  

The way forward is a managed/unmanaged C++ project.  All legacy objects are held as pointers to classes that wrap them.  A thin wrapper, one managed class for one legacy class.  Wrap the pointer in a nice template base class taking a type for the wrapped.  Have a pointer expose method that throws an exception if the wrapped pointer is null.  Ensure IDisposable is derived from and the ~ClassName, and !ClassName methods are both implemented (finalize and Dispose methods).  In the dispose, clean up the unmanaged pointer.

Callbacks from the native?  How to: Marshal Callbacks and Delegates Using C++ Interop.  It’s very important you don’t try this if the legacy callback expected is not __stdcall.  It will mess up the stack when you leave the callback.  This was my problem.  So, I created a class to set up the callback.  The legacy function that sets of the callback takes a callback and a void * as data.  For the callback I passed a normal callback function of my own, for the void * I passed a __stdcall callback as set up in the article.  When the normal callback gets called, I simple use the given void * as a pointer to a __stdcall callback and call that.  One thing about the article, gcnew GetTheAnswerDelegate, can be called passing an object as the first parameter, and a method as the second.  Getting your callback into an instance of a class.

Strings: How to: Convert System::String to wchar_t* or char*. A nice wrapper class can’t be resisted.

If COM is the required for some other reasons:  Don’t forget “oleautomation” attribute on your non-IDispatch interfaces (in your IDL).

This is a handy way to bind COM enums to a WPF control in XAML.  (Note the requirement of the loc namespace to point to where your COMTypes class is).  One can use System.Enum.Parse to get the selected enum value back from the combo box.

XAML:
<Window.Resources>
    <ObjectDataProvider MethodName="GetMyCOMEnums
        ObjectType="{x:Type loc:COMTypes}" x:Key="MyComEnums">
    </ObjectDataProvider>
</Window.Resources>
<ComboBox Height="26" Margin="400,29,0,0" Name="m_type" VerticalAlignment="Top" HorizontalAlignment="Left" Width="121" ItemsSource="{Binding Source={StaticResource MyComEnums}}" />

A class in your project:

public class COMTypes
{
   public static Array GetMyCOMEnums()
   {
       return Enum.GetValues(typeof(MyCOMLib.MyEnumType));
   }
}

Advertisements

2 thoughts on “Managed, Unmanaged and COM

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s