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