[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