TheStrangeQuark
TheStrangeQuark

Reputation: 2405

Getting errno after an error in wrapped c function in Python

I'm learning how to wrap c functions using Python's ctypes' and am able to wrap and call a function, but I can't figure out how to get theerrno` after there is an error. For this example, I'm wrapping inotify_add_watch. This isn't the full code, just an example of something that will cause an error:

import ctypes

c_lib = ctypes.cdll.LoadLibrary('libc.so.6')

inotify_add = c_lib.inotify_add_watch
inotify_add.argtypes = (ctypes.c_int, ctypes.c_char_p, ctypes.c_uint32)
inotify_add.restype = ctypes.c_int

# This will cause an EBADF error
inotify_add(32, b'/tmp', 1)  # returns -1

And the documentation I linked says this will return -1 which it does, but that it also will set errno appropriately. I cannot figure out how to access errno now. If I try ctypes.get_errno(), this just returns 0. If I try to call c_lib.errno(), this causes a segmentation error, so that isn't working either. Is there a way I can retrieve errno?

Upvotes: 0

Views: 881

Answers (1)

Mark Tolonen
Mark Tolonen

Reputation: 178021

You have to get errno from the same CRT library that Python was built with. So for Python 3.7 on Windows. I don't have Linux handy to try, so hopefully this puts you in the right direction.

>>> dll = CDLL('ucrtbase',use_errno=True)
>>> get_errno()
0
>>> dll._access(b'nonexisting',0)
-1
>>> get_errno()
2

Errno 2 is ENOENT (No such file or directory) so it got set and looks correct.

A different CRT library has a different errno instance so it isn't captured correctly by Python for use with set_errno()/get_errno().

Upvotes: 2

Related Questions