2015-06-06 25 views
6

Sto invocando una funzione non gestita nel mio codice C#.Attributi [In] [Out] Marshal's

La dichiarazione di questa funzione è la seguente:

int myFun(unsigned char* inputBuffer, unsigned char* &outputBuffer); 

uso questa funzione come segue:

[DllImport("myDLL.dll", CallingConvention = CallingConvention.Cdecl)] 
private static extern int myFun([In] byte[] inputBuffer, out IntPtr outputBuffer); 

byte[] a = Encoding.ASCII.GetBytes("sampletext!"); 
IntPtr b; 
res = myFun(a, out b); 

Anche se citato [InAttribute] per byte[] inputBuffer, la funzione changeds ancora i valori di a. Sembra che CLR stia utilizzando il proprio comportamento di marshalling predefinito. Ho usato byte[] perché è equivalente a C# unsigned char*.

Quando sostituisco byte[] con char[], il CLR seguirà i miei attributi In-Out.

Apprezzo molto il vostro aiuto. Per maggiori informazioni leggere questo msdn page.

+0

Forse "MarshalAs" è quello che stai cercando? – atlaste

+1

Il marshaller pinvoke copia solo i dati quando deve. Non deve con byte [], si limita a pin l'array e passa un puntatore al primo elemento. Quindi il codice nativo parte direttamente sull'array gestito. Molto efficiente. Diverso per char [], gli elementi devono essere convertiti da un valore di 16 bit in un valore di 8 bit. Otterrai valori Encoding.Default. Il marshaller pinvoke * deve * copiare, non verrà copiato senza [Out]. –

risposta

8

Dal documentation, con la mia attenzione:

Come un'ottimizzazione, array di tipi copiabili e le classi che contengono solo i membri copiabili sono riposte invece copiati durante marshalling. Questi tipi possono apparire come marshalling come parametri In/Out quando il chiamante e il chiamato si trovano nello stesso appartamento. Tuttavia, questi tipi vengono in realtà sottoposti al marshalling dei parametri In e devono essere applicati gli attributi InAttribute e OutAttribute se si desidera eseguire il marshalling dell'argomento come parametro In/Out.

Poiché byte è blittabile, la matrice di byte è bloccata anziché copiata, quindi marshalling come In/Out.

Quando sostituisco byte [] con char [] il CLR seguirà i miei attributi In-Out.

Il codice C# char è not blittable. Un array di char non è bloccato e pertanto i marshalling [In] char[] come parametro In.

+0

* Il carattere di tipo C# non è intercambiabile. * E se usasse Charset Unicode? – xanatos

+0

@xanatos Il collegamento doc nella mia lista di risposte 'System.Char' come non blittable –

+0

@David Heffernan, molte grazie per la risposta. Questo articolo è utile pure. https://msdn.microsoft.com/en-us/library/23acw07k%28v=vs.110%29.aspx –