Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r162:157449ed6904
Date: 2014-12-05 15:48 +0100
http://bitbucket.org/cffi/creflect/changeset/157449ed6904/

Log:    more copying from _cffi_backend

diff --git a/zeffir/cfunc.c b/zeffir/cfunc.c
--- a/zeffir/cfunc.c
+++ b/zeffir/cfunc.c
@@ -46,6 +46,67 @@
 
 #define ROUND_UP(n)   (((n) + 7) & ~7)
 
+static Py_ssize_t _prepare_pointer_call_argument(CTypeDescrObject *ctptr,
+                                                 PyObject *init,
+                                                 char **output_data)
+{
+    /* 'ctptr' is here a pointer type 'ITEM *'.  Accept as argument an
+       initializer for an array 'ITEM[]'.  This includes the case of
+       passing a Python byte string to a 'char *' argument.
+
+       This function returns -1 if an error occurred,
+       0 if conversion succeeded (into *output_data),
+       or N > 0 if conversion would require N bytes of storage.
+    */
+    Py_ssize_t length, datasize;
+    CTypeDescrObject *ctitem;
+
+    if (CData_Check(init))
+        goto convert_default;
+
+    ctitem = ctptr->ct_itemdescr;
+    /* XXX some code duplication, how to avoid it? */
+    if (PyBytes_Check(init)) {
+        /* from a string: just returning the string here is fine.
+           We assume that the C code won't modify the 'char *' data. */
+        if ((ctptr->ct_flags & CT_CAST_ANYTHING) ||
+            ((ctitem->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED))
+             && (ctitem->ct_size == sizeof(char)))) {
+#if defined(CFFI_MEM_DEBUG) || defined(CFFI_MEM_LEAK)
+            length = PyBytes_GET_SIZE(init) + 1;
+#else
+            *output_data = PyBytes_AS_STRING(init);
+            return 0;
+#endif
+        }
+        else
+            goto convert_default;
+    }
+    else if (PyList_Check(init) || PyTuple_Check(init)) {
+        length = PySequence_Fast_GET_SIZE(init);
+    }
+    else {
+        /* refuse to receive just an integer (and interpret it
+           as the array size) */
+        goto convert_default;
+    }
+
+    if (ctitem->ct_size <= 0)
+        goto convert_default;
+    datasize = length * ctitem->ct_size;
+    if ((datasize / ctitem->ct_size) != length) {
+        PyErr_SetString(PyExc_OverflowError,
+                        "array size would overflow a Py_ssize_t");
+        return -1;
+    }
+    if (datasize <= 0)
+        datasize = 1;
+    return datasize;
+
+ convert_default:
+    return convert_from_object((char *)output_data, ctptr, init);
+}
+
 static PyObject *zfs_call(PyObject *self, PyObject *args)
 {
     ZefFuncSupportObject *zfs = (ZefFuncSupportObject *)self;
@@ -69,11 +130,34 @@
 
     for (i = 0; i < nargs; i++) {
         CTypeDescrObject *ct = zfs->zfs_args[i];
-        PyObject *x = PyTuple_GET_ITEM(args, i);
+        PyObject *obj = PyTuple_GET_ITEM(args, i);
+        char *data;
         lloffset = ROUND_UP(lloffset);
-        llargs[i] = llbuffer + lloffset;
-        if (convert_from_object(llbuffer + lloffset, ct, x) < 0)
-            return NULL;
+        data = llbuffer + lloffset;
+        llargs[i] = data;
+
+        if (ct->ct_flags & CT_POINTER) {
+            char *tmpbuf;
+            Py_ssize_t datasize = _prepare_pointer_call_argument(
+                                            ct, obj, (char **)data);
+            if (datasize == 0) {
+                /* successfully filled '*data' */
+            }
+            else if (datasize < 0) {
+                return NULL;
+            }
+            else {
+                tmpbuf = alloca(datasize);
+                memset(tmpbuf, 0, datasize);
+                *(char **)data = tmpbuf;
+                if (convert_array_from_object(tmpbuf, ct, obj) < 0)
+                    return NULL;
+            }
+        }
+        else {
+            if (convert_from_object(data, ct, obj) < 0)
+                return NULL;
+        }
         lloffset += ct->ct_size;
     }
 
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
@@ -16,7 +16,6 @@
     assert res == 42
 
 def test_function_with_array_arg():
-    py.test.skip("in-progress")
     ffi, lib = support.compile_and_open('function')
     res = lib.add_from_array([30, 2, 10], 3)
     assert type(res) is int
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to