[pypy-commit] creflect default: fix ffi.addressof(). Also allows ffi.new("struct_type") directly,

arigo noreply at buildbot.pypy.org
Fri Dec 5 19:38:48 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r176:620bef5903b4
Date: 2014-12-05 19:39 +0100
http://bitbucket.org/cffi/creflect/changeset/620bef5903b4/

Log:	fix ffi.addressof(). Also allows ffi.new("struct_type") directly,
	as an extension that seems to make sense for now

diff --git a/zeffir/builder.c b/zeffir/builder.c
--- a/zeffir/builder.c
+++ b/zeffir/builder.c
@@ -45,13 +45,18 @@
     return result;
 }
 
-static CTypeDescrObject *get_cached_type(_crx_builder_t *cb, PyObject *name_obj)
+static PyObject *get_types_dict(_crx_builder_t *cb)
+{
+    return ((zeffir_builder_t *)cb)->types_dict;
+}
+
+static CTypeDescrObject *get_cached_type(PyObject *types_dict,
+                                         PyObject *name_obj)
 {
     /* Look up the type called 'name_obj' and check that it's a type with the
        right flags.  Returns either the type or NULL, without changing
        the reference counts.  Never raises an exception.
     */
-    PyObject *types_dict = ((zeffir_builder_t *)cb)->types_dict;
     PyObject *x;
 
     assert(name_obj != NULL);
@@ -62,13 +67,13 @@
         return (CTypeDescrObject *)x;
 }
 
-static void put_cached_type(_crx_builder_t *cb, PyObject *name_obj,
+static int put_cached_type(PyObject *types_dict, PyObject *name_obj,
                             CTypeDescrObject *ct)
 {
-    PyObject *types_dict = ((zeffir_builder_t *)cb)->types_dict;
-    PyDict_SetItem(types_dict, name_obj, (PyObject *)ct);
+    int err = PyDict_SetItem(types_dict, name_obj, (PyObject *)ct);
     Py_DECREF(ct);   /* still a reference in the dict,
                         unless PyDict_SetItem failed */
+    return err;
 }
 
 static _crx_type_t *_zef_primitive(_crx_builder_t *cb, Py_ssize_t size,
@@ -84,7 +89,7 @@
     if (name_obj == NULL)
         return NULL;
 
-    ct = get_cached_type(cb, name_obj);
+    ct = get_cached_type(get_types_dict(cb), name_obj);
     if (ct && (ct->ct_flags == flags) && (ct->ct_size == size))
         goto done;
 
@@ -95,7 +100,8 @@
     ct->ct_size = size;
     ct->ct_flags = flags;
 
-    put_cached_type(cb, name_obj, ct);
+    if (put_cached_type(get_types_dict(cb), name_obj, ct) < 0)
+        ct = NULL;
 
  done:
     Py_DECREF(name_obj);
@@ -207,7 +213,7 @@
                == extra_len);
     }
 
-    ct = get_cached_type(cb, name_obj);
+    ct = get_cached_type(get_types_dict(cb), name_obj);
     if (ct && (ct->ct_flags == CT_FUNCTION))
         goto done;
 
@@ -219,7 +225,7 @@
     ct->ct_flags = CT_FUNCTION;
     /* XXX more... */
 
-    put_cached_type(cb, name_obj, ct);
+    put_cached_type(get_types_dict(cb), name_obj, ct);
 
  done:
     Py_DECREF(name_obj);
@@ -241,12 +247,9 @@
     return _zef_function(cb, ret, args, nargs, 1);
 }
 
-static _crx_type_t *zef_get_pointer_type(_crx_builder_t *cb,
-                                         _crx_type_t *totype, int toquals)
+static CTypeDescrObject *fetch_pointer_type(PyObject *types_dict,
+                                            CTypeDescrObject *totype)
 {
-    if (PyErr_Occurred())
-        return NULL;
-
     const char *extra;
     PyObject *name_obj;
     CTypeDescrObject *ct;
@@ -260,7 +263,7 @@
     if (name_obj == NULL)
         return NULL;
 
-    ct = get_cached_type(cb, name_obj);
+    ct = get_cached_type(types_dict, name_obj);
     if (ct && (ct->ct_flags & CT_POINTER))
         goto done;
 
@@ -280,13 +283,22 @@
          totype->ct_size == sizeof(char)))
         ct->ct_flags |= CT_CAST_ANYTHING;   /* 'void *' or 'char *' only */
 
-    put_cached_type(cb, name_obj, ct);
+    put_cached_type(types_dict, name_obj, ct);
 
  done:
     Py_DECREF(name_obj);
     return ct;
 }
 
+static _crx_type_t *zef_get_pointer_type(_crx_builder_t *cb,
+                                         _crx_type_t *totype, int toquals)
+{
+    if (PyErr_Occurred())
+        return NULL;
+
+    return fetch_pointer_type(get_types_dict(cb), totype);
+}
+
 static _crx_type_t *_zef_array_type(_crx_builder_t *cb, _crx_type_t *ctitem,
                                     size_t len, CTypeDescrObject *ctptr)
 {
@@ -318,7 +330,7 @@
         return NULL;
 
     if (cb != NULL) {
-        ct = get_cached_type(cb, name_obj);
+        ct = get_cached_type(get_types_dict(cb), name_obj);
         if (ct && (ct->ct_flags & CT_ARRAY))
             goto done;
     }
@@ -356,7 +368,7 @@
             Py_INCREF(ct);
             ctptr->ct_stuff = (PyObject *)ct;
         }
-        put_cached_type(cb, name_obj, ct);
+        put_cached_type(get_types_dict(cb), name_obj, ct);
     }
     else {
         assert(length < 0);
@@ -400,7 +412,7 @@
     if (name_obj == NULL)
         return NULL;
 
-    ct = get_cached_type(cb, name_obj);
+    ct = get_cached_type(get_types_dict(cb), name_obj);
     if (ct && (ct->ct_flags == flag))
         goto done;
 
@@ -442,7 +454,7 @@
     if (name_obj == NULL)
         return result;
 
-    result.type = get_cached_type(cb, name_obj);
+    result.type = get_cached_type(get_types_dict(cb), name_obj);
     if (result.type == NULL)
         PyErr_Format(ZefError, "undefined type: '%s'", name);
     return result;
diff --git a/zeffir/cdata.c b/zeffir/cdata.c
--- a/zeffir/cdata.c
+++ b/zeffir/cdata.c
@@ -1207,6 +1207,7 @@
     if (ct == NULL)
         return NULL;
 
+    assert(ct->ct_flags & CT_POINTER);
     if (ct->ct_stuff == NULL) {
         if (fill_array_type(ct) < 0)
             return NULL;
diff --git a/zeffir/ffi_obj.c b/zeffir/ffi_obj.c
--- a/zeffir/ffi_obj.c
+++ b/zeffir/ffi_obj.c
@@ -191,9 +191,9 @@
         return NULL;
 
     explicitlength = -1;
-    if (ct->ct_flags & CT_POINTER) {
+    if (ct->ct_flags & (CT_POINTER | CT_STRUCT | CT_UNION)) {
         dataoffset = offsetof(CDataObject_own_nolength, alignment);
-        ctitem = ct->ct_itemdescr;
+        ctitem = (ct->ct_flags & CT_POINTER) ? ct->ct_itemdescr : ct;
         datasize = ctitem->ct_size;
         if (datasize < 0) {
             PyErr_Format(PyExc_TypeError,
@@ -395,7 +395,11 @@
             if (cf == NULL)
                 return NULL;
             offset = cf->cf_offset;
+            ct = cf->cf_type;
         }
+        ct = fetch_pointer_type(self->types_dict, ct);
+        if (ct == NULL)
+            return NULL;
         return new_simple_cdata(cd->c_data + offset, ct);
     }
     else if (ZefLib_Check(obj)) {
diff --git a/zeffir/test/struct.crx b/zeffir/test/struct.crx
--- a/zeffir/test/struct.crx
+++ b/zeffir/test/struct.crx
@@ -3,6 +3,11 @@
     long b;
 } mystruct_t;
 
+typedef struct {
+    int foo[5];
+    //int bar[];
+} myarrstr_t;
+
 
 // CREFLECT: start
 
@@ -10,4 +15,9 @@
     int a, b;
 } mystruct_t;
 
+typedef struct {
+    int foo[5];
+    //int bar[];
+} myarrstr_t;
+
 // CREFLECT: end
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
@@ -6,6 +6,7 @@
     ffi, lib = support.compile_and_open('struct')
     p = ffi.new('mystruct_t *', [-5, 0x600112233])
     assert p.a == -5
+    assert p[0].a == -5
     assert p.b == 0x600112233
     p.b += 1
     assert p.b == 0x600112234
@@ -19,10 +20,27 @@
     ffi, lib = support.compile_and_open('struct')
     p = ffi.new("mystruct_t *")
     assert ffi.addressof(p[0]) == p
+    assert ffi.typeof(ffi.addressof(p[0])) == ffi.typeof("mystruct_t *")
     assert ffi.addressof(p[0], None) == p
     assert ffi.addressof(p[0], "a") == p
+    assert ffi.typeof(ffi.addressof(p[0], "a")) == ffi.typeof("int *")
     assert ffi.addressof(p[0], "b") != p
     assert ffi.addressof(p[0], "b") == ffi.addressof(p, "b")
+    assert ffi.typeof(ffi.addressof(p[0], "b")) == ffi.typeof("long *")
     assert ffi.addressof(p, "a") == p
     py.test.raises(TypeError, ffi.addressof, p)
     py.test.raises(TypeError, ffi.addressof, p, None)
+    #
+    p = ffi.new("myarrstr_t *")
+    assert ffi.typeof(ffi.addressof(p, "foo")) == ffi.typeof("int(*)[5]")
+    assert ffi.typeof(p.foo) == ffi.typeof("int[5]")
+    #assert ffi.typeof(ffi.addressof(p, "bar")) == ffi.typeof("int(*)[]")
+
+def test_new_nonptr_struct():
+    ffi, lib = support.compile_and_open('struct')
+    s = ffi.new("mystruct_t", [-5, 0x600112233])
+    assert s.a == -5
+    assert s.b == 0x600112233
+    s.b += 1
+    assert s.b == 0x600112234
+    assert ffi.addressof(s)[0] == s
diff --git a/zeffir/zeffir.h b/zeffir/zeffir.h
--- a/zeffir/zeffir.h
+++ b/zeffir/zeffir.h
@@ -21,3 +21,5 @@
 static int convert_from_object_bitfield(char *, CFieldObject *, PyObject *);
 
 static int fill_array_type(CTypeDescrObject *ctptr);
+static CTypeDescrObject *fetch_pointer_type(PyObject *types_dict,
+                                            CTypeDescrObject *totype);


More information about the pypy-commit mailing list