[pypy-commit] pypy cffi-1.0: in-progress

arigo noreply at buildbot.pypy.org
Sun May 17 20:21:57 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r77358:045a150964ce
Date: 2015-05-17 19:51 +0200
http://bitbucket.org/pypy/pypy/changeset/045a150964ce/

Log:	in-progress

diff --git a/pypy/module/_cffi_backend/cdlopen.py b/pypy/module/_cffi_backend/cdlopen.py
--- a/pypy/module/_cffi_backend/cdlopen.py
+++ b/pypy/module/_cffi_backend/cdlopen.py
@@ -1,11 +1,13 @@
 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
 from rpython.rlib.objectmodel import specialize
+from rpython.rlib.rdynload import dlopen, dlsym, dlclose, DLOpenError
+from pypy.module._rawffi.interp_rawffi import wrap_dlopenerror
 
 from pypy.module._cffi_backend.parse_c_type import (
     _CFFI_OPCODE_T, GLOBAL_S, CDL_INTCONST_S,
     ll_set_cdl_realize_global_int)
 from pypy.module._cffi_backend.realize_c_type import getop
-from pypy.module._cffi_backend import cffi_opcode
+from pypy.module._cffi_backend import cffi_opcode, lib_obj
 
 
 class StringDecoder:
@@ -91,3 +93,17 @@
         rffi.setintfield(ffi.ctxobj.ctx, 'c_num_globals', n)
 
     # ...
+
+
+def ffi_dlopen(ffi, filename, flags):
+    with rffi.scoped_str2charp(filename) as ll_libname:
+        if filename is None:
+            filename = "<None>"
+        try:
+            handle = dlopen(ll_libname, flags)
+        except DLOpenError, e:
+            raise wrap_dlopenerror(space, e, filename)
+    return lib_obj.W_LibObject(ffi, filename, handle)
+
+def ffi_dlclose(xxx):
+    yyyy
diff --git a/pypy/module/_cffi_backend/ffi_obj.py b/pypy/module/_cffi_backend/ffi_obj.py
--- a/pypy/module/_cffi_backend/ffi_obj.py
+++ b/pypy/module/_cffi_backend/ffi_obj.py
@@ -477,6 +477,32 @@
         return self.ffi_type(w_arg, ACCEPT_STRING | ACCEPT_CDATA)
 
 
+    @unwrap_spec(filename="str_or_None", flags=int)
+    def descr_dlopen(self, filename, flags=0):
+        """\
+Load and return a dynamic library identified by 'name'.  The standard
+C library can be loaded by passing None.
+
+Note that functions and types declared with 'ffi.cdef()' are not
+linked to a particular library, just like C headers.  In the library
+we only look for the actual (untyped) symbols at the time of their
+first access."""
+        #
+        from pypy.module._cffi_backend import cdlopen
+        return cdlopen.ffi_dlopen(self, filename, flags)
+
+
+    def descr_dlclose(self, w_lib):
+        """\
+Close a library obtained with ffi.dlopen().  After this call, access to
+"functions or variables from the library will fail (possibly with a
+segmentation fault)."""
+        #
+        from pypy.module._cffi_backend import cdlopen
+        lib = self.space.interp_w(W_LibObject, w_lib)
+        return cdlopen.ffi_dlclose(self, lib)
+
+
     @unwrap_spec(name=str)
     def descr_integer_const(self, name):
         """\
@@ -539,6 +565,8 @@
         buffer      = interp2app(W_FFIObject.descr_buffer),
         callback    = interp2app(W_FFIObject.descr_callback),
         cast        = interp2app(W_FFIObject.descr_cast),
+        dlclose     = interp2app(W_FFIObject.descr_dlclose),
+        dlopen      = interp2app(W_FFIObject.descr_dlopen),
         from_buffer = interp2app(W_FFIObject.descr_from_buffer),
         from_handle = interp2app(W_FFIObject.descr_from_handle),
         gc          = interp2app(W_FFIObject.descr_gc),
diff --git a/pypy/module/_cffi_backend/lib_obj.py b/pypy/module/_cffi_backend/lib_obj.py
--- a/pypy/module/_cffi_backend/lib_obj.py
+++ b/pypy/module/_cffi_backend/lib_obj.py
@@ -1,5 +1,6 @@
 from rpython.rlib import jit
 from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rlib.rdynload import DLLHANDLE
 
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.interpreter.baseobjspace import W_Root
@@ -16,12 +17,13 @@
 
 class W_LibObject(W_Root):
 
-    def __init__(self, ffi, libname):
+    def __init__(self, ffi, libname, libhandle=rffi.cast(DLLHANDLE, 0)):
         self.space = ffi.space
         self.ctx = ffi.ctxobj.ctx
         self.ffi = ffi
         self.dict_w = {}          # content, built lazily
         self.libname = libname    # some string that gives the name of the lib
+        self.libhandle = libhandle   # the dlopen()ed handle, if any
 
     def descr_repr(self):
         return self.space.wrap("<Lib object for '%s'>" % self.libname)
diff --git a/pypy/module/_cffi_backend/test/test_re_python.py b/pypy/module/_cffi_backend/test/test_re_python.py
--- a/pypy/module/_cffi_backend/test/test_re_python.py
+++ b/pypy/module/_cffi_backend/test/test_re_python.py
@@ -14,6 +14,7 @@
             from cffi import ffiplatform
         except ImportError:
             py.test.skip("system cffi module not found or older than 1.0.0")
+        space = cls.space
         SRC = """
         #define FOOBAR (-42)
         static const int FOOBAZ = -43;
@@ -35,7 +36,7 @@
         ext = ffiplatform.get_extension(str(c_file), '_test_re_python',
                                         export_symbols=['add42', 'globalvar42'])
         outputfilename = ffiplatform.compile(str(tmpdir), ext)
-        #mod.extmod = outputfilename
+        cls.w_extmod = space.wrap(outputfilename)
         #mod.tmpdir = tmpdir
         #
         ffi = FFI()
@@ -54,7 +55,6 @@
         ffi.emit_python_code(str(tmpdir.join('re_python_pysrc.py')))
         #mod.original_ffi = ffi
         #
-        space = cls.space
         space.appexec([space.wrap(str(tmpdir))], """(path):
             import _cffi_backend     # force it to be initialized
             import sys
@@ -77,40 +77,40 @@
         assert ffi.integer_const('FOOBAR') == -42
         assert ffi.integer_const('FOOBAZ') == -43
 
-    def test_large_constant():
+    def test_large_constant(self):
         from re_python_pysrc import ffi
         assert ffi.integer_const('BIGPOS') == 420000000000
         assert ffi.integer_const('BIGNEG') == -420000000000
 
-    def test_function():
+    def test_function(self):
         import _cffi_backend
         from re_python_pysrc import ffi
-        lib = ffi.dlopen(extmod)
+        lib = ffi.dlopen(self.extmod)
         assert lib.add42(-10) == 32
         assert type(lib.add42) is _cffi_backend.FFI.CData
 
-    def test_dlclose():
+    def test_dlclose(self):
         import _cffi_backend
         from re_python_pysrc import ffi
-        lib = ffi.dlopen(extmod)
+        lib = ffi.dlopen(self.extmod)
         ffi.dlclose(lib)
         e = py.test.raises(ffi.error, ffi.dlclose, lib)
         assert str(e.value) == (
             "library '%s' is already closed or was not created with ffi.dlopen()"
-            % (extmod,))
+            % (self.extmod,))
 
-    def test_constant_via_lib():
+    def test_constant_via_lib(self):
         from re_python_pysrc import ffi
-        lib = ffi.dlopen(extmod)
+        lib = ffi.dlopen(self.extmod)
         assert lib.FOOBAR == -42
         assert lib.FOOBAZ == -43
 
-    def test_opaque_struct():
+    def test_opaque_struct(self):
         from re_python_pysrc import ffi
         ffi.cast("struct foo_s *", 0)
         py.test.raises(TypeError, ffi.new, "struct foo_s *")
 
-    def test_nonopaque_struct():
+    def test_nonopaque_struct(self):
         from re_python_pysrc import ffi
         for p in [ffi.new("struct bar_s *", [5, b"foobar"]),
                   ffi.new("bar_t *", [5, b"foobar"])]:
@@ -118,13 +118,13 @@
             assert p.a[0] == ord('f')
             assert p.a[5] == ord('r')
 
-    def test_enum():
+    def test_enum(self):
         from re_python_pysrc import ffi
         assert ffi.integer_const("BB") == 1
         e = ffi.cast("enum foo_e", 2)
         assert ffi.string(e) == "CC"
 
-    def test_include_1():
+    def test_include_1(self):
         sub_ffi = FFI()
         sub_ffi.cdef("static const int k2 = 121212;")
         sub_ffi.include(original_ffi)
@@ -137,7 +137,7 @@
         assert ffi.integer_const('FOOBAR') == -42
         assert ffi.integer_const('FOOBAZ') == -43
         assert ffi.integer_const('k2') == 121212
-        lib = ffi.dlopen(extmod)     # <- a random unrelated library would be fine
+        lib = ffi.dlopen(self.extmod)     # <- a random unrelated library would be fine
         assert lib.FOOBAR == -42
         assert lib.FOOBAZ == -43
         assert lib.k2 == 121212
@@ -145,9 +145,9 @@
         p = ffi.new("bar_t *", [5, b"foobar"])
         assert p.a[4] == ord('a')
 
-    def test_global_var():
+    def test_global_var(self):
         from re_python_pysrc import ffi
-        lib = ffi.dlopen(extmod)
+        lib = ffi.dlopen(self.extmod)
         assert lib.globalvar42 == 1234
         p = ffi.addressof(lib, 'globalvar42')
         lib.globalvar42 += 5
@@ -155,7 +155,7 @@
         p[0] -= 1
         assert lib.globalvar42 == 1238
 
-    def test_rtld_constants():
+    def test_rtld_constants(self):
         from re_python_pysrc import ffi
         ffi.RTLD_NOW    # check that we have the attributes
         ffi.RTLD_LAZY


More information about the pypy-commit mailing list