title: Passing C++/CLI Class Method as C function pointer
body: <p>I have a third-party C library that provides this header:</p>
  
  <pre><code>//CLibrary.h
  #include &lt;Windows.h&gt;
  #include &lt;process.h&gt;
  typedef void (WINAPI *CLibEventCallback)(int event, void *data);
  __declspec(dllexport) bool CLibStart (CLibEventCallback callback, void *data);
  
  // CLibrary.c -- sample implementation
  static CLibEventCallback cb;
  
  void _cdecl DoWork (void *ptr)
  {
      for (int i = 0; i &lt; 10; ++i)
      {
          cb (i*i, ptr);
          Sleep (500);
      }
  }
  
  __declspec(dllexport) bool CLibStart (CLibEventCallback callback, void *data)
  {
      cb = callback; // save address for DoWork thread...
      _beginthread (DoWork, 0, data);
      return true;
  }
  </code></pre>
  
  <p>I need to create a C++/CLI class that can call <strong>CLibStart</strong> and provide a class method as the function pointer.  As suggested below, this needs to be done with GetFunctionPointerForDelegate.  Because the delete constructor includes 'this' and doesn't require a static method, I don't need to pass 'this' into CLibStart.</p>
  
  <pre><code>using namespace System;
  using namespace System::Runtime::InteropServices;
  
  namespace Sample {
      public ref class ManagedClass
      {   
          delegate void CLibraryDelegate (int event, void *data);
  
      private:
          CLibraryDelegate^ managedDelegate;
          IntPtr unmanagedDelegatePtr;
          int someInstanceData;
  
      public:
          ManagedClass() 
          { 
              this-&gt;managedDelegate = gcnew CLibraryDelegate(this, &amp;ManagedClass::ManagedCallback);
              this-&gt;unmanagedDelegatePtr = Marshal::GetFunctionPointerForDelegate(this-&gt;managedDelegate);
              this-&gt;someInstanceData = 42;
          }
  
          void Start ()
          {
              // since the delegate includes an implicit 'this' (as static function is not needed)
              // I no longer need to pass 'this' in the second parameter!
              CLibStart ((CLibEventCallback) (void *) unmanagedDelegatePtr, nullptr); 
          }
  
      private:
          void Log (String^ msg)
          {
              Console::WriteLine (String::Format ("someInstanceData: {0}, message: {1}", this-&gt;someInstanceData, msg));  
          }
  
          void ManagedCallback (int eventType, void *data)
          {
              // no longer need "data" to contain 'this'
              this-&gt;Log (String::Format ("Received Event {0}", eventType));
          }
      };
  }
  </code></pre>
  
  <p>All of this compiles and runs fine using this C# tester:</p>
  
  <pre><code>using System;
  using Sample;
  
  namespace Tester
  {
      class Program
      {
          static void Main(string[] args)
          {
              var mc = new ManagedClass();
              mc.Start();
              Console.ReadKey();
          }
      }
  }
  </code></pre>
  
  <p>Sample output:</p>
  
  <pre><code>Received Event 0
  Received Event 1
  Received Event 4
  Received Event 9
  Received Event 16
  Received Event 25
  Received Event 36
  Received Event 49
  Received Event 64
  Received Event 81
  </code></pre>
  
  <p><strong>Outstanding questions:</strong>  </p>
  
  <ol>
  <li>I have this feeling that I need to use gcroot and/or pin_ptr?  If
  so, how? where?</li>
  </ol>
  
  <p>Thanks.</p>