[pypy-commit] creflect default: addressof(Lib, "some_global_var")
arigo
noreply at buildbot.pypy.org
Fri Dec 5 18:49:35 CET 2014
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r174:a9718f1fb634
Date: 2014-12-05 18:49 +0100
http://bitbucket.org/cffi/creflect/changeset/a9718f1fb634/
Log: addressof(Lib, "some_global_var")
diff --git a/zeffir/cglob.c b/zeffir/cglob.c
--- a/zeffir/cglob.c
+++ b/zeffir/cglob.c
@@ -61,3 +61,8 @@
{
return convert_from_object(zgs->zgs_data, zgs->zgs_type, obj);
}
+
+static PyObject *addressof_global_var(ZefGlobSupportObject *zgs)
+{
+ return new_simple_cdata(zgs->zgs_data, zgs->zgs_type);
+}
diff --git a/zeffir/ffi_obj.c b/zeffir/ffi_obj.c
--- a/zeffir/ffi_obj.c
+++ b/zeffir/ffi_obj.c
@@ -365,35 +365,69 @@
static PyObject *ffi_addressof(ZefFFIObject *self, PyObject *args)
{
+ PyObject *obj;
char *fieldname = NULL;
- CDataObject *cd;
- CTypeDescrObject *ct;
- Py_ssize_t offset;
- if (!PyArg_ParseTuple(args, "O!|z:addressof", &CData_Type, &cd, &fieldname))
+ if (!PyArg_ParseTuple(args, "O|z:addressof", &obj, &fieldname))
return NULL;
- ct = cd->c_type;
- if (fieldname != NULL && ct->ct_flags & CT_POINTER)
- ct = ct->ct_itemdescr;
+ if (CData_Check(obj)) {
+ CDataObject *cd = (CDataObject *)obj;
+ CTypeDescrObject *ct;
+ Py_ssize_t offset;
- if (!(ct->ct_flags & (CT_STRUCT|CT_UNION))) {
+ ct = cd->c_type;
+ if (fieldname != NULL && ct->ct_flags & CT_POINTER)
+ ct = ct->ct_itemdescr;
+
+ if (!(ct->ct_flags & (CT_STRUCT|CT_UNION))) {
+ PyErr_Format(PyExc_TypeError,
+ "expected a struct or union cdata, got '%s'",
+ ct->ct_name);
+ return NULL;
+ }
+
+ if (fieldname == NULL) {
+ offset = 0;
+ }
+ else {
+ CFieldObject *cf = _ffi_field(ct, fieldname);
+ if (cf == NULL)
+ return NULL;
+ offset = cf->cf_offset;
+ }
+ return new_simple_cdata(cd->c_data + offset, ct);
+ }
+ else if (ZefLib_Check(obj)) {
+ PyObject *attr, *name;
+
+ if (fieldname == NULL) {
+ PyErr_SetString(PyExc_TypeError, "addressof(Lib, fieldname) "
+ "cannot be used with only one argument");
+ return NULL;
+ }
+ name = PyString_FromString(fieldname);
+ if (name == NULL)
+ return NULL;
+ attr = lib_findattr((ZefLibObject *)obj, name);
+ Py_DECREF(name);
+ if (attr == NULL)
+ return NULL;
+
+ if (ZefGlobSupport_Check(attr))
+ return addressof_global_var((ZefGlobSupportObject *)attr);
+
PyErr_Format(PyExc_TypeError,
- "expected a struct or union cdata, got '%s'",
- ct->ct_name);
+ "cannot take the address of constant '%s'",
+ fieldname);
return NULL;
}
-
- if (fieldname == NULL) {
- offset = 0;
+ else {
+ PyErr_SetString(PyExc_TypeError, "addressof() first argument must be "
+ "a cdata struct or union, a pointer to one, or a Lib "
+ "object");
+ return NULL;
}
- else {
- CFieldObject *cf = _ffi_field(ct, fieldname);
- if (cf == NULL)
- return NULL;
- offset = cf->cf_offset;
- }
- return new_simple_cdata(cd->c_data + offset, ct);
}
static PyMethodDef ffi_methods[] = {
diff --git a/zeffir/lib_obj.c b/zeffir/lib_obj.c
--- a/zeffir/lib_obj.c
+++ b/zeffir/lib_obj.c
@@ -12,6 +12,8 @@
PyObject *l_libname_obj; /* same, as a PyObject */
};
+#define ZefLib_Check(ob) ((Py_TYPE(ob) == &ZefLib_Type))
+
static void lib_dealloc(ZefLibObject *lib)
{
(void)lib_close(lib);
diff --git a/zeffir/test/test_global.py b/zeffir/test/test_global.py
--- a/zeffir/test/test_global.py
+++ b/zeffir/test/test_global.py
@@ -32,3 +32,10 @@
assert hash(lib.myglobptr) == hash(lib.myglobptr)
lib.myglobptr = ffi.NULL
assert lib.myglobptr == ffi.NULL
+
+def test_addressof():
+ ffi, lib = support.compile_and_open('global')
+ p = ffi.addressof(lib, 'myglob')
+ assert p == lib.myglobptr
+ lib.myglobptr = ffi.NULL
+ assert p != lib.myglobptr
More information about the pypy-commit
mailing list