title: Call a C++ function from C# and the param is a interface pointer
body: <p>I have a C++ DLL. It contains the following function:</p>
  
  <pre><code>struct Message {
      int id;
      unsigned short messageLength;
      unsigned char* message;
  };
  
  class Listener {
  public:
      virtual void OnMessage(Message* message);
  };
  
  void init(Listener* listener);
  </code></pre>
  
  <p>Is there a way to call the function 'init' from C#? I know you can use [DllImport] in C# to call C++ functions, but the pointers are giving me a hard time.</p>
  
  <p>Any help would be appreciated!</p>
  
  <h2>My Solution</h2>
  
  <h3>C++ Code</h3>
  
  <pre><code>typedef void (*MessageHander)(Message* message);
  
  class MessageDelegate : public Listener {
  public:
      MessageHander* messageCallback; // hold the callback funtion
  
      virtual void OnMessage(Message* message) {
          if (messageCallback) {
              (*messageCallback)(message);
          }   
      }
  }
  
  static MessageDelegate messageDelegate;
  
  void initEx(MessageHander* handler) {
      messageDelegate.messageCallback = handler;
      init(messageDelegate);
  }
  </code></pre>
  
  <h3>C# Code</h3>
  
  <pre><code>[Serializable]
  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
  public struct Message {
      public int id;
      public ushort messageShort;
      public IntPtr message;
  }
  
  class Program {
      [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
      public delegate void MessageHandler(ref Message message);
  
      [DllImport("MyCPlusPlusDLLName", CallingConvention = CallingConvention.Cdecl)]
      public static extern void initEx(ref MessageHandler callback);
  
      public void OnMessage(ref Message message) {
          byte[] rawMessage = new byte[message.messageLength];
          Marshal.Copy(message.message, rawMessage, 0, message.messageLength);
          // some other logic
      }
  
      public void Run() {
          MessageHandler handler = new MessageHandler(this.OnMessage);
          initEx(ref handler);
      }
  }
  </code></pre>