views:

195

answers:

3

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

+3  A: 

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?

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.

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.)

binarycoder
Yeah, I would agree with this. It would probably be better to set a C wrapper a target function that would in turn return the value of errno from that.
supercheetah
A: 

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.

skolima
A: 

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.

There are two problems with calling GetLastError directly:

  • The runtime might do sometime after the PInvoke returns before you are able to get the last error
  • 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).
earlNameless