Domanda

Sto cercando la sintassi corretta per passare un array di struct a un C ++ non gestito dll.

i miei importazioni dll sono chiamati in questo modo

    #define _DllImport [DllImport("Controller.dll", CallingConvention = CallingConvention::Cdecl)] static
_DllImport bool _Validation(/* array of struct somehow */);

Nel mio codice cliente ho

List<MyStruct^> list;
MyObject::_Validation(/* list*/);

So System :: Runtime :: :: InteropServices maresciallo ha un sacco di metodi utili per fare cose come questa, ma non sono sicuro di quale utilizzare.

È stato utile?

Soluzione

Crea una versione gestita della struct non gestito utilizzando StructLayout.Sequential (assicuratevi di mettere le cose nello stesso ordine). Si dovrebbe quindi essere in grado di passarlo come si vorrebbe passare a qualsiasi funzione di gestione (ad esempio, la convalida (MyStruct [] pStructs).

Per esempio, diciamo che la nostra funzione nativa ha questo prototipo:

extern "C" {

STRUCTINTEROPTEST_API int fnStructInteropTest(MYSTRUCT *pStructs, int nItems);

}

e il MYSTRUCT nativo è definito come segue:

struct MYSTRUCT
{
    int a;
    int b;
    char c;
};

Poi in C #, si definisce una versione gestita della struct come segue:

[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct MYSTRUCT
{
    public int a;
    public int b;
    public byte c;
}

E il prototipo gestito come segue:

    [System.Runtime.InteropServices.DllImportAttribute("StructInteropTest.dll", EntryPoint = "fnStructInteropTest")]
    public static extern int fnStructInteropTest(MYSTRUCT[] pStructs, int nItems);

È quindi possibile chiamare la funzione passandogli un array di struct MyStruct come segue:

    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();
    }

Altri suggerimenti

È possibile utilizzare Marshall.StructureToPtr per ottenere un IntPtr che potrebbe essere passato in un MyStruct * array nativo.

Tuttavia, non sono sicuro di come fare questo da un elenco direttamente. Credo che è necessario convertire questo a una matrice e utilizzare un pin_ptr (per evitare che il GC di muoversi vostra memoria) prima di passarlo al codice nativo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top