[pypy-commit] cffi cffi-1.0: ffi.dlclose(). Global variables.
arigo
noreply at buildbot.pypy.org
Sat May 16 14:25:26 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r2014:f077a8aeded1
Date: 2015-05-16 14:26 +0200
http://bitbucket.org/cffi/cffi/changeset/f077a8aeded1/
Log: ffi.dlclose(). Global variables.
diff --git a/c/cdlopen.c b/c/cdlopen.c
--- a/c/cdlopen.c
+++ b/c/cdlopen.c
@@ -73,23 +73,27 @@
static PyObject *ffi_dlclose(PyObject *self, PyObject *args)
{
LibObject *lib;
+ void *libhandle;
if (!PyArg_ParseTuple(args, "O!", &Lib_Type, &lib))
return NULL;
- if (lib->l_libhandle == NULL) {
+ libhandle = lib->l_libhandle;
+ lib->l_libhandle = NULL;
+
+ if (libhandle == NULL) {
PyErr_Format(FFIError, "library '%s' is already closed "
"or was not created with ffi.dlopen()",
- PyText_AS_UTF8(lib->l_libhandle));
+ PyText_AS_UTF8(lib->l_libname));
return NULL;
}
- if (cdlopen_close(lib->l_libname, lib->l_libhandle) < 0)
- return NULL;
-
/* Clear the dict to force further accesses to do cdlopen_fetch()
again, and fail because the library was closed. */
PyDict_Clear(lib->l_dict);
+ if (cdlopen_close(lib->l_libname, libhandle) < 0)
+ return NULL;
+
Py_INCREF(Py_None);
return Py_None;
}
diff --git a/c/lib_obj.c b/c/lib_obj.c
--- a/c/lib_obj.c
+++ b/c/lib_obj.c
@@ -139,6 +139,7 @@
return NULL;
}
memset((char *)xfunc, 0, sizeof(struct CPyExtFunc_s));
+ assert(g->address);
xfunc->md.ml_meth = (PyCFunction)g->address;
xfunc->md.ml_flags = flags;
xfunc->md.ml_name = g->name;
@@ -250,6 +251,7 @@
if (ct == NULL)
return NULL;
+ assert(g->address);
assert(ct->ct_size > 0);
data = alloca(ct->ct_size);
((void(*)(char*))g->address)(data);
@@ -272,20 +274,22 @@
x = NULL;
}
else {
- x = make_global_var(ct, g->address);
+ void *address = g->address;
+ if (address == NULL) {
+ /* for dlopen() style */
+ address = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s);
+ }
+ x = make_global_var(ct, address);
}
Py_DECREF(ct);
break;
- case _CFFI_OP_DLOPEN:
+ case _CFFI_OP_DLOPEN_FUNC:
{
- /* For dlopen(): the function or global variable of the given
- 'name'. We use dlsym() to get the address of something in
- the dynamic library, which we interpret as being exactly of
- the specified type. If this type is a function (not a
- function pointer), then we assume it is a regular function
- in the dynamic library; otherwise, we assume it is a global
- variable.
+ /* For dlopen(): the function of the given 'name'. We use
+ dlsym() to get the address of something in the dynamic
+ library, which we interpret as being exactly a function of
+ the specified type.
*/
PyObject *ct1;
void *address = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s);
@@ -298,10 +302,8 @@
if (ct1 == NULL)
return NULL;
- if (CTypeDescr_Check(ct1))
- x = make_global_var((CTypeDescrObject *)ct1, address);
- else
- x = new_simple_cdata(address, unwrap_fn_as_fnptr(ct1));
+ assert(!CTypeDescr_Check(ct1)); /* must be a function */
+ x = new_simple_cdata(address, unwrap_fn_as_fnptr(ct1));
Py_DECREF(ct1);
break;
diff --git a/cffi/cffi_opcode.py b/cffi/cffi_opcode.py
--- a/cffi/cffi_opcode.py
+++ b/cffi/cffi_opcode.py
@@ -51,7 +51,7 @@
OP_CONSTANT = 29
OP_CONSTANT_INT = 31
OP_GLOBAL_VAR = 33
-OP_DLOPEN = 35
+OP_DLOPEN_FUNC = 35
PRIM_VOID = 0
PRIM_BOOL = 1
diff --git a/cffi/parse_c_type.h b/cffi/parse_c_type.h
--- a/cffi/parse_c_type.h
+++ b/cffi/parse_c_type.h
@@ -24,7 +24,7 @@
#define _CFFI_OP_CONSTANT 29
#define _CFFI_OP_CONSTANT_INT 31
#define _CFFI_OP_GLOBAL_VAR 33
-#define _CFFI_OP_DLOPEN 35
+#define _CFFI_OP_DLOPEN_FUNC 35
#define _CFFI_PRIM_VOID 0
#define _CFFI_PRIM_BOOL 1
diff --git a/cffi/recompiler.py b/cffi/recompiler.py
--- a/cffi/recompiler.py
+++ b/cffi/recompiler.py
@@ -706,7 +706,7 @@
type_index = self._typesdict[tp.as_raw_function()]
numargs = len(tp.args)
if self.target_is_python:
- meth_kind = OP_DLOPEN
+ meth_kind = OP_DLOPEN_FUNC
elif numargs == 0:
meth_kind = OP_CPYTHON_BLTN_N # 'METH_NOARGS'
elif numargs == 1:
diff --git a/testing/cffi1/test_dlopen.py b/testing/cffi1/test_dlopen.py
--- a/testing/cffi1/test_dlopen.py
+++ b/testing/cffi1/test_dlopen.py
@@ -1,5 +1,5 @@
import py
-from cffi import FFI, VerificationError
+from cffi import FFI, VerificationError, CDefError
from cffi.recompiler import make_py_source
from testing.udir import udir
@@ -29,6 +29,23 @@
"the value of constant 'BB' (only integer constants are "
"supported, and only if their value are specified in the cdef)")
+def test_invalid_global_constant_2():
+ ffi = FFI()
+ ffi.cdef("static const float BB = 12;")
+ target = udir.join('test_invalid_global_constants_2.py')
+ e = py.test.raises(VerificationError, make_py_source, ffi,
+ 'test_invalid_global_constants_2', str(target))
+ assert str(e.value) == (
+ "ffi.dlopen() will not be able to figure out "
+ "the value of constant 'BB' (only integer constants are "
+ "supported, and only if their value are specified in the cdef)")
+
+def test_invalid_global_constant_3():
+ ffi = FFI()
+ e = py.test.raises(CDefError, ffi.cdef, "#define BB 12.34")
+ assert str(e.value).startswith(
+ "only supports one of the following syntax:")
+
def test_invalid_dotdotdot_in_macro():
ffi = FFI()
ffi.cdef("#define FOO ...")
@@ -176,3 +193,17 @@
target = udir.join('test_array_overflow.py')
py.test.raises(OverflowError, make_py_source,
ffi, 'test_array_overflow', str(target))
+
+def test_global_var():
+ ffi = FFI()
+ ffi.cdef("int myglob;")
+ target = udir.join('test_global_var.py')
+ assert make_py_source(ffi, 'test_global_var', str(target))
+ assert target.read() == r"""# auto-generated file
+import _cffi_backend
+
+ffi = _cffi_backend.FFI(b'test_global_var',
+ _types = b'\x00\x00\x07\x01',
+ _globals = (b'\x00\x00\x00\x21myglob',0,),
+)
+"""
diff --git a/testing/cffi1/test_re_python.py b/testing/cffi1/test_re_python.py
--- a/testing/cffi1/test_re_python.py
+++ b/testing/cffi1/test_re_python.py
@@ -12,6 +12,7 @@
#define BIGPOS 420000000000L
#define BIGNEG -420000000000L
int add42(int x) { return x + 42; }
+ int globalvar42 = 1234;
struct foo_s;
typedef struct bar_s { int x; signed char a[]; } bar_t;
enum foo_e { AA, BB, CC };
@@ -32,6 +33,7 @@
#define BIGPOS 420000000000L
#define BIGNEG -420000000000L
int add42(int);
+ int globalvar42;
struct foo_s;
typedef struct bar_s { int x; signed char a[]; } bar_t;
enum foo_e { AA, BB, CC };
@@ -54,9 +56,21 @@
assert ffi.integer_const('BIGNEG') == -420000000000
def test_function():
+ import _cffi_backend
from re_python_pysrc import ffi
lib = ffi.dlopen(extmod)
assert lib.add42(-10) == 32
+ assert type(lib.add42) is _cffi_backend.FFI.CData
+
+def test_dlclose():
+ import _cffi_backend
+ from re_python_pysrc import ffi
+ lib = ffi.dlopen(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,))
def test_constant_via_lib():
from re_python_pysrc import ffi
@@ -103,3 +117,13 @@
#
p = ffi.new("bar_t *", [5, "foobar"])
assert p.a[4] == ord('a')
+
+def test_global_var():
+ from re_python_pysrc import ffi
+ lib = ffi.dlopen(extmod)
+ assert lib.globalvar42 == 1234
+ p = ffi.addressof(lib, 'globalvar42')
+ lib.globalvar42 += 5
+ assert p[0] == 1239
+ p[0] -= 1
+ assert lib.globalvar42 == 1238
More information about the pypy-commit
mailing list