Commits

Armin Rigo  committed 7c1abc5

errno support, by special-casing "ffi.C.errno" to make it look exactly like in C.

  • Participants
  • Parent commits 641fb6b

Comments (0)

Files changed (4)

 
 def _make_ffi_library(ffi, backendlib, libname=None):
     function_cache = {}
+    backend = ffi._backend
     #
     class FFILibrary(object):
         def __getattribute__(self, name):
+            if libname is None and name == 'errno':
+                return backend.get_errno()
+            #
             try:
                 return function_cache[name]
             except KeyError:
             raise AttributeError(name)
 
         def __setattr__(self, name, value):
+            if libname is None and name == 'errno':
+                backend.set_errno(value)
+                return
+            #
             key = 'variable ' + name
             if key in ffi._declarations:
                 node = ffi._declarations[key]

File ffi/backend_ctypes.py

 
     def load_library(self, name=Ellipsis):
         if name is Ellipsis:
-            name = 'c'    # on Posix only
-        path = ctypes.util.find_library(name)
+            path = None       # the C library
+        else:
+            if '/' in name:
+                path = name
+            else:
+                path = ctypes.util.find_library(name)
+                if path is None:
+                    raise OSError("library not found: %r" % (name,))
         cdll = ctypes.CDLL(path)
         return CTypesLibrary(self, cdll)
 
                                         type(x).__name__)
                     return ctype(x).value
 
-            _from_ctypes = staticmethod(_identity)
+            @staticmethod
+            def _from_ctypes(value):
+                return value
         #
         CTypesPrimitive._fix_class()
         return CTypesPrimitive
         ctypes_stuff.insert(0, BResult._ctype)
         #
         class CTypesFunction(CTypesData):
-            _ctype = ctypes.CFUNCTYPE(*ctypes_stuff)
+            _ctype = ctypes.CFUNCTYPE(*ctypes_stuff, use_errno=True)
             _reftypename = '%s(* &)(%s)' % (BResult._get_c_name(), nameargs)
             _name = None
             _own_callback = None
         CTypesEnum._fix_class()
         return CTypesEnum
 
+    def get_errno(self):
+        return ctypes.get_errno()
+
+    def set_errno(self, value):
+        ctypes.set_errno(value)
+
 
 class CTypesLibrary(object):
 
         ctypes.memmove(ctypes.addressof(ctypes_obj),
                        ctypes.addressof(new_ctypes_obj),
                        ctypes.sizeof(BType._ctype))
-
-
-def _identity(x):
-    return x

File testing/test_ownlib.py

+import py
+import subprocess
+from ffi import FFI
+
+
+SOURCE = """\
+#include <errno.h>
+
+int test_getting_errno(void) {
+    errno = 123;
+    return -1;
+}
+
+int test_setting_errno(void) {
+    return errno;
+}
+"""
+
+def setup_module(mod):
+    from testing.udir import udir
+    udir.join('testownlib.c').write(SOURCE)
+    subprocess.check_call('gcc testownlib.c -shared -fPIC -o testownlib.so',
+                          cwd=str(udir), shell=True)
+    mod.module = str(udir.join('testownlib.so'))
+
+def test_getting_errno():
+    ffi = FFI()
+    ffi.cdef("""
+        int test_getting_errno(void);
+    """)
+    ownlib = ffi.load(module)
+    res = ownlib.test_getting_errno()
+    assert res == -1
+    assert ffi.C.errno == 123
+
+def test_setting_errno():
+    ffi = FFI()
+    ffi.cdef("""
+        int test_setting_errno(void);
+    """)
+    ownlib = ffi.load(module)
+    ffi.C.errno = 42
+    res = ownlib.test_setting_errno()
+    assert res == 42

File testing/udir.py

+import py
+
+udir = py.path.local.make_numbered_dir(prefix = 'ffi-')