Reputation: 418
I am converting an application originally written in vb6 to vb.net. One of the things this application does is that it sends a “Type” object to a dll. I tried converting the type to a structure and p/invoking the dll but it does not seem to work. I’ve been stuck for a week any help would be really appreciated
here is the vb6 code for the type
'Define WICS Communications Control Block (CCB).
Type WicsCCBType ' Create user-defined type.
CCBNum As String * 1
CCBVer As String * 1
Resp1 As String * 4
Resp2 As String * 4
PLUA As String * 8
LLUA As String * 8
Mode As String * 8
ReqMax As String * 5
ResMax As String * 5
End Type
and here is how the dll is called
Private Declare Sub WICSRASP Lib "wicsrasp.dll" (MyWicsCCB As WicsCCBType)
WICSRASP MyWicsCCB
this is what i tried with vb.net but it is not working
'Define WICS Communications Control Block (CCB).
<System.Runtime.InteropServices.StructLayoutAttribute( _
System.Runtime.InteropServices.LayoutKind.Sequential, _
CharSet:=System.Runtime.InteropServices.CharSet.[Unicode])> _
Structure WicsCCBType ' Create user-defined type.
<MarshalAs(UnmanagedType.ByValTStr, sizeconst:=1)> Dim CCBNum As String
<MarshalAs(UnmanagedType.ByValTStr, sizeconst:=1)> Dim CCBVer As String
<MarshalAs(UnmanagedType.ByValTStr, sizeconst:=4)> Dim Resp1 As String
<MarshalAs(UnmanagedType.ByValTStr, sizeconst:=4)> Dim Resp2 As String
<MarshalAs(UnmanagedType.ByValTStr, sizeconst:=8)> Dim PLUA As String
<MarshalAs(UnmanagedType.ByValTStr, sizeconst:=8)> Dim LLUA As String
<MarshalAs(UnmanagedType.ByValTStr, sizeconst:=8)> Dim Mode As String
<MarshalAs(UnmanagedType.ByValTStr, sizeconst:=5)> Dim ReqMax As String
<MarshalAs(UnmanagedType.ByValTStr, sizeconst:=5)> Dim ResMax As String
End Structure
and here is where i tried to call it
<System.Runtime.InteropServices.DllImportAttribute("C:\windows\system32\wicsrasp.dll")> _
Public Shared Sub WICSRASP(
ByRef CCB As WicsCCBType,
ByRef Request As DAWicsRequestType,
ByRef Response As DAWicsResponseType)
End Sub
Dim CCB As New modWICSDiary.WicsCCBType()
CCB.CCBNum = "B"
CCB.CCBVer = "2"
CCB.LLUA = " "
CCB.Mode = "CICSMO2 "
CCB.ReqMax = "2100 "
CCB.ResMax = "2100 "
CCB.Resp1 = "0 "
CCB.Resp2 = "0 "
CCB.PLUA = "WICSPLU "
NativeMethods.WICSRASP(CCB)
As to the values, the same values work for the vb6 type
again thank you in advance
Upvotes: 4
Views: 1729
Reputation: 10855
I don't know if this has been solved by the OP yet, but here's my take on it.
Fixed-length strings inside UDTs in VB6 are not marshalled as pointers but are inlined into the structure. Additionally, VB6 converts Unicode to Ansi before marshalling. And VB6 uses 4 byte alignment.
The type will look this this in memory with the padding, with each successive field being named A through I in the illustration, and _ being a pad byte due to alignment.
CCBNum As String * 1
|
|+-CCBVer As String * 1
||
|| Resp1 As String * 4
|| |
|| | Resp2 As String * 4
|| | |
|| | | PLUA As String * 8
|| | | |
|| | | | LLUA As String * 8
|| | | | |
|| | | | | Mode As String * 8
|| | | | | |
|| | | | | | ReqMax As String * 5
|| | | | | | |
|| | | | | | | ResMax As String * 5
|| | | | | | | |
|| | | | | | | |
VV V V V V V V V
AB__CCCCDDDDEEEEEEEEFFFFFFFFGGGGGGGGHHHHH___IIIII___
Therefore the CharSet should be Ansi, the StructAlignment should be 4. The use of ByValTString is fine, as is the use of SizeConst.
Upvotes: 1
Reputation: 30398
The VB6 will "marshal" all those string elements as ANSI strings. Change the Vb.Net marshalling code accordingly.
UnmanagedType.LPStr
in those MarshalAs
attributes? Pack=4
in the StructLayoutAttribute
? Useful link which explains the assumptions made by the VB6 Declare
Upvotes: 1