我要创建结构类型的在VB.net阵列。 但我得到的错误在编组此错误。 我要通过这个阵列结构类型的中到DLL函数。
代码:结构的声明:
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
Public Structure dx_entry
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=10)> _
Public dx As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=3)> _
Public type As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=1)> _
Public narray As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=1)> _
Public ctier As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=1)> _
Public poa As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=1)> _
Public poa_rsvd As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=81)> _
Public filler As String
End Structure
initiallization和编组的代码:
Dim stpDx(2) As dx_entry
stpDx(1).dx = "5939" & Space(6)
stpDx(1).type = "BK" & Space(1)
stpDx(1).narray = Space(1)
stpDx(1).ctier = Space(1)
stpDx(1).poa = "Y"
stpDx(1).poa_rsvd = Space(1)
stpDx(1).filler = Space(81)
stpDx(2).dx = "1231" & Space(6)
stpDx(2).type = "BF" & Space(1)
stpDx(2).narray = Space(1)
stpDx(2).ctier = Space(1)
stpDx(2).poa = "Y"
stpDx(2).poa_rsvd = Space(1)
stpDx(2).filler = Space(81)
Dim pDxBuf As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(stpDx))
Marshal.StructureToPtr(stpDx, pDxBuf, False)
ezg_Block.pDx = pDxBuf
我收到以下错误:
An unhandled exception of type 'System.ArgumentException' occurred in Audit_Demo_2307.exe
附加信息:键入dx_entry []不能被编组为不接受管理结构; 没有有意义的大小或偏移量可以被计算。
我看着这个一点点,和第一个问题似乎是你传递一个数组到Marshal.SizeOf
方法(这是此调用抛出异常)。 因为你的结构的所有成员有一个固定的大小,你就知道该类型的所有实例都具有相同的大小。 所以,你可以而要求Marshal.SizeOf
返回的大小对于一个这样的例子:
Dim structSize As Integer = Marshal.SizeOf(GetType(dx_entry))
接下来的事情是, Marshal.StructureToPtr
从结构,而不是结构的数组的数据复制。 所以,你需要复制你的结构数组所分配内存的其他方式。 有没有方法将在一个呼叫为你做这个,但你可以做的是你的阵列中的每个结构的实例复制到一个字节数组(使用Marshal.Copy
方法),然后复制该字节数组存储器由指针指向。
这是最容易做的两步火箭。 首先,让我们作出这样的结构数组转换为字节数组的方法:
Private Shared Function GetByteArray(ByVal array As dx_entry()) As Byte()
Dim structSize As Integer = Marshal.SizeOf(GetType(dx_entry))
Dim size As Integer = structSize * array.Length
Dim dataBuffer As Byte() = New Byte(size - 1) {}
For i As Integer = 0 To array.Length - 1
Dim pTemp As IntPtr = Marshal.AllocHGlobal(structSize)
Marshal.StructureToPtr(array(i), pTemp, True)
Marshal.Copy(pTemp, dataBuffer, 0 + (i * structSize), structSize)
Marshal.FreeHGlobal(pTemp)
Next
Return dataBuffer
End Function
其次,使用GetByteArray
方法和返回的字节数组复制到存储指向指针:
Dim data As Byte() = GetByteArray(stpDx)
Dim pDxBuf As IntPtr = Marshal.AllocHGlobal(data.Length)
Marshal.Copy(data, 0, pDxBuf, data.Length)
ezg_Block.pDx = pDxBuf
我希望做你在找什么?
作为一个侧面说明; 因为你在结构指定每个字段的大小固定,你不需要垫在你的代码空间的价值; 这是由框架编组数据时的照顾。
更新
要读取数据回来,你基本上需要做同样的事情,但反向:
Private Shared Function GetStructArray(ByVal dataBuffer() As Byte) As dx_entry()
Dim structSize As Integer = Marshal.SizeOf(GetType(dx_entry))
If dataBuffer.Length Mod structSize <> 0 Then
Throw New ArgumentException("Argument is of wrong length", "dataBuffer")
End If
Dim elementCount As Integer = Convert.ToInt32(dataBuffer.Length / structSize)
Dim size As Integer = structSize * elementCount
Dim result() As dx_entry = New dx_entry(elementCount - 1) {}
For i As Integer = 0 To elementCount - 1
Dim pTemp As IntPtr = Marshal.AllocHGlobal(structSize)
Marshal.Copy(dataBuffer, 0 + (i * structSize), pTemp, structSize)
result(i) = DirectCast(Marshal.PtrToStructure(pTemp, GetType(dx_entry)), dx_entry)
Marshal.FreeHGlobal(pTemp)
Next
Return result
End Function
叫这样的:
Dim structSize As Integer = Marshal.SizeOf(GetType(dx_entry))
Dim newdata() As Byte = New Byte(structSize * numberOfElements -1) {}
Marshal.Copy(ezg_Block.pDx, newdata, 0, newdata.Length)
Dim newstruct() As dx_entry = GetStructArray(data)
注意 :要获得这一切都正常工作,您将需要调整结构了一下:看来你需要通过1.增加SizeConst这是因为字符串是空值终止的,所以我们需要有对的位置空字节,以及:
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _
Public Structure dx_entry
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=11)> _
Public dx As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=4)> _
Public type As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=2)> _
Public narray As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=2)> _
Public ctier As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=2)> _
Public poa As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=2)> _
Public poa_rsvd As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=82)> _
Public filler As String
End Structure