Доступ к глобальной переменной 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 (потенциально).