[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