从C#访问C全局变量'errno'

时间:2022-09-06 13:51:52

Is it possible to access the "errno" variable in C# when P/Invoking? This is similar to Win32 GetLastError().

P / Invoking时是否可以在C#中访问“errno”变量?这类似于Win32 GetLastError()。

3 个解决方案

#1


8  

I'm fairly sure that there is a way, but it probably is a bad idea. How would you guarantee that the runtime has not called some CRT function during its internal processing that has affected the errno?

我很确定有办法,但这可能是一个坏主意。您如何保证运行时在其内部处理过程中没有调用某些CRT函数影响了errno?

For the same reason, you should not call GetLastError directly either. The DllImportAttribute provides a SetLastError property so the runtime knows to immediately capture the last error and store it in a place that the managed code can read using Marshal.GetLastWin32Error.

出于同样的原因,您也不应该直接调用GetLastError。 DllImportAttribute提供SetLastError属性,因此运行时知道立即捕获最后一个错误并将其存储在托管代码可以使用Marshal.GetLastWin32Error读取的位置。

I think the most robust thing you could do in this case is make a C DLL that performs both the actual C work and the capture of the errno. (Note that just writing a wrapper around the errno capture would still have the concerns mentioned above.)

我认为在这种情况下你能做的最强大的事情是制作一个C DLL,它既可以执行实际的C工作,也可以执行errno的捕获。 (注意,只是在errno捕获周围编写一个包装器仍然会有上面提到的问题。)

#2


2  

Yes, it is possible - GetLastError does exactly that. However, as binarycoder pointed out, you should not do this directly - instead, set SetLastError on your DllImport to have this performed and cached automatically (and to avoid multithreading problems or runtime-invoked functions modifying the errno value) - then, on invoking the P/Invoked function, check it's return status, and if it's showing an error condition - throw Win32Exception, which reads the value of last error automatically. Yes, even on Mono on Linux.

是的,有可能 - GetLastError就是这样做的。但是,正如二进制编码器指出的那样,你不应该直接这样做 - 而是在你的DllImport上设置SetLastError以自动执行和缓存(并避免多线程问题或运行时调用的函数修改errno值) - 然后,在调用时P / Invoked函数,检查它的返回状态,如果它显示错误条件 - 抛出Win32Exception,它会自动读取上一个错误的值。是的,甚至在Linux上的Mono上也是如此。

#3


2  

The solution is to use SetLastError on DllImport. This will make the runtime save the last error so it can be accessed from Marshal.GetLastWin32Error.

解决方案是在DllImport上使用SetLastError。这将使运行时保存最后一个错误,以便可以从Marshal.GetLastWin32Error访问它。

There are two problems with calling GetLastError directly:

直接调用GetLastError有两个问题:

  • The runtime might do sometime after the PInvoke returns before you are able to get the last error
  • 运行时可能会在PInvoke返回之后的某个时间执行,然后才能获得最后一个错误

  • Multiple .NET threads can reside on the same native thread. This can result in 2 .NET threads doing PInvokes, native libraries not knowing any better, would then overwrite the last error. So thread A in .NET getting thread B's last error (potentially).
  • 多个.NET线程可以驻留在同一本机线程上。这可能导致2个.NET线程执行PInvokes,本机库不知道更好,然后会覆盖最后一个错误。因此,.NET中的线程A获取线程B的最后一个错误(可能)。

#1


8  

I'm fairly sure that there is a way, but it probably is a bad idea. How would you guarantee that the runtime has not called some CRT function during its internal processing that has affected the errno?

我很确定有办法,但这可能是一个坏主意。您如何保证运行时在其内部处理过程中没有调用某些CRT函数影响了errno?

For the same reason, you should not call GetLastError directly either. The DllImportAttribute provides a SetLastError property so the runtime knows to immediately capture the last error and store it in a place that the managed code can read using Marshal.GetLastWin32Error.

出于同样的原因,您也不应该直接调用GetLastError。 DllImportAttribute提供SetLastError属性,因此运行时知道立即捕获最后一个错误并将其存储在托管代码可以使用Marshal.GetLastWin32Error读取的位置。

I think the most robust thing you could do in this case is make a C DLL that performs both the actual C work and the capture of the errno. (Note that just writing a wrapper around the errno capture would still have the concerns mentioned above.)

我认为在这种情况下你能做的最强大的事情是制作一个C DLL,它既可以执行实际的C工作,也可以执行errno的捕获。 (注意,只是在errno捕获周围编写一个包装器仍然会有上面提到的问题。)

#2


2  

Yes, it is possible - GetLastError does exactly that. However, as binarycoder pointed out, you should not do this directly - instead, set SetLastError on your DllImport to have this performed and cached automatically (and to avoid multithreading problems or runtime-invoked functions modifying the errno value) - then, on invoking the P/Invoked function, check it's return status, and if it's showing an error condition - throw Win32Exception, which reads the value of last error automatically. Yes, even on Mono on Linux.

是的,有可能 - GetLastError就是这样做的。但是,正如二进制编码器指出的那样,你不应该直接这样做 - 而是在你的DllImport上设置SetLastError以自动执行和缓存(并避免多线程问题或运行时调用的函数修改errno值) - 然后,在调用时P / Invoked函数,检查它的返回状态,如果它显示错误条件 - 抛出Win32Exception,它会自动读取上一个错误的值。是的,甚至在Linux上的Mono上也是如此。

#3


2  

The solution is to use SetLastError on DllImport. This will make the runtime save the last error so it can be accessed from Marshal.GetLastWin32Error.

解决方案是在DllImport上使用SetLastError。这将使运行时保存最后一个错误,以便可以从Marshal.GetLastWin32Error访问它。

There are two problems with calling GetLastError directly:

直接调用GetLastError有两个问题:

  • The runtime might do sometime after the PInvoke returns before you are able to get the last error
  • 运行时可能会在PInvoke返回之后的某个时间执行,然后才能获得最后一个错误

  • Multiple .NET threads can reside on the same native thread. This can result in 2 .NET threads doing PInvokes, native libraries not knowing any better, would then overwrite the last error. So thread A in .NET getting thread B's last error (potentially).
  • 多个.NET线程可以驻留在同一本机线程上。这可能导致2个.NET线程执行PInvokes,本机库不知道更好,然后会覆盖最后一个错误。因此,.NET中的线程A获取线程B的最后一个错误(可能)。