[pypy-commit] creflect default: port more from _cffi_backend

arigo noreply at buildbot.pypy.org
Sat Dec 6 20:11:06 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r190:4f6dbe2e4bdc
Date: 2014-12-06 20:11 +0100
http://bitbucket.org/cffi/creflect/changeset/4f6dbe2e4bdc/

Log:	port more from _cffi_backend

diff --git a/zeffir/builder.c b/zeffir/builder.c
--- a/zeffir/builder.c
+++ b/zeffir/builder.c
@@ -224,15 +224,21 @@
 
     ct->ct_size = -1;
     ct->ct_flags = CT_FUNCTION;
+    ct->ct_stuff = make_func_support(ret, args, nargs, dotdotdot, 0);
+    if (ct->ct_stuff == NULL) {
+        Py_DECREF(ct);
+        ct = NULL;
+        goto done;
+    }
 
     put_cached_type(get_types_dict(cb), name_obj, ct);
 
  done:
     Py_DECREF(name_obj);
 
-    if (ct->ct_stuff == NULL && trampl != NULL && !PyErr_Occurred()) {
+    if (!PyErr_Occurred() && trampl != NULL) {
         assert(!dotdotdot);   /* should have 'trampl == NULL' in this case */
-        ct->ct_stuff = make_func_support(ret, args, nargs, trampl, 0);
+        provide_trampoline(ct->ct_stuff, trampl);
     }
     return ct;
 }
diff --git a/zeffir/cdata.c b/zeffir/cdata.c
--- a/zeffir/cdata.c
+++ b/zeffir/cdata.c
@@ -1903,3 +1903,40 @@
                      Py_TYPE(ob)->tp_name, ct->ct_name);
     return NULL;
 }
+
+static PyObject *get_field_name(CTypeDescrObject *ct, CFieldObject *cf)
+{
+    Py_ssize_t i = 0;
+    PyObject *d_key, *d_value;
+    while (PyDict_Next(ct->ct_stuff, &i, &d_key, &d_value)) {
+        if (d_value == (PyObject *)cf)
+            return d_key;
+    }
+    Py_FatalError("_cffi_backend: get_field_name()");
+    return NULL;
+}
+
+static PyObject *cstructtype_getfields(CTypeDescrObject *ct)
+{
+    if (ct->ct_size >= 0) {
+        CFieldObject *cf;
+        PyObject *res = PyList_New(0);
+        if (res == NULL)
+            return NULL;
+        for (cf = ct->ct_fields; cf != NULL; cf = cf->cf_next) {
+            PyObject *o = PyTuple_Pack(2, get_field_name(ct, cf),
+                                       (PyObject *)cf);
+            int err = (o != NULL) ? PyList_Append(res, o) : -1;
+            Py_XDECREF(o);
+            if (err < 0) {
+                Py_DECREF(res);
+                return NULL;
+            }
+        }
+        return res;
+    }
+    else {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+}
diff --git a/zeffir/cfunc.c b/zeffir/cfunc.c
--- a/zeffir/cfunc.c
+++ b/zeffir/cfunc.c
@@ -2,7 +2,12 @@
 typedef struct {
     PyObject_HEAD
 
+    /* note that 'zfs_trampl' is either a '_crx_trampoline0_fn' or a
+       '_crx_trampoline1_fn', depending on how the ZefFuncSupportObject
+       is going to be used.
+    */
     int                 zfs_nargs;
+    int                 zfs_dotdotdot;
     void               *zfs_trampl;
     PyMethodDef         zfs_md;
     size_t              zfs_size_args;
@@ -199,7 +204,7 @@
     }
 
     zfs = (ZefFuncSupportObject *)ct->ct_stuff;
-    if (zfs == NULL) {
+    if (zfs->zfs_trampl == NULL) {
         PyErr_SetString(ZefError, "cdata '%s' cannot be called, because no "
                         "wrapper was generated for functions of this type ");
         return NULL;
@@ -220,12 +225,8 @@
 
 static PyObject *make_func_support(_crx_type_t *ret,
                                    _crx_qual_type args[], int nargs,
-                                   void *trampl, size_t extra_alloc)
+                                   int dotdotdot, size_t extra_alloc)
 {
-    /* note that 'trampl' is either a '_crx_trampoline0_fn' or a
-       '_crx_trampoline1_fn', depending on how the ZefFuncSupportObject
-       is going to be used.
-    */
     int i;
     size_t size = (sizeof(ZefFuncSupportObject)
                    + (nargs - 1) * sizeof(CTypeDescrObject *)
@@ -236,8 +237,9 @@
     PyObject_Init((PyObject *)zfs, &ZefFuncSupport_Type);
 
     memset(&zfs->zfs_md, 0, sizeof(PyMethodDef));
+    zfs->zfs_trampl = NULL;
     zfs->zfs_nargs = nargs;
-    zfs->zfs_trampl = trampl;
+    zfs->zfs_dotdotdot = dotdotdot;
     zfs->zfs_ret = ret;
     Py_INCREF(ret);
 
@@ -258,6 +260,13 @@
     return (PyObject *)zfs;
 }
 
+static void provide_trampoline(PyObject *zfs, void *trampl)
+{
+    if (((ZefFuncSupportObject *)zfs)->zfs_trampl == NULL) {
+        ((ZefFuncSupportObject *)zfs)->zfs_trampl = trampl;
+    }
+}
+
 static PyObject *make_builtin_func(PyObject *libname_obj,
                                    const char *funcname, _crx_type_t *ret,
                                    _crx_qual_type args[], int nargs,
@@ -265,11 +274,13 @@
 {
     char *p;
     ZefFuncSupportObject *zfs;
-    zfs = (ZefFuncSupportObject *)make_func_support(ret, args, nargs, trampl,
+    zfs = (ZefFuncSupportObject *)make_func_support(ret, args, nargs, 0,
                                                     strlen(funcname) + 1);
     if (zfs == NULL)
         return NULL;
 
+    zfs->zfs_trampl = trampl;
+
     p = (char *)(zfs->zfs_args + nargs);
     zfs->zfs_md.ml_name = strcpy(p, funcname);
     zfs->zfs_md.ml_meth = &zfs_call;
@@ -281,3 +292,33 @@
     Py_DECREF(zfs);
     return res;
 }
+
+static PyObject *cfunctype_getargs(CTypeDescrObject *ct)
+{
+    ZefFuncSupportObject *zfs = (ZefFuncSupportObject *)ct->ct_stuff;
+    int i;
+    PyObject *tup = PyTuple_New(zfs->zfs_nargs);
+    if (tup == NULL)
+        return NULL;
+
+    for (i = 0; i < zfs->zfs_nargs; i++) {
+        PyObject *obj = (PyObject *)zfs->zfs_args[i];
+        Py_INCREF(obj);
+        PyTuple_SET_ITEM(tup, i, obj);
+    }
+    return tup;
+}
+
+static PyObject *cfunctype_getresult(CTypeDescrObject *ct)
+{
+    ZefFuncSupportObject *zfs = (ZefFuncSupportObject *)ct->ct_stuff;
+    PyObject *res = (PyObject *)zfs->zfs_ret;
+    Py_INCREF(res);
+    return res;
+}
+
+static PyObject *cfunctype_getellipsis(CTypeDescrObject *ct)
+{
+    ZefFuncSupportObject *zfs = (ZefFuncSupportObject *)ct->ct_stuff;
+    return PyBool_FromLong(zfs->zfs_dotdotdot);
+}
diff --git a/zeffir/ctype.c b/zeffir/ctype.c
--- a/zeffir/ctype.c
+++ b/zeffir/ctype.c
@@ -102,6 +102,176 @@
     return 0;
 }
 
+
+static PyObject *nosuchattr(const char *attr)
+{
+    PyErr_SetString(PyExc_AttributeError, attr);
+    return NULL;
+}
+
+static PyObject *ctypeget_kind(CTypeDescrObject *ct, void *context)
+{
+    char *result;
+    if (ct->ct_flags & CT_PRIMITIVE_ANY) {
+        if (ct->ct_flags & CT_IS_ENUM)
+            result = "enum";
+        else
+            result = "primitive";
+    }
+    else if (ct->ct_flags & CT_POINTER) {
+        result = "pointer";
+    }
+    else if (ct->ct_flags & CT_ARRAY) {
+        result = "array";
+    }
+    else if (ct->ct_flags & CT_VOID) {
+        result = "void";
+    }
+    else if (ct->ct_flags & CT_STRUCT) {
+        result = "struct";
+    }
+    else if (ct->ct_flags & CT_UNION) {
+        result = "union";
+    }
+    else if (ct->ct_flags & CT_FUNCTION) {
+        result = "function";
+    }
+    else if (ct->ct_flags & CT_UNKNOWN) {
+        result = "opaque";
+    }
+    else
+        result = "?";
+
+    return PyText_FromString(result);
+}
+
+static PyObject *ctypeget_cname(CTypeDescrObject *ct, void *context)
+{
+    return PyText_FromString(ct->ct_name);
+}
+
+static PyObject *ctypeget_item(CTypeDescrObject *ct, void *context)
+{
+    if (ct->ct_flags & (CT_POINTER | CT_ARRAY)) {
+        Py_INCREF(ct->ct_itemdescr);
+        return (PyObject *)ct->ct_itemdescr;
+    }
+    return nosuchattr("item");
+}
+
+static PyObject *ctypeget_length(CTypeDescrObject *ct, void *context)
+{
+    if (ct->ct_flags & CT_ARRAY) {
+        if (ct->ct_length >= 0) {
+            return PyInt_FromSsize_t(ct->ct_length);
+        }
+        else {
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
+    }
+    return nosuchattr("length");
+}
+
+static PyObject *ctypeget_fields(CTypeDescrObject *ct, void *context)
+{
+    if (ct->ct_flags & (CT_STRUCT | CT_UNION)) {
+        return cstructtype_getfields(ct);
+    }
+    return nosuchattr("fields");
+}
+
+static PyObject *ctypeget_args(CTypeDescrObject *ct, void *context)
+{
+    if (ct->ct_flags & CT_FUNCTION) {
+        return cfunctype_getargs(ct);
+    }
+    return nosuchattr("args");
+}
+
+static PyObject *ctypeget_result(CTypeDescrObject *ct, void *context)
+{
+    if (ct->ct_flags & CT_FUNCTION) {
+        return cfunctype_getresult(ct);
+    }
+    return nosuchattr("result");
+}
+
+static PyObject *ctypeget_ellipsis(CTypeDescrObject *ct, void *context)
+{
+    if (ct->ct_flags & CT_FUNCTION) {
+        return cfunctype_getellipsis(ct);
+    }
+    return nosuchattr("ellipsis");
+}
+
+static PyObject *ctypeget_elements(CTypeDescrObject *ct, void *context)
+{
+    if (ct->ct_flags & CT_IS_ENUM) {
+        PyObject *res = PyTuple_GetItem(ct->ct_stuff, 1);
+        if (res) res = PyDict_Copy(res);
+        return res;
+    }
+    return nosuchattr("elements");
+}
+
+static PyObject *ctypeget_relements(CTypeDescrObject *ct, void *context)
+{
+    if (ct->ct_flags & CT_IS_ENUM) {
+        PyObject *res = PyTuple_GetItem(ct->ct_stuff, 0);
+        if (res) res = PyDict_Copy(res);
+        return res;
+    }
+    return nosuchattr("relements");
+}
+
+static PyGetSetDef ctypedescr_getsets[] = {
+    {"kind", (getter)ctypeget_kind, NULL, "kind"},
+    {"cname", (getter)ctypeget_cname, NULL, "C name"},
+    {"item", (getter)ctypeget_item, NULL, "pointer to, or array of"},
+    {"length", (getter)ctypeget_length, NULL, "array length or None"},
+    {"fields", (getter)ctypeget_fields, NULL, "struct or union fields"},
+    {"args", (getter)ctypeget_args, NULL, "function argument types"},
+    {"result", (getter)ctypeget_result, NULL, "function result type"},
+    {"ellipsis", (getter)ctypeget_ellipsis, NULL, "function has '...'"},
+    {"elements", (getter)ctypeget_elements, NULL, "enum elements"},
+    {"relements", (getter)ctypeget_relements, NULL, "enum elements, reverse"},
+    {NULL}                        /* sentinel */
+};
+
+static PyObject *
+ctypedescr_dir(PyObject *ct, PyObject *noarg)
+{
+    int err;
+    struct PyGetSetDef *gsdef;
+    PyObject *res = PyList_New(0);
+    if (res == NULL)
+        return NULL;
+
+    for (gsdef = ctypedescr_getsets; gsdef->name; gsdef++) {
+        PyObject *x = PyObject_GetAttrString(ct, gsdef->name);
+        if (x == NULL) {
+            PyErr_Clear();
+        }
+        else {
+            Py_DECREF(x);
+            x = PyText_FromString(gsdef->name);
+            err = (x != NULL) ? PyList_Append(res, x) : -1;
+            Py_XDECREF(x);
+            if (err < 0) {
+                Py_DECREF(res);
+                return NULL;
+            }
+        }
+    }
+    return res;
+}
+
+static PyMethodDef ctypedescr_methods[] = {
+    {"__dir__",   ctypedescr_dir,  METH_NOARGS},
+    {NULL,        NULL}           /* sentinel */
+};
+
 static PyTypeObject CTypeDescr_Type = {
     PyVarObject_HEAD_INIT(NULL, 0)
     "zeffir.CType",
@@ -130,7 +300,7 @@
     offsetof(CTypeDescrObject, ct_weakreflist), /* tp_weaklistoffset */
     0,                                          /* tp_iter */
     0,                                          /* tp_iternext */
-    0,//ctypedescr_methods,                         /* tp_methods */
+    ctypedescr_methods,                         /* tp_methods */
     0,                                          /* tp_members */
-    0,//ctypedescr_getsets,                         /* tp_getset */
+    ctypedescr_getsets,                         /* tp_getset */
 };
diff --git a/zeffir/test/test_c.py b/zeffir/test/test_c.py
new file mode 100644
--- /dev/null
+++ b/zeffir/test/test_c.py
@@ -0,0 +1,57 @@
+import py
+import support
+
+import sys
+if sys.version_info < (3,):
+    type_or_class = "type"
+    mandatory_b_prefix = ''
+    mandatory_u_prefix = 'u'
+    bytechr = chr
+    bitem2bchr = lambda x: x
+    class U(object):
+        def __add__(self, other):
+            return eval('u'+repr(other).replace(r'\\u', r'\u')
+                                       .replace(r'\\U', r'\U'))
+    u = U()
+    str2bytes = str
+else:
+    type_or_class = "class"
+    long = int
+    unicode = str
+    unichr = chr
+    mandatory_b_prefix = 'b'
+    mandatory_u_prefix = ''
+    bytechr = lambda n: bytes([n])
+    bitem2bchr = bytechr
+    u = ""
+    str2bytes = lambda s: bytes(s, "ascii")
+
+def size_of_int():
+    ffi = support.new_ffi()
+    return ffi.sizeof("int")
+
+def size_of_long():
+    ffi = support.new_ffi()
+    return ffi.sizeof("long")
+
+def size_of_ptr():
+    ffi = support.new_ffi()
+    return ffi.sizeof("void*")
+
+
+def test_new_primitive_type():
+    ffi = support.new_ffi()
+    py.test.raises(ffi.error, ffi.typeof, "foo")
+    p = ffi.typeof("signed char")
+    assert repr(p) == "<ctype 'signed char'>"
+
+def check_dir(p, expected):
+    got = set(name for name in dir(p) if not name.startswith('_'))
+    assert got == set(expected)
+
+def test_inspect_primitive_type():
+    ffi = support.new_ffi()
+    p = ffi.typeof("signed char")
+    assert p.kind == "primitive"
+    assert p.cname == "signed char"
+    check_dir(p, ['cname', 'kind'])
diff --git a/zeffir/zeffir.h b/zeffir/zeffir.h
--- a/zeffir/zeffir.h
+++ b/zeffir/zeffir.h
@@ -29,4 +29,8 @@
                                      size_t extra_text_len);
 static PyObject *gc_weakrefs_build(ZefFFIObject *ffi, CDataObject *cd,
                                    PyObject *destructor);
-static PyObject*cdata_call(CDataObject *cd, PyObject *args, PyObject *kwds);
+static PyObject *cdata_call(CDataObject *cd, PyObject *args, PyObject *kwds);
+static PyObject *cfunctype_getargs(CTypeDescrObject *ct);
+static PyObject *cfunctype_getresult(CTypeDescrObject *ct);
+static PyObject *cfunctype_getellipsis(CTypeDescrObject *ct);
+static PyObject *cstructtype_getfields(CTypeDescrObject *ct);


More information about the pypy-commit mailing list