[pypy-commit] creflect default: correct call argument types

arigo noreply at buildbot.pypy.org
Fri Dec 5 15:48:23 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r161:081d71b47603
Date: 2014-12-05 15:43 +0100
http://bitbucket.org/cffi/creflect/changeset/081d71b47603/

Log:	correct call argument types

diff --git a/zeffir/cfunc.c b/zeffir/cfunc.c
--- a/zeffir/cfunc.c
+++ b/zeffir/cfunc.c
@@ -5,12 +5,19 @@
     int                 zfs_nargs;
     _crx_trampoline0_fn zfs_trampl;
     PyMethodDef         zfs_md;
-    char                zfs_funcname[1];
+    size_t              zfs_size_args;
+    CTypeDescrObject   *zfs_ret;
+    CTypeDescrObject   *zfs_args[1];
 
 } ZefFuncSupportObject;
 
 static void zef_func_support_dealloc(ZefFuncSupportObject *zfs)
 {
+    int i;
+    for (i = zfs->zfs_nargs - 1; i >= 0; i--)
+        Py_DECREF(zfs->zfs_args[i]);
+    Py_DECREF(zfs->zfs_ret);
+
     PyObject_Del(zfs);
 }
 
@@ -37,33 +44,42 @@
     Py_TPFLAGS_DEFAULT,                         /* tp_flags */
 };
 
+#define ROUND_UP(n)   (((n) + 7) & ~7)
+
 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 */
+    char *llbuffer;
+    size_t lloffset;
 
     actualnargs = PyTuple_Size(args);
     if (actualnargs != nargs) {
         if (!PyErr_Occurred())
             PyErr_Format(PyExc_TypeError,
                          "'%s()' expected %d arguments, but got %zd",
-                         zfs->zfs_funcname, nargs, actualnargs);
+                         zfs->zfs_md.ml_name, nargs, actualnargs);
         return NULL;
     }
 
+    llbuffer = alloca(zfs->zfs_size_args);
+    lloffset = zfs->zfs_ret->ct_size;
+
     for (i = 0; i < nargs; i++) {
-        llinput[i] = PyInt_AsLong(PyTuple_GET_ITEM(args, i));
-        if (PyErr_Occurred())
+        CTypeDescrObject *ct = zfs->zfs_args[i];
+        PyObject *x = PyTuple_GET_ITEM(args, i);
+        lloffset = ROUND_UP(lloffset);
+        llargs[i] = llbuffer + lloffset;
+        if (convert_from_object(llbuffer + lloffset, ct, x) < 0)
             return NULL;
-        llargs[i] = &llinput[i];
+        lloffset += ct->ct_size;
     }
 
-    zfs->zfs_trampl(llargs, &lloutput);
+    zfs->zfs_trampl(llargs, llbuffer);
 
-    return PyInt_FromLong(lloutput);
+    return convert_to_object(llbuffer, zfs->zfs_ret);
 }
 
 static PyObject *make_builtin_func(PyObject *libname_obj,
@@ -71,7 +87,11 @@
                                    _crx_qual_type args[], int nargs,
                                    _crx_trampoline0_fn trampl)
 {
-    size_t size = sizeof(ZefFuncSupportObject) + strlen(funcname);
+    int i;
+    char *p;
+    size_t size = (sizeof(ZefFuncSupportObject)
+                   + (nargs - 1) * sizeof(CTypeDescrObject *)
+                   + strlen(funcname) + 1);
     ZefFuncSupportObject *zfs = (ZefFuncSupportObject *)PyObject_Malloc(size);
     if (zfs == NULL)
         return PyErr_NoMemory();
@@ -79,9 +99,26 @@
 
     zfs->zfs_nargs = nargs;
     zfs->zfs_trampl = trampl;
+    zfs->zfs_ret = ret;
+    Py_INCREF(ret);
+
+    assert(ret->ct_size >= 0);
+    size = ret->ct_size;
+
+    for (i = 0; i < nargs; i++) {
+        CTypeDescrObject *ct = args[i].type;
+        if (ct->ct_flags & CT_ARRAY)
+            ct = (CTypeDescrObject *)ct->ct_stuff;    /* array -> pointer */
+        Py_INCREF(ct);
+        zfs->zfs_args[i] = ct;
+        assert(ct->ct_size >= 0);
+        size = ROUND_UP(size) + ct->ct_size;
+    }
+    zfs->zfs_size_args = size;
+    p = (char *)(zfs->zfs_args + nargs);
 
     memset(&zfs->zfs_md, 0, sizeof(PyMethodDef));
-    zfs->zfs_md.ml_name = strcpy(zfs->zfs_funcname, funcname);
+    zfs->zfs_md.ml_name = strcpy(p, funcname);
     zfs->zfs_md.ml_meth = &zfs_call;
     zfs->zfs_md.ml_flags = METH_VARARGS;
     /*zfs->zfs_md.ml_doc = ... */
diff --git a/zeffir/test/test_function.py b/zeffir/test/test_function.py
--- a/zeffir/test/test_function.py
+++ b/zeffir/test/test_function.py
@@ -9,7 +9,6 @@
     assert res == 43
 
 def test_function_with_pointer_arg():
-    py.test.skip("in-progress")
     ffi, lib = support.compile_and_open('function')
     p = ffi.new("int[]", [30, 2, 10])
     res = lib.add_from_array(p, 3)


More information about the pypy-commit mailing list