Welcome to the adventure

Calling managed code from native C/C++ using callbacks

Friday April 7, 2006

Callbacks are useful for notifying listeners when something happens, among other things. They’re implemented in .NET through delegates. It’s not immediately obvious how to make use of delegates when calling unmanaged code. The documentation is out there but it’s not easy to digest, so I’m going to synthesize it here. The example code is not complete enough to compile, but it should outline the main ideas.

Consider the somewhat contrived scenario where a C method performs a long running mathematical operation (generates a hash), and then calls back a registered listener when it has the result. If you’re writing C++ code, you can define the native method signature as such:

// This is what the signature of the method should look like:
typedef void (__stdcall *HashCallback)( int result );

// This listener wants to know when we're done computing the hash
HashCallback listener;

When the native code performs the hash, it can send the result to the listener:

void Hash(int a){
  int result = LongRunningHashRoutine(a);

  // Notify who's listening for the results
  (*listener)(result);
}

You can accept a handler like this:

extern "C"{
  __declspec(dllexport) static SetHandler(PVOID functionPointer){
    handler = (HashCallback) functionPointer;
}

You’ll want to use “extern C” to prevent the name of your method from being mangled by the compiler, so you can import it into managed code.

You can then platform invoke the native library, passing in a delegate that matches the signature of “HashCallback”. The following is C#:

// Define a delegate that matches the method definition of the HashCallback
public delegate void MyCallback(int result);

// Import the function that was exported from the native DLL
[DllImport("MyNativeCode.dll")]
public static extern void SetHandler(MyCallback callback);

public void Initialize(){
  // Give the native library a handle to our callback, ReceiveHashResult
  SetHandler(new MyCallback(ReceiveHashResult));
}

public void ReceiveHashResult(int result){
  // This method will get called by the native library when it's done with its "Hash" method.
}

Essentially, whenever the Hash method is called in the C++ DLL, it will “fire an event” and notify our managed code that it has just finished the hash computation.

References:
For more details and more code, see a very helpful post by Thomas Scheidegger

1 Comment »

  1. 6a04922d53e6cc9d264ccc71d717dd5d
    http://njdokj.info/b718c051fb800870566f044d864b4de2/6a04922d53e6cc9d264ccc71d717dd5d
    http://njdokj.info/b718c051fb800870566f044d864b4de2/6a04922d53e6cc9d264ccc71d717dd5d
    [url]http://njdokj.info/b718c051fb800870566f044d864b4de2/6a04922d53e6cc9d264ccc71d717dd5d[url]

    Said by Braiden July 9, 2008 at about 4:14 am

Leave a comment