2010-03-21 13 views

Odpowiedz

7

Jestem dość pewny, że istnieje sposób, ale prawdopodobnie jest to zły pomysł. W jaki sposób można zagwarantować, że środowisko wykonawcze nie wywoływało funkcji CRT podczas przetwarzania wewnętrznego, które wpłynęło na errno?

Z tego samego powodu nie należy bezpośrednio dzwonić pod numer GetLastError. Właściwość DllImportAttribute zapewnia właściwość SetLastError, więc środowisko wykonawcze wie, aby natychmiast przechwycić ostatni błąd i zapisać go w miejscu, które kod zarządzany może odczytać, używając Marshal.GetLastWin32Error.

Myślę, że najbardziej niezawodną rzeczą, jaką można zrobić w tym przypadku, jest utworzenie biblioteki DLL, która wykonuje zarówno rzeczywistą pracę C, jak i przechwytywanie errno. (Należy pamiętać, że samo zapisanie opakowania wokół przechwytywania errno nadal będzie miało powyższe obawy.)

+0

Tak, zgodziłbym się z tym. Prawdopodobnie lepiej byłoby ustawić wrapper C jako funkcję docelową, która z kolei zwróci wartość errno z tego. – supercheetah

2

Tak, jest to możliwe - GetLastError robi dokładnie to. Jednakże, jak zauważył binarycoder, nie powinieneś robić tego bezpośrednio - zamiast tego ustaw SetLastError na swoim DllImport, aby to zostało wykonane i automatycznie zapisane w pamięci podręcznej (i aby uniknąć problemów z wielowątkowością lub wywołanych w czasie wykonywania funkcji modyfikujących wartość errno) - wtedy, po wywołaniu Funkcja P/Invoked, sprawdź status powrotu i jeśli pokazuje warunek błędu - wyślij Win32Exception, który automatycznie odczytuje wartość ostatniego błędu. Tak, nawet w Mono na Linuksie.

2

Rozwiązaniem jest użycie SetLastError na DllImport. Spowoduje to, że środowisko wykonawcze zapisze ostatni błąd, aby można było uzyskać do niego dostęp od Marshal.GetLastWin32Error.

Istnieją dwa problemy z wywołaniem GetLastError bezpośrednio:

  • Środowisko wykonawcze może zrobić kiedyś po PInvoke powraca przed jesteś w stanie dostać się ostatni błąd
  • NET Wiele wątków może znajdować się na tym samym rodzimy wątek. Może to spowodować, że 2 wątki .NET wykonujące PInvokes, natywne biblioteki nie znające żadnej lepszej, będą wtedy nadpisywać ostatni błąd. Wątek A w .NET uzyskuje ostatni błąd wątku B (potencjalnie).
+0

Czy możesz pokazać przykład składni używania 'SetLastError' na' DllImport'? –