Md23 Ответов: 1

Как я Маршалл больших структур в VB.NET


У меня есть структура массивов, которые довольно велики. Я все время получаю исключение "исключение выброшено(vcruntime140d.dll нарушение доступа к месту записи" это происходит на члене описания.

Что я уже пробовал:

   <DllImport("ConvertRaw.dll", CallingConvention:=CallingConvention.Cdecl)>
   Public Function OpenRawFile(<MarshalAs(UnmanagedType.LPStr)> x As String, ByRef CurrentStamp As RawDataHeader) As Integer
   End Function


<StructLayout(LayoutKind.Sequential)>
   Public Structure RawDataHeader
      Public numChannels As Integer
      Public syncpattern As Integer
      Public runnumber As Integer
      Public muxpitch As Integer
      <MarshalAs(UnmanagedType.ByValArray, SizeConst:=4096)>
      Public channels() As Integer
      <MarshalAs(UnmanagedType.ByValArray, SizeConst:=508)>
      Public description() As Byte
      Public scanlistblocks As Integer

End Structure
      Dim stamp1 As New RawDataHeader

      Dim result As Integer
      Dim sizeOfHeader As Integer = Marshal.SizeOf(GetType(RawDataHeader))
      Dim pHeader As IntPtr = Marshal.AllocHGlobal(sizeOfHeader)
      Dim i As Integer
      Dim x As String

      Try
         result = OpenRawFile("C:\Raw_Data\H12091.raw", pHeader)
         stamp1 = DirectCast(Marshal.PtrToStructure(pHeader, GetType(RawDataHeader)), RawDataHeader)
      Finally
         Marshal.FreeCoTaskMem(pHeader)
      End Try


Это моя структура c++

typedef struct {
   int  numChannels;
   int	syncpattern;						
   int	run;							
   int	datastream;
   int  channels[4096];	
   char description[508]		
   int	scanlistblocks;						

}RawDataHeader;	

Gerry Schmitz

У вас есть какие-нибудь идеи, "сколько" может быть "слишком большим"? Или начните с "одного" int и продолжайте добавлять, пока он не сломается.

Md23

ScanList() работает, но тогда, если я добавлю в DataWidths (), это не так. Я получаю эту ошибку о том, что структура слишком велика

Gerry Schmitz

64 КБ всегда было "магическим числом", не знаю, применимо ли оно к вам, но каждый из ваших блоков "4096" занимает 16 КБ.

Md23

К сожалению, именно такого размера они все и должны быть...

1 Ответов

Рейтинг:
7

Richard Deeming

Согласно с эта тема на форумах MSDN[^], вам нужно изменить параметр, чтобы он был IntPtr, выделите память для хранения структуры, а затем используйте PtrToStructure чтобы считывать данные в вашу структуру.

<DllImport("ConvertRaw.dll", CallingConvention:=CallingConvention.Cdecl)>
Public Function OpenRawFile(<MarshalAs(UnmanagedType.LPStr)> x As String, ByVal CurrentStamp As IntPtr) As Integer
End Function

...

Dim result As Integer
Dim stamp1 As RawDataHeader
Dim sizeOfHeader As Integer = Marshal.SizeOf(GetType(RawDataHeader))
Dim pHeader As IntPtr = Marshal.AllocCoTaskMem(sizeOfHeader)
Try
    result = OpenRawFile("C:\Raw_Data\H12091.raw", pHeader)
    stamp1 = DirectCast(Marshal.PtrToStructure(pHeader, GetType(RawDataHeader)), RawDataHeader)
Finally
    Marshal.FreeCoTaskMem(pHeader)
End Try
NB: Это потребует копирования данных, возвращаемых из метода C++, поэтому производительность может быть не очень высокой.


Md23

Я сделал это, и все работало, пока я не добрался до описания в файле c++. Я получил исключение исключение выброшенное на 0x0F35337E (vcruntime140d.dll) в ConsoleApp3.exe: 0xC0000005: нарушение доступа место записи 0x00DD2D7C.

Richard Deeming

Вы уверены, что ваш VB.NET определение структуры соответствует тому, о чем идет речь? Я получал ... "никакой значимый размер или смещение не могут быть вычислены" ошибка на экране Marshal.SizeOf линия до тех пор, пока я не удалил MarshalAs атрибут из списка entries член.

В соответствии с вашей структурой C++ этот член называется streamtype, и не является массивом. Вы объявили его одиночным Integer, но добавил атрибут, чтобы маршалировать его как массив из 4096 ints.

Md23

Я исправил это здесь, но на самом деле эта часть была прокомментирована в моем коде, когда я ее запустил. Почему то это только описание

Md23

Я обновил свой код здесь. Я получаю сообщение об ошибке на полное описание

Richard Deeming

Где же возникает ошибка? Я думал, вы сказали, что это из вашего кода C++, который вы не показали.

Richard Deeming

И опять же, ваша структура C++ не соответствует вашей VB.NET структура.

Md23

Я все понял. Теперь мне нужно было передать IntPtr по значению.

Richard Deeming

Хороший улов. Я обновил свой ответ. :)

KarstenK

Это должно быть ошибкой в коде вашего приложения. Выдохни его ;-)

Md23

Это только на одном члене структуры. Все остальные работают нормально