2010-03-21 12 views

risposta

7

Sono abbastanza sicuro che ci sia un modo, ma probabilmente è una cattiva idea. Come garantiresti che il runtime non abbia richiamato alcuna funzione CRT durante l'elaborazione interna che ha interessato lo errno?

Per lo stesso motivo, non chiamare direttamente GetLastError. Il DllImportAttribute fornisce una proprietà SetLastError in modo che il runtime sappia immediatamente catturare l'ultimo errore e memorizzarlo in una posizione che il codice gestito può leggere utilizzando Marshal.GetLastWin32Error.

Penso che la cosa più efficace che si possa fare in questo caso sia creare una DLL C che esegua sia l'effettivo lavoro C che l'acquisizione dello errno. (Si noti che la sola scrittura di un wrapper attorno all'acquisizione errno avrebbe ancora le preoccupazioni sopra menzionate.)

+0

Sì, sarei d'accordo. Probabilmente sarebbe meglio impostare un wrapper C come una funzione target che restituirebbe a sua volta il valore di errno. – supercheetah

2

Sì, è possibile - GetLastError fa esattamente questo. Tuttavia, come indicato da binarycoder, non dovresti farlo direttamente - invece, imposta SetLastError sul tuo DllImport affinché questo venga eseguito e memorizzato nella cache automaticamente (e per evitare problemi di multithreading o funzioni richiamate dal runtime che modificano il valore errno), quindi, invocando il P/Funzione richiamata, controlla lo stato di ritorno e se mostra una condizione di errore - lancia Win32Exception, che legge automaticamente il valore dell'ultimo errore. Sì, anche su Mono su Linux.

2

La soluzione è utilizzare SetLastError su DllImport. Ciò farà sì che il runtime salvi l'ultimo errore, quindi è possibile accedervi da Marshal.GetLastWin32Error.

Ci sono due problemi con chiamando direttamente GetLastError:

  • Il runtime potrebbe fare qualche tempo dopo la PInvoke torna prima di essere in grado di ottenere l'ultimo errore
  • multi-thread .NET possono risiedere sullo stesso nativo filo. Ciò può causare 2 thread .NET che eseguono PInvokes, le librerie native che non lo conoscono meglio, quindi sovrascrivono l'ultimo errore. Quindi, il thread A in .NET riceve l'ultimo errore del thread B (potenzialmente).
+0

Puoi mostrare un esempio della sintassi per l'uso di 'SetLastError' su' DllImport'? –