[pypy-commit] creflect default: ffi.addressof

arigo noreply at buildbot.pypy.org
Fri Dec 5 18:49:34 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r173:832fea94ecfa
Date: 2014-12-05 18:40 +0100
http://bitbucket.org/cffi/creflect/changeset/832fea94ecfa/

Log:	ffi.addressof

diff --git a/zeffir/ffi_obj.c b/zeffir/ffi_obj.c
--- a/zeffir/ffi_obj.c
+++ b/zeffir/ffi_obj.c
@@ -317,6 +317,26 @@
     return NULL;
 }
 
+static CFieldObject *_ffi_field(CTypeDescrObject *ct, const char *fieldname)
+{
+    CFieldObject *cf;
+    if (ct->ct_stuff == NULL) {
+        PyErr_Format(PyExc_TypeError, "'%s' is incomplete", ct->ct_name);
+        return NULL;
+    }
+    cf = (CFieldObject *)PyDict_GetItemString(ct->ct_stuff, fieldname);
+    if (cf == NULL) {
+        PyErr_Format(PyExc_KeyError, "'%s' has got no field '%s'",
+                     ct->ct_name, fieldname);
+        return NULL;
+    }
+    if (cf->cf_bitshift >= 0) {
+        PyErr_SetString(PyExc_TypeError, "not supported for bitfields");
+        return NULL;
+    }
+    return cf;
+}
+
 static PyObject *ffi_offsetof(ZefFFIObject *self, PyObject *args)
 {
     PyObject *arg;
@@ -337,25 +357,47 @@
                      ct->ct_name);
         return NULL;
     }
-    if (ct->ct_stuff == NULL) {
-        PyErr_Format(PyExc_TypeError, "'%s' is incomplete", ct->ct_name);
+    cf = _ffi_field(ct, fieldname);
+    if (cf == NULL)
+        return NULL;
+    return PyInt_FromSsize_t(cf->cf_offset);
+}
+
+static PyObject *ffi_addressof(ZefFFIObject *self, PyObject *args)
+{
+    char *fieldname = NULL;
+    CDataObject *cd;
+    CTypeDescrObject *ct;
+    Py_ssize_t offset;
+
+    if (!PyArg_ParseTuple(args, "O!|z:addressof", &CData_Type, &cd, &fieldname))
+        return NULL;
+
+    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;
     }
 
-    cf = (CFieldObject *)PyDict_GetItemString(ct->ct_stuff, fieldname);
-    if (cf == NULL) {
-        PyErr_Format(PyExc_KeyError, "'%s' has got no field '%s'",
-                     ct->ct_name, fieldname);
-        return NULL;
+    if (fieldname == NULL) {
+        offset = 0;
     }
-    if (cf->cf_bitshift >= 0) {
-        PyErr_SetString(PyExc_TypeError, "not supported for bitfields");
-        return NULL;
+    else {
+        CFieldObject *cf = _ffi_field(ct, fieldname);
+        if (cf == NULL)
+            return NULL;
+        offset = cf->cf_offset;
     }
-    return PyInt_FromSsize_t(cf->cf_offset);
+    return new_simple_cdata(cd->c_data + offset, ct);
 }
 
 static PyMethodDef ffi_methods[] = {
+    {"addressof",     (PyCFunction)ffi_addressof,METH_VARARGS},
     {"close_library", ffi_close_library,         METH_VARARGS | METH_STATIC},
     {"load_library",  (PyCFunction)ffi_load_library,
                                                  METH_VARARGS | METH_KEYWORDS},
diff --git a/zeffir/test/test_struct.py b/zeffir/test/test_struct.py
--- a/zeffir/test/test_struct.py
+++ b/zeffir/test/test_struct.py
@@ -14,3 +14,15 @@
     ffi, lib = support.compile_and_open('struct')
     assert ffi.offsetof("mystruct_t", "a") == 0
     assert ffi.offsetof("mystruct_t", "b") == ffi.sizeof("long")
+
+def test_addressof():
+    ffi, lib = support.compile_and_open('struct')
+    p = ffi.new("mystruct_t *")
+    assert ffi.addressof(p[0]) == p
+    assert ffi.addressof(p[0], None) == p
+    assert ffi.addressof(p[0], "a") == p
+    assert ffi.addressof(p[0], "b") != p
+    assert ffi.addressof(p[0], "b") == ffi.addressof(p, "b")
+    assert ffi.addressof(p, "a") == p
+    py.test.raises(TypeError, ffi.addressof, p)
+    py.test.raises(TypeError, ffi.addressof, p, None)


More information about the pypy-commit mailing list