L
LeoAyala
Guest
I have created a C# application that needs to communicate with an unmanaged library (DLL). The unmanaged library posts messages to my app via a callback. In the unmanaged DLL, the callback is defined as follows:
typedef BOOL (*UPDATEMSG)(unsigned int nID, TCHAR *tcMESSAGE);
The unmanaged DLL has a method that is called to register the callback method. So, I created a delegate as follows and call the unmanaged DLL to register the callback.
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool UPDATEMSG(uint nID, string sMessage);
[DllImport("dllname.dll", CallingConvention.StdCall)]
public static extern void RegisterMsgUpdateEvent(UPDATEMSG UpdateMsg);
During initialization of my app, i call the register method and pass the delegate. Since this is maintained until the app is closed, I read that I must protect it from the garbage collector.
updateMsg = new UPDATEMSG(UpdateMsgEvent);
someCallbackPinHandle = GCHandle.Alloc(updateMsg, GCHandleType.Normal);
The app 'appears' to work just fine. It is able to receive messages from the unmanaged DLL. However, when I close the app, the UI closes but Visual Studio shows it as still running and I have to stop the debugger. If I run the app directly, when I close it, the UI closes but the Task Manager show process still running. It is as though the unmanaged DLL keeps it in memory.
If I change GCHandleType to Pinned, then I get an exception when calling GCHandle.Alloc()
Object contains non-primitive or non-blittable data.
I think this is because, on the unmanaged side, the string that is passed via the callback is defined as TCHAR tcName[MAX_PATH]. Based on what I read about passing arrays, I think I understand the exception but I don't understand why it 'appeared' to work when GCHandleType was set to Normal. I also commented the use of the GCHandle and the app process still hung.
I know the problem is related to the callback since the problem does not occur if I do not register the callback with the unmanaged DLL. Besides the callback, my app can call other methods on the unmanaged DLL without problems.
Does anyone have an idea what I may be doing wrong?
Thanks in advance,
LA
Continue reading...
typedef BOOL (*UPDATEMSG)(unsigned int nID, TCHAR *tcMESSAGE);
The unmanaged DLL has a method that is called to register the callback method. So, I created a delegate as follows and call the unmanaged DLL to register the callback.
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool UPDATEMSG(uint nID, string sMessage);
[DllImport("dllname.dll", CallingConvention.StdCall)]
public static extern void RegisterMsgUpdateEvent(UPDATEMSG UpdateMsg);
During initialization of my app, i call the register method and pass the delegate. Since this is maintained until the app is closed, I read that I must protect it from the garbage collector.
updateMsg = new UPDATEMSG(UpdateMsgEvent);
someCallbackPinHandle = GCHandle.Alloc(updateMsg, GCHandleType.Normal);
The app 'appears' to work just fine. It is able to receive messages from the unmanaged DLL. However, when I close the app, the UI closes but Visual Studio shows it as still running and I have to stop the debugger. If I run the app directly, when I close it, the UI closes but the Task Manager show process still running. It is as though the unmanaged DLL keeps it in memory.
If I change GCHandleType to Pinned, then I get an exception when calling GCHandle.Alloc()
Object contains non-primitive or non-blittable data.
I think this is because, on the unmanaged side, the string that is passed via the callback is defined as TCHAR tcName[MAX_PATH]. Based on what I read about passing arrays, I think I understand the exception but I don't understand why it 'appeared' to work when GCHandleType was set to Normal. I also commented the use of the GCHandle and the app process still hung.
I know the problem is related to the callback since the problem does not occur if I do not register the callback with the unmanaged DLL. Besides the callback, my app can call other methods on the unmanaged DLL without problems.
Does anyone have an idea what I may be doing wrong?
Thanks in advance,
LA
Continue reading...