I have this function declared in legacy VB6 code and I'm trying to move the calling code into .NET. So I need to translate the following into C#.
Private Declare Sub FooFunc "foo.dll" _
(ByRef A As Long, _
ByVal B As String, _
ByRef C As Long, _
ByRef D As Integer,)
I don't have documentation on foo.dll. All I have is the current calling code in VB6 that was written by someone long gone:
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)
...
- parameter
a
may be modified by the dll so I think I need theout
keyword - parameter
b
is not modified - parameter
c
is an array of input values and not modified - parameter
d
is a preallocated array that will get output values. The confusing part is that the first item is passed in, but I know the array is filled up with values when called from VB6 like this
I'm thinking I need something like the following in C# but I get a AccessViolationException
when I call the function.
[DllImport("foo.dll")]
public static extern void FooFunc(out int a, string b, int[] c, short[] d);
I've tried a few other variations and looking at more explanations on SO but nothing quite matches the odd way the VB6 code passes the arrays and I don't know if that is tripping things up or not. Maybe that is a way to get it to work like a C-style array? And filling the first would just be an odd convention used by whoever made foo.dll I imagine.
Edit 1:
It seems like FooFunc was meant to take in C arrays originally, but C# and even VB6 would pass in SafeArrays which have bytes for rank and bounds before the actual array data. If that's true, then passing by reference the first element makes sense because then FooFunc can read the rest of the data.
However, because unmanaged code can't modify managed arrays directly, I need some way of allocating an unmanaged array that can be modified by unmanaged code and passing a pointer to the first element as a parameter. Is there a way to do that?