[pypy-commit] cffi cffi-1.0: struct/unions

arigo noreply at buildbot.pypy.org
Mon May 11 19:29:51 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1976:73400152d574
Date: 2015-05-11 17:55 +0200
http://bitbucket.org/cffi/cffi/changeset/73400152d574/

Log:	struct/unions

diff --git a/_cffi1/cdlopen.c b/_cffi1/cdlopen.c
--- a/_cffi1/cdlopen.c
+++ b/_cffi1/cdlopen.c
@@ -134,8 +134,9 @@
     ffi->ctx_is_nonempty = 1;
 
     if (types_len > 0) {
+        /* unpack a string of 4-byte entries into an array of _cffi_opcode_t */
         _cffi_opcode_t *ntypes;
-        Py_ssize_t i, n = types_len / 4;    /* 4 bytes entries */
+        Py_ssize_t i, n = types_len / 4;
 
         building = PyMem_Malloc(n * sizeof(_cffi_opcode_t));
         if (building == NULL)
@@ -147,29 +148,95 @@
             types += 4;
         }
         ffi->types_builder.ctx.types = ntypes;
+        ffi->types_builder.ctx.num_types = n;
         building = NULL;
     }
 
     if (globals != NULL) {
-        struct _cffi_global_s *nglob;
+        /* unpack a tuple of strings, each of which describes one global_s
+           entry with no specified address or size */
+        struct _cffi_global_s *nglobs;
         Py_ssize_t i, n = PyTuple_GET_SIZE(globals);
 
-        building = PyMem_Malloc(n * sizeof(struct _cffi_global_s));
+        i = n * sizeof(struct _cffi_global_s);
+        building = PyMem_Malloc(i);
         if (building == NULL)
             goto error;
-        memset(building, 0, n * sizeof(struct _cffi_global_s));
-        nglob = (struct _cffi_global_s *)building;
+        memset(building, 0, i);
+        nglobs = (struct _cffi_global_s *)building;
 
         for (i = 0; i < n; i++) {
             char *g = PyString_AS_STRING(PyTuple_GET_ITEM(globals, i));
-            nglob[i].type_op = cdl_opcode(g);
-            nglob[i].name = g + 4;
+            nglobs[i].type_op = cdl_opcode(g);
+            nglobs[i].name = g + 4;
         }
-        ffi->types_builder.ctx.globals = nglob;
+        ffi->types_builder.ctx.globals = nglobs;
         ffi->types_builder.ctx.num_globals = n;
         building = NULL;
     }
 
+    if (struct_unions != NULL) {
+        /* unpack a tuple of struct/unions, each described as a sub-tuple;
+           the item 0 of each sub-tuple describes the struct/union, and
+           the items 1..N-1 describe the fields, if any */
+        struct _cffi_struct_union_s *nstructs;
+        struct _cffi_field_s *nfields;
+        Py_ssize_t i, n = PyTuple_GET_SIZE(struct_unions);
+        Py_ssize_t nf = 0;   /* total number of fields */
+
+        for (i = 0; i < n; i++) {
+            nf += PyTuple_GET_SIZE(PyTuple_GET_ITEM(struct_unions, i)) - 1;
+        }
+        i = (n * sizeof(struct _cffi_struct_union_s) +
+             nf * sizeof(struct _cffi_field_s));
+        building = PyMem_Malloc(i);
+        if (building == NULL)
+            goto error;
+        memset(building, 0, i);
+        nstructs = (struct _cffi_struct_union_s *)building;
+        nfields = (struct _cffi_field_s *)(nstructs + n);
+        nf = 0;
+
+        for (i = 0; i < n; i++) {
+            /* 'desc' is the tuple of strings (desc_struct, desc_field_1, ..) */
+            PyObject *desc = PyTuple_GET_ITEM(struct_unions, i);
+            Py_ssize_t j, nf1 = PyTuple_GET_SIZE(desc) - 1;
+            char *s = PyString_AS_STRING(PyTuple_GET_ITEM(desc, 0));
+            /* 's' is the first string, describing the struct/union */
+            nstructs[i].type_index = cdl_int(s);
+            nstructs[i].flags = cdl_int(s + 4);
+            nstructs[i].name = s + 8;
+            if (nstructs[i].flags & _CFFI_F_OPAQUE) {
+                nstructs[i].size = (size_t)-1;
+                nstructs[i].alignment = -1;
+                nstructs[i].first_field_index = -1;
+                nstructs[i].num_fields = 0;
+                assert(nf1 == 0);
+            }
+            else {
+                nstructs[i].size = (size_t)-2;
+                nstructs[i].alignment = -2;
+                nstructs[i].first_field_index = nf;
+                nstructs[i].num_fields = nf1;
+            }
+            for (j = 0; j < nf1; j++) {
+                char *f = PyString_AS_STRING(PyTuple_GET_ITEM(desc, j + 1));
+                /* 'f' is one of the other strings beyond the first one,
+                   describing one field each */
+                nfields[nf].field_type_op = cdl_opcode(f);
+                nfields[nf].name = f + 4;
+                nfields[nf].field_offset = (size_t)-1;
+                nfields[nf].field_size = (size_t)-1;
+                /* XXXXXXXXXXX BITFIELD MISSING XXXXXXXXXXXXXXXX */
+                nf++;
+            }
+        }
+        ffi->types_builder.ctx.struct_unions = nstructs;
+        ffi->types_builder.ctx.fields = nfields;
+        ffi->types_builder.ctx.num_struct_unions = n;
+        building = NULL;
+    }
+
     if (consts != NULL) {
         Py_INCREF(consts);
         ffi->types_builder.known_constants = consts;
diff --git a/_cffi1/ffi_obj.c b/_cffi1/ffi_obj.c
--- a/_cffi1/ffi_obj.c
+++ b/_cffi1/ffi_obj.c
@@ -694,94 +694,6 @@
 static PyObject *ffi_dlopen(PyObject *self, PyObject *args);  /* forward */
 static PyObject *ffi_dlclose(PyObject *self, PyObject *args);  /* forward */
 
-#if 0
-static PyObject *ffi__set_types(FFIObject *self, PyObject *args)
-{
-    PyObject *lst1, *lst2;
-    _cffi_opcode_t *types = NULL;
-    struct _cffi_struct_union_s *struct_unions = NULL;
-    struct _cffi_typename_s *typenames = NULL;
-
-    if (!PyArg_ParseTuple(args, "O!O!",
-                          &PyList_Type, &lst1, &PyList_Type, &lst2))
-        return NULL;
-
-    if (self->ctx_is_static) {
-     bad_usage:
-        PyMem_Free(typenames);
-        PyMem_Free(struct_unions);
-        PyMem_Free(types);
-        if (!PyErr_Occurred())
-            PyErr_SetString(PyExc_RuntimeError, "internal error");
-        return NULL;
-    }
-
-    cleanup_builder_c(self->types_builder);
-
-    int i;
-    int lst1_length = PyList_GET_SIZE(lst1) / 2;
-    int lst2_length = PyList_GET_SIZE(lst2) / 2;
-    Py_ssize_t newsize0 = sizeof(_cffi_opcode_t) * (lst1_length + lst2_length);
-    Py_ssize_t newsize1 = sizeof(struct _cffi_struct_union_s) * lst1_length;
-    Py_ssize_t newsize2 = sizeof(struct _cffi_typename_s) * lst2_length;
-    types = PyMem_Malloc(newsize0);
-    struct_unions = PyMem_Malloc(newsize1);
-    typenames = PyMem_Malloc(newsize2);
-    if (!types || !struct_unions || !typenames) {
-        PyErr_NoMemory();
-        goto bad_usage;
-    }
-    memset(types, 0, newsize0);
-    memset(struct_unions, 0, newsize1);
-    memset(typenames, 0, newsize2);
-
-    for (i = 0; i < lst1_length; i++) {
-        PyObject *x = PyList_GET_ITEM(lst1, i * 2);
-        if (!PyString_Check(x))
-            goto bad_usage;
-        struct_unions[i].name = PyString_AS_STRING(x);
-        struct_unions[i].type_index = i;
-
-        x = PyList_GET_ITEM(lst1, i * 2 + 1);
-        if (!CTypeDescr_Check(x))
-            goto bad_usage;
-        types[i] = x;
-        struct_unions[i].flags = ((CTypeDescrObject *)x)->ct_flags & CT_UNION ?
-            _CFFI_F_UNION : 0;
-        struct_unions[i].size = (size_t)-2;
-        struct_unions[i].alignment = -2;
-    }
-    for (i = 0; i < lst2_length; i++) {
-        PyObject *x = PyList_GET_ITEM(lst2, i * 2);
-        if (!PyString_Check(x))
-            goto bad_usage;
-        typenames[i].name = PyString_AS_STRING(x);
-        typenames[i].type_index = lst1_length + i;
-
-        x = PyList_GET_ITEM(lst2, i * 2 + 1);
-        if (!CTypeDescr_Check(x))
-            goto bad_usage;
-        types[lst1_length + i] = x;
-    }
-    for (i = 0; i < lst1_length + lst2_length; i++) {
-        PyObject *x = (PyObject *)types[i];
-        Py_INCREF(x);
-    }
-
-    Py_INCREF(args);     /* to keep alive the strings in '.name' */
-    Py_XDECREF(self->dynamic_types);
-    self->dynamic_types = args;
-    self->types_builder.ctx.types = types;
-    self->types_builder.num_types_imported = lst1_length + lst2_length;
-    self->types_builder.ctx.struct_unions = struct_unions;
-    self->types_builder.ctx.num_struct_unions = lst1_length;
-    self->types_builder.ctx.typenames = typenames;
-    self->types_builder.ctx.num_typenames = lst2_length;
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-#endif
 
 #define METH_VKW  (METH_VARARGS | METH_KEYWORDS)
 static PyMethodDef ffi_methods[] = {
diff --git a/_cffi1/manual2.py b/_cffi1/manual2.py
--- a/_cffi1/manual2.py
+++ b/_cffi1/manual2.py
@@ -2,8 +2,8 @@
 
 ffi = _cffi_backend.FFI(b"manual2",
     _version = 0x2600,
-    _types = b'\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x00\x09\x00\x00\x00\x0B',
-    _globals = (b'\x00\x00\x00#close',),
+    _types = b'\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x00\x09\x00\x00\x00\x0B\x00\x00\x01\x03',
+    _globals = (b'\x00\x00\x00#close',b'\x00\x00\x05#stdout'),
     _struct_unions = ((b'\x00\x00\x00\x03\x00\x00\x00\x00point_s',b'\x00\x00\x01\x11x',b'\x00\x00\x01\x11y'),),
     _enums = (b'\x00\x00\x00\x04\x00\x00\x00\x01myenum_e\x00AA,BB,CC',),
     _typenames = (b'\x00\x00\x00\x01myint_t',),
@@ -17,3 +17,11 @@
 assert lib.BB == 1
 x = lib.close(-42)
 assert x == -1
+
+print lib.stdout
+
+print ffi.new("struct point_s *")
+print ffi.offsetof("struct point_s", "x")
+print ffi.offsetof("struct point_s", "y")
+
+del ffi
diff --git a/_cffi1/realize_c_type.c b/_cffi1/realize_c_type.c
--- a/_cffi1/realize_c_type.c
+++ b/_cffi1/realize_c_type.c
@@ -63,7 +63,7 @@
         const void *mem[] = {builder->ctx.types,
                              builder->ctx.globals,
                              builder->ctx.struct_unions,
-                             builder->ctx.fields,
+                             //builder->ctx.fields: allocated with struct_unions
                              builder->ctx.enums,
                              builder->ctx.typenames};
         for (i = 0; i < sizeof(mem) / sizeof(*mem); i++) {


More information about the pypy-commit mailing list