Доступ к глобальной переменной 'errno' из C # - PullRequest
9 голосов
/ 21 марта 2010

Возможно ли получить доступ к переменной "errno" в C # при P / Invoking? Это похоже на Win32 GetLastError ().

Ответы [ 3 ]

8 голосов
/ 21 марта 2010

Я вполне уверен, что есть способ, но, вероятно, это плохая идея. Как бы вы гарантировали, что среда выполнения не вызывала какую-либо функцию CRT во время своей внутренней обработки, которая повлияла на errno?

По той же причине вам также не следует звонить GetLastError напрямую. DllImportAttribute предоставляет свойство SetLastError, поэтому среда выполнения знает, что нужно немедленно зафиксировать последнюю ошибку и сохранить ее в месте, которое управляемый код может прочитать, используя Marshal.GetLastWin32Error.

Я думаю, что самая надежная вещь, которую вы могли бы сделать в этом случае, - это создать C DLL, которая выполняет как реальную работу C, так и захват errno. (Обратите внимание, что простое написание обертки вокруг захвата errno все равно будет иметь проблемы, упомянутые выше.)

2 голосов
/ 26 марта 2010

Решение состоит в том, чтобы использовать SetLastError на DllImport. Это заставит среду выполнения сохранить последнюю ошибку, чтобы к ней можно было обратиться из Marshal.GetLastWin32Error.

Есть две проблемы с прямым вызовом GetLastError:

  • Время выполнения может закончиться через некоторое время после возврата PInvoke, прежде чем вы сможете получить последнюю ошибку
  • Несколько потоков .NET могут находиться в одном собственном потоке. Это может привести к тому, что 2 .NET-потока, выполняющие PInvokes, нативные библиотеки, не знающие ничего лучшего, перезапишут последнюю ошибку. Поэтому поток A в .NET получает последнюю ошибку потока B (потенциально).
2 голосов
/ 21 марта 2010

Да, это возможно - GetLastError делает именно это. Однако, как указал двоичный кодер, вам не следует делать это напрямую - вместо этого установите SetLastError на DllImport, чтобы это выполнялось и автоматически кэшировалось (и чтобы избежать проблем с многопоточностью или вызванных во время выполнения функций, изменяющих значение errno) - затем, при вызове функции P / Invoked, проверьте ее состояние возврата, и, если он показывает состояние ошибки, - бросить Win32Exception, который автоматически считывает значение последней ошибки. Да, даже на Mono в Linux.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...