Sunday, May 6, 2018

Interop between Unmanaged C++ with Managed C#

Managed C# Code -> ManagedCS.dll ( Assembly)

  • create methods as static public
  • set output path to a location where the ManagedDll.lib can reference during runtime

public static class ManagedClass
    {
        public static void ShowValue(ref int value)
        {
            DialogResult result = MessageBox.Show("C# Message Box", "C# Message Box", MessageBoxButtons.OKCancel);
            if (result == DialogResult.OK)
                value = 1;
            else
                value = 2;
            return;
        }

        public static void PassString(string s)
        {
            MessageBox.Show(s);
        }

        public static void PassImage(byte[] byteArray)
        {
            //byte[] imageBytes = Convert.FromBase64String(base64String);

            MemoryStream ms = new MemoryStream(byteArray, 0, byteArray.Length);

            // Convert byte[] to Image
            ms.Write(byteArray, 0, byteArray.Length);
            Image image = Image.FromStream(ms, true);

            image.Save(@"c:\Out\Out.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
        }

        public static void PassFloat(float f)
        {
            Console.WriteLine("F=" + f);

        }
    }




Managed C++ Code -> ManagedDLL.lib


  • cretaed as a CLR class library project  ( /clr)
  • Add reference to managedCS.dll 
  • Create a wrapper class
  • Use Marshall to convert data types before passing to managed code

public ref class DoWork
{
public:void ShowCSharpMessageBox(int *value)
{
ManagedCS::ManagedClass::ShowValue(*value); // call csharp dll
return;
}
public:void PassCSharpString( char *str) 
  {

 
  String  ^s = Marshal::PtrToStringAnsi(static_cast(str) );
  ManagedCS::ManagedClass::PassString(s);

  }
public:void PassCShrapFloat(float value)
{
ManagedCS::ManagedClass::PassFloat(value);
return;
}
  public:void PassCSharpImage(unsigned char str[], int len )
  {
printf("len = %d", len);
  array ^byteArray = gcnew array(len + 2);
  Marshal::Copy( (IntPtr)str, byteArray, 0, len );    
  ManagedCS::ManagedClass::PassImage ( byteArray);

  }

  • export the methods to unmanaged code

__declspec(dllexport) void ShowMessageBox(int *value)
{
ManagedDLL::DoWork work;
work.ShowCSharpMessageBox(value);
}

__declspec(dllexport) void PassString(char *s)
{
ManagedDLL::DoWork work;
work.PassCSharpString(s);
}
__declspec(dllexport) void PassFloat(float f)
{
ManagedDLL::DoWork work;
work.PassCShrapFloat(f);
}
__declspec(dllexport) void PassImage(unsigned char *s, int len)
{
ManagedDLL::DoWork work;
work.PassCSharpImage(s, len);

}


Unmanaged C++

  • Add references to exported methods in code
_declspec(dllexport) void ShowMessageBox(int *value);
_declspec(dllexport) void PassString(char *s);
_declspec(dllexport) void PassFloat(float f);
_declspec(dllexport) void PassImage(unsigned char *s, int len);
  • Add linker input to point to the ManagedDLL.lib