[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