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

Reply via email to