2010-03-26 9 views
11

que tienen una función C con la siguiente firma:¿Cómo clasifico un puntero a una matriz de punteros a estructuras?

int my_function(int n, struct player **players) 

players es un puntero a un array de punteros a objetos struct player. n es la cantidad de punteros en la matriz. La función no modifica la matriz ni el contenido de las estructuras, y no retiene ningún puntero después de regresar.

He intentado lo siguiente:

[DllImport("mylibary.dll")] 
static extern int my_function(int n, 
    [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] 
    player_in []players); 

Sin embargo, que reúne los datos como un puntero a una matriz de estructuras, no un puntero a un array de punteros a estructuras.

Respuesta

11

Creo que tendrá que hacer algunas de las referencias manualmente. La declaración de la función debe tener este aspecto:

[DllImport("mylibary.dll")] 
private static extern int my_function(int n, IntPtr players); 

Vamos a tener que destinar parte de la memoria nativa y reunir las estructuras a que antes de pasarlo a la función nativa:

private static void CallFunction(Player[] players) 
{ 
    var allocatedMemory = new List<IntPtr>(); 

    int intPtrSize = Marshal.SizeOf(typeof(IntPtr)); 
    IntPtr nativeArray = Marshal.AllocHGlobal(intPtrSize * players.Length); 
    for (int i = 0; i < players.Length; i++) 
    { 
     IntPtr nativePlayer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Player))); 
     allocatedMemory.Add(nativePlayer); 
     Marshal.StructureToPtr(players[i], nativePlayer, false); 

     Marshal.WriteIntPtr(nativeArray, i * intPtrSize, nativePlayer); 
    } 

    my_function(players.Length, nativeArray); 

    Marshal.FreeHGlobal(nativeArray); 

    foreach (IntPtr ptr in allocatedMemory) 
    { 
     Marshal.FreeHGlobal(ptr); 
    } 
} 

Si su función nativa va a conservar y reutilizar estas ubicaciones de memoria, esto no funcionará. Si este es el caso, espere a que se libere la memoria hasta que crea que ya no se está utilizando o, en el método nativo, copie los datos pasados ​​y deje que el lado administrado limpie su memoria inmediatamente después de la llamada.

Cuestiones relacionadas