2009-05-07 8 views
6

que tienen un proyecto de C# que importa una DLL de C, el DLL tiene esta función:punteros pasar de código no administrado

int primary_read_serial(int handle, int *return_code, int *serial, int length); 

Quiero conseguir el acceso al parámetro de serie. De hecho, tengo que devolver un carácter del parámetro de serie, pero no estoy muy seguro de lo que estoy haciendo y me gustaría entender lo que está pasando, y por supuesto ponerlo en funcionamiento.

Por lo tanto, estoy muy seguro de que se está accediendo al dll, otras funciones sin punteros funcionan bien. ¿Cómo manejo los punteros? ¿Debo organizarlo? Tal vez tengo que tener un lugar fijo para poner la información que?

Una explicación sería genial.

Gracias! Richard

Respuesta

8

Deberá usar un IntPtr y Marshal que IntPtr en cualquier estructura de C# en la que desee colocarlo. En su caso, deberá ordenarlo en un int [].

Esto se hace en varias etapas:

  • Asignar un mango no administrado
  • Llame a la función con la matriz unamanged
  • Convertir la matriz a matriz de bytes logrado
  • Convertir matriz de bytes a int array
  • Liberar el controlador no administrado

Ese código debe darle una idea:

// The import declaration 
[DllImport("Library.dll")] 
public static extern int primary_read_serial(int, ref int, IntPtr, int) ; 


// Allocate unmanaged buffer 
IntPtr serial_ptr = Marshal.AllocHGlobal(length * sizeof(int)); 

try 
{ 
    // Call unmanaged function 
    int return_code; 
    int result = primary_read_serial(handle, ref return_code, serial_ptr, length); 

    // Safely marshal unmanaged buffer to byte[] 
    byte[] bytes = new byte[length * sizeof(int)]; 
    Marshal.Copy(serial_ptr, bytes, 0, length); 

    // Converter to int[] 
    int[] ints = new int[length]; 
    for (int i = 0; i < length; i++) 
    { 
     ints[i] = BitConverter.ToInt32(bytes, i * sizeof(int)); 
    } 

} 
finally 
{ 
    Marshal.FreeHGlobal(serial_ptr); 
} 

no se olvide el try-finally, o correrá el riesgo de fuga de la manija no administrado.

+0

Específicamente, asigne una matriz no administrada y una int administrada [] y Marshal. Copie su IntPtr de la matriz no administrada a la administrada. –

+1

try-catch o try-finally? – MedicineMan

+0

try-finally, gracias por señalarlo. Fijo. – Coincoin

0

Al escribir su P/invocar la declaración de esa función, trate de usar ref palabra clave para los parámetros de puntero de este tipo:

[DllImport("YouDll.dll", EntryPoint = "primary_read_serial")] 
public static extern int primary_read_serial(int, ref int, ref int, int) ; 

No estoy seguro de si es necesario especificar el nombre de los parámetros en C#. Y recuerde, cuando llame a ese método, también tendrá que usar ref en los argumentos que está pasando por referencia.

+0

Si se supone que es una matriz, debe asegurarse de pasar como IntPtr y Marshal. Sin embargo, copie a una matriz administrada. –

2

Si entiendo lo que estás tratando de hacer, esto debería funcionar para ti.

unsafe 
{ 
    int length = 1024; // Length of data to read. 

    fixed (byte* data = new byte[length]) // Pins array to stack so a pointer can be retrieved. 
    { 
     int returnCode; 
     int retValue = primary_read_serial(0, &returnCode, data, length); 

     // At this point, `data` should contain all the read data. 
    } 
} 

JaredPar le da la forma sencilla de hacerlo, sin embargo, que es sólo para cambiar su declaración de la función externa de modo que C# hace el cálculo de referencias para que en el fondo.

Espero que esto le dé una idea de lo que está sucediendo en un nivel ligeramente inferior de todos modos.

Cuestiones relacionadas