I have to port some VBA Code to VB DotNet
The following code block defines several types in VBA.
Public Type ProbParamKind
Na As Long
Nc As Long
Nstep As Long
MaxCycles As Long
AxialPts As Long
End Type
Public Type RunOptKind
KeyProdID As Long
KeyImpID As Long
KeyProdSpec As Double
KeyImpSpec As Double
RecoveryTarget As Double
PurgeFactor As Double
CoCurCutOff As Double
BedSizeFactor As Double
BedVol As Double
BedLen As Double
TempWall As Double
NonAdiabaticFrac As Double
ISOmodel(1 To 8) As Byte 'Array of bytes representing IsoModel As String *
8
End Type
Public Type GasKind
GasID(1 To 8) As Byte 'Array of bytes representing GasID As String * 8
Mw As Double
CpPar(1 To 4) As Double
MuPar(1 To 2) As Double
LmdaPar(1 To 3) As Double
End Type
It makes a call to a fortran dll using arrays of these types and a long to
return an error code.
Public Declare Sub PSAEngine Lib "PSAxEngine.dll" ( _
ProbParam As ProbParamKind, RunOpt As RunOptKind, _
Gases As GasKind, ByRef errFlag As Long)
It works fine.
I have defined these structures in VB DotNet that match the types in VBA
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> Public
Structure ProbParamKind
Dim Na As Int32
Dim Nc As Int32
Dim Nstep As Int32
Dim MaxCycles As Int32
Dim AxialPts As Int32
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> Public
Structure RunOptKind
Dim KeyProdID As Int32
Dim KeyImpID As Int32
Dim KeyProdSpec As Double
Dim KeyImpSpec As Double
Dim RecoveryTarget As Double
Dim PurgeFactor As Double
Dim CoCurCutOff As Double
Dim BedSizeFactor As Double
Dim BedVol As Double
Dim BedLen As Double
Dim TempWall As Double
Dim NonAdiabaticFrac As Double
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)> Dim ISOmodel()
As Byte
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> Public
Structure GasKind
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)> Dim GasID() As
Byte
Dim Mw As Double
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)> Dim CpPar() As
Double
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=2)> Dim MuPar() As
Double
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=3)> Dim LmdaPar() As
Double
End Structure
Here is the dotnet call definition
Public Declare Sub PSAEngine Lib "PSAxEngine.dll" ( _
ByRef ProbParam As ProbParamKind, ByRef RunOpt As RunOptKind, _
ByRef Gases As GasKind, ByRef errFlag As Int32)
Here is the call in code
Call PSAEngine(ProbParam, RunOpt, Gases(0), errFlag)
When I try to use the same fortran dll with matching arrays, I get junk
after the first element of the array of GasKind.
Gases is loaded correctly with 10 elements in the code before the call.
The first element contains the data I set to be passed in. Starting with the
second element, elements contain jibberish (and it differs from one
execution to the next I might add so I don't think it is just a shift of
position).
Can anyone give me a hint as to what I have missed?
I think the second element of the GasKind array is being read from the wrong
memory address but I can't tell why.
DLI - 14 Feb 2008 17:56 GMT
In regards to this posting, I did google this thread:
http://www.dotnet247.com/247reference/msgs/43/215864.aspx
The following quote is from that very long thread
The marshaller cannot handle "embedded arrays of structures" and "variable
length structs". It can only handle embedded arrays of blittable types(int,
char etc) - as I illustrated in a previous post.
If you really want to use C# to pass such managed structures to unmanaged
code, you'll need to help the marshaller by passing as argument to the API,
a pointer to a buffer, that contains a copy of the managed struct fields you
marshalled using the Marshal.WriteXX methods. On return you need to copy the
buffer contents back to the managed structure using the Marshal.ReadXX
Does anyone know if this has been changed in Visual Studio 2005?
Would we still have to use Marshal.WriteXX methods to pass an array of
structures to un-managed dll?