[pypy-commit] pypy default: update to cffi/ba124ec241c1
arigo
pypy.commits at gmail.com
Sun Jan 5 09:34:00 EST 2020
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r98446:35b130c4015c
Date: 2020-01-05 14:16 +0100
http://bitbucket.org/pypy/pypy/changeset/35b130c4015c/
Log: update to cffi/ba124ec241c1
diff --git a/extra_tests/cffi_tests/cffi0/test_ownlib.py b/extra_tests/cffi_tests/cffi0/test_ownlib.py
--- a/extra_tests/cffi_tests/cffi0/test_ownlib.py
+++ b/extra_tests/cffi_tests/cffi0/test_ownlib.py
@@ -372,3 +372,29 @@
assert s.top == 22
assert s.right == 33
assert s.bottom == 44
+
+ def test_dlopen_handle(self):
+ if self.module is None:
+ py.test.skip("fix the auto-generation of the tiny test lib")
+ if sys.platform == 'win32':
+ py.test.skip("uses 'dl' explicitly")
+ if self.__class__.Backend is CTypesBackend:
+ py.test.skip("not for the ctypes backend")
+ backend = self.Backend()
+ ffi1 = FFI(backend=backend)
+ ffi1.cdef("""void *dlopen(const char *filename, int flags);
+ int dlclose(void *handle);""")
+ lib1 = ffi1.dlopen('dl')
+ handle = lib1.dlopen(self.module.encode(sys.getfilesystemencoding()),
+ backend.RTLD_LAZY)
+ assert ffi1.typeof(handle) == ffi1.typeof("void *")
+ assert handle
+
+ ffi = FFI(backend=backend)
+ ffi.cdef("""unsigned short foo_2bytes(unsigned short a);""")
+ lib = ffi.dlopen(handle)
+ x = lib.foo_2bytes(1000)
+ assert x == 1042
+
+ err = lib1.dlclose(handle)
+ assert err == 0
diff --git a/extra_tests/cffi_tests/cffi1/test_re_python.py b/extra_tests/cffi_tests/cffi1/test_re_python.py
--- a/extra_tests/cffi_tests/cffi1/test_re_python.py
+++ b/extra_tests/cffi_tests/cffi1/test_re_python.py
@@ -261,3 +261,24 @@
# based on issue #429
from re_python_pysrc import ffi
ffi.new("selfref_ptr_t")
+
+def test_dlopen_handle():
+ import _cffi_backend
+ from re_python_pysrc import ffi
+ if sys.platform == 'win32':
+ py.test.skip("uses 'dl' explicitly")
+ ffi1 = FFI()
+ ffi1.cdef("""void *dlopen(const char *filename, int flags);
+ int dlclose(void *handle);""")
+ lib1 = ffi1.dlopen('dl')
+ handle = lib1.dlopen(extmod.encode(sys.getfilesystemencoding()),
+ _cffi_backend.RTLD_LAZY)
+ assert ffi1.typeof(handle) == ffi1.typeof("void *")
+ assert handle
+
+ lib = ffi.dlopen(handle)
+ assert lib.add42(-10) == 32
+ assert type(lib.add42) is _cffi_backend.FFI.CData
+
+ err = lib1.dlclose(handle)
+ assert err == 0
diff --git a/extra_tests/cffi_tests/cffi1/test_recompiler.py b/extra_tests/cffi_tests/cffi1/test_recompiler.py
--- a/extra_tests/cffi_tests/cffi1/test_recompiler.py
+++ b/extra_tests/cffi_tests/cffi1/test_recompiler.py
@@ -349,9 +349,9 @@
lib = verify(ffi, 'test_verify_exact_field_offset',
"""struct foo_s { short a; int b; };""")
e = py.test.raises(ffi.error, ffi.new, "struct foo_s *", []) # lazily
- assert str(e.value) == ("struct foo_s: wrong offset for field 'b' (cdef "
- 'says 0, but C compiler says 4). fix it or use "...;" '
- "in the cdef for struct foo_s to make it flexible")
+ assert str(e.value).startswith(
+ "struct foo_s: wrong offset for field 'b' (cdef "
+ 'says 0, but C compiler says 4). fix it or use "...;" ')
def test_type_caching():
ffi1 = FFI(); ffi1.cdef("struct foo_s;")
diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
--- a/lib_pypy/cffi/api.py
+++ b/lib_pypy/cffi/api.py
@@ -141,7 +141,11 @@
linked to a particular library, just like C headers; in the
library we only look for the actual (untyped) symbols.
"""
- assert isinstance(name, basestring) or name is None
+ if not (isinstance(name, basestring) or
+ name is None or
+ isinstance(name, self.CData)):
+ raise TypeError("dlopen(name): name must be a file name, None, "
+ "or an already-opened 'void *' handle")
with self._lock:
lib, function_cache = _make_ffi_library(self, name, flags)
self._function_caches.append(function_cache)
@@ -799,9 +803,9 @@
def _load_backend_lib(backend, name, flags):
import os
- if name is None:
- if sys.platform != "win32":
- return backend.load_library(None, flags)
+ if not isinstance(name, basestring):
+ if sys.platform != "win32" or name is not None:
+ return backend.load_library(name, flags)
name = "c" # Windows: load_library(None) fails, but this works
# on Python 2 (backward compatibility hack only)
first_error = None
@@ -935,7 +939,7 @@
backendlib.close_lib()
self.__dict__.clear()
#
- if libname is not None:
+ if isinstance(libname, basestring):
try:
if not isinstance(libname, str): # unicode, on Python 2
libname = libname.encode('utf-8')
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
@@ -15,10 +15,11 @@
def __init__(self, ffi, w_filename, flags):
space = ffi.space
- fname, handle = misc.dlopen_w(space, w_filename, flags)
+ fname, handle, autoclose = misc.dlopen_w(space, w_filename, flags)
W_LibObject.__init__(self, ffi, fname)
self.libhandle = handle
- self.register_finalizer(space)
+ if autoclose:
+ self.register_finalizer(space)
def _finalize_(self):
h = self.libhandle
diff --git a/pypy/module/_cffi_backend/libraryobj.py b/pypy/module/_cffi_backend/libraryobj.py
--- a/pypy/module/_cffi_backend/libraryobj.py
+++ b/pypy/module/_cffi_backend/libraryobj.py
@@ -18,8 +18,10 @@
def __init__(self, space, w_filename, flags):
self.space = space
- self.name, self.handle = misc.dlopen_w(space, w_filename, flags)
- self.register_finalizer(space)
+ self.name, self.handle, autoclose = (
+ misc.dlopen_w(space, w_filename, flags))
+ if autoclose:
+ self.register_finalizer(space)
def _finalize_(self):
h = self.handle
diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py
--- a/pypy/module/_cffi_backend/misc.py
+++ b/pypy/module/_cffi_backend/misc.py
@@ -8,7 +8,7 @@
from rpython.rlib.objectmodel import specialize, we_are_translated
from rpython.rlib.rarithmetic import r_uint, r_ulonglong
from rpython.rlib.unroll import unrolling_iterable
-from rpython.rlib.rdynload import dlopen, DLOpenError
+from rpython.rlib.rdynload import dlopen, DLOpenError, DLLHANDLE
from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
from rpython.translator.tool.cbuild import ExternalCompilationInfo
@@ -398,7 +398,26 @@
# ____________________________________________________________
def dlopen_w(space, w_filename, flags):
- if WIN32 and space.isinstance_w(w_filename, space.w_unicode):
+ from pypy.module._cffi_backend.cdataobj import W_CData
+ from pypy.module._cffi_backend import ctypeptr
+
+ autoclose = True
+ if isinstance(w_filename, W_CData):
+ # 'flags' ignored in this case
+ w_ctype = w_filename.ctype
+ if (not isinstance(w_ctype, ctypeptr.W_CTypePointer) or
+ not w_ctype.is_void_ptr):
+ raise oefmt(space.w_TypeError,
+ "dlopen() takes a file name or 'void *' handle, not '%s'",
+ w_ctype.name)
+ handle = w_filename.unsafe_escaping_ptr()
+ if not handle:
+ raise oefmt(space.w_RuntimeError, "cannot call dlopen(NULL)")
+ fname = w_ctype.extra_repr(handle)
+ handle = rffi.cast(DLLHANDLE, handle)
+ autoclose = False
+ #
+ elif WIN32 and space.isinstance_w(w_filename, space.w_unicode):
fname = space.text_w(space.repr(w_filename))
utf8_name = space.utf8_w(w_filename)
uni_len = space.len_w(w_filename)
@@ -419,4 +438,4 @@
handle = dlopen(ll_libname, flags)
except DLOpenError as e:
raise wrap_dlopenerror(space, e, fname)
- return fname, handle
+ return fname, handle, autoclose
diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -308,8 +308,8 @@
w_FFIError = get_ffi_error(w_ctype.space)
raise oefmt(w_FFIError,
'%s: %s%s%s (cdef says %d, but C compiler says %d).'
- ' fix it or use "...;" in the cdef for %s to '
- 'make it flexible',
+ ' fix it or use "...;" as the last field in the '
+ 'cdef for %s to make it flexible',
w_ctype.name, msg1, msg2, msg3,
cdef_value, compiler_value, w_ctype.name)
w_ctype._custom_field_pos = True
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
@@ -75,6 +75,9 @@
typedef struct bar_s { int x; signed char a[]; } bar_t;
enum foo_e { AA, BB, CC };
typedef struct selfref { struct selfref *next; } *selfref_ptr_t;
+
+ void *dlopen(const char *filename, int flags);
+ int dlclose(void *handle);
""")
ffi.set_source('re_python_pysrc', None)
ffi.emit_python_code(str(tmpdir.join('re_python_pysrc.py')))
@@ -96,6 +99,11 @@
return fix_path
""")
+ cls.w_dl_libpath = space.w_None
+ if sys.platform != 'win32':
+ import ctypes.util
+ cls.w_dl_libpath = space.wrap(ctypes.util.find_library('dl'))
+
def teardown_method(self, meth):
self.space.appexec([], """():
import sys
@@ -244,3 +252,22 @@
self.fix_path()
from re_python_pysrc import ffi
ffi.new("selfref_ptr_t")
+
+ def test_dlopen_handle(self):
+ import _cffi_backend, sys
+ self.fix_path()
+ from re_python_pysrc import ffi
+ if self.dl_libpath is None:
+ py.test.skip("uses 'dl' explicitly")
+ lib1 = ffi.dlopen(self.dl_libpath)
+ handle = lib1.dlopen(self.extmod.encode(sys.getfilesystemencoding()),
+ _cffi_backend.RTLD_LAZY)
+ assert ffi.typeof(handle) == ffi.typeof("void *")
+ assert handle
+
+ lib = ffi.dlopen(handle)
+ assert lib.add42(-10) == 32
+ assert type(lib.add42) is _cffi_backend.FFI.CData
+
+ err = lib1.dlclose(handle)
+ assert err == 0
diff --git a/pypy/module/_cffi_backend/test/test_recompiler.py b/pypy/module/_cffi_backend/test/test_recompiler.py
--- a/pypy/module/_cffi_backend/test/test_recompiler.py
+++ b/pypy/module/_cffi_backend/test/test_recompiler.py
@@ -343,9 +343,9 @@
'test_verify_exact_field_offset',
"""struct foo_s { short a; int b; };""")
e = raises(ffi.error, ffi.new, "struct foo_s *", []) # lazily
- assert str(e.value) == ("struct foo_s: wrong offset for field 'b' (cdef "
- 'says 0, but C compiler says 4). fix it or use "...;" '
- "in the cdef for struct foo_s to make it flexible")
+ assert str(e.value).startswith(
+ "struct foo_s: wrong offset for field 'b' (cdef "
+ 'says 0, but C compiler says 4). fix it or use "...;" ')
def test_type_caching(self):
ffi1, lib1 = self.prepare(
More information about the pypy-commit
mailing list