Как маршалировать массив структуры C++/CLI в неуправляемый C++
Вопрос
Я ищу правильный синтаксис для передачи массива структур в неуправляемую dll C++.
мой импорт dll называется так
#define _DllImport [DllImport("Controller.dll", CallingConvention = CallingConvention::Cdecl)] static
_DllImport bool _Validation(/* array of struct somehow */);
В моем клиентском коде у меня есть
List<MyStruct^> list;
MyObject::_Validation(/* list*/);
Я знаю, что в System::Runtime::InteropServices::Marshal есть много полезных методов для подобных вещей, но я не уверен, какой из них использовать.
Решение
Создайте управляемую версию неуправляемой структуры с помощью StructLayout.Sequential (обязательно расположите все в том же порядке).После этого вы сможете передать его так же, как и любую управляемую функцию (например, Validation(MyStruct[] pStructs).
Например, предположим, что наша собственная функция имеет такой прототип:
extern "C" {
STRUCTINTEROPTEST_API int fnStructInteropTest(MYSTRUCT *pStructs, int nItems);
}
а собственный MYSTRUCT определяется следующим образом:
struct MYSTRUCT
{
int a;
int b;
char c;
};
Затем в C# вы определяете управляемую версию структуры следующим образом:
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct MYSTRUCT
{
public int a;
public int b;
public byte c;
}
И управляемый прототип выглядит следующим образом:
[System.Runtime.InteropServices.DllImportAttribute("StructInteropTest.dll", EntryPoint = "fnStructInteropTest")]
public static extern int fnStructInteropTest(MYSTRUCT[] pStructs, int nItems);
Затем вы можете вызвать функцию, передав ей массив структур MYSTRUCT следующим образом:
static void Main(string[] args)
{
MYSTRUCT[] structs = new MYSTRUCT[5];
for (int i = 0; i < structs.Length; i++)
{
structs[i].a = i;
structs[i].b = i + structs.Length;
structs[i].c = (byte)(60 + i);
}
NativeMethods.fnStructInteropTest(structs, structs.Length);
Console.ReadLine();
}
Другие советы
Вы можете использовать Маршалл.StructureToPtr чтобы получить IntPtr, который можно было бы передать в собственный массив MyStruct*.
Однако я не уверен, как это сделать напрямую из списка.Я считаю, что вам нужно преобразовать это в массив и использовать pin_ptr (чтобы предотвратить перемещение GC в вашей памяти) перед передачей его в собственный код.