I’ve made this to call unmanaged function from C code. pCallback is a function pointer so on the managed side is a delegate.
[DllImport("MyDLL.dll")]
public static extern Result SetCallback(
IntPtr handle,
Delegate pCallback,
CallbackType Type);
Now I am setting
public delegate void pfnCallback(uint PromptID, ttsEventType evt, IntPtr lData);
public Form1()
{
pfnCallback cb = new pfnCallback(cback);
(...)
Wrapper.SetCallback(handle, cb, IntPtr.Zero, CallBackType.DEFAULT);
(...)
}
It gives my an error saying “… when passing delegates to unmanaged code, they must be kept alive … “
Can anyone help me ?
Regards
You are confusing the delegate type declaration with the instance of the delegate. Yes, you made your delegate declaration public, that was wrong. Only the Form1 class uses it, it should be private. It is the instance of the delegate that matters here, the one you created with the new statement.
Right now, you are storing the instance in a local variable of the Form1 constructor. That keeps a reference on the instance for a few microseconds. As soon as the constructor completes, that reference is gone and the garbage collector can collect the delegate instance at any point after that. It cannot see that the unmanaged code keeps a reference to it, the collector can only discover references held by managed code.
Nothing good happens when the unmanaged code calls the callback on a collected delegate instance, you’ll hear a loud kaboom. You must change your code so that there will be a managed reference to the instance. One easy way to do this is to add a private member to the Form1 class to store the instance.
Even that might not be good enough, the Form1 object will be garbage collected at some point in the future as well. Which collects the delegate object as well. You also must make sure that the unmanaged code cannot use the callback after that happens. Given the name of the class (Form1), that isn’t that likely to happen in this specific case. But code defensively and make a call that resets the callback in the form’s FormClosing event handler.