2011-03-08 11 views
6

No soy realmente un tipo CS, así que si alguno de ustedes genios aquí puede señalarme en la dirección correcta, estaré eternamente agradecido.flotar * de C a C#

que tienen una función de línea de comandos c-código que se utiliza para escribir sus resultados en un archivo. Convertí para devolverlo de datos a través de un flotador * matriz a un programa en C++ como tales (para evitar archivo constante I/O):

float * mgrib(int argc, char **argv) 

Esto funcionó perfectamente. Ahora necesito incluir esto en un programa C#, y aquí es donde las cosas se ponen feas.

Lo primero que hice para evitar el char ** fue convertir los argumentos en una serie de bool. Eso funcionó bien si permití que todavía se volcara al archivo.

El problema está haciendo juegos malabares la matriz flotador c-estilo en C#. Dentro del código c, se asignó con malloc.

Así que aquí es todo lo que he intentado sin éxito (Sé que el tamaño de la matriz):

  1. hacer una función "libre" para exportar a llamar desde C# para liberar la memoria cuando estoy Estoy hecho con eso. Después de algunos bucles, C# se bloquea sin previo aviso.

  2. Libere el malloc de C# con Marshal.FreeCoTaskMem. Mismo resultado.

  3. Mueva el flotador * a un argumento y elimine el c-code malloc. (Void mgrib (..., flotar datos *, ...)

__A) Asignar con Marshal.AllocCoTaskMem. Libéralo con Marshal.FreeCoTaskMem.

__b) Uso Marshal.Copy a asignar. Liberarlo con Marshal.FreeCoTaskMem (¿Tal vez esto está mal?)

He incursionado en casi todo lo que pude encontrar en internet. Por favor, avíseme si se necesita más información. Espero que esto sea solo un concepto simple que me estoy perdiendo.

+5

Olvidar el prototipo C y escribir una limpia con C#. Devuelve una matriz flotante (flotante []) en su lugar. – stefan

+1

Por favor, publique su C# code –

+2

¿Está tratando de hacer esto bien o fácilmente? La manera más fácil sería dejar ambos programas casi intactos, pero tener la comunicación a través de una tubería en lugar de un archivo. Para hacerlo bien, probablemente sea mejor que escriba todo el programa en un idioma. –

Respuesta

4

Utilice esta firma para su función C (reemplace mgrib.dll con nombre de biblioteca real).

[DllImport("mgrib.dll", EntryPoint = "mgrib")] 
public static extern IntPtr mgrib(
    int argc, 
    [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] 
    StringBuilder[] argv); 

Llame a la función mgrib de la siguiente manera:

// Prepare arguments in proper manner 
int argc = 0; 
StringBuilder[] argv = new StringBuilder[ argc ]; 
IntPtr pointer = mgrib(argc, argv); 

Cuando se realiza la llamada, se puede obtener el resultado como este:

float[] result = new float[ size ]; 
Marshal.Copy(pointer, result, 0, size); 

EDITAR:

Como el mgrib es un llocating la memoria utilizando malloc, tenemos que liberar la memoria utilizando free función. Sin embargo, tendrá que envolver la llamada a la función free en otra función que será exportado de biblioteca nativa.

extern "C" __declspec(dllexport) void mgrib_free(float* pointer); 

void mgrib_free(float* pointer) 
{ 
    free(result); 
} 

Y luego importarlo en este aspecto:

[DllImport("mgrib.dll", EntryPoint = "mgrib_free", 
      CallingConvention = CallingConvention.Cdecl)] 
public static extern void mgrib_free(IntPtr pointer); 

e invocar la siguiente manera:

mgrib_free(pointer); 
+0

Descanso, muchas gracias por su respuesta detallada. Esto es exactamente lo que hice para uno de mis muchos intentos. Tu respuesta me dio la confianza para profundizar un poco más y pasar por cada iteración (ugh). Descubrí que no importa lo que el programa se bloquea sin previo aviso después de acceder a 'mgrib' 256 veces. Eso es demasiada coincidencia. Estaba usando Marshal.FreeCoTaskMem. Marshal.FreeHGlobal arroja un error de manejo. Así que creo que está bastante claro ahora que FreeCoTaskMem no lo está cortando, de alguna manera la memoria no se está liberando. ¿Alguna idea a alguien? – Anthony

+0

@Anthony: ¿Ayuda la nueva información? –

+0

Eso fue lo primero que intenté, pero antes aprendí a usar IntPtr. Lo probaré. Gracias por regresar a esto. – Anthony