Как преобразовать массив структуры C ++ / CLI в неуправляемый C ++ - PullRequest
1 голос
/ 09 апреля 2009

Я ищу правильный синтаксис для передачи массива структуры в неуправляемую 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 имеет много полезных методов для выполнения подобных вещей, но я не уверен, какой именно.

Ответы [ 2 ]

3 голосов
/ 09 апреля 2009

Создайте управляемую версию неуправляемой структуры с помощью 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();
    }
1 голос
/ 09 апреля 2009

Вы можете использовать Marshall.StructureToPtr , чтобы получить IntPtr, который можно передать в собственный массив MyStruct *.

Однако я не уверен, как сделать это напрямую из Списка. Я полагаю, что вам нужно преобразовать это в массив и использовать pin_ptr (чтобы GC не перемещал вашу память) перед передачей его в собственный код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...