3

我正在开发一个使用非托管 dll 的 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用作 size 的数组rev

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

有人有想法么?

最后一点,这是否类似于如何将 aStringBuilder用作非托管方法的参数,该方法采用char*参数来检索可变长度的字符串?

4

1 回答 1

4

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

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

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

于 2012-12-31T23:05:01.547 回答