This class extends ctypes.CDLL with automatic checking of errno and automatically raises an exception when set by the function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import ctypes
class CDLL_errno(ctypes.CDLL):
class _FuncPtr(ctypes._CFuncPtr):
_flags_ = ctypes._FUNCFLAG_CDECL | ctypes._FUNCFLAG_USE_ERRNO
_restype_ = ctypes.c_int
def __call__(self, *args):
ctypes.set_errno(0)
try:
return ctypes._CFuncPtr.__call__(self, *args)
finally:
errno = ctypes.get_errno()
if errno:
import os
raise IOError(errno, os.strerror(errno))
def __init__(self, *args, **kw):
ctypes.CDLL.__init__(self, *args, **kw)
del self._FuncPtr
|
The ctypes modules provides a useful feature for Windows users: if a DLL contains function that follow the calling convention of returning HRESULT you can use the WinDLL() class to load it. This installs a _check_retval_ checker for the function result and when is != S_OK it will automatically raise a WindowsError exception and automatically set the error code and description.
For POSIX there is no single standard value to indicate that errno should be checked. For some functions it is a null pointer. For others it is -1, etc. This means that a _check_retval_ checker cannot be used to implement such automatic exception handling.
This class works around this limitation by wrapping __call__ instead of using _check_retval_. Before the call errno is zeroed and if it is non-zero after the call an exception is raised.
Why del self._FuncPtr :
The CDLL.__init__ sets a _FuncPtr as an instance member. Deleting it re-exposes the one in this class.