P / Invoke导致具有struct和callback参数的方法崩溃

时间:2012-03-02 16:16:20

标签: c# interop pinvoke

我有一个DLL,我需要P / Invoke以下C方法:

int DAOpen(HANDLE *hOpen, UNIT *flags, void *callback, void *userData)

使用P / Invoke助手,我想出了以下签名:

[DllImportAttribute("<libName>", EntryPoint="DAOpen")]  
    static extern  int DAOpen(  
    out IntPtr hOpen,  
    ref uint flags,  
    IntPtr callback,  
    IntPtr userData);

回调参数必须与以下C签名对应:

void CallBack(  
    int event,  
    int socket,  
    struct _iComStructure *plcom,  
    void *eventData,  
    void *myData)

转换为

delegate void CallBack(  
    int @event,  
    int socket,  
    IntPtr plcom,  
    IntPtr eventData,  
    IntPtr myData);

现在,我正在通过以下方式进行呼叫:

void MyCallBack(int @event, int socket, IntPtr plcom, IntPtr eventData, IntPtr myData)  
{  
    // does nothing for now  
}

IntPtr hOpen;  
uint flags = 0;  
CallBack callBack = MyCallBack;  
StringBuilder userData = new StringBuilder(userData.ToString());


int rc = DAOpen(
out hOpen,    
ref flags,  
Marshal.GetFunctionPointerForDelegate(callBack),  Marshal.StringToHGlobalAnsi(userData.ToString()));

我对这段代码遇到的问题是,当我执行DAOpen调用时,它会崩溃或者我得到FatalExecutionEngineError。我知道这肯定是一个编组错误,但我无法弄清楚......

感谢您的帮助!

更新

正如所建议的那样,我试图通过以下方式确定回调:

GCHandle callbackHandle = GCHandle.Alloc(callBack, GCHandleType.Pinned);

我收到ArgumentException这条消息:

Object contains non-primitive or non-blittable data

如果我没有指定GCHandleType(即我得到一个句柄)似乎工作正常,但当然原来的问题仍然存在。

我有什么理由不能把代表钉住吗?

感谢您的投入!

1 个答案:

答案 0 :(得分:2)

您是否已采取任何措施确保代表不被垃圾收集?

您可以在通话期间触发第0代收藏。 尝试在调用函数中创建局部变量, 或者手动将代表固定在GC句柄中。

<强>更新

另外,请查看调用约定 本机API中的回调。它是stdcall吗? 如果没有,则不能使用GetFunctionPointerForDelegate 返回指向期望stdcall参数的本机函数的指针。

在这种情况下,使用委托类型并在委托定义上放置一个“UnmanagedFunctionPointerAttribute”,而不是我们的intptr,它指定了本机调用约定。