[pypy-commit] creflect default: tweak tweak tweak

arigo noreply at buildbot.pypy.org
Sat Nov 29 22:32:49 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r126:80866ed7c824
Date: 2014-11-29 22:33 +0100
http://bitbucket.org/cffi/creflect/changeset/80866ed7c824/

Log:	tweak tweak tweak

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
@@ -2,6 +2,7 @@
 from udir import udir, include_dir
 
 def setup_module(mod):
+    global zeffir, zeffir_lib_path
     zeffir_dir = os.path.join(os.path.dirname(__file__), '..')
     zeffir_lib_path = str(udir.join('zeffir.so'))
     err = os.system("cd '%s' && "
@@ -10,7 +11,6 @@
     assert not err
     #
     sys.path.insert(0, str(udir))
-    global zeffir
     import zeffir
     #
     basic_c_path = str(udir.join('basic.c'))
@@ -20,15 +20,16 @@
             "gcc -g -I../../creflect -fPIC -shared '%s' -o '%s'" %
             (zeffir_dir, basic_c_path, basic_c_path, basic_lib_path))
     assert not err
-    #
-    global ffi, lib
-    ffi, lib = zeffir.open('basic', relative_to=zeffir_lib_path)
 
 
 def test_ffi_type():
+    ffi, lib = zeffir.open('basic', relative_to=zeffir_lib_path)
     assert type(ffi).__module__ == 'zeffir'
     assert type(ffi).__name__ == 'FFI'
+    assert repr(ffi) == "<zeffir.FFI object for '%s/libbasic.so'>" % (
+        os.path.dirname(zeffir_lib_path),)
 
 def test_forty_two():
+    ffi, lib = zeffir.open('basic', relative_to=zeffir_lib_path)
     assert lib.forty_two == 42
     assert type(lib.forty_two) is int
diff --git a/zeffir/zeffir.c b/zeffir/zeffir.c
--- a/zeffir/zeffir.c
+++ b/zeffir/zeffir.c
@@ -1,4 +1,5 @@
 #include <Python.h>
+#include <dlfcn.h>
 #include "../creflect/creflect.h"
 #include "../creflect/creflect_cdecl.h"
 
@@ -7,15 +8,23 @@
 
 typedef struct {
     PyObject_HEAD
+    void *dl_lib;
     char *libname;
 } PyFFIObject;
 
 static void ffi_dealloc(PyFFIObject *ffi)
 {
+    if (ffi->dl_lib != NULL)
+        dlclose(ffi->dl_lib);
     free(ffi->libname);
     PyObject_Del(ffi);
 }
 
+static PyObject *ffi_repr(PyFFIObject *ffi)
+{
+    return PyString_FromFormat("<zeffir.FFI object for '%s'>", ffi->libname);
+}
+
 static PyTypeObject FFI_Type = {
     PyVarObject_HEAD_INIT(NULL, 0)
     "zeffir.FFI",
@@ -26,7 +35,7 @@
     0,                                          /* tp_getattr */
     0,                                          /* tp_setattr */
     0,                                          /* tp_compare */
-    0,                                          /* tp_repr */
+    (reprfunc)ffi_repr,                         /* tp_repr */
     0,                                          /* tp_as_number */
     0,                                          /* tp_as_sequence */
     0,                                          /* tp_as_mapping */
@@ -54,19 +63,51 @@
 {
     char *keywords[] = {"libname", "relative_to", NULL};
     char *libname, *relative_to;
+    char *path;
 
     if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss", keywords,
                                      &libname, &relative_to))
         return NULL;
 
+    char *last_slash = strrchr(relative_to, '/');
+    if (last_slash == NULL) {
+        relative_to = "./";
+        last_slash = relative_to + 1;
+    }
+    size_t n = last_slash + 1 - relative_to;
+    path = malloc(n + strlen(libname) + 16);
+    if (path == NULL)
+        return PyErr_NoMemory();
+    memcpy(path, relative_to, n);
+    strcpy(path + n, "lib");
+    strcat(path + n, libname);
+    strcat(path + n, ".so");
+
+    dlerror();   /* clear errors */
+    void *dl_lib = dlopen(path, RTLD_LAZY);
+    if (dl_lib == NULL) {
+        char *error = dlerror();
+        if (error == NULL)
+            error = "failed to open";
+        PyErr_Format(PyExc_OSError, "%s: %s", path, error);
+        goto error;
+    }
+
     PyFFIObject *ffi = PyObject_New(PyFFIObject, &FFI_Type);
     if (ffi == NULL)
-        return NULL;
-    ffi->libname = strdup(libname);
+        goto error;
+    ffi->dl_lib = dl_lib;
+    ffi->libname = path;
 
     PyObject *result = Py_BuildValue("OO", ffi, Py_None);
     Py_DECREF(ffi);
     return result;
+
+ error:
+    if (dl_lib != NULL)
+        dlclose(dl_lib);
+    free(path);
+    return NULL;
 }
 
 


More information about the pypy-commit mailing list