我需要用C语言编写一个用C语言编写的DLL。我在C#中编写了一个包装器DLL,它包装了每个C接口函数。 我推出了一个功能正常的代码,但最终崩溃了以下消息:
托管调试助手' CallbackOnCollectedDelegate'已在D:\ WrapperTest \ bin \ x64 \ Debug \ WrapperTest.exe'中检测到问题。
附加信息:对垃圾收集的类型' vJoyInterfaceWrap!vJoyInterfaceWrap.vJoy + WrapFfbCbFunc :: Invoke'进行回调。
负责崩溃的部分与C#代码向DLL注册的回调函数有关。当DLL从注册的回调函数调用(或返回)时发生崩溃。
// Definition of callback function prototype
// Parameter 1: Pointer to a data structure to be used inside the CB function
// Parameter 2: Pointer to user-defined data passed during registration
typedef void (CALLBACK *FfbGenCB)(PVOID, PVOID);
// Registration of CB function.
// Parameter cb is a pointer to the callback function.
// Parameter data is a pointer to user-defined data
VOID __cdecl FfbRegisterGenCB(FfbGenCB cb, PVOID data);
我希望用户定义的数据是一个对象(而不是IntPtr)。 为此,我使用预定义的回调函数封装用户的回调函数,该函数将IntPtr转换为对象。 在注册期间,我注册预定义的回调函数并将用户定义的数据(C#对象)转换为IntPtr。
// The user-defined CB function is of type FfbCbFunc
// FfbCbFunc is defined:
public delegate void FfbCbFunc(IntPtr data, object userData);
// The registration of the predefined callback function _WrapFfbCbFunc is done by calling
// function FfbRegisterGenCB:
public void FfbRegisterGenCB(FfbCbFunc cb, object data)
{
// Convert object to pointer
GCHandle handle1 = GCHandle.Alloc(data);
// Apply the user-defined CB function
_g_FfbCbFunc = new FfbCbFunc(cb);
WrapFfbCbFunc wf = new WrapFfbCbFunc(_WrapFfbCbFunc);
_FfbRegisterGenCB(wf, (IntPtr)handle1);
}
以下是其他定义和声明:
// Placeholder for user defined callback function
private static FfbCbFunc _g_FfbCbFunc;
// predefined callback function that encapsulates the user-defined callback function
public delegate void WrapFfbCbFunc(IntPtr data, IntPtr userData);
public void _WrapFfbCbFunc(IntPtr data, IntPtr userData)
{
// Convert userData from pointer to object
GCHandle handle2 = (GCHandle)userData;
object obj = handle2.Target as object;
// Call user-defined CB function
_g_FfbCbFunc(data, obj);
}
答案 0 :(得分:1)
包装回调函数及其引用必须是 static :
// Make wf global and static
private static WrapFfbCbFunc wf;
// Make the wrapping callback function static
public static void _WrapFfbCbFunc(IntPtr data, IntPtr userData)
{
object obj = null;
if (userData != IntPtr.Zero)
{
// Convert userData from pointer to object
GCHandle handle2 = (GCHandle)userData;
obj = handle2.Target as object;
}
// Call user-defined CB function
_g_FfbCbFunc(data, obj);
}
P.S。
我不认为这是一个非常糟糕的问题,可以通过-1票获得奖励。 就个人而言,我只是忽略了一些不感兴趣的问题。