C# pInvoke to a C function
本文关键字:function to pInvoke | 更新日期: 2023-09-27 18:33:25
我将不胜感激,因为我已经坚持了几天的问题。
我有一个本机C++函数类型声明如下:
typedef STATUS (T_TED_AcppBoxDYN_RegisterEventCallback) (
PEventCallback function, // pointer to the customer callback
PVOID param // custom data (returned in callback)
);
其中PEventCallback
和PEVENT
声明如下:
typedef int (*PEventCallback) (PEVENT event, PVOID param);
typedef struct
{
int nEventId;
void* pParam;
} EVENT,*PEVENT;
C++代码提供指向该类型的函数的指针作为全局变量:
T_TED_AcppBoxDYN_RegisterEventCallback* TED_AcppBoxDYN_RegisterEventCallback
= NULL;
稍后通过以下代码初始化:
#ifdef LOAD_PROC_ADDRESS
#undef LOAD_PROC_ADDRESS
#endif
#define LOAD_PROC_ADDRESS(handle,func) '
if((func=(T_##func*)GetProcAddress(handle,#func))==NULL) '
{'
sMsg.Format( "Error occurs while loading entry point'n'%s''n"'
"from detector DLL '%s''n", GetName (), #func );'
MessageBox(NULL, sMsg.GetBuffer(), "Load Proc Error", MB_OK | MB_ICONSTOP);'
return (false);'
}
bool P5100EDllManager::LoadProc ()
{
CString sMsg;
HMODULE hDllHandle = GetHandle();
if (hDllHandle == NULL)
{
return false; // cannot load the proc if the dll has not been loaded
}
LOAD_PROC_ADDRESS(hDllHandle, TED_AcppBoxDYN_RegisterEventCallback);
return true;
}
我想从 C# 调用指向函数。 为此,我定义了一个 C# 包装器:
public delegate void TDICallBack(IntPtr callbackEvent, IntPtr pParam);
[DllImport(DLL, EntryPoint = "TED_AcppBoxDYN_RegisterEventCallback", CallingConvention = CallingConvention.Cdecl)]
private static extern int TED_AcppBoxDYN_RegisterEventCallback(TDICallBack callBack, IntPtr param);
public void RegisterEventCallback(TDICallBack callBack, IntPtr param)
{
TED_AcppBoxDYN_RegisterEventCallback(callBack, param);
}
我是这样使用它的:
TdiapiFacade.RegisterEventCallback(OnTdiCallBack, IntPtr.Zero);
public void OnTdiCallBack(IntPtr ptr, IntPtr param)
{
}
RegisterEventCallback()
似乎工作成功,但在应该调用回调函数的位置,应用程序崩溃。如您所见,在此阶段,我什至没有解开提供给回调函数的参数。
我需要做什么才能完成这项工作?
> P/invoke 不允许访问导出的数据(变量),例如函数指针。 DLL 中需要一个帮助程序,可以是包装函数指针的导出函数,也可以是返回函数指针的函数(返回类型将被视为 C# 中的委托)。
感谢您的输入
我已经解决了这个问题,通过修改我的回调的注册:
void RegisterCB()
{
var ret = TdiapiFacade.RegisterEventCallback(OnTdiCallBack, new IntPtr());
HandleError(ret);
}
对此:
private TDIAPI.TDICallBack callback;
void RegisterCB()
{
callback = new TDIAPI.TDICallBack(OnTdiCallBack);
var ret = TdiapiFacade.RegisterEventCallback(callback , new IntPtr());
HandleError(ret);
}
这解决了问题,现在我的回调被正确调用了。