C # providing C ++ callbacks, access violation in _threadex.c in endthread ()
I have a C # Windows service application that passes a callback function pointer to a C ++ dll. I have defined both a function pointer on the C # side and C ++ side for the __stdcall type. Everything works fine until the callback is called by the C ++ dll and causes an unhandled exception access violation at 0x04cb0e. Debugging stops at threadex.c when endthread is called in a C # application.
public delegate void NotificationFunc(int notifycode, IntPtr Userdata);
[DllImport("notice.dll")]
void INotify(NotificationFunc notefunc,IntPtr Userdata);//ignore the IntPtr Userdata
.
.
.
NotificationFunc notefunc = new NotificationFunc(Noticallback);
INotify(notefunc, Intptr.zero);
//notice.dll triggers this callback thru the delegate passed in
void Noticallback(int notifycode, IntPtr userdata)
{
Swtich(notifycode)
{
//my actions
}
.
.//Error Exceptions happens here when trying to end the thread/call
}
I know I have to handle cleaning up these callback resources as this is a one way event. I tried GC and GCHandle so that it isn't GC, but it seems like there is always a memory leak or error. Can anyone please help? Thanks to
Wikipedia has a pretty decent article on this topic. If I were you, I would use C ++ / CLI as it is faster and not as tightly coupled. This kind of P / Invoke where you put all definitions all over the place is so error prone. And if you ever change or if the spec changes for you, for your datatypes or something, the C ++ / CLI will automatically update, but unfortunately any explicit P / Invoke decilators like you are here should always be re-wired.
a source to share
You must prevent managed code from collecting the delegate using GCHandle.Alloc
:
public delegate void NotificationFunc(int notifycode, IntPtr Userdata);
[DllImport("notice.dll")]
static extern void INotify(NotificationFunc notefunc,IntPtr Userdata); // Note IntPtr as the callback type
NotificationFunc notefunc = new NotificationFunc(Noticallback);
// Now, allocate a GCHandle to prevent the delegate from being collected
GCHandle handle = GCHandle.Alloc(notefunc);
INotify(notefunc, Intptr.Zero);
// Free the handle when it no longer needed
handle.Free();
a source to share