Ho un programma C# che deve passare un buffer di caratteri a una funzione non gestita. Ho trovato due modi che sembrano funzionare in modo affidabile, ma non sono sicuro di quale scegliere.Chiamare la funzione non gestita da C#: devo passare a StringBuilder o usare un codice non sicuro?
Ecco la firma della funzione non gestita.
extern "C" __declspec(dllexport) int getNextResponse(char *buffer);
La prima opzione è definire il buffer come StringBuilder, come indicato di seguito.
//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);
Questo è semplice, e funziona, e penso che io in fondo capisco perché funziona perché lo StringBuilder ha un buffer di dietro le quinte, in modo (presumo) lo strato di interoperabilità è solo schierando lo StringBuilder ad un char *.
L'altra opzione utilizza codice non sicuro.
//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);
Il secondo approccio è più codice, ma è anche più esplicito su cosa sta succedendo.
Questi due approcci sono fondamentalmente la stessa cosa? C'è qualche ragione per scegliere l'una rispetto all'altra?
Cosa succede se il Garbage Collector rialloca lo StringBuilder passato senza un'istruzione fissa durante l'esecuzione getNextResponse? Ogni parametro del puntatore utilizzato nelle funzioni importate deve essere fisso? O mi manca seomthing? – Luca