Я не уверен, что вам нужен Pack = 8
. Упаковка по умолчанию более или менее совместима между C# и C ++.
Поле szAcc
, вероятно, использует Unicode. Для переключения укажите CharSet=CharSet.Ansi
в своем [StructLayout]
Наконец, если ваш C API имеет двойной указатель на их массив, вы должны выделить эту память особым образом, либо CoTaskMemAllo c или LocalAllo c, забыл какой. Вместо этого проще и эффективнее реализовать 2 функции. Один для получения необходимого размера массива. Еще один, чтобы записать их в буфер, выделенный вызывающей стороной, одиночный указатель в C ++, а не двойной указатель, и UnmanagedType.LPArray
в C#.
Обновление
распределение не должно быть необходимым, поскольку в документации указано, что вызов возвращает указатель на его внутреннюю структуру данных
Среда выполнения не знает, что было написано в этой документации, все равно пытается освободить, и вылетает. Вы можете использовать out IntPtr
в C# API и маршалировать вручную.
Если у вас современный. NET, используйте unsafe, приведите IntPtr к PlcSymbolDescStruct*
необработанному указателю и создайте ReadOnlySpan<PlcSymbolDescStruct>
из этот необработанный указатель.
, если вы застряли на старом рабочем столе. NET, вызовите Marshal.PtrToStructure<PlcSymbolDescStruct>
в al oop, увеличивая указатель на Marshal.SizeOf<PlcSymbolDescStruct>()
байтов между l oop итерациями. В этом случае нет необходимости использовать небезопасный код.