[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