[pypy-commit] cffi cffi-1.0: Just enough to pass this small demo

arigo noreply at buildbot.pypy.org
Mon May 11 17:24:08 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1975:dbbbc44e0a15
Date: 2015-05-11 17:24 +0200
http://bitbucket.org/cffi/cffi/changeset/dbbbc44e0a15/

Log:	Just enough to pass this small demo

diff --git a/_cffi1/cdlopen.c b/_cffi1/cdlopen.c
--- a/_cffi1/cdlopen.c
+++ b/_cffi1/cdlopen.c
@@ -20,6 +20,12 @@
     return address;
 }
 
+static void cdlopen_close_ignore_errors(void *libhandle)
+{
+    if (libhandle != NULL)
+        dlclose(libhandle);
+}
+
 static int cdlopen_close(PyObject *libname, void *libhandle)
 {
     if (libhandle != NULL && dlclose(libhandle) != 0) {
@@ -31,7 +37,38 @@
     return 0;
 }
 
+static PyObject *ffi_dlopen(PyObject *self, PyObject *args)
+{
+    char *filename_or_null, *printable_filename;
+    void *handle;
+    int flags = 0;
 
+    if (PyTuple_GET_SIZE(args) == 0 || PyTuple_GET_ITEM(args, 0) == Py_None) {
+        PyObject *dummy;
+        if (!PyArg_ParseTuple(args, "|Oi:load_library",
+                              &dummy, &flags))
+            return NULL;
+        filename_or_null = NULL;
+    }
+    else if (!PyArg_ParseTuple(args, "et|i:load_library",
+                          Py_FileSystemDefaultEncoding, &filename_or_null,
+                          &flags))
+        return NULL;
+
+    if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0)
+        flags |= RTLD_NOW;
+    printable_filename = filename_or_null ? filename_or_null : "<None>";
+
+    handle = dlopen(filename_or_null, flags);
+    if (handle == NULL) {
+        const char *error = dlerror();
+        PyErr_Format(PyExc_OSError, "cannot load library '%s': %s",
+                     printable_filename, error);
+        return NULL;
+    }
+    return (PyObject *)lib_internal_new((FFIObject *)self,
+                                        printable_filename, handle);
+}
 
 static PyObject *ffi_dlclose(PyObject *self, PyObject *args)
 {
@@ -56,3 +93,101 @@
     Py_INCREF(Py_None);
     return Py_None;
 }
+
+
+static int cdl_int(char *src)
+{
+    unsigned char *usrc = (unsigned char *)src;
+    return (usrc[0] << 24) | (usrc[1] << 16) | (usrc[2] << 8) | usrc[3];
+}
+
+static _cffi_opcode_t cdl_opcode(char *src)
+{
+    return (_cffi_opcode_t)(Py_ssize_t)cdl_int(src);
+}
+
+static int ffiobj_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    FFIObject *ffi;
+    static char *keywords[] = {"module_name", "_version", "_types",
+                               "_globals", "_struct_unions", "_enums",
+                               "_typenames", "_consts", NULL};
+    char *ffiname = NULL, *types = NULL, *building = NULL;
+    Py_ssize_t version = -1;
+    Py_ssize_t types_len = 0;
+    PyObject *globals = NULL, *struct_unions = NULL, *enums = NULL;
+    PyObject *typenames = NULL, *consts = NULL;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sns#O!OOOO:FFI", keywords,
+                                     &ffiname, &version, &types, &types_len,
+                                     &PyTuple_Type, &globals,
+                                     &struct_unions, &enums,
+                                     &typenames, &consts))
+        return -1;
+
+    ffi = (FFIObject *)self;
+    if (ffi->ctx_is_nonempty) {
+        PyErr_SetString(PyExc_ValueError,
+                        "cannot call FFI.__init__() more than once");
+        return -1;
+    }
+    ffi->ctx_is_nonempty = 1;
+
+    if (types_len > 0) {
+        _cffi_opcode_t *ntypes;
+        Py_ssize_t i, n = types_len / 4;    /* 4 bytes entries */
+
+        building = PyMem_Malloc(n * sizeof(_cffi_opcode_t));
+        if (building == NULL)
+            goto error;
+        ntypes = (_cffi_opcode_t *)building;
+
+        for (i = 0; i < n; i++) {
+            ntypes[i] = cdl_opcode(types);
+            types += 4;
+        }
+        ffi->types_builder.ctx.types = ntypes;
+        building = NULL;
+    }
+
+    if (globals != NULL) {
+        struct _cffi_global_s *nglob;
+        Py_ssize_t i, n = PyTuple_GET_SIZE(globals);
+
+        building = PyMem_Malloc(n * sizeof(struct _cffi_global_s));
+        if (building == NULL)
+            goto error;
+        memset(building, 0, n * sizeof(struct _cffi_global_s));
+        nglob = (struct _cffi_global_s *)building;
+
+        for (i = 0; i < n; i++) {
+            char *g = PyString_AS_STRING(PyTuple_GET_ITEM(globals, i));
+            nglob[i].type_op = cdl_opcode(g);
+            nglob[i].name = g + 4;
+        }
+        ffi->types_builder.ctx.globals = nglob;
+        ffi->types_builder.ctx.num_globals = n;
+        building = NULL;
+    }
+
+    if (consts != NULL) {
+        Py_INCREF(consts);
+        ffi->types_builder.known_constants = consts;
+    }
+
+    /* Above, we took directly some "char *" strings out of the strings,
+       typically from somewhere inside tuples.  Keep them alive by
+       incref'ing the whole input arguments. */
+    Py_INCREF(args);
+    Py_XINCREF(kwds);
+    ffi->types_builder._keepalive1 = args;
+    ffi->types_builder._keepalive2 = kwds;
+    return 0;
+
+ error:
+    if (building != NULL)
+        PyMem_Free(building);
+    if (!PyErr_Occurred())
+        PyErr_NoMemory();
+    return -1;
+}
diff --git a/_cffi1/ffi_obj.c b/_cffi1/ffi_obj.c
--- a/_cffi1/ffi_obj.c
+++ b/_cffi1/ffi_obj.c
@@ -83,35 +83,8 @@
     return (PyObject *)ffi_internal_new(type, NULL);
 }
 
-static int ffiobj_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    FFIObject *ffi;
-    static char *keywords[] = {"module_name", "_version", "_types",
-                               "_globals", "_struct_unions", "_enums",
-                               "_typenames", "_consts", NULL};
-    char *ffiname = NULL, *types = NULL;
-    Py_ssize_t version = -1;
-    Py_ssize_t types_len = 0;
-    PyObject *globals = NULL, *struct_unions = NULL, *enums = NULL;
-    PyObject *typenames = NULL, *consts = NULL;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sns#OOOOO:FFI", keywords,
-                                     &ffiname, &version, &types, &types_len,
-                                     &globals, &struct_unions, &enums,
-                                     &typenames, &consts))
-        return -1;
-
-    ffi = (FFIObject *)self;
-    if (ffi->ctx_is_nonempty) {
-        PyErr_SetString(PyExc_ValueError,
-                        "cannot call FFI.__init__() more than once");
-        return -1;
-    }
-
-    //...;
-    ffi->ctx_is_nonempty = 1;
-    return 0;
-}
+/* forward, declared in cdlopen.c because it's mostly useful for this case */
+static int ffiobj_init(PyObject *self, PyObject *args, PyObject *kwds);
 
 #define ACCEPT_STRING   1
 #define ACCEPT_CTYPE    2
diff --git a/_cffi1/lib_obj.c b/_cffi1/lib_obj.c
--- a/_cffi1/lib_obj.c
+++ b/_cffi1/lib_obj.c
@@ -72,15 +72,12 @@
     return result;
 }
 
-static int cdlopen_close(PyObject *libname, void *libhandle);  /* forward */
+static void cdlopen_close_ignore_errors(void *libhandle);  /* forward */
 static void *cdlopen_fetch(PyObject *libname, void *libhandle, char *symbol);
 
 static void lib_dealloc(LibObject *lib)
 {
-    if (cdlopen_close(lib->l_libname, lib->l_libhandle) < 0) {
-        PyErr_WriteUnraisable((PyObject *)lib);
-        PyErr_Clear();
-    }
+    cdlopen_close_ignore_errors(lib->l_libhandle);
     Py_DECREF(lib->l_dict);
     Py_DECREF(lib->l_libname);
     Py_XDECREF(lib->l_includes);
@@ -208,8 +205,8 @@
             return NULL;  /* no error set, continue looking elsewhere */
 
         PyErr_Format(PyExc_AttributeError,
-                     "cffi lib '%.200s' has no function,"
-                     " global variable or constant named '%.200s'",
+                     "cffi library '%.200s' has no function, constant "
+                     "or global variable named '%.200s'",
                      PyText_AS_UTF8(lib->l_libname), s);
         return NULL;
     }
@@ -435,16 +432,16 @@
     PyObject *libname, *dict;
 
     libname = PyText_FromString(module_name);
+    if (libname == NULL)
+        goto err1;
+
     dict = PyDict_New();
-    if (libname == NULL || dict == NULL) {
-        Py_XDECREF(dict);
-        Py_XDECREF(libname);
-        return NULL;
-    }
+    if (dict == NULL)
+        goto err2;
 
     lib = PyObject_New(LibObject, &Lib_Type);
     if (lib == NULL)
-        return NULL;
+        goto err3;
 
     lib->l_types_builder = &ffi->types_builder;
     lib->l_dict = dict;
@@ -454,6 +451,14 @@
     lib->l_ffi = ffi;
     lib->l_libhandle = dlopen_libhandle;
     return lib;
+
+ err3:
+    Py_DECREF(dict);
+ err2:
+    Py_DECREF(libname);
+ err1:
+    cdlopen_close_ignore_errors(dlopen_libhandle);
+    return NULL;
 }
 
 static PyObject *address_of_global_var(PyObject *args)
diff --git a/_cffi1/manual2.py b/_cffi1/manual2.py
new file mode 100644
--- /dev/null
+++ b/_cffi1/manual2.py
@@ -0,0 +1,19 @@
+import _cffi_backend
+
+ffi = _cffi_backend.FFI(b"manual2",
+    _version = 0x2600,
+    _types = b'\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x00\x09\x00\x00\x00\x0B',
+    _globals = (b'\x00\x00\x00#close',),
+    _struct_unions = ((b'\x00\x00\x00\x03\x00\x00\x00\x00point_s',b'\x00\x00\x01\x11x',b'\x00\x00\x01\x11y'),),
+    _enums = (b'\x00\x00\x00\x04\x00\x00\x00\x01myenum_e\x00AA,BB,CC',),
+    _typenames = (b'\x00\x00\x00\x01myint_t',),
+    _consts = {'AA':0,'BB':1,'CC':2},
+)
+
+
+
+# trying it out
+lib = ffi.dlopen(None)
+assert lib.BB == 1
+x = lib.close(-42)
+assert x == -1
diff --git a/_cffi1/realize_c_type.c b/_cffi1/realize_c_type.c
--- a/_cffi1/realize_c_type.c
+++ b/_cffi1/realize_c_type.c
@@ -4,6 +4,8 @@
     PyObject *types_dict;
     PyObject *included_ffis;
     PyObject *known_constants;
+    PyObject *_keepalive1;
+    PyObject *_keepalive2;
 } builder_c_t;
 
 
@@ -72,6 +74,8 @@
     Py_XDECREF(builder->included_ffis);
     Py_XDECREF(builder->types_dict);
     Py_XDECREF(builder->known_constants);
+    Py_XDECREF(builder->_keepalive1);
+    Py_XDECREF(builder->_keepalive2);
 }
 
 static int init_builder_c(builder_c_t *builder,
@@ -89,6 +93,8 @@
     builder->types_dict = ldict;
     builder->included_ffis = NULL;
     builder->known_constants = NULL;
+    builder->_keepalive1 = NULL;
+    builder->_keepalive2 = NULL;
     return 0;
 }
 


More information about the pypy-commit mailing list