Pergunta

Eu estou procurando a sintaxe correta para passar uma matriz estrutura para um C ++ não gerenciado dll.

meus importações dll são chamados assim

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

No meu código cliente Tenho

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

Eu sei Sistema :: Runtime :: InteropServices :: Marshal tem um monte de métodos úteis para fazer coisas como esta, mas eu não tenho certeza sobre qual usar.

Foi útil?

Solução

Crie uma versão gerenciada da estrutura não gerenciado usando StructLayout.Sequential (certifique-se de colocar as coisas na mesma ordem). Você deve então ser capaz de passá-lo como você deseja passá-lo para qualquer função gerenciada (por exemplo, Validação (MyStruct [] pStructs).

Por exemplo, digamos que a nossa função nativa tem este protótipo:

extern "C" {

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

}

eo MYSTRUCT nativa é definido da seguinte forma:

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

Então, em C #, você define uma versão gerenciada da estrutura da seguinte maneira:

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

E o protótipo conseguiu o seguinte:

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

Você pode então chamar a função de passá-lo uma matriz de estruturas MyStruct da seguinte forma:

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

Outras dicas

Você pode usar Marshall.StructureToPtr para obter um IntPtr que poderia ser passado em um MyStruct nativo * array.

No entanto, eu não tenho certeza de como fazer isso a partir de uma lista diretamente. Eu acredito que você precisa para converter isso em um array e usar um pin_ptr (para evitar que o GC de se mover sua memória) antes de passá-lo para o código nativo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top