Tengo un programa C# que necesita pasar un búfer char a una función no administrada. He encontrado dos maneras que parecen funcionar de manera confiable, pero no estoy seguro de cuál elegir.Llamar a la función no administrada desde C#: ¿debería pasar StringBuilder o utilizar un código inseguro?
Aquí está la firma de la función no administrada.
extern "C" __declspec(dllexport) int getNextResponse(char *buffer);
La primera opción es definir el búfer como un StringBuilder, de la siguiente manera.
//at class level...
[DllImport("mydll.dll")]
static extern int getNextResponse(StringBuilder buffer);
//in main method body...
StringBuilder sb = new StringBuilder(" ", 65536);
int rc = getNextResponse(sb);
Esto es simple, y funciona, y creo que básicamente entiendo por qué funciona debido a que el StringBuilder tiene un buffer detrás de las escenas, por lo que (supongo) la capa de interoperabilidad se acaba el guiado de la StringBuilder a un char *.
La otra opción es usar código inseguro.
//at class level...
[DllImport("mydll.dll")]
static extern int getNextResponse(byte* buffer);
//separate method...
private static unsafe int runGetNextResponse(byte[] buffer)
{
fixed (byte* p = buffer)
{
int rc = getNextResponse(p);
return rc;
}
}
//in main method body...
byte[] b = new byte[65536];
int rc = runGetNextResponse(b);
El segundo enfoque es más código, pero también es más explícito sobre lo que está sucediendo.
¿Estos dos enfoques son básicamente lo mismo? ¿Hay alguna razón para elegir uno sobre el otro?
¿Qué ocurre si el recolector de basura reasigna el StringBuilder pasado sin una instrucción fija durante la ejecución getNextResponse? ¿Se deben fijar todos los parámetros de puntero utilizados en las funciones importadas? ¿O me estoy perdiendo algo? – Luca