[pypy-commit] creflect default: in-progress: simple function calls

arigo noreply at buildbot.pypy.org
Mon Dec 1 13:19:13 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r135:083a62ba609e
Date: 2014-12-01 13:19 +0100
http://bitbucket.org/cffi/creflect/changeset/083a62ba609e/

Log:	in-progress: simple function calls

diff --git a/zeffir/test/function.crx b/zeffir/test/function.crx
new file mode 100644
--- /dev/null
+++ b/zeffir/test/function.crx
@@ -0,0 +1,11 @@
+// CREFLECT: start
+
+int simple_function(int);
+
+// CREFLECT: end
+
+
+int simple_function(int x)
+{
+    return x + 1;
+}
diff --git a/zeffir/test/test_function.py b/zeffir/test/test_function.py
new file mode 100644
--- /dev/null
+++ b/zeffir/test/test_function.py
@@ -0,0 +1,8 @@
+import support
+
+
+def test_simple_function():
+    ffi, lib = support.compile_and_open('function')
+    res = lib.simple_function(42)
+    assert type(res) is int
+    assert res == 43
diff --git a/zeffir/zef_builder.c b/zeffir/zef_builder.c
--- a/zeffir/zef_builder.c
+++ b/zeffir/zef_builder.c
@@ -4,9 +4,9 @@
 
 typedef struct {
     _crx_builder_t cb;
-    PyLibObject *lib;
-    PyFFIObject *ffi;
-    PyObject *dict;
+    ZefLibObject *lib;
+    ZefFFIObject *ffi;
+    PyObject *l_dict;
 } zeffir_builder_t;
 
 static PyObject *zef_cache_primitive_signed;
@@ -157,13 +157,22 @@
                             _crx_type_t *ret, _crx_qual_type args[], int nargs,
                             _crx_trampoline0_fn trampl, void *directcall)
 {
-    abort();
+    PyObject *l_dict = ((zeffir_builder_t *)cb)->l_dict;
+    ZefFFIObject *ffi = ((zeffir_builder_t *)cb)->ffi;
+
+    assert(trampl != NULL);
+    PyObject *x = make_builtin_func(ffi, name, ret, args, nargs, trampl);
+    if (x == NULL)
+        return;
+
+    PyDict_SetItemString(l_dict, name, x);
+    Py_DECREF(x);
 }
 
 static void zef_define_num_const(_crx_builder_t *cb, const char *name,
                                  _crx_type_t *ct, _crx_num_const_t *value)
 {
-    PyObject *dict = ((zeffir_builder_t *)cb)->dict;
+    PyObject *l_dict = ((zeffir_builder_t *)cb)->l_dict;
 
     assert(ct->ct_flags & CT_PRIMITIVE_ANY);
 
@@ -171,7 +180,7 @@
     if (x == NULL)
         return;
 
-    PyDict_SetItemString(dict, name, x);
+    PyDict_SetItemString(l_dict, name, x);
     Py_DECREF(x);
 }
 
@@ -180,26 +189,27 @@
     abort();
 }
 
-static int load_creflect_main(PyLibObject *lib)
+static int load_creflect_main(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->dl_lib, creflect_main);
+    crxmain = (int(*)(_crx_builder_t *))dlsym(lib->ffi->f_dl_lib,
+                                              creflect_main);
     if (crxmain == NULL) {
         PyErr_Format(PyExc_OSError, "%s: symbol '%s' not found",
-                     lib->ffi->libname, creflect_main);
+                     lib->ffi->f_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->libname, creflect_main);
+                     lib->ffi->f_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->libname, result & 0xFF,
+                     "expected %d", lib->ffi->f_libname, result & 0xFF,
                      CREFLECT_VERSION);
         return -1;
     }
@@ -230,11 +240,12 @@
             zef_define_num_const,
             zef_error,
         },
-        lib,        /* lib */
-        lib->ffi,   /* ffi */
-        lib->dict,  /* dict */
+        lib,          /* lib */
+        lib->ffi,     /* ffi */
+        lib->l_dict,  /* l_dict */
     };
     crxmain(&builder.cb);
+
     return PyErr_Occurred() ? -1 : 0;
 }
 
diff --git a/zeffir/zef_cdata.c b/zeffir/zef_cdata.c
new file mode 100644
--- /dev/null
+++ b/zeffir/zef_cdata.c
@@ -0,0 +1,1 @@
+
diff --git a/zeffir/zef_cfunc.c b/zeffir/zef_cfunc.c
new file mode 100644
--- /dev/null
+++ b/zeffir/zef_cfunc.c
@@ -0,0 +1,96 @@
+
+typedef struct {
+    PyObject_HEAD
+
+    ZefFFIObject       *zfs_ffi;
+    int                 zfs_nargs;
+    _crx_trampoline0_fn zfs_trampl;
+    PyMethodDef         zfs_md;
+    char                zfs_funcname[1];
+
+} ZefFuncSupportObject;
+
+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",
+    sizeof(ZefFuncSupportObject),
+    0,
+    (destructor)zef_builtin_support_dealloc,    /* tp_dealloc */
+    0,                                          /* tp_print */
+    0,                                          /* tp_getattr */
+    0,                                          /* tp_setattr */
+    0,                                          /* tp_compare */
+    0,                                          /* tp_repr */
+    0,                                          /* tp_as_number */
+    0,                                          /* tp_as_sequence */
+    0,                                          /* tp_as_mapping */
+    0,                                          /* tp_hash */
+    0,                                          /* tp_call */
+    0,                                          /* tp_str */
+    PyObject_GenericGetAttr,                    /* tp_getattro */
+    0,                                          /* tp_setattro */
+    0,                                          /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT,                         /* tp_flags */
+};
+
+static PyObject *zfs_call(PyObject *self, PyObject *args)
+{
+    ZefFuncSupportObject *zfs = (ZefFuncSupportObject *)self;
+    int i, nargs = zfs->zfs_nargs;
+    Py_ssize_t actualnargs;
+    void *llargs[nargs];
+    int llinput[nargs], lloutput;   /* temp */
+
+    actualnargs = PyTuple_Size(args);
+    if (actualnargs != nargs) {
+        if (!PyErr_Occurred())
+            PyErr_Format(PyExc_TypeError, "'%s' expects %d arguments, got %zd",
+                         zfs->zfs_funcname, nargs, actualnargs);
+        return NULL;
+    }
+
+    for (i = 0; i < nargs; i++) {
+        llinput[i] = PyInt_AsLong(PyTuple_GET_ITEM(args, i));
+        if (PyErr_Occurred())
+            return NULL;
+        llargs[i] = &llinput[i];
+    }
+
+    zfs->zfs_trampl(llargs, &lloutput);
+
+    return PyInt_FromLong(lloutput);
+}
+
+static PyObject *make_builtin_func(ZefFFIObject *ffi, const char *funcname,
+                                   _crx_type_t *ret,
+                                   _crx_qual_type args[], int nargs,
+                                   _crx_trampoline0_fn trampl)
+{
+    size_t size = sizeof(ZefFuncSupportObject) + strlen(funcname);
+    ZefFuncSupportObject *zfs = (ZefFuncSupportObject *)PyObject_Malloc(size);
+    if (zfs == NULL)
+        return PyErr_NoMemory();
+    PyObject_Init((PyObject *)zfs, &ZefFuncSupport_Type);
+
+    Py_INCREF(ffi);
+    zfs->zfs_ffi = ffi;
+    zfs->zfs_nargs = nargs;
+    zfs->zfs_trampl = trampl;
+
+    memset(&zfs->zfs_md, 0, sizeof(PyMethodDef));
+    zfs->zfs_md.ml_name = strcpy(zfs->zfs_funcname, funcname);
+    zfs->zfs_md.ml_meth = &zfs_call;
+    zfs->zfs_md.ml_flags = METH_VARARGS;
+    /*zfs->zfs_md.ml_doc = ... */
+
+    PyObject *res = PyCFunction_NewEx(&zfs->zfs_md, (PyObject *)zfs,
+                                      ffi->f_libname_obj);
+    Py_DECREF(zfs);
+    return res;
+}
diff --git a/zeffir/zef_ffi_obj.c b/zeffir/zef_ffi_obj.c
--- a/zeffir/zef_ffi_obj.c
+++ b/zeffir/zef_ffi_obj.c
@@ -1,27 +1,28 @@
 
-struct PyFFIObject_s {
+struct ZefFFIObject_s {
     PyObject_HEAD
-    void *dl_lib;
-    char *libname;
+    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 */
 };
 
-static void ffi_dealloc(PyFFIObject *ffi)
+static void ffi_dealloc(ZefFFIObject *ffi)
 {
-    if (ffi->dl_lib != NULL)
-        dlclose(ffi->dl_lib);
-    free(ffi->libname);
+    if (ffi->f_dl_lib != NULL)
+        dlclose(ffi->f_dl_lib);
+    Py_DECREF(ffi->f_libname_obj);
     PyObject_Del(ffi);
 }
 
-static PyObject *ffi_repr(PyFFIObject *ffi)
+static PyObject *ffi_repr(ZefFFIObject *ffi)
 {
-    return PyString_FromFormat("<zeffir.FFI object for '%s'>", ffi->libname);
+    return PyString_FromFormat("<zeffir.FFI object for '%s'>", ffi->f_libname);
 }
 
-static PyTypeObject FFI_Type = {
+static PyTypeObject ZefFFI_Type = {
     PyVarObject_HEAD_INIT(NULL, 0)
     "zeffir.FFI",
-    sizeof(PyFFIObject),
+    sizeof(ZefFFIObject),
     0,
     (destructor)ffi_dealloc,                    /* tp_dealloc */
     0,                                          /* tp_print */
diff --git a/zeffir/zef_funcs.c b/zeffir/zef_funcs.c
deleted file mode 100644
--- a/zeffir/zef_funcs.c
+++ /dev/null
@@ -1,77 +0,0 @@
-
-static PyObject *b_open(PyObject *self, PyObject *args, PyObject *kwds)
-{
-    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");
-
-    PyFFIObject *ffi = NULL;
-    PyLibObject *lib = NULL;
-    PyObject *dict = NULL;
-
-    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;
-    }
-
-    ffi = PyObject_New(PyFFIObject, &FFI_Type);
-    if (ffi == NULL)
-        goto error;
-    ffi->dl_lib = dl_lib;  dl_lib = NULL;
-    ffi->libname = path;   path = NULL;
-
-    dict = PyDict_New();
-    if (dict == NULL)
-        goto error;
-
-    lib = PyObject_New(PyLibObject, &Lib_Type);
-    if (lib == NULL)
-        goto error;
-    lib->ffi = ffi;    ffi = NULL;
-    lib->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);
-    free(path);
-    return NULL;
-}
-
-
-static PyMethodDef ZeffirMethods[] = {
-    {"open",   (PyCFunction)b_open, METH_KEYWORDS},
-    {NULL,     NULL}    /* Sentinel */
-};
diff --git a/zeffir/zef_lib_obj.c b/zeffir/zef_lib_obj.c
--- a/zeffir/zef_lib_obj.c
+++ b/zeffir/zef_lib_obj.c
@@ -1,26 +1,26 @@
 
-struct PyLibObject_s {
+struct ZefLibObject_s {
     PyObject_HEAD
-    PyObject *dict;
-    PyFFIObject *ffi;
+    PyObject *l_dict;
+    ZefFFIObject *ffi;
 };
 
-static void lib_dealloc(PyLibObject *lib)
+static void lib_dealloc(ZefLibObject *lib)
 {
-    Py_DECREF(lib->dict);
+    Py_DECREF(lib->l_dict);
     Py_DECREF(lib->ffi);
     PyObject_Del(lib);
 }
 
-static PyObject *lib_repr(PyLibObject *lib)
+static PyObject *lib_repr(ZefLibObject *lib)
 {
     return PyString_FromFormat("<zeffir.Lib object for '%s'>",
-                               lib->ffi->libname);
+                               lib->ffi->f_libname);
 }
 
 static PyObject *lib_dir(PyObject *lib, PyObject *noarg)
 {
-    return PyDict_Keys(((PyLibObject *)lib)->dict);
+    return PyDict_Keys(((ZefLibObject *)lib)->l_dict);
 }
 
 static PyMethodDef lib_methods[] = {
@@ -29,14 +29,14 @@
 };
 
 static PyMemberDef lib_members[] = {
-    {"__dict__", T_OBJECT, offsetof(PyLibObject, dict), READONLY},
+    {"__dict__", T_OBJECT, offsetof(ZefLibObject, l_dict), READONLY},
     {NULL}
 };
 
-static PyTypeObject Lib_Type = {
+static PyTypeObject ZefLib_Type = {
     PyVarObject_HEAD_INIT(NULL, 0)
     "zeffir.Lib",
-    sizeof(PyLibObject),
+    sizeof(ZefLibObject),
     0,
     (destructor)lib_dealloc,                    /* tp_dealloc */
     0,                                          /* tp_print */
@@ -68,5 +68,5 @@
     0,                                          /* tp_dict */
     0,                                          /* tp_descr_get */
     0,                                          /* tp_descr_set */
-    offsetof(PyLibObject, dict),                /* tp_dictoffset */
+    offsetof(ZefLibObject, l_dict),              /* tp_dictoffset */
 };
diff --git a/zeffir/zeffir.c b/zeffir/zeffir.c
--- a/zeffir/zeffir.c
+++ b/zeffir/zeffir.c
@@ -6,8 +6,8 @@
 
 
 typedef struct _crx_type_s CTypeDescrObject;
-typedef struct PyLibObject_s PyLibObject;
-typedef struct PyFFIObject_s PyFFIObject;
+typedef struct ZefLibObject_s ZefLibObject;
+typedef struct ZefFFIObject_s ZefFFIObject;
 
 
 /************************************************************/
@@ -15,13 +15,91 @@
 /* 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 "zef_funcs.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 */
+};
+
 PyMODINIT_FUNC
 initzeffir(void)
 {
@@ -34,8 +112,12 @@
     if (PyErr_Occurred())
         return;
 
-    if (PyType_Ready(&FFI_Type) < 0)
+    if (PyType_Ready(&ZefFFI_Type) < 0)
         return;
-    if (PyType_Ready(&Lib_Type) < 0)
+    if (PyType_Ready(&ZefLib_Type) < 0)
+        return;
+    if (PyType_Ready(&CTypeDescr_Type) < 0)
+        return;
+    if (PyType_Ready(&ZefFuncSupport_Type) < 0)
         return;
 }


More information about the pypy-commit mailing list