2010-02-07 6 views
24

Supponiamo che tu stia chiamando una funzione Win32 che riempirà il tuo array di byte. Si crea una matrice di dimensione 32, vuota. Quindi passarlo alla funzione Win32 da riempire int e utilizzarla successivamente nel codice gestito. Esiste la possibilità che l'array di byte possa essere spostato o sovrascritto tra il momento in cui è stato allocato e compilato dalla funzione Win32?Quando si passa un array byte [] gestito tramite PInvoke per essere compilato da Win32, deve essere bloccato?

risposta

34

Risposta breve: No, pinning non è necessario in questo caso

Longer Risposta:

Il CLR Inchioderò automaticamente i riferimenti a oggetti gestiti quando l'attraversare il confine PInvoke. Non appena la funzione PInvoke viene chiusa, il riferimento verrà sbloccato. Quindi in situazioni come avere una funzione nativa riempire uno byte[] non è necessario bloccare manualmente perché l'oggetto è utilizzato solo dal codice nativo durante la chiamata di funzione.

Il blocco manuale della matrice diventa necessario se il codice nativo memorizza nella cache il puntatore gestito. Quando ciò accade, devi pin manualmente l'array fino a quando il codice nativo non ha più bisogno del puntatore. In questo caso presumo il puntatore non è memorizzato quindi non è necessario pin

Riferimento - http://msdn.microsoft.com/en-us/magazine/cc163910.aspx#S2

+0

Ok, quindi la domanda è cosa succede quando la chiamata Win32 non ritorna immediatamente? Supponiamo ad esempio una chiamata a ReadFile() che utilizza I/O sovrapposti e un evento di reset manuale? La chiamata ritorna immediatamente, mentre viene eseguita l'operazione di I/O. In questo caso, l'array di byte deve essere bloccato? Come si può sapere se la libreria nativa sta memorizzando nella cache la matrice –

+1

Beh, dovrei aver letto prima il collegamento perché fornisce ReadFileEx e I/O sovrapposti come esempio di quando è necessario eseguire il pin. –

0

Mi spiace rispondere alla mia domanda, ma credo che se il tipo è blittabile, poiché byte [] è, allora l'array verrebbe bloccato durante il marshalling dal runtime, quindi non sarebbe necessario alcun pinning. Un oggetto nell'altro tempo sarebbe diverso. Per favore correggimi se sbaglio.

+1

Qual è il modo migliore per bloccare un byte [] in C#? –

+1

Pin un byte [] usando la parola chiave 'fixed' all'interno di un blocco di codice' non sicuro'. Vedi http://msdn.microsoft.com/en-us/library/f58wzh21(VS.71).aspx –

+1

@Reed: Penso che sia proprio qui. Il codice del marshaller pinerà l'array durante la chiamata da managaged a nativo, quindi l'array dovrà essere pinned esplicitamente solo se si desidera fare riferimento nel codice nativo in un altro momento. –

2

secondo MSDN Marshaling Arrays of Types solamente un array passato per riferimento può essere scritto dal codice non gestito. Quindi sembra che tu devi dichiarare il parametro array [out] o [in, out] se vuoi riempirlo sul lato non gestito.

Questa pagina http://msdn.microsoft.com/en-us/library/aa719896(VS.71).aspx riesce ad andare avanti e avanti senza mai dire esplicitamente che il marshaller attacca gli array durante la chiamata da gestito a non gestito, ma gran parte di ciò che descrive non funzionerebbe se il marshaller non avesse pin.

Problemi correlati