我在旧版 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);