2008-11-14 15 views
20

Ejemplo C API de firma:¿Cómo puedo pasar un puntero a una matriz usando p/invoke en C#?

void Func(unsigned char* bytes);

En C, cuando quiero pasar un puntero a una matriz, que puedo hacer:

unsigned char* bytes = new unsigned char[1000]; 
Func(bytes); // call 

¿Cómo traduzco la API de arriba para P/¿Invocar de manera que pueda pasar un puntero a la matriz de bytes C#?

Respuesta

31

La manera más fácil de pasar una matriz de bytes es declarar el parámetro en su instrucción de importación como una matriz de bytes.

[DllImport EntryPoint="func" CharSet=CharSet.Auto, SetLastError=true] 
public extern static void Func(byte[]); 

byte[] ar = new byte[1000]; 
Func(ar); 

También debería poder declarar manualmente el parámetro como IntPtr y Marshal.

[DllImport EntryPoint="func" CharSet=CharSet.Auto, SetLastError=true] 
public extern static void Func(IntPtr p); 

byte[] ar = new byte[1000]; 
IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(byte)) * ar.Length); 
Marshal.Copy(ar, 0, p, ar.Length); 
Func(p); 
Marshal.FreeHGlobal(p); 
+0

por qué funcionaría el primer enfoque, y el segundo no funcionaría. Esto es lo que estoy enfrentando en una aplicación de Windows Phone. – moubarak

+1

Sé que esta publicación es un poco antigua, pero 'Marshal.SizeOf (object)' no funciona con matrices. Estoy bastante seguro de que obtendrás una excepción si pasas una matriz pero no tengo VS abierto en frente de mí ahora mismo para intentarlo. Para determinar correctamente el tamaño de una matriz, para su ejemplo, el código sería 'Marshal.SizeOf (typeof (byte)) * ar.Length'. – 9ee1

+0

Sí, tienes razón 9ee1. Marshal.SizeOf se puede usar para una estructura pero no para una matriz. He actualizado el código de ejemplo en consecuencia. Gracias. – asponge

6

Puede utilizar código no seguro:

unsafe 
{ 
    fixed(byte* pByte = byteArray) 
    IntPtr intPtr = new IntPtr((void *) pByte); 
    Func(intPtr); 
} 

Si necesita usar el código de seguridad, puede utilizar algunos trucos:

IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(byteArray)); 
Marshal.Copy(byteArray, 0, intPtr, Marshal.SizeOf(byteArray)); 

Func(intPtr); 

Marshal.FreeHGlobal(intPtr); 

Sin embargo, el código de seguridad va a ser mi humilde opinión lenta .

3

Aquí está la firma apropiada para la función nativa.

[System.Runtime.InteropServices.DllImportAttribute("<Unknown>", EntryPoint="Func")] 
public static extern void Func(System.IntPtr bytes) ; 
Cuestiones relacionadas