Изменение структуры C в VB.NET

Я пытаюсь использовать другую DLL, закодированную в C в приложении VB.NET. Приложение 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?

Ответы