AccessViolationException将数组传递给本机函数

问题描述 投票:0回答:1

我在传统的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,它在实际数组数据之前有排序和分区的字节。如果这是真的,那么通过引用传递第一个元素是有意义的,因为然后FooFunc可以读取其余的数据。

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

c# vb6 vb6-migration
1个回答
1
投票

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

[DllImport("foo.dll")]
public static extern void FooFunc(ref int a, string b, ref int c, ref short d);
© www.soinside.com 2019 - 2024. All rights reserved.