将委托传递给一个非托管方法,该方法需要一个带有int数组指针的委托方法

时间:2012-12-31 22:47:34

标签: c# delegates callback marshalling dllimport

我正在使用一个C#应用程序,它使用一个非托管的dll作为一个方法,它接受一个函数指针作为它的一个参数。由于我无法访问非托管dll的实际C ++源代码,因此我只能依赖于使用相同dll的C ++示例中的代码片段。我遇到的问题是我所做的传递给非托管方法的代理无效。

下面是我尝试使用的方法的DllImport,它接受我创建的委托:

[DllImport("pos_tk.dll")]
static internal extern ErrorCode AddSIGHandle([MarshalAs(UnmanagedType.FunctionPtr)] SIG_Callback func);

这是我目前的代表签名:

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void SIG_Callback ([MarshalAs(UnmanagedType.LPArray)] ref int[] buf, int rev, object sender);

这是C ++示例代码段使用的功能,我将代理基于:

void __stdcall point_handle (int *buf, int rev, LPVOID pParam)

现在,在您告诉我将委托的ref int[] buf参数更改为ref int buf之前,程序将在尝试回调后抛出InvalidVariant错误。代码段使用int *buf作为大小为rev的数组。

使用上面的代码,应用程序在尝试回调时抛出AccessViolationException。我的预感是我应该为ref int[] buf参数使用不同的类型,但我已经尝试了我能想到的一切。我一整天都在搜索Google,SO和MSDN,但没有运气。

有人有什么想法吗?

作为最后一点,这是否与您使用StringBuilder作为非托管方法的参数的方式相似,该方法采用char*参数来检索可变长度字符串?

1 个答案:

答案 0 :(得分:4)

来回传递数组总是PITA ...尝试这个签名,似乎适用:

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void point_handle(
    [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)]
    int[] buf,
    int rev,
    IntPtr pParam);

编辑:只是详细说明,当你有一个“C风格”数组(即T *)以及参数中指定的长度时,SizeParamIndex就是你的救赎;基本上它说“嘿,有一个未知长度的数组进来,但这个索引的参数会告诉你它们中有多少。使用它和类型来帮助编组”