Introduction
This tip mainly shows how to pass a C# delegate to C++ with the aid of exported DLL functions.
The C++ version of the callback (which is a delegate in C#)
typedef void (__stdcall *fnNotify)(int notifyCode, NotifyStruct* notifyInfo);
How the delegate signature looks like in C#
public delegate void
DelegateNotify(int notifyCode, ref DLLLoader.NotifyStruct notifyInfo);
As you should be already aware, you have to instantiate the delegate by code which looks something like this:
new DelegateNotify(fnNotify);
Let's take a look at the function that would be accepting the callback..
The C++ exported DLL function which takes the callback as argument
extern "C" DLL_IMPORTEXPORT void SetNotifyCallBack(fnNotify callBack);
The C# version of the imported C++ function
[DllImport("TestDLL.dll", CharSet = CharSet.Auto)]
public static extern void SetNotifyCallBack(MulticastDelegate callback);
The above definition is inside a DLLLoader
class.
Note the MulticaseDelegate
argument type which actually does the trick of converting a delegate to a passable C++ callback.
Points of Interest
In the above C++ exported function, the callback takes a simple structure which contains notification data. So this tip also shows a way to marshall simple structures from C++ to C# through the callback function. So here is a little about marshalling simple structures to and fro C# and C++).
The structure to be marshalled (C# version)
public class DLLLoader
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct NotifyStruct
{
public int notifyHeader;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string notifyDescription;
}
[DllImport("TestDLL.dll", CharSet = CharSet.Auto)]
public static extern void SetNotifyCallBack(MulticastDelegate callback);
}
The definition of the same in C++
typedef struct _tagNotifyStruct
{
int notifyHeader;
wchar_t notifyDescription[NGH_EXPLORERITEM_MAXLEN];
}NotifyStruct;
Now we have defined the structure which is consistent both in C++ and C# (they have to be consistent of course, otherwise they won't work), let's turn our attention to the real thing... passing the Callback (delegate in C#).. to C++
Finally .. Create Delegate and Pass to C++
DelegateNotify callback = new DelegateNotify(fnNotify);
DLLLoader.SetCallBack(callback);
Acknowledgements
History
- 29th May, 2012: Tip uploaded