How to marshal double array for PInvoke?

J

jim4u

I am porting a vb library to vb.net. The vb library has an external
call to an unmanaged dll.

Existing code:

//External function declaration
Private Declare Function Uncompress& Lib "COMPR.DLL" (ByVal SrcSt$,
ByVal SrcLen&, Dest As Any, ByVal DestLen&)

//Invocation of external function
lReturn = Uncompress(sCompressedResult, Len(sCompressedResult),
aResults(ARRAY_START), ByVal lNewLength)

[where aResults is a double array. The COMPR.Uncompress function
basically uncompress a string 'sCompressedResult' and fills the array
aResults. The array is initialized before calling the external
function]

My understanding is that( Please correct me if I am wrong):
a. The third parameter in declaration 'Dest as Any' means a parameter
of variant type.
b. At invocation, the first element of the double array is passed.
i.e., a pointer to the first element in the double array is passed to
the external function.
c. The Uncompress function expands the compressed data, fills/replaces
the double array with values.
d. The changed values are available to the caller after the Uncompress
function has returned.

Now, I have to call the COMPR.Uncompress method from Vb.Net.
From browsing the net, I got a lot of information regarding this(
Please correct me if I am wrong):
a. We have to mark the parameter as InAttribute(), Out().
b. We should pin the object so that GC does not change address.
c. We should pass a pointer TO THE FIRST OBJECT OF THE ARRAY to the
native function.
d. Array of type double is non-blittable and so we have to do the
marshaling.

This is the code I wrote:

//External method declaration
<DllImport("COMPPL32.dll", EntryPoint:="EtUnCompress",
SetLastError:=True, CharSet:=CharSet.Auto, ExactSpelling:=True,
CallingConvention:=CallingConvention.StdCall)> _

Public Shared Function UnCompress(ByVal compressedResult As String,
ByVal length As Long, <InAttribute(), Out(),
MarshalAs(UnmanagedType.Struct)> ByRef destinationArrayElement As
Object, ByVal newLength As Long) As Long

End Function

//Invocation
'Pin the object
Dim resultsHandle As GCHandle
resultsHandle = GCHandle.Alloc(aResults(ARRAY_START),
GCHandleType.Pinned)
Dim resultsPointer As IntPtr = resultsHandle.AddrOfPinnedObject()

'Invoke
returnValue = UnCompress(sCompressedResult, Len(sCompressedResult),
resultsPointer, newLength)


My problem is that I get the return value correctly, but the array does
not get changed....I get the same data that is passed to the external
function. I think the changes made by the native function is not
persisting.

There is no problem with any of the parameters - I have checked the
same parameters using the existing vb dll and it works. I would like to
know why I dont get the modified array even though I am passing a
pointer to the first element of the array and am pinning the element.

Is this the correct way to marshal (UnmanagedType.struct) and is this
the correct way to pin object?

Any help would be appreciated,

Jim
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top