Доступ к глобальной переменной C 'errno' из C#
можно ли получить доступ к переменной "errno" в C# при вызове P/? Это похоже на Win32 GetLastError ().
3 ответов
Я уверен, что есть способ, но это, вероятно, плохая идея. Как бы вы гарантировали, что среда выполнения не вызвала некоторую функцию CRT во время ее внутренней обработки, которая повлияла на errno
?
по той же причине, вы не должны называть GetLastError
напрямую. The DllImportAttribute
предоставляет SetLastError
свойство, чтобы среда выполнения знала, чтобы немедленно захватить последнюю ошибку и сохранить ее в месте, которое управляемый код может прочитать с помощью Marshal.GetLastWin32Error
.
Я думаю, самое надежное, что вы можете сделать в этом случае, - это сделать DLL C, которая выполняет как фактическую работу C, так и захват errno
. (Обратите внимание, что просто писать обертку вокруг errno
захват по-прежнему будет иметь проблемы, упомянутые выше.)
Да, возможно -GetLastError
делает именно это. Однако, как указал binarycoder, вы не должны делать это напрямую - вместо этого установите SetLastError
на DllImport
чтобы это выполнялось и кэшировалось автоматически (и чтобы избежать проблем с многопоточностью или вызванных во время выполнения функций, изменяющих errno
value) - затем при вызове функции P / Invoked проверьте ее статус возврата, и если она показывает условие ошибки-throw Win32Exception
, который автоматически считывает значение последней ошибки. Да, даже на Mono в Linux.
решение заключается в использовании SetLastError
on DllImport
. Это заставит среду выполнения сохранить последнюю ошибку, чтобы к ней можно было получить доступ из Marshal.GetLastWin32Error
.
есть две проблемы с вызовом GetLastError
напрямую:
- среда выполнения может сделать через некоторое время после возвращения PInvoke, прежде чем вы сможете получить последнюю ошибку
- несколько потоков .NET могут находиться в одном собственном потоке. Это может привести к 2 .Чистые потоки делают PInvokes, родной библиотеки, не зная ни лучше бы тогда переписали последнюю ошибку. Таким образом, поток A в .NET получает последнюю ошибку потока B (потенциально).