Author: Armin Rigo <[email protected]>
Branch: cffi-1.0
Changeset: r2003:4ce7f03d4fc9
Date: 2015-05-16 10:19 +0200
http://bitbucket.org/cffi/cffi/changeset/4ce7f03d4fc9/
Log: Various tweaks until we get some more-or-less complete dlopen()
support
diff --git a/c/cffi1_module.c b/c/cffi1_module.c
--- a/c/cffi1_module.c
+++ b/c/cffi1_module.c
@@ -176,7 +176,7 @@
if (make_included_tuples(module_name, ctx->includes,
&ffi->types_builder.included_ffis,
- &lib->l_includes) < 0)
+ &lib->l_types_builder->included_libs) < 0)
return NULL;
return m;
diff --git a/c/ffi_obj.c b/c/ffi_obj.c
--- a/c/ffi_obj.c
+++ b/c/ffi_obj.c
@@ -73,6 +73,7 @@
{
Py_VISIT(ffi->types_builder.types_dict);
Py_VISIT(ffi->types_builder.included_ffis);
+ Py_VISIT(ffi->types_builder.included_libs);
Py_VISIT(ffi->gc_wrefs);
return 0;
}
@@ -86,6 +87,53 @@
/* forward, declared in cdlopen.c because it's mostly useful for this case */
static int ffiobj_init(PyObject *self, PyObject *args, PyObject *kwds);
+static PyObject *ffi_fetch_int_constant(FFIObject *ffi, char *name,
+ int recursion)
+{
+ int index;
+
+ index = search_in_globals(&ffi->types_builder.ctx, name, strlen(name));
+ if (index >= 0) {
+ const struct _cffi_global_s *g;
+ g = &ffi->types_builder.ctx.globals[index];
+
+ switch (_CFFI_GETOP(g->type_op)) {
+ case _CFFI_OP_CONSTANT_INT:
+ case _CFFI_OP_ENUM:
+ return realize_global_int(&ffi->types_builder, index);
+
+ default:
+ PyErr_Format(FFIError,
+ "function, global variable or non-integer constant "
+ "'%.200s' must be fetched from their original 'lib' "
+ "object", name);
+ return NULL;
+ }
+ }
+
+ if (ffi->types_builder.included_ffis != NULL) {
+ Py_ssize_t i;
+ PyObject *included_ffis = ffi->types_builder.included_ffis;
+
+ if (recursion > 100) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "recursion overflow in ffi.include() delegations");
+ return NULL;
+ }
+
+ for (i = 0; i < PyTuple_GET_SIZE(included_ffis); i++) {
+ FFIObject *ffi1;
+ PyObject *x;
+
+ ffi1 = (FFIObject *)PyTuple_GET_ITEM(included_ffis, i);
+ x = ffi_fetch_int_constant(ffi1, name, recursion + 1);
+ if (x != NULL || PyErr_Occurred())
+ return x;
+ }
+ }
+ return NULL; /* no exception set, means "not found" */
+}
+
#define ACCEPT_STRING 1
#define ACCEPT_CTYPE 2
#define ACCEPT_CDATA 4
@@ -697,6 +745,30 @@
static PyObject *ffi_dlopen(PyObject *self, PyObject *args); /* forward */
static PyObject *ffi_dlclose(PyObject *self, PyObject *args); /* forward */
+PyDoc_STRVAR(ffi_int_const_doc,
+"Get the value of an integer constant.\n"
+"\n"
+"'ffi.integer_const(\"xxx\")' is equivalent to 'lib.xxx' if xxx names an\n"
+"integer constant. The point of this function is limited to use cases\n"
+"where you have an 'ffi' object but not any associated 'lib' object.");
+
+static PyObject *ffi_int_const(FFIObject *self, PyObject *args, PyObject *kwds)
+{
+ char *name;
+ PyObject *x;
+ static char *keywords[] = {"name", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", keywords, &name))
+ return NULL;
+
+ x = ffi_fetch_int_constant(self, name, 0);
+
+ if (x == NULL && !PyErr_Occurred()) {
+ PyErr_Format(PyExc_AttributeError,
+ "integer constant '%.200s' not found", name);
+ }
+ return x;
+}
#define METH_VKW (METH_VARARGS | METH_KEYWORDS)
static PyMethodDef ffi_methods[] = {
@@ -714,6 +786,7 @@
#ifdef MS_WIN32
{"getwinerror",(PyCFunction)ffi_getwinerror,METH_VARARGS,
ffi_getwinerror_doc},
#endif
+ {"integer_const",(PyCFunction)ffi_int_const,METH_VKW, ffi_int_const_doc},
{"new", (PyCFunction)ffi_new, METH_VKW, ffi_new_doc},
{"new_handle", (PyCFunction)ffi_new_handle, METH_O, ffi_new_handle_doc},
{"offsetof", (PyCFunction)ffi_offsetof, METH_VARARGS, ffi_offsetof_doc},
diff --git a/c/lib_obj.c b/c/lib_obj.c
--- a/c/lib_obj.c
+++ b/c/lib_obj.c
@@ -23,7 +23,6 @@
builder_c_t *l_types_builder; /* same as the one on the ffi object */
PyObject *l_dict; /* content, built lazily */
PyObject *l_libname; /* some string that gives the name of the lib
*/
- PyObject *l_includes; /* tuple of LibObjects included here */
FFIObject *l_ffi; /* reference back to the ffi object */
void *l_libhandle; /* the dlopen()ed handle, if any */
};
@@ -80,7 +79,6 @@
cdlopen_close_ignore_errors(lib->l_libhandle);
Py_DECREF(lib->l_dict);
Py_DECREF(lib->l_libname);
- Py_XDECREF(lib->l_includes);
Py_DECREF(lib->l_ffi);
PyObject_Del(lib);
}
@@ -89,7 +87,6 @@
{
Py_VISIT(lib->l_dict);
Py_VISIT(lib->l_libname);
- Py_VISIT(lib->l_includes);
Py_VISIT(lib->l_ffi);
return 0;
}
@@ -159,15 +156,18 @@
int index;
const struct _cffi_global_s *g;
CTypeDescrObject *ct;
+ builder_c_t *types_builder = lib->l_types_builder;
char *s = PyText_AsUTF8(name);
if (s == NULL)
return NULL;
- index = search_in_globals(&lib->l_types_builder->ctx, s, strlen(s));
+ index = search_in_globals(&types_builder->ctx, s, strlen(s));
if (index < 0) {
- if (lib->l_includes != NULL) {
+ if (types_builder->included_libs != NULL) {
Py_ssize_t i;
+ PyObject *included_ffis = types_builder->included_ffis;
+ PyObject *included_libs = types_builder->included_libs;
if (recursion > 100) {
PyErr_SetString(PyExc_RuntimeError,
@@ -175,18 +175,31 @@
return NULL;
}
- for (i = 0; i < PyTuple_GET_SIZE(lib->l_includes); i++) {
+ for (i = 0; i < PyTuple_GET_SIZE(included_libs); i++) {
LibObject *lib1;
- lib1 = (LibObject *)PyTuple_GET_ITEM(lib->l_includes, i);
- x = PyDict_GetItem(lib1->l_dict, name);
- if (x != NULL) {
- Py_INCREF(x);
- goto found;
+
+ lib1 = (LibObject *)PyTuple_GET_ITEM(included_libs, i);
+ if (lib1 != NULL) {
+ x = PyDict_GetItem(lib1->l_dict, name);
+ if (x != NULL) {
+ Py_INCREF(x);
+ goto found;
+ }
+ x = lib_build_and_cache_attr(lib1, name, recursion + 1);
+ if (x != NULL) {
+ Py_INCREF(x);
+ goto found;
+ }
}
- x = lib_build_and_cache_attr(lib1, name, recursion + 1);
- if (x != NULL) {
- Py_INCREF(x);
- goto found;
+ else {
+ FFIObject *ffi1;
+
+ ffi1 = (FFIObject *)PyTuple_GetItem(included_ffis, i);
+ if (ffi1 == NULL)
+ return NULL;
+ x = ffi_fetch_int_constant(ffi1, s, recursion + 1);
+ if (x != NULL)
+ goto found;
}
if (PyErr_Occurred())
return NULL;
@@ -203,7 +216,7 @@
return NULL;
}
- g = &lib->l_types_builder->ctx.globals[index];
+ g = &types_builder->ctx.globals[index];
switch (_CFFI_GETOP(g->type_op)) {
@@ -224,7 +237,7 @@
{
/* a constant integer whose value, in an "unsigned long long",
is obtained by calling the function at g->address */
- x = realize_global_int(lib->l_types_builder, index);
+ x = realize_global_int(types_builder, index);
break;
}
@@ -232,8 +245,7 @@
{
/* a constant which is not of integer type */
char *data;
- ct = realize_c_type(lib->l_types_builder,
- lib->l_types_builder->ctx.types,
+ ct = realize_c_type(types_builder, types_builder->ctx.types,
_CFFI_GETARG(g->type_op));
if (ct == NULL)
return NULL;
@@ -248,8 +260,7 @@
case _CFFI_OP_GLOBAL_VAR:
/* global variable of the exact type specified here */
- ct = realize_c_type(lib->l_types_builder,
- lib->l_types_builder->ctx.types,
+ ct = realize_c_type(types_builder, types_builder->ctx.types,
_CFFI_GETARG(g->type_op));
if (ct == NULL)
return NULL;
@@ -281,8 +292,8 @@
if (address == NULL)
return NULL;
- ct1 = realize_c_type_or_func(lib->l_types_builder,
- lib->l_types_builder->ctx.types,
+ ct1 = realize_c_type_or_func(types_builder,
+ types_builder->ctx.types,
_CFFI_GETARG(g->type_op));
if (ct1 == NULL)
return NULL;
@@ -438,7 +449,6 @@
lib->l_types_builder = &ffi->types_builder;
lib->l_dict = dict;
lib->l_libname = libname;
- lib->l_includes = NULL;
Py_INCREF(ffi);
lib->l_ffi = ffi;
lib->l_libhandle = dlopen_libhandle;
diff --git a/c/realize_c_type.c b/c/realize_c_type.c
--- a/c/realize_c_type.c
+++ b/c/realize_c_type.c
@@ -3,6 +3,7 @@
struct _cffi_type_context_s ctx; /* inlined substructure */
PyObject *types_dict;
PyObject *included_ffis;
+ PyObject *included_libs;
PyObject *_keepalive1;
PyObject *_keepalive2;
} builder_c_t;
@@ -71,6 +72,7 @@
}
}
Py_XDECREF(builder->included_ffis);
+ Py_XDECREF(builder->included_libs);
Py_XDECREF(builder->types_dict);
Py_XDECREF(builder->_keepalive1);
Py_XDECREF(builder->_keepalive2);
@@ -90,6 +92,7 @@
builder->types_dict = ldict;
builder->included_ffis = NULL;
+ builder->included_libs = NULL;
builder->_keepalive1 = NULL;
builder->_keepalive2 = NULL;
return 0;
diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -494,6 +494,10 @@
raise ValueError("set_source() must be called before"
" distutils_extension()")
source, kwds = self._assigned_source
+ if source is None:
+ raise TypeError("distutils_extension() is only for C extension "
+ "modules, not for dlopen()-style pure Python "
+ "modules")
mkpath(tmpdir)
ext, updated = recompile(self, self._recompiler_module_name,
source, tmpdir=tmpdir,
@@ -511,6 +515,21 @@
if not hasattr(self, '_assigned_source'):
raise ValueError("set_source() must be called before
emit_c_code()")
source, kwds = self._assigned_source
+ if source is None:
+ raise TypeError("emit_c_code() is only for C extension modules, "
+ "not for dlopen()-style pure Python modules")
+ recompile(self, self._recompiler_module_name, source,
+ c_file=filename, call_c_compiler=False, **kwds)
+
+ def emit_python_code(self, filename):
+ from .recompiler import recompile
+ #
+ if not hasattr(self, '_assigned_source'):
+ raise ValueError("set_source() must be called before
emit_c_code()")
+ source, kwds = self._assigned_source
+ if source is not None:
+ raise TypeError("emit_python_code() is only for dlopen()-style "
+ "pure Python modules, not for C extension modules")
recompile(self, self._recompiler_module_name, source,
c_file=filename, call_c_compiler=False, **kwds)
diff --git a/cffi/recompiler.py b/cffi/recompiler.py
--- a/cffi/recompiler.py
+++ b/cffi/recompiler.py
@@ -783,10 +783,7 @@
self._lsts["field"].extend(c_fields)
#
if cname is None: # unknown name, for _add_missing_struct_unions
- #size_align = (' (size_t)-2, -2, /* unnamed */\n' +
- # ' _cffi_FIELDS_FOR_%s, %d },' % (approxname,
- # len(enumfields),))
- size = -2
+ size = '(size_t)-2'
align = -2
comment = "unnamed"
else:
@@ -796,11 +793,6 @@
else:
size = 'sizeof(%s)' % (cname,)
align = 'offsetof(struct _cffi_align_%s, y)' %
(approxname,)
- #size_align = ('\n' +
- # ' %s,\n' % (size,) +
- # ' %s,\n' % (align,) +
- # ' _cffi_FIELDS_FOR_%s, %d },' % (approxname,
- # len(enumfields),))
comment = None
else:
size = '(size_t)-1'
@@ -1107,15 +1099,24 @@
module_name = module_name.encode('ascii')
if ffi._windows_unicode:
ffi._apply_windows_unicode(kwds)
- if c_file is None:
- c_file = os.path.join(tmpdir, module_name + '.c')
- ext = _get_extension(module_name, c_file, kwds)
- updated = make_c_source(ffi, module_name, preamble, c_file)
- if call_c_compiler:
- outputfilename = ffiplatform.compile(tmpdir, ext)
- return outputfilename
+ if preamble is not None:
+ if c_file is None:
+ c_file = os.path.join(tmpdir, module_name + '.c')
+ ext = _get_extension(module_name, c_file, kwds)
+ updated = make_c_source(ffi, module_name, preamble, c_file)
+ if call_c_compiler:
+ outputfilename = ffiplatform.compile(tmpdir, ext)
+ return outputfilename
+ else:
+ return ext, updated
else:
- return ext, updated
+ if c_file is None:
+ c_file = os.path.join(tmpdir, module_name + '.py')
+ updated = make_py_source(ffi, module_name, c_file)
+ if call_c_compiler:
+ return c_file
+ else:
+ return None, updated
def _verify(ffi, module_name, preamble, *args, **kwds):
# FOR TESTS ONLY
diff --git a/testing/cffi1/test_re_python.py b/testing/cffi1/test_re_python.py
new file mode 100644
--- /dev/null
+++ b/testing/cffi1/test_re_python.py
@@ -0,0 +1,38 @@
+import sys
+from cffi import FFI
+from cffi import recompiler, ffiplatform
+from testing.udir import udir
+
+
+def setup_module(mod):
+ SRC = """
+ #define FOOBAR (-42)
+ int add42(int x) { return x + 42; }
+ """
+ tmpdir = udir.join('test_re_python')
+ tmpdir.ensure(dir=1)
+ c_file = tmpdir.join('_test_re_python.c')
+ c_file.write(SRC)
+ ext = ffiplatform.get_extension(str(c_file), '_test_re_python')
+ outputfilename = ffiplatform.compile(str(tmpdir), ext)
+ mod.extmod = outputfilename
+ #
+ ffi = FFI()
+ ffi.cdef("""
+ #define FOOBAR -42
+ int add42(int);
+ """)
+ ffi.set_source('re_python_pysrc', None)
+ ffi.emit_python_code(str(tmpdir.join('re_python_pysrc.py')))
+ #
+ sys.path.insert(0, str(tmpdir))
+
+
+def test_constant():
+ from re_python_pysrc import ffi
+ assert ffi.integer_const('FOOBAR') == -42
+
+def test_function():
+ from re_python_pysrc import ffi
+ lib = ffi.dlopen(extmod)
+ assert lib.add42(-10) == 32
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit