How to use delegates in native Windows Mobile
Wednesday, January 2nd, 2008Delegate in C# is a nice function wrapper. Similar to function pointers in C/C++, it references a method and then you can use as a callback function. Every once in a while, a developer will need to call a managed-code delegate from a native code. For example, our mobile SIP client application we developed for eMobile is written mostly in managed code, but, is also using SIP stack libraries written in native code.
We needed a way to pass events from the SIP stack to the application layer. So, we had to transform a managed code delegate into a C function pointer. It turns out that’s very easy. If you know what you’re doing that is.
First thing to do is to declare the delegate in the managed code:
public delegate void OnIncomingCallDelegate(string aCallerID);
Now you need to declare its equivalent function pointer in native code:
typedef void (CALLBACK* NATIVEINCOMINGCALLUPDATE)(char* aCallId);
Alrighty then. Next step is to pass the delegate to the native DLL. That’s actually easier than you might think. You’ll need to pass the managed-code deleagte to the native-code DLL.
[DllImport("SipStackMvDriver.dll")] public static extern void SetupCallbackFunction(OnIncomingCallDelegate aOnIncomingCall);
The declaration on the native header file will look like this:
SIPSTACKMVDRIVER_API void SetupCallbackFunction(NATIVEINCOMINGCALLUPDATE aIncomingCallback);
where SIPSTACKDRIVER_API is a macro for DLL import/export declaratrion:
#ifdef SIPSTACKDRIVER_EXPORTS #define SIPSTACKDRIVER_API __declspec(dllexport) #else #define SIPSTACKDRIVER_API __declspec(dllimport) #endif
Guess what? you’re done!
Well, actually, almost done. You just have to do some preemptive work to prevent the delegate from being collected by the garbage-collector.
OnIncomingCallDelegate voipIncomingCallDelegate = new OnIncomingCallDelegate(OnIncomingCall);
GCHandle.Alloc(voipIncomingCallDelegate); // preventing the Garbage-collector from disposing the delegate
Now you’re done. Your delegates might require some marshalling tweaking but that’s an issue for another post.