C#pInvoke到C函数

C#pInvoke到C函数,c#,pinvoke,C#,Pinvoke,我会很感激你能帮我解决一个困扰了我几天的问题 我有一个声明为:的本机C++函数类型 typedef STATUS (T_TED_AcppBoxDYN_RegisterEventCallback) ( PEventCallback function, // pointer to the customer callback PVOID param // custom data (returned in callback) )

我会很感激你能帮我解决一个困扰了我几天的问题

我有一个声明为:

的本机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#调用pointed to函数。为此,我定义了一个C#包装器:

我是这样使用它的:

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);
}

这解决了问题,现在我的回调被正确调用。

与您的断言相反,C代码没有声明任何函数。如果它是有效的C(我和CDECL对此表示怀疑),那么它将
T_TED\u AcppBoxDYN\u RegisterEventCallback
声明为函数类型的别名。也许它是有效的C++,但是即使在这种情况下,它必须声明类型别名,而不是该类型的实际函数或函数指针。C++如何定义<代码>状态>代码>?不能直接从C语言调用非托管C++实例函数。因为您没有
这个
指针。此外,您的
TDICallback
代理必须是Cdecl。您需要
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
属性。请参阅typedef int STATUS;//!<错误代码type@Jim:他试图调用的函数似乎不是成员函数。
private TDIAPI.TDICallBack callback;
void RegisterCB()
{
    callback = new TDIAPI.TDICallBack(OnTdiCallBack);
    var ret = TdiapiFacade.RegisterEventCallback(callback , new IntPtr());
    HandleError(ret);
}