Czy jest możliwe uzyskanie dostępu do zmiennej "errno" w języku C#, gdy P/Invoking? Jest to podobne do Win32 GetLastError().Access C zmienna globalna "errno" z C#
Odpowiedz
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.)
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.
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).
Czy możesz pokazać przykład składni używania 'SetLastError' na' DllImport'? –
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