AccessViolationException 将数组传递给本机函数



我在旧版 VB6 代码中声明了此函数,我正在尝试将调用代码移动到 .NET 中。所以我需要将以下内容翻译成 C#。

Private Declare Sub FooFunc "foo.dll" _
(ByRef A As Long, _
ByVal B As String, _
ByRef C As Long, _
ByRef D As Integer,)

我没有关于 foo.dll 的文档。我所拥有的只是 VB6 中的当前调用代码,该代码是由早已消失的人编写的:

Dim a as Long
Dim b as String
Dim c(2001) as Integer
Dim d(2001) as Long
c(0) = itemCount
d(0) = itemCount
For i = 1 To itemCount
c(i) = ...
Next
Call FooFunc(a, b, c(0), d(0))
DoSomethingWithD(d)
...
  • 参数a可能会被 dll 修改,所以我想我需要out关键字
  • 参数b未修改
  • 参数c是输入值数组,未修改
  • 参数d是一个将获取输出值的预分配数组。令人困惑的部分是传入第一项,但我知道从 VB6 调用时数组被填充了值,如下所示

我想我在 C# 中需要类似以下内容的东西,但是当我调用该函数时,我得到了一个AccessViolationException

[DllImport("foo.dll")]
public static extern void FooFunc(out int a, string b, int[] c, short[] d);

我已经尝试了其他一些变体,并查看了有关SO的更多解释,但是没有什么与VB6代码传递数组的奇怪方式完全匹配,我不知道这是否会使事情绊倒。也许这是一种让它像 C 样式数组一样工作的方法?我想,填补第一个只是制作foo的人使用的奇怪惯例.dll我想。

编辑 1:

似乎FooFunc最初是为了接收C数组,但是C#甚至VB6都会传入SafeArrays,这些SafeArrays在实际数组数据之前具有用于排名和边界的字节。如果这是真的,那么通过引用传递第一个元素是有意义的,因为这样FooFunc就可以读取其余的数据。

但是,由于非托管代码不能直接修改托管数组,因此我需要某种方法来分配可由非托管代码修改的非托管数组,并将指向第一个元素的指针作为参数传递。有没有办法做到这一点?

我认为你误读了代码。对 FooFunc 的调用不会传递数组,它会索引成几个数组,并传递对索引值的引用,以便可以更改它们。

[DllImport("foo.dll")]
public static extern void FooFunc(ref int a, string b, ref int c, ref short d);

相关内容

  • 没有找到相关文章

最新更新