我正在尝试在我的VB.NET应用程序中使用C编码的其他人的DLL。 我的VB.NET应用程序发送一些指向DLL和DLL的回调指针,然后回调我的VB.NET应用程序中的函数。
DLL在VB.NET中调用一个函数并传递一个C结构的指针。 我的VB.NET应用程序必须修改结构值,因此DLL可以使用新的结构值。我不能修改DLL的代码,因为它是别人的DLL。
typedef struct {
uint8_t index;
uint8_t value;
uint8_t leds[4];
struct {
int8_t x;
int8_t y;
int8_t z;
} input[10];
} REPORT;
我的VB.NET结构定义是
<StructLayout(LayoutKind.Sequential)> _
Public Structure INPUTS
Public x As SByte
Public y As SByte
Public z As SByte
End Structure
<StructLayout(LayoutKind.Sequential)> _
Public Structure REPORT
Public index As Byte
Public value As Byte
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=4)>
Public leds() As Byte
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=10)>
Public input() As INPUTS
Sub New(numleds As Integer, numinputs As Integer)
ReDim Me.leds(numleds)
ReDim Me.input(numinputs)
End Sub
End Structure
我的VB.NET委托被声明为
Public Delegate Function Del_Read(ByVal lpReport As IntPtr) As Byte
vb.net将vb.net委托发送给C DLL
Public Ext_Read As Del_Read = New Del_Read(AddressOf Read)
SendToDll(Marshal.GetFunctionPointerForDelegate(Ext_Read))
我的VB.NET函数声明为
Public Function Read(ByVal lpReport As IntPtr) As Byte
Dim report As New REPORT(3, 9)
report.index = 0
report.value = 5
report.input(0).x = 90
report.input(0).y = 0
report.input(0).z = 0
report.input(1).x = 180
report.input(1).y = 0
report.input(1).z = 0
Dim size As Integer = Marshal.SizeOf(report)
Dim ptrMem As IntPtr = Marshal.AllocCoTaskMem(size)
Marshal.StructureToPtr(report, ptrMem, False)
Dim bytes As Byte() = New Byte(size - 1) {}
Marshal.Copy(ptrMem, bytes, 0, bytes.Length)
Marshal.FreeCoTaskMem(ptrMem)
Marshal.Copy(bytes, 0, lpReport, size)
Return 1
End Function
当函数结束时,我得到以下错误。
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
我尝试了不同的代码,例如Marshal.AllocHGlobal
或将函数声明为
Public Function Read(ByRef localReport As REPORT) As Byte
即使代码编译得很好,错误也是因为Marshal.StructureToPtr以某种方式,因为如果我将代码更改为如下所示,我没有错误,DLL获得新值。唯一的问题是我必须手动计算report.input(0)
,report.input(1)
等的偏移量。
Public Function Read(ByVal lpReport As IntPtr) As Byte
Dim report As New REPORT(3, 9)
report.index = 0
report.value = 5
Dim size As Integer = Marshal.SizeOf(report)
Dim bytes As Byte() = New Byte(size - 1) {}
bytes(0) = report.index
bytes(1) = report.value
Marshal.Copy(bytes, 0, lpReport, size)
Return 1
End Function
为什么代码失败的任何想法?或者更简单的方法来修改从DLL发送的结构?