L'utilizzo di ref
o out
è non arbitrario. Se il codice nativo richiede il pass-by-reference (un puntatore), allora deve utilizzare le parole chiave se il tipo di parametro è un tipo di valore. In modo che il jitter sappia generare un puntatore al valore. E tu devi ometterli se il tipo di parametro è un tipo di riferimento (classe), gli oggetti sono già puntatori sotto il cofano.
Gli attributi [In] e [Out] sono quindi necessari per risolvere l'ambiguità sui puntatori, non specificano il flusso di dati. [In] è sempre implicito dal marshaller di pinvoke, quindi non è necessario specificarlo esplicitamente. Ma tu devi usare [Out] se ti aspetti di vedere eventuali modifiche apportate dal codice nativo a una struct o un membro della classe nel tuo codice. Il marshaller pinvoke evita di copiare automaticamente per evitare le spese.
Un'ulteriore peculiarità è che [Out] non è spesso necessario. Accade quando il valore è blittable, una parola costosa che significa che il valore gestito o il layout dell'oggetto è identico al layout nativo. Il marshaller pinvoke può quindi prendere una scorciatoia, bloccare l'oggetto e passare un puntatore all'archivio oggetti gestiti. Vedrai inevitabilmente delle modifiche poiché il codice nativo sta modificando direttamente l'oggetto gestito.
Qualcosa che in generale vuoi fortemente perseguire, è molto efficiente. Aiuta dando il tipo all'attributo [StructLayout (LayoutKind.Sequential)], sopprime un'ottimizzazione che il CLR usa per riorganizzare i campi per ottenere l'oggetto più piccolo. E usando solo campi di tipi di valore semplici o buffer di dimensioni fisse, anche se spesso non hai questa scelta. Non utilizzare mai una bool, utilizzare invece byte. Non esiste un modo semplice per scoprire se un tipo è blittabile, a parte il fatto che non funziona correttamente o utilizzando il debugger e confrontare i valori del puntatore.
Basta essere espliciti e utilizzare sempre [Out] quando ne hai bisogno. Non costa nulla se si rivela che non è necessario. Ed è auto-documentante.E puoi star bene che funzionerà anche se l'architettura del codice nativo cambia.
fonte
2015-11-20 01:25:15
Puoi dare un esempio concreto per favore. Vuoi conoscere la differenza tra '[In, Out] ref int foo' e' ref int foo'? Così com'è, alla tua domanda mancano i dettagli, e credo che tu abbia bisogno di uno (o più) esempi concreti. –
Qualcosa di simile, è: [DllImport ("MyDll.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool myFunction ([In, Out] SomeStruct [] aStruct; lo stesso che usare ref al posto di [In , Out]. – PerryC
Inoltre, hai appena combinato [In, Out] e ref;)? – PerryC