[pypy-commit] creflect default: another reorganization, split more the ffi and the lib

arigo noreply at buildbot.pypy.org
Mon Dec 1 22:14:28 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r137:111c65f6cc20
Date: 2014-12-01 21:40 +0100
http://bitbucket.org/cffi/creflect/changeset/111c65f6cc20/

Log:	another reorganization, split more the ffi and the lib

diff --git a/zeffir/zef_builder.c b/zeffir/builder.c
rename from zeffir/zef_builder.c
rename to zeffir/builder.c
--- a/zeffir/zef_builder.c
+++ b/zeffir/builder.c
@@ -5,11 +5,36 @@
 typedef struct {
     _crx_builder_t cb;
     ZefLibObject *lib;
+    PyObject *l_dict;
     ZefFFIObject *ffi;
-    PyObject *l_dict;
+    PyObject *types_dict;
 } zeffir_builder_t;
 
-static PyObject *zef_cache_primitive_signed;
+static CTypeDescrObject *get_cached_type(_crx_builder_t *cb, const char *name,
+                                         int accept_flags)
+{
+    PyObject *types_dict = ((zeffir_builder_t *)cb)->types_dict;
+    PyObject *x = PyDict_GetItemString(types_dict, name);
+    CTypeDescrObject *ct;
+
+    if (x == NULL || !CTypeDescr_Check(x))
+        return NULL;
+    ct = (CTypeDescrObject *)x;
+    if ((ct->ct_flags & accept_flags) == 0)
+        return NULL;
+    return ct;
+}
+
+static _crx_type_t *put_cached_type(_crx_builder_t *cb, const char *name,
+                                    CTypeDescrObject *ct)
+{
+    PyObject *types_dict = ((zeffir_builder_t *)cb)->types_dict;
+    int err = PyDict_SetItemString(types_dict, name, (PyObject *)ct);
+    Py_DECREF(ct);
+    if (err < 0)
+        return NULL;
+    return ct;    /* still a reference in the dict */
+}
 
 static _crx_type_t *zef_get_void_type(_crx_builder_t *cb)
 {
@@ -29,33 +54,26 @@
 static _crx_type_t *zef_get_signed_type(_crx_builder_t *cb, size_t sz,
                                         const char *name)
 {
-    PyObject *x = PyDict_GetItemString(zef_cache_primitive_signed, name);
-    CTypeDescrObject *td = (CTypeDescrObject *)x;
+    CTypeDescrObject *td = get_cached_type(cb, name, CT_PRIMITIVE_SIGNED);
+    if (td != NULL && td->ct_size == sz)
+        return td;
 
-    if (td == NULL) {
-        int err;
-        size_t name_length = strlen(name);
+    size_t name_length = strlen(name);
 
-        td = ctypedescr_new(name_length + 1);
-        if (td == NULL)
-            return NULL;
+    td = ctypedescr_new(name_length + 1);
+    if (td == NULL)
+        return NULL;
 
-        memcpy(td->ct_name, name, name_length + 1);
-        td->ct_name_position = name_length;
-        td->ct_size = sz;
-        //td->ct_length = ptypes->align;
-        //td->ct_extra = ffitype;
-        td->ct_flags = CT_PRIMITIVE_SIGNED;
-        if (td->ct_size <= sizeof(long))
-            td->ct_flags |= CT_PRIMITIVE_FITS_LONG;
+    memcpy(td->ct_name, name, name_length + 1);
+    td->ct_name_position = name_length;
+    td->ct_size = sz;
+    //td->ct_length = ptypes->align;
+    //td->ct_extra = ffitype;
+    td->ct_flags = CT_PRIMITIVE_SIGNED;
+    if (td->ct_size <= sizeof(long))
+        td->ct_flags |= CT_PRIMITIVE_FITS_LONG;
 
-        x = (PyObject *)td;
-        err = PyDict_SetItemString(zef_cache_primitive_signed, name, x);
-        Py_DECREF(x);
-        if (err < 0)
-            return NULL;
-    }
-    return td;
+    return put_cached_type(cb, name, td);
 }
 
 static _crx_type_t *zef_get_unsigned_type(_crx_builder_t *cb, size_t sz,
@@ -158,10 +176,11 @@
                             _crx_trampoline0_fn trampl, void *directcall)
 {
     PyObject *l_dict = ((zeffir_builder_t *)cb)->l_dict;
-    ZefFFIObject *ffi = ((zeffir_builder_t *)cb)->ffi;
+    PyObject *l_libname_obj = ((zeffir_builder_t *)cb)->lib->l_libname_obj;
 
     assert(trampl != NULL);
-    PyObject *x = make_builtin_func(ffi, name, ret, args, nargs, trampl);
+    PyObject *x = make_builtin_func(l_libname_obj, name, ret,
+                                    args, nargs, trampl);
     if (x == NULL)
         return;
 
@@ -189,27 +208,27 @@
     abort();
 }
 
-static int load_creflect_main(ZefLibObject *lib)
+static int load_creflect_main(ZefFFIObject *ffi, ZefLibObject *lib)
 {
     const char *creflect_main = "_creflect_main";   /* XXX fixed for now */
     int (*crxmain)(_crx_builder_t *);
-    crxmain = (int(*)(_crx_builder_t *))dlsym(lib->ffi->f_dl_lib,
-                                              creflect_main);
+
+    crxmain = (int(*)(_crx_builder_t *))dlsym(lib->l_dl_lib, creflect_main);
     if (crxmain == NULL) {
         PyErr_Format(PyExc_OSError, "%s: symbol '%s' not found",
-                     lib->ffi->f_libname, creflect_main);
+                     lib->l_libname, creflect_main);
         return -1;
     }
 
     int result = crxmain(NULL);
     if ((result & ~0xFF) != MAGIC_CREFLECT_TAG) {
         PyErr_Format(PyExc_OSError, "%s: %s() is not a creflect entry point",
-                     lib->ffi->f_libname, creflect_main);
+                     lib->l_libname, creflect_main);
         return -1;
     }
     if ((result & 0xFF) != CREFLECT_VERSION) {
         PyErr_Format(PyExc_OSError, "%s was made with creflect version %d, "
-                     "expected %d", lib->ffi->f_libname, result & 0xFF,
+                     "expected %d", lib->l_libname, result & 0xFF,
                      CREFLECT_VERSION);
         return -1;
     }
@@ -240,17 +259,12 @@
             zef_define_num_const,
             zef_error,
         },
-        lib,          /* lib */
-        lib->ffi,     /* ffi */
-        lib->l_dict,  /* l_dict */
+        lib,              /* lib */
+        lib->l_dict,      /* l_dict */
+        ffi,              /* ffi */
+        ffi->types_dict,  /* types_dict */
     };
     crxmain(&builder.cb);
 
     return PyErr_Occurred() ? -1 : 0;
 }
-
-static void init_caches(void)
-{
-    if ((zef_cache_primitive_signed = PyDict_New()) == NULL)
-        return;
-}
diff --git a/zeffir/zef_cdata.c b/zeffir/cdata.c
rename from zeffir/zef_cdata.c
rename to zeffir/cdata.c
diff --git a/zeffir/zef_cfunc.c b/zeffir/cfunc.c
rename from zeffir/zef_cfunc.c
rename to zeffir/cfunc.c
--- a/zeffir/zef_cfunc.c
+++ b/zeffir/cfunc.c
@@ -2,7 +2,6 @@
 typedef struct {
     PyObject_HEAD
 
-    ZefFFIObject       *zfs_ffi;
     int                 zfs_nargs;
     _crx_trampoline0_fn zfs_trampl;
     PyMethodDef         zfs_md;
@@ -12,13 +11,12 @@
 
 static void zef_builtin_support_dealloc(ZefFuncSupportObject *zfs)
 {
-    Py_DECREF(zfs->zfs_ffi);
     PyObject_Del(zfs);
 }
 
 static PyTypeObject ZefFuncSupport_Type = {
     PyVarObject_HEAD_INIT(NULL, 0)
-    "zeffir.BuiltinSupport",
+    "zeffir.FuncSupport",
     sizeof(ZefFuncSupportObject),
     0,
     (destructor)zef_builtin_support_dealloc,    /* tp_dealloc */
@@ -67,8 +65,8 @@
     return PyInt_FromLong(lloutput);
 }
 
-static PyObject *make_builtin_func(ZefFFIObject *ffi, const char *funcname,
-                                   _crx_type_t *ret,
+static PyObject *make_builtin_func(PyObject *libname_obj,
+                                   const char *funcname, _crx_type_t *ret,
                                    _crx_qual_type args[], int nargs,
                                    _crx_trampoline0_fn trampl)
 {
@@ -78,8 +76,6 @@
         return PyErr_NoMemory();
     PyObject_Init((PyObject *)zfs, &ZefFuncSupport_Type);
 
-    Py_INCREF(ffi);
-    zfs->zfs_ffi = ffi;
     zfs->zfs_nargs = nargs;
     zfs->zfs_trampl = trampl;
 
@@ -90,7 +86,7 @@
     /*zfs->zfs_md.ml_doc = ... */
 
     PyObject *res = PyCFunction_NewEx(&zfs->zfs_md, (PyObject *)zfs,
-                                      ffi->f_libname_obj);
+                                      libname_obj);
     Py_DECREF(zfs);
     return res;
 }
diff --git a/zeffir/zef_ctype.c b/zeffir/ctype.c
rename from zeffir/zef_ctype.c
rename to zeffir/ctype.c
diff --git a/zeffir/zef_ffi_obj.c b/zeffir/ffi_obj.c
rename from zeffir/zef_ffi_obj.c
rename to zeffir/ffi_obj.c
--- a/zeffir/zef_ffi_obj.c
+++ b/zeffir/ffi_obj.c
@@ -1,24 +1,125 @@
+
+/* An FFI object has methods like ffi.new().  It is also a container for the
+   type declarations (typedefs and structs) that you can use, say in ffi.new().
+   They are in a dictionary available in the 'types' attribute, which you
+   can edit manually (e.g. 'ffi.types.update(ffi2.types)').
+
+   The method ffi.load_library() finds a creflect dynamic library, load
+   its type declarations into ffi.types, and returns a Lib object with
+   the functions, global variables and constants as attributes.  Once the
+   Lib object goes out of scope (or ffi.close_library() is called), the
+   library is unloaded; accessing functions or global variables afterwards
+   will segfault.
+
+   There is no direct internal reference between the FFI and the Lib object.
+*/
 
 struct ZefFFIObject_s {
     PyObject_HEAD
-    void *f_dl_lib;      /* keep the library returned by 'dlopen()' */
-    char *f_libname;     /* the original argument to 'dlopen()' */
-    PyObject *f_libname_obj;   /* same, as a PyObject */
+    PyObject *types_dict;
 };
 
 static void ffi_dealloc(ZefFFIObject *ffi)
 {
-    if (ffi->f_dl_lib != NULL)
-        dlclose(ffi->f_dl_lib);
-    Py_DECREF(ffi->f_libname_obj);
-    PyObject_Del(ffi);
+    PyObject_GC_UnTrack(ffi);
+    Py_DECREF(ffi->types_dict);
+    PyObject_GC_Del(ffi);
 }
 
-static PyObject *ffi_repr(ZefFFIObject *ffi)
+static int ffi_traverse(ZefFFIObject *ffi, visitproc visit, void *arg)
 {
-    return PyString_FromFormat("<zeffir.FFI object for '%s'>", ffi->f_libname);
+    Py_VISIT(ffi->types_dict);
+    return 0;
 }
 
+static PyObject *ffiobj_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    char *keywords[] = {NULL};
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "", keywords))
+        return NULL;
+
+    PyObject *dict = PyDict_New();
+    if (dict == NULL)
+        return NULL;
+
+    ZefFFIObject *ffi = PyObject_GC_New(ZefFFIObject, &ZefFFI_Type);
+    if (ffi == NULL) {
+        Py_DECREF(dict);
+        return NULL;
+    }
+    ffi->types_dict = dict;
+    PyObject_GC_Track(ffi);
+
+    return (PyObject *)ffi;
+}
+
+static PyObject *ffi_load_library(ZefFFIObject *self, PyObject *args,
+                                  PyObject *kwds)
+{
+    char *keywords[] = {"libname", "relative_to", NULL};
+    char *libname, *relative_to = NULL;
+    char *relative_dir;
+    PyObject *path;
+    ZefLibObject *lib;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|z", keywords,
+                                     &libname, &relative_to))
+        return NULL;
+
+    if (relative_to == NULL) {
+        relative_dir = strdup("");
+    }
+    else {
+        char *last_slash = strrchr(relative_to, '/');
+        if (last_slash == NULL)
+            relative_dir = strdup("./");
+        else
+            relative_dir = strndup(relative_to, last_slash + 1 - relative_to);
+    }
+    if (relative_dir == NULL)
+        return PyErr_NoMemory();
+
+    path = PyString_FromFormat("%slib%s.so", relative_dir, libname);
+    free(relative_dir);
+    if (path == NULL)
+        return NULL;
+
+    lib = lib_create(path);
+    Py_DECREF(path);
+
+    if (load_creflect_main(self, lib) < 0) {
+        Py_DECREF(lib);
+        return NULL;
+    }
+    return (PyObject *)lib;
+}
+
+static PyObject *ffi_close_library(PyObject *no_self, PyObject *args)
+{
+    ZefLibObject *lib;
+
+    if (!PyArg_ParseTuple(args, "O!", &lib, &ZefLib_Type))
+        return NULL;
+
+    if (lib_close(lib) < 0)
+        return NULL;
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyMethodDef ffi_methods[] = {
+    {"load_library",   (PyCFunction)ffi_load_library,
+                                           METH_VARARGS | METH_KEYWORDS},
+    {"close_library",  ffi_close_library,  METH_VARARGS | METH_STATIC},
+    {NULL}
+};
+
+static PyMemberDef ffi_members[] = {
+    {"types", T_OBJECT, offsetof(ZefFFIObject, types_dict), READONLY},
+    {NULL}
+};
+
 static PyTypeObject ZefFFI_Type = {
     PyVarObject_HEAD_INIT(NULL, 0)
     "zeffir.FFI",
@@ -29,7 +130,7 @@
     0,                                          /* tp_getattr */
     0,                                          /* tp_setattr */
     0,                                          /* tp_compare */
-    (reprfunc)ffi_repr,                         /* tp_repr */
+    0,                                          /* tp_repr */
     0,                                          /* tp_as_number */
     0,                                          /* tp_as_sequence */
     0,                                          /* tp_as_mapping */
@@ -39,14 +140,24 @@
     PyObject_GenericGetAttr,                    /* tp_getattro */
     0,                                          /* tp_setattro */
     0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT,                         /* tp_flags */
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
     0,                                          /* tp_doc */
-    0,                                          /* tp_traverse */
+    (traverseproc)ffi_traverse,                 /* tp_traverse */
     0,                                          /* tp_clear */
     0,                                          /* tp_richcompare */
     0,                                          /* tp_weaklistoffset */
     0,                                          /* tp_iter */
     0,                                          /* tp_iternext */
-    0,                                          /* tp_methods */
-    0,                                          /* tp_members */
+    ffi_methods,                                /* tp_methods */
+    ffi_members,                                /* tp_members */
+    0,                                          /* tp_getset */
+    0,                                          /* tp_base */
+    0,                                          /* tp_dict */
+    0,                                          /* tp_descr_get */
+    0,                                          /* tp_descr_set */
+    0,                                          /* tp_dictoffset */
+    0,                                          /* tp_init */
+    0,                                          /* tp_alloc */
+    ffiobj_new,                                 /* tp_new */
+    PyObject_GC_Del,                            /* tp_free */
 };
diff --git a/zeffir/zef_lib_obj.c b/zeffir/lib_obj.c
rename from zeffir/zef_lib_obj.c
rename to zeffir/lib_obj.c
--- a/zeffir/zef_lib_obj.c
+++ b/zeffir/lib_obj.c
@@ -1,21 +1,47 @@
+
+/* A Lib object is special in the sense that it has a custom __getattr__
+   which only returns objects from the internal, inaccessible 'l_dict'.
+   (It raises AttributeError for anything else, like '__class__'.)
+*/
 
 struct ZefLibObject_s {
     PyObject_HEAD
-    PyObject *l_dict;
-    ZefFFIObject *ffi;
+    PyObject *l_dict;         /* functions, global variables and constants */
+    void *l_dl_lib;           /* keep the library returned by 'dlopen()' */
+    char *l_libname;          /* the original argument to 'dlopen()' */
+    PyObject *l_libname_obj;  /* same, as a PyObject */
 };
 
 static void lib_dealloc(ZefLibObject *lib)
 {
-    Py_DECREF(lib->l_dict);
-    Py_DECREF(lib->ffi);
+    (void)lib_close(lib);
     PyObject_Del(lib);
 }
 
 static PyObject *lib_repr(ZefLibObject *lib)
 {
-    return PyString_FromFormat("<zeffir.Lib object for '%s'>",
-                               lib->ffi->f_libname);
+    return PyString_FromFormat("<zeffir.Lib object for '%.200s'%s>",
+                               lib->l_libname,
+                               lib->l_dl_lib == NULL ? " (closed)" : "");
+}
+
+static PyObject *lib_getattr(ZefLibObject *lib, PyObject *name)
+{
+    if (lib->l_dict == NULL) {
+        PyErr_Format(PyExc_ValueError, "lib '%.200s' was closed",
+                     lib->l_libname);
+        return NULL;
+    }
+
+    PyObject *x = PyDict_GetItem(lib->l_dict, name);
+    if (x == NULL) {
+        PyErr_Format(PyExc_AttributeError,
+                     "lib '%.200s' has no function,"
+                     " global variable or constant '%.200s'",
+                     lib->l_libname,
+                     PyString_Check(name) ? PyString_AS_STRING(name) : "?");
+    }
+    return x;
 }
 
 static PyObject *lib_dir(PyObject *lib, PyObject *noarg)
@@ -28,11 +54,6 @@
     {NULL,        NULL}           /* sentinel */
 };
 
-static PyMemberDef lib_members[] = {
-    {"__dict__", T_OBJECT, offsetof(ZefLibObject, l_dict), READONLY},
-    {NULL}
-};
-
 static PyTypeObject ZefLib_Type = {
     PyVarObject_HEAD_INIT(NULL, 0)
     "zeffir.Lib",
@@ -50,7 +71,7 @@
     0,                                          /* tp_hash */
     0,                                          /* tp_call */
     0,                                          /* tp_str */
-    PyObject_GenericGetAttr,                    /* tp_getattro */
+    (getattrofunc)lib_getattr,                  /* tp_getattro */
     0,                                          /* tp_setattro */
     0,                                          /* tp_as_buffer */
     Py_TPFLAGS_DEFAULT,                         /* tp_flags */
@@ -62,7 +83,7 @@
     0,                                          /* tp_iter */
     0,                                          /* tp_iternext */
     lib_methods,                                /* tp_methods */
-    lib_members,                                /* tp_members */
+    0,                                          /* tp_members */
     0,                                          /* tp_getset */
     0,                                          /* tp_base */
     0,                                          /* tp_dict */
@@ -70,3 +91,54 @@
     0,                                          /* tp_descr_set */
     offsetof(ZefLibObject, l_dict),              /* tp_dictoffset */
 };
+
+static void lib_dlerror(ZefLibObject *lib)
+{
+    char *error = dlerror();
+    if (error == NULL)
+        error = "(no error reported)";
+    PyErr_Format(PyExc_OSError, "%s: %s", lib->l_libname, error);
+}
+
+static ZefLibObject *lib_create(PyObject *path)
+{
+    ZefLibObject *lib;
+
+    lib = PyObject_New(ZefLibObject, &ZefLib_Type);
+    if (lib == NULL)
+        return NULL;
+
+    lib->l_dl_lib = NULL;
+    lib->l_libname = PyString_AS_STRING(path);
+    Py_INCREF(path);
+    lib->l_libname_obj = path;
+    lib->l_dict = PyDict_New();
+    if (lib->l_dict == NULL) {
+        Py_DECREF(lib);
+        return NULL;
+    }
+
+    lib->l_dl_lib = dlopen(lib->l_libname, RTLD_LAZY);
+    if (lib->l_dl_lib == NULL) {
+        lib_dlerror(lib);
+        Py_DECREF(lib);
+        return NULL;
+    }
+    return lib;
+}
+
+static int lib_close(ZefLibObject *lib)
+{
+    void *dl_lib;
+    Py_CLEAR(lib->l_dict);
+
+    dl_lib = lib->l_dl_lib;
+    if (dl_lib != NULL) {
+        lib->l_dl_lib = NULL;
+        if (dlclose(dl_lib) != 0) {
+            lib_dlerror(lib);
+            return -1;
+        }
+    }
+    return 0;
+}
diff --git a/zeffir/test/support.py b/zeffir/test/support.py
--- a/zeffir/test/support.py
+++ b/zeffir/test/support.py
@@ -11,9 +11,8 @@
     if err:
         raise OSError("%r\n==> error code %s" % (cmd, err))
 
-def compile_and_open(modname):
-    """Process with creflect 'modname.crx', compile the result, and load it."""
 
+def new_ffi():
     if not os.path.exists(zeffir_lib_path):
         run("cd '%s' && "
             "gcc -g -I'%s' -Wall -Werror -fPIC -shared zeffir.c -o '%s'" %
@@ -24,6 +23,13 @@
     import zeffir
     del sys.path[0]
 
+    return zeffir.FFI()
+
+
+def compile_and_open(modname):
+    """Process with creflect 'modname.crx', compile the result, and load it."""
+
+    ffi = new_ffi()
     mod_c_path = str(udir.join('%s.c' % modname))
     mod_lib_path = str(udir.join('lib%s.so' % modname))
     if not os.path.exists(mod_lib_path):
@@ -33,4 +39,5 @@
             (zeffir_dir, modname, mod_c_path, mod_c_path, mod_lib_path))
         assert os.path.exists(mod_lib_path)
 
-    return zeffir.open(modname, relative_to=zeffir_lib_path)
+    lib = ffi.load_library(modname, relative_to=zeffir_lib_path)
+    return ffi, lib
diff --git a/zeffir/test/test_basic.py b/zeffir/test/test_basic.py
--- a/zeffir/test/test_basic.py
+++ b/zeffir/test/test_basic.py
@@ -1,3 +1,4 @@
+import py
 import os
 import support
 
@@ -6,7 +7,7 @@
     ffi, lib = support.compile_and_open('basic')
     assert type(ffi).__module__ == 'zeffir'
     assert type(ffi).__name__ == 'FFI'
-    assert repr(ffi) == "<zeffir.FFI object for '%s/libbasic.so'>" % (
+    assert repr(lib) == "<zeffir.Lib object for '%s/libbasic.so'>" % (
         os.path.dirname(support.zeffir_lib_path),)
 
 def test_forty_two():
@@ -17,3 +18,7 @@
 def test_dir():
     ffi, lib = support.compile_and_open('basic')
     assert dir(lib) == ['forty_two']
+
+def test_no_special_attribute():
+    ffi, lib = support.compile_and_open('basic')
+    py.test.raises(AttributeError, getattr, lib, '__class__')
diff --git a/zeffir/zeffir.c b/zeffir/zeffir.c
--- a/zeffir/zeffir.c
+++ b/zeffir/zeffir.c
@@ -5,98 +5,21 @@
 #include "../creflect/creflect_cdecl.h"
 
 
-typedef struct _crx_type_s CTypeDescrObject;
-typedef struct ZefLibObject_s ZefLibObject;
-typedef struct ZefFFIObject_s ZefFFIObject;
-
-
 /************************************************************/
 /* Works by including all other .c files.                   */
 /* Allows all function and global symbols to remain static. */
 
-#include "zef_ctype.c"
-#include "zef_cdata.c"
-#include "zef_ffi_obj.c"
-#include "zef_lib_obj.c"
-#include "zef_cfunc.c"
-#include "zef_builder.c"
+#include "zeffir.h"
+#include "ctype.c"
+#include "cdata.c"
+#include "lib_obj.c"
+#include "ffi_obj.c"
+#include "cfunc.c"
+#include "builder.c"
 
 /************************************************************/
 
-
-static PyObject *z_open(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    char *keywords[] = {"libname", "relative_to", NULL};
-    char *libname, *relative_to, *relative_dir;
-    PyObject *path;
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", keywords,
-                                     &libname, &relative_to))
-        return NULL;
-
-    char *last_slash = strrchr(relative_to, '/');
-    if (last_slash == NULL)
-        relative_dir = strdup(".");
-    else
-        relative_dir = strndup(relative_to, last_slash - relative_to);
-    if (relative_dir == NULL)
-        return PyErr_NoMemory();
-
-    path = PyString_FromFormat("%s/lib%s.so", relative_dir, libname);
-    free(relative_dir);
-    if (path == NULL)
-        return NULL;
-
-    ZefFFIObject *ffi = NULL;
-    ZefLibObject *lib = NULL;
-    PyObject *dict = NULL;
-
-    dlerror();   /* clear errors */
-    void *dl_lib = dlopen(PyString_AS_STRING(path), RTLD_LAZY);
-    if (dl_lib == NULL) {
-        char *error = dlerror();
-        if (error == NULL)
-            error = "failed to open";
-        PyErr_Format(PyExc_OSError, "%s: %s", PyString_AS_STRING(path), error);
-        goto error;
-    }
-
-    ffi = PyObject_New(ZefFFIObject, &ZefFFI_Type);
-    if (ffi == NULL)
-        goto error;
-    ffi->f_dl_lib = dl_lib;     dl_lib = NULL;
-    ffi->f_libname = PyString_AS_STRING(path);
-    ffi->f_libname_obj = path;  path = NULL;
-
-    dict = PyDict_New();
-    if (dict == NULL)
-        goto error;
-
-    lib = PyObject_New(ZefLibObject, &ZefLib_Type);
-    if (lib == NULL)
-        goto error;
-    lib->ffi = ffi;      ffi = NULL;
-    lib->l_dict = dict;  dict = NULL;
-
-    if (load_creflect_main(lib) < 0)
-        goto error;
-
-    PyObject *result = Py_BuildValue("OO", lib->ffi, lib);
-    Py_DECREF(lib);
-    return result;
-
- error:
-    Py_XDECREF(dict);
-    Py_XDECREF(lib);
-    Py_XDECREF(ffi);
-    if (dl_lib != NULL)
-        dlclose(dl_lib);
-    Py_XDECREF(path);
-    return NULL;
-}
-
 static PyMethodDef ZeffirMethods[] = {
-    {"open",   (PyCFunction)z_open, METH_KEYWORDS},
     {NULL,     NULL}    /* Sentinel */
 };
 
@@ -106,10 +29,7 @@
     PyObject *m;
 
     m = Py_InitModule("zeffir", ZeffirMethods);
-    (void)m;
-
-    init_caches();
-    if (PyErr_Occurred())
+    if (m == NULL)
         return;
 
     if (PyType_Ready(&ZefFFI_Type) < 0)
@@ -120,4 +40,7 @@
         return;
     if (PyType_Ready(&ZefFuncSupport_Type) < 0)
         return;
+
+    if (PyModule_AddObject(m, "FFI", (PyObject *)&ZefFFI_Type) < 0)
+        return;
 }
diff --git a/zeffir/zeffir.h b/zeffir/zeffir.h
new file mode 100644
--- /dev/null
+++ b/zeffir/zeffir.h
@@ -0,0 +1,9 @@
+
+typedef struct _crx_type_s CTypeDescrObject;
+typedef struct ZefLibObject_s ZefLibObject;
+typedef struct ZefFFIObject_s ZefFFIObject;
+
+static PyTypeObject ZefFFI_Type;
+
+static int lib_close(ZefLibObject *);
+static int load_creflect_main(ZefFFIObject *, ZefLibObject *);


More information about the pypy-commit mailing list