[pypy-commit] creflect default: copy loads of code from _cffi_backend.c
arigo
noreply at buildbot.pypy.org
Fri Dec 5 12:24:41 CET 2014
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r158:64bc5e56d01a
Date: 2014-12-05 12:24 +0100
http://bitbucket.org/cffi/creflect/changeset/64bc5e56d01a/
Log: copy loads of code from _cffi_backend.c
diff --git a/zeffir/builder.c b/zeffir/builder.c
--- a/zeffir/builder.c
+++ b/zeffir/builder.c
@@ -288,9 +288,12 @@
return ct;
}
-static _crx_type_t *zef_get_array_type(_crx_builder_t *cb, _crx_type_t *ctitem,
- size_t len)
+static _crx_type_t *_zef_array_type(_crx_builder_t *cb, _crx_type_t *ctitem,
+ size_t len, CTypeDescrObject *ctptr)
{
+ /* this function is called with different sets of non-NULL arguments
+ from various functions (just afterwards)
+ */
if (PyErr_Occurred())
return NULL;
@@ -315,9 +318,11 @@
if (name_obj == NULL)
return NULL;
- ct = get_cached_type(cb, name_obj);
- if (ct && (ct->ct_flags & CT_ARRAY))
- goto done;
+ if (cb != NULL) {
+ ct = get_cached_type(cb, name_obj);
+ if (ct && (ct->ct_flags & CT_ARRAY))
+ goto done;
+ }
if (length < 0) {
arraysize = -1;
@@ -331,6 +336,12 @@
}
}
+ if (ctptr == NULL) {
+ ctptr = zef_get_pointer_type(cb, ctitem, 0);
+ if (PyErr_Occurred())
+ goto done;
+ }
+
ct = ctypedescr_new(name_obj, ctitem->ct_name_position);
if (ct == NULL)
goto done;
@@ -338,18 +349,43 @@
ct->ct_size = arraysize;
ct->ct_length = length;
ct->ct_flags = CT_ARRAY;
+ Py_INCREF(ctptr);
+ ct->ct_stuff = (PyObject *)ctptr;
- put_cached_type(cb, name_obj, ct);
+ if (cb != NULL) {
+ if (length < 0 && ctptr->ct_stuff == NULL) {
+ Py_INCREF(ct);
+ ctptr->ct_stuff = (PyObject *)ct;
+ }
+ put_cached_type(cb, name_obj, ct);
+ }
+ else {
+ assert(length < 0);
+ assert(ctptr->ct_stuff == NULL);
+ ctptr->ct_stuff = (PyObject *)ct;
+ }
done:
Py_DECREF(name_obj);
return ct;
}
+static int fill_array_type(CTypeDescrObject *ctptr)
+{
+ _zef_array_type(NULL, ctptr->ct_itemdescr, (size_t)-1, ctptr);
+ return PyErr_Occurred() ? -1 : 0;
+}
+
+static _crx_type_t *zef_get_array_type(_crx_builder_t *cb, _crx_type_t *ctitem,
+ size_t len)
+{
+ return _zef_array_type(cb, ctitem, len, NULL);
+}
+
static _crx_type_t *zef_get_incomplete_array_type(_crx_builder_t *cb,
_crx_type_t *ctitem)
{
- return zef_get_array_type(cb, ctitem, (size_t)-1);
+ return _zef_array_type(cb, ctitem, (size_t)-1, NULL);
}
static _crx_type_t *zef_get_struct_type(_crx_builder_t *cb, const char *name)
diff --git a/zeffir/cdata.c b/zeffir/cdata.c
--- a/zeffir/cdata.c
+++ b/zeffir/cdata.c
@@ -6,6 +6,17 @@
PyObject *c_weakreflist;
} CDataObject;
+struct cfieldobject_s {
+ PyObject_HEAD
+ CTypeDescrObject *cf_type;
+ Py_ssize_t cf_offset;
+ short cf_bitshift; /* >= 0: bitshift; or BS_REGULAR or BS_EMPTY_ARRAY */
+ short cf_bitsize;
+ struct cfieldobject_s *cf_next;
+};
+#define BS_REGULAR (-1) /* a regular field, not with bitshift */
+#define BS_EMPTY_ARRAY (-2) /* a field which is an array 'type[0]' */
+
typedef union {
unsigned char m_char;
unsigned short m_short;
@@ -39,7 +50,763 @@
#define CDataOwn_Check(ob) (Py_TYPE(ob) == &CDataOwning_Type || \
Py_TYPE(ob) == &CDataOwningGC_Type)
+/************************************************************/
+static int
+CDataObject_Or_PyFloat_Check(PyObject *ob)
+{
+ return (PyFloat_Check(ob) ||
+ (CData_Check(ob) &&
+ (((CDataObject *)ob)->c_type->ct_flags & CT_PRIMITIVE_FLOAT)));
+}
+
+static PY_LONG_LONG
+_my_PyLong_AsLongLong(PyObject *ob)
+{
+ /* (possibly) convert and cast a Python object to a long long.
+ Like PyLong_AsLongLong(), this version accepts a Python int too, and
+ does convertions from other types of objects. The difference is that
+ this version refuses floats. */
+#if PY_MAJOR_VERSION < 3
+ if (PyInt_Check(ob)) {
+ return PyInt_AS_LONG(ob);
+ }
+ else
+#endif
+ if (PyLong_Check(ob)) {
+ return PyLong_AsLongLong(ob);
+ }
+ else {
+ PyObject *io;
+ PY_LONG_LONG res;
+ PyNumberMethods *nb = ob->ob_type->tp_as_number;
+
+ if (CDataObject_Or_PyFloat_Check(ob) ||
+ nb == NULL || nb->nb_int == NULL) {
+ PyErr_SetString(PyExc_TypeError, "an integer is required");
+ return -1;
+ }
+ io = (*nb->nb_int) (ob);
+ if (io == NULL)
+ return -1;
+
+ if (PyIntOrLong_Check(io)) {
+ res = _my_PyLong_AsLongLong(io);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "integer conversion failed");
+ res = -1;
+ }
+ Py_DECREF(io);
+ return res;
+ }
+}
+
+static unsigned PY_LONG_LONG
+_my_PyLong_AsUnsignedLongLong(PyObject *ob, int strict)
+{
+ /* (possibly) convert and cast a Python object to an unsigned long long.
+ Like PyLong_AsLongLong(), this version accepts a Python int too, and
+ does convertions from other types of objects. If 'strict', complains
+ with OverflowError and refuses floats. If '!strict', rounds floats
+ and masks the result. */
+#if PY_MAJOR_VERSION < 3
+ if (PyInt_Check(ob)) {
+ long value1 = PyInt_AS_LONG(ob);
+ if (strict && value1 < 0)
+ goto negative;
+ return (unsigned PY_LONG_LONG)(PY_LONG_LONG)value1;
+ }
+ else
+#endif
+ if (PyLong_Check(ob)) {
+ if (strict) {
+ if (_PyLong_Sign(ob) < 0)
+ goto negative;
+ return PyLong_AsUnsignedLongLong(ob);
+ }
+ else {
+ return PyLong_AsUnsignedLongLongMask(ob);
+ }
+ }
+ else {
+ PyObject *io;
+ unsigned PY_LONG_LONG res;
+ PyNumberMethods *nb = ob->ob_type->tp_as_number;
+
+ if ((strict && CDataObject_Or_PyFloat_Check(ob)) ||
+ nb == NULL || nb->nb_int == NULL) {
+ PyErr_SetString(PyExc_TypeError, "an integer is required");
+ return (unsigned PY_LONG_LONG)-1;
+ }
+ io = (*nb->nb_int) (ob);
+ if (io == NULL)
+ return (unsigned PY_LONG_LONG)-1;
+
+ if (PyIntOrLong_Check(io)) {
+ res = _my_PyLong_AsUnsignedLongLong(io, strict);
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError, "integer conversion failed");
+ res = (unsigned PY_LONG_LONG)-1;
+ }
+ Py_DECREF(io);
+ return res;
+ }
+
+ negative:
+ PyErr_SetString(PyExc_OverflowError,
+ "can't convert negative number to unsigned");
+ return (unsigned PY_LONG_LONG)-1;
+}
+
+#define _read_raw_data(type) \
+ do { \
+ if (size == sizeof(type)) { \
+ type r; \
+ memcpy(&r, target, sizeof(type)); \
+ return r; \
+ } \
+ } while(0)
+
+static PY_LONG_LONG
+read_raw_signed_data(char *target, int size)
+{
+ _read_raw_data(signed char);
+ _read_raw_data(short);
+ _read_raw_data(int);
+ _read_raw_data(long);
+ _read_raw_data(PY_LONG_LONG);
+ Py_FatalError("read_raw_signed_data: bad integer size");
+ return 0;
+}
+
+static unsigned PY_LONG_LONG
+read_raw_unsigned_data(char *target, int size)
+{
+ _read_raw_data(unsigned char);
+ _read_raw_data(unsigned short);
+ _read_raw_data(unsigned int);
+ _read_raw_data(unsigned long);
+ _read_raw_data(unsigned PY_LONG_LONG);
+ Py_FatalError("read_raw_unsigned_data: bad integer size");
+ return 0;
+}
+
+#define _write_raw_data(type) \
+ do { \
+ if (size == sizeof(type)) { \
+ type r = (type)source; \
+ memcpy(target, &r, sizeof(type)); \
+ return; \
+ } \
+ } while(0)
+
+static void
+write_raw_integer_data(char *target, unsigned PY_LONG_LONG source, int size)
+{
+ _write_raw_data(unsigned char);
+ _write_raw_data(unsigned short);
+ _write_raw_data(unsigned int);
+ _write_raw_data(unsigned long);
+ _write_raw_data(unsigned PY_LONG_LONG);
+ Py_FatalError("write_raw_integer_data: bad integer size");
+}
+
+static double
+read_raw_float_data(char *target, int size)
+{
+ _read_raw_data(float);
+ _read_raw_data(double);
+ Py_FatalError("read_raw_float_data: bad float size");
+ return 0;
+}
+
+static long double
+read_raw_longdouble_data(char *target)
+{
+ int size = sizeof(long double);
+ _read_raw_data(long double);
+ Py_FatalError("read_raw_longdouble_data: bad long double size");
+ return 0;
+}
+
+static void
+write_raw_float_data(char *target, double source, int size)
+{
+ _write_raw_data(float);
+ _write_raw_data(double);
+ Py_FatalError("write_raw_float_data: bad float size");
+}
+
+static void
+write_raw_longdouble_data(char *target, long double source)
+{
+ int size = sizeof(long double);
+ _write_raw_data(long double);
+}
+
+static PyObject *
+new_simple_cdata(char *data, CTypeDescrObject *ct)
+{
+ CDataObject *cd = PyObject_New(CDataObject, &CData_Type);
+ if (cd == NULL)
+ return NULL;
+ Py_INCREF(ct);
+ cd->c_data = data;
+ cd->c_type = ct;
+ cd->c_weakreflist = NULL;
+ return (PyObject *)cd;
+}
+
+static CDataObject *_new_casted_primitive(CTypeDescrObject *ct)
+{
+ int dataoffset = offsetof(CDataObject_casted_primitive, alignment);
+ CDataObject *cd = (CDataObject *)PyObject_Malloc(dataoffset + ct->ct_size);
+ if (PyObject_Init((PyObject *)cd, &CData_Type) == NULL)
+ return NULL;
+ Py_INCREF(ct);
+ cd->c_type = ct;
+ cd->c_data = ((char*)cd) + dataoffset;
+ cd->c_weakreflist = NULL;
+ return cd;
+}
+
+//845
+static PyObject *convert_to_object(char *data, CTypeDescrObject *ct)
+{
+ if (!(ct->ct_flags & CT_PRIMITIVE_ANY)) {
+ /* non-primitive types (check done just for performance) */
+ if (ct->ct_flags & CT_POINTER) {
+ char *ptrdata = *(char **)data;
+ /*READ(data, sizeof(char *))*/
+ return new_simple_cdata(ptrdata, ct);
+ }
+ else if (ct->ct_flags & CT_ARRAY) {
+ if (ct->ct_length < 0) {
+ /* we can't return a <cdata 'int[]'> here, because we don't
+ know the length to give it. As a compromize, returns
+ <cdata 'int *'> in this case. */
+ ct = (CTypeDescrObject *)ct->ct_stuff;
+ }
+ return new_simple_cdata(data, ct);
+ }
+ else if (ct->ct_size < 0) {
+ PyErr_Format(PyExc_TypeError, "cdata '%s' is opaque",
+ ct->ct_name);
+ return NULL;
+ }
+ else if (ct->ct_flags & (CT_STRUCT|CT_UNION)) {
+ return new_simple_cdata(data, ct);
+ }
+ }
+ else if (ct->ct_flags & CT_PRIMITIVE_SIGNED) {
+ PY_LONG_LONG value;
+ /*READ(data, ct->ct_size)*/
+ value = read_raw_signed_data(data, ct->ct_size);
+ if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG)
+ return PyInt_FromLong((long)value);
+ else
+ return PyLong_FromLongLong(value);
+ }
+ else if (ct->ct_flags & CT_PRIMITIVE_UNSIGNED) {
+ unsigned PY_LONG_LONG value;
+ /*READ(data, ct->ct_size)*/
+ value = read_raw_unsigned_data(data, ct->ct_size);
+
+ if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG)
+ return PyInt_FromLong((long)value);
+ else
+ return PyLong_FromUnsignedLongLong(value);
+ }
+ else if (ct->ct_flags & CT_PRIMITIVE_FLOAT) {
+ /*READ(data, ct->ct_size)*/
+ if (!(ct->ct_flags & CT_IS_LONGDOUBLE)) {
+ double value = read_raw_float_data(data, ct->ct_size);
+ return PyFloat_FromDouble(value);
+ }
+ else {
+ long double value = read_raw_longdouble_data(data);
+ CDataObject *cd = _new_casted_primitive(ct);
+ if (cd != NULL)
+ write_raw_longdouble_data(cd->c_data, value);
+ return (PyObject *)cd;
+ }
+ }
+ else if (ct->ct_flags & CT_PRIMITIVE_CHAR) {
+ /*READ(data, ct->ct_size)*/
+ return PyBytes_FromStringAndSize(data, 1);
+ }
+
+ PyErr_Format(PyExc_SystemError,
+ "convert_to_object: '%s'", ct->ct_name);
+ return NULL;
+}
+
+#if 0
+static PyObject *
+convert_to_object_bitfield(char *data, CFieldObject *cf)
+{
+ CTypeDescrObject *ct = cf->cf_type;
+ /*READ(data, ct->ct_size)*/
+
+ if (ct->ct_flags & CT_PRIMITIVE_SIGNED) {
+ unsigned PY_LONG_LONG value, valuemask, shiftforsign;
+ PY_LONG_LONG result;
+
+ value = (unsigned PY_LONG_LONG)read_raw_signed_data(data, ct->ct_size);
+ valuemask = (1ULL << cf->cf_bitsize) - 1ULL;
+ shiftforsign = 1ULL << (cf->cf_bitsize - 1);
+ value = ((value >> cf->cf_bitshift) + shiftforsign) & valuemask;
+ result = ((PY_LONG_LONG)value) - (PY_LONG_LONG)shiftforsign;
+
+ if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG)
+ return PyInt_FromLong((long)result);
+ else
+ return PyLong_FromLongLong(result);
+ }
+ else {
+ unsigned PY_LONG_LONG value, valuemask;
+
+ value = read_raw_unsigned_data(data, ct->ct_size);
+ valuemask = (1ULL << cf->cf_bitsize) - 1ULL;
+ value = (value >> cf->cf_bitshift) & valuemask;
+
+ if (ct->ct_flags & CT_PRIMITIVE_FITS_LONG)
+ return PyInt_FromLong((long)value);
+ else
+ return PyLong_FromUnsignedLongLong(value);
+ }
+}
+#endif
+
+static int _convert_overflow(PyObject *init, const char *ct_name)
+{
+ PyObject *s;
+ if (PyErr_Occurred()) /* already an exception pending */
+ return -1;
+ s = PyObject_Str(init);
+ if (s == NULL)
+ return -1;
+ PyErr_Format(PyExc_OverflowError, "integer %s does not fit '%s'",
+ PyText_AS_UTF8(s), ct_name);
+ Py_DECREF(s);
+ return -1;
+}
+
+static int _convert_to_char(PyObject *init)
+{
+ if (PyBytes_Check(init) && PyBytes_GET_SIZE(init) == 1) {
+ return (unsigned char)(PyBytes_AS_STRING(init)[0]);
+ }
+ if (CData_Check(init) &&
+ (((CDataObject *)init)->c_type->ct_flags & CT_PRIMITIVE_CHAR)) {
+ char *data = ((CDataObject *)init)->c_data;
+ /*READ(data, 1)*/
+ return *(unsigned char *)data;
+ }
+ PyErr_Format(PyExc_TypeError,
+ "initializer for ctype 'char' must be a "STR_OR_BYTES
+ " of length 1, not %.200s", Py_TYPE(init)->tp_name);
+ return -1;
+}
+
+//1009
+static int _convert_error(PyObject *init, const char *ct_name,
+ const char *expected)
+{
+ if (CData_Check(init))
+ PyErr_Format(PyExc_TypeError,
+ "initializer for ctype '%s' must be a %s, "
+ "not cdata '%s'",
+ ct_name, expected,
+ ((CDataObject *)init)->c_type->ct_name);
+ else
+ PyErr_Format(PyExc_TypeError,
+ "initializer for ctype '%s' must be a %s, "
+ "not %.200s",
+ ct_name, expected, Py_TYPE(init)->tp_name);
+ return -1;
+}
+
+//1031
+static Py_ssize_t get_new_array_length(PyObject **pvalue)
+{
+ PyObject *value = *pvalue;
+
+ if (PyList_Check(value) || PyTuple_Check(value)) {
+ return PySequence_Fast_GET_SIZE(value);
+ }
+ else if (PyBytes_Check(value)) {
+ /* from a string, we add the null terminator */
+ return PyBytes_GET_SIZE(value) + 1;
+ }
+ else {
+ Py_ssize_t explicitlength;
+ explicitlength = PyNumber_AsSsize_t(value, PyExc_OverflowError);
+ if (explicitlength < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_ValueError, "negative array length");
+ return -1;
+ }
+ *pvalue = Py_None;
+ return explicitlength;
+ }
+}
+
+//1061
+static int convert_field_from_object(char *data, CFieldObject *cf,
+ PyObject *value)
+{
+ data += cf->cf_offset;
+ if (cf->cf_bitshift >= 0)
+ return convert_from_object_bitfield(data, cf, value);
+ else
+ return convert_from_object(data, cf->cf_type, value);
+}
+
+//1071
+static int convert_vfield_from_object(char *data, CFieldObject *cf,
+ PyObject *value, Py_ssize_t *optvarsize)
+{
+ /* a special case for var-sized C99 arrays */
+ if ((cf->cf_type->ct_flags & CT_ARRAY) && cf->cf_type->ct_size < 0) {
+ Py_ssize_t varsizelength = get_new_array_length(&value);
+ if (varsizelength < 0)
+ return -1;
+ if (optvarsize != NULL) {
+ /* in this mode, the only purpose of this function is to compute
+ the real size of the structure from a var-sized C99 array */
+ Py_ssize_t size, itemsize;
+ assert(data == NULL);
+ itemsize = cf->cf_type->ct_itemdescr->ct_size;
+ size = cf->cf_offset + itemsize * varsizelength;
+ if (size < 0 ||
+ ((size - cf->cf_offset) / itemsize) != varsizelength) {
+ PyErr_SetString(PyExc_OverflowError,
+ "array size would overflow a Py_ssize_t");
+ return -1;
+ }
+ if (size > *optvarsize)
+ *optvarsize = size;
+ return 0;
+ }
+ /* if 'value' was only an integer, get_new_array_length() returns
+ it and convert 'value' to be None. Detect if this was the case,
+ and if so, stop here, leaving the content uninitialized
+ (it should be zero-initialized from somewhere else). */
+ if (value == Py_None)
+ return 0;
+ }
+ if (optvarsize == NULL)
+ return convert_field_from_object(data, cf, value);
+ else
+ return 0;
+}
+
+//1110
+static int convert_array_from_object(char *data, CTypeDescrObject *ct,
+ PyObject *init)
+{
+ /* used by convert_from_object(), and also to decode lists/tuples/unicodes
+ passed as function arguments. 'ct' is an CT_ARRAY in the first case
+ and a CT_POINTER in the second case. */
+ const char *expected;
+ CTypeDescrObject *ctitem = ct->ct_itemdescr;
+
+ if (PyList_Check(init) || PyTuple_Check(init)) {
+ PyObject **items;
+ Py_ssize_t i, n;
+ n = PySequence_Fast_GET_SIZE(init);
+ if (ct->ct_length >= 0 && n > ct->ct_length) {
+ PyErr_Format(PyExc_IndexError,
+ "too many initializers for '%s' (got %zd)",
+ ct->ct_name, n);
+ return -1;
+ }
+ items = PySequence_Fast_ITEMS(init);
+ for (i=0; i<n; i++) {
+ if (convert_from_object(data, ctitem, items[i]) < 0)
+ return -1;
+ data += ctitem->ct_size;
+ }
+ return 0;
+ }
+ else if ((ctitem->ct_flags & (CT_PRIMITIVE_CHAR |
+ CT_PRIMITIVE_SIGNED |
+ CT_PRIMITIVE_UNSIGNED))
+ && (ctitem->ct_size == sizeof(char))) {
+ char *srcdata;
+ Py_ssize_t n;
+ if (!PyBytes_Check(init)) {
+ expected = STR_OR_BYTES" or list or tuple";
+ goto cannot_convert;
+ }
+ n = PyBytes_GET_SIZE(init);
+ if (ct->ct_length >= 0 && n > ct->ct_length) {
+ PyErr_Format(PyExc_IndexError,
+ "initializer "STR_OR_BYTES" is too long for '%s' "
+ "(got %zd characters)", ct->ct_name, n);
+ return -1;
+ }
+ if (n != ct->ct_length)
+ n++;
+ srcdata = PyBytes_AS_STRING(init);
+ memcpy(data, srcdata, n);
+ return 0;
+ }
+ else {
+ expected = "list or tuple";
+ goto cannot_convert;
+ }
+
+ cannot_convert:
+ return _convert_error(init, ct->ct_name, expected);
+}
+
+//1190
+static int convert_struct_from_object(char *data, CTypeDescrObject *ct,
+ PyObject *init, Py_ssize_t *optvarsize)
+{
+ const char *expected;
+
+ if (ct->ct_flags & CT_UNION) {
+ Py_ssize_t n = PyObject_Size(init);
+ if (n < 0)
+ return -1;
+ if (n > 1) {
+ PyErr_Format(PyExc_ValueError,
+ "initializer for '%s': %zd items given, but "
+ "only one supported (use a dict if needed)",
+ ct->ct_name, n);
+ return -1;
+ }
+ }
+ if (PyList_Check(init) || PyTuple_Check(init)) {
+ PyObject **items = PySequence_Fast_ITEMS(init);
+ Py_ssize_t i, n = PySequence_Fast_GET_SIZE(init);
+ CFieldObject *cf = (CFieldObject *)ct->ct_extra;
+
+ for (i=0; i<n; i++) {
+ if (cf == NULL) {
+ PyErr_Format(PyExc_ValueError,
+ "too many initializers for '%s' (got %zd)",
+ ct->ct_name, n);
+ return -1;
+ }
+ if (convert_vfield_from_object(data, cf, items[i], optvarsize) < 0)
+ return -1;
+ cf = cf->cf_next;
+ }
+ return 0;
+ }
+ if (PyDict_Check(init)) {
+ PyObject *d_key, *d_value;
+ Py_ssize_t i = 0;
+ CFieldObject *cf;
+
+ while (PyDict_Next(init, &i, &d_key, &d_value)) {
+ cf = (CFieldObject *)PyDict_GetItem(ct->ct_stuff, d_key);
+ if (cf == NULL) {
+ PyErr_SetObject(PyExc_KeyError, d_key);
+ return -1;
+ }
+ if (convert_vfield_from_object(data, cf, d_value, optvarsize) < 0)
+ return -1;
+ }
+ return 0;
+ }
+ expected = optvarsize == NULL ? "list or tuple or dict or struct-cdata"
+ : "list or tuple or dict";
+ return _convert_error(init, ct->ct_name, expected);
+}
+
+#ifdef __GNUC__
+# if __GNUC__ >= 4
+/* Don't go inlining this huge function. Needed because occasionally
+ it gets inlined in places where is causes a warning: call to
+ __builtin___memcpy_chk will always overflow destination buffer
+ (which is places where the 'ct' should never represent such a large
+ primitive type anyway). */
+__attribute__((noinline))
+# endif
+#endif
+//1257
+static int convert_from_object(char *data, CTypeDescrObject *ct, PyObject *init)
+{
+ const char *expected;
+ char buf[sizeof(PY_LONG_LONG)];
+
+ /*if (ct->ct_size > 0)*/
+ /*WRITE(data, ct->ct_size)*/
+
+ if (ct->ct_flags & CT_ARRAY) {
+ return convert_array_from_object(data, ct, init);
+ }
+ if (ct->ct_flags & CT_POINTER) {
+ char *ptrdata;
+ CTypeDescrObject *ctinit;
+
+ if (!CData_Check(init)) {
+ expected = "cdata pointer";
+ goto cannot_convert;
+ }
+ ctinit = ((CDataObject *)init)->c_type;
+ if (!(ctinit->ct_flags & CT_POINTER)) {
+ if (ctinit->ct_flags & CT_ARRAY)
+ ctinit = (CTypeDescrObject *)ctinit->ct_stuff;
+ else {
+ expected = "pointer or array";
+ goto cannot_convert;
+ }
+ }
+ if (ctinit != ct) {
+ if ((ct->ct_flags & CT_CAST_ANYTHING) ||
+ (ctinit->ct_flags & CT_CAST_ANYTHING))
+ ; /* accept void* or char* as either source or target */
+ else {
+ expected = "pointer to same type";
+ goto cannot_convert;
+ }
+ }
+ ptrdata = ((CDataObject *)init)->c_data;
+
+ *(char **)data = ptrdata;
+ return 0;
+ }
+ if (ct->ct_flags & CT_PRIMITIVE_SIGNED) {
+ PY_LONG_LONG value = _my_PyLong_AsLongLong(init);
+ if (value == -1 && PyErr_Occurred())
+ return -1;
+ write_raw_integer_data(buf, value, ct->ct_size);
+ if (value != read_raw_signed_data(buf, ct->ct_size))
+ goto overflow;
+ write_raw_integer_data(data, value, ct->ct_size);
+ return 0;
+ }
+ if (ct->ct_flags & CT_PRIMITIVE_UNSIGNED) {
+ unsigned PY_LONG_LONG value = _my_PyLong_AsUnsignedLongLong(init, 1);
+ if (value == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())
+ return -1;
+ if (ct->ct_flags & CT_IS_BOOL)
+ if (value & ~1) /* value != 0 && value != 1 */
+ goto overflow;
+ write_raw_integer_data(buf, value, ct->ct_size);
+ if (value != read_raw_unsigned_data(buf, ct->ct_size))
+ goto overflow;
+ write_raw_integer_data(data, value, ct->ct_size);
+ return 0;
+ }
+ if (ct->ct_flags & CT_PRIMITIVE_FLOAT) {
+ double value;
+ if ((ct->ct_flags & CT_IS_LONGDOUBLE) &&
+ CData_Check(init) &&
+ (((CDataObject *)init)->c_type->ct_flags & CT_IS_LONGDOUBLE)) {
+ long double lvalue;
+ char *initdata = ((CDataObject *)init)->c_data;
+ /*READ(initdata, sizeof(long double))*/
+ lvalue = read_raw_longdouble_data(initdata);
+ write_raw_longdouble_data(data, lvalue);
+ return 0;
+ }
+ value = PyFloat_AsDouble(init);
+ if (value == -1.0 && PyErr_Occurred())
+ return -1;
+ if (!(ct->ct_flags & CT_IS_LONGDOUBLE))
+ write_raw_float_data(data, value, ct->ct_size);
+ else
+ write_raw_longdouble_data(data, (long double)value);
+ return 0;
+ }
+ if (ct->ct_flags & CT_PRIMITIVE_CHAR) {
+ int res;
+ assert(ct->ct_size == sizeof(char));
+ res = _convert_to_char(init);
+ if (res < 0)
+ return -1;
+ data[0] = res;
+ return 0;
+ }
+ if (ct->ct_flags & (CT_STRUCT|CT_UNION)) {
+
+ if (CData_Check(init)) {
+ if (((CDataObject *)init)->c_type == ct && ct->ct_size >= 0) {
+ memcpy(data, ((CDataObject *)init)->c_data, ct->ct_size);
+ return 0;
+ }
+ }
+ return convert_struct_from_object(data, ct, init, NULL);
+ }
+ PyErr_Format(PyExc_SystemError,
+ "convert_from_object: '%s'", ct->ct_name);
+ return -1;
+
+ overflow:
+ return _convert_overflow(init, ct->ct_name);
+
+ cannot_convert:
+ return _convert_error(init, ct->ct_name, expected);
+}
+
+//1383
+static int convert_from_object_bitfield(char *data, CFieldObject *cf,
+ PyObject *init)
+{
+ CTypeDescrObject *ct = cf->cf_type;
+ PY_LONG_LONG fmin, fmax, value = PyLong_AsLongLong(init);
+ unsigned PY_LONG_LONG rawfielddata, rawvalue, rawmask;
+ if (value == -1 && PyErr_Occurred())
+ return -1;
+
+ if (ct->ct_flags & CT_PRIMITIVE_SIGNED) {
+ fmin = -(1LL << (cf->cf_bitsize-1));
+ fmax = (1LL << (cf->cf_bitsize-1)) - 1LL;
+ if (fmax == 0)
+ fmax = 1; /* special case to let "int x:1" receive "1" */
+ }
+ else {
+ fmin = 0LL;
+ fmax = (PY_LONG_LONG)((1ULL << cf->cf_bitsize) - 1ULL);
+ }
+ if (value < fmin || value > fmax) {
+ /* phew, PyErr_Format does not support "%lld" in Python 2.6 */
+ PyObject *svalue = NULL, *sfmin = NULL, *sfmax = NULL;
+ PyObject *lfmin = NULL, *lfmax = NULL;
+ svalue = PyObject_Str(init);
+ if (svalue == NULL) goto skip;
+ lfmin = PyLong_FromLongLong(fmin);
+ if (lfmin == NULL) goto skip;
+ sfmin = PyObject_Str(lfmin);
+ if (sfmin == NULL) goto skip;
+ lfmax = PyLong_FromLongLong(fmax);
+ if (lfmax == NULL) goto skip;
+ sfmax = PyObject_Str(lfmax);
+ if (sfmax == NULL) goto skip;
+ PyErr_Format(PyExc_OverflowError,
+ "value %s outside the range allowed by the "
+ "bit field width: %s <= x <= %s",
+ PyText_AS_UTF8(svalue),
+ PyText_AS_UTF8(sfmin),
+ PyText_AS_UTF8(sfmax));
+ skip:
+ Py_XDECREF(svalue);
+ Py_XDECREF(sfmin);
+ Py_XDECREF(sfmax);
+ Py_XDECREF(lfmin);
+ Py_XDECREF(lfmax);
+ return -1;
+ }
+
+ rawmask = ((1ULL << cf->cf_bitsize) - 1ULL) << cf->cf_bitshift;
+ rawvalue = ((unsigned PY_LONG_LONG)value) << cf->cf_bitshift;
+ /*WRITE(data, ct->ct_size)*/
+ rawfielddata = read_raw_unsigned_data(data, ct->ct_size);
+ rawfielddata = (rawfielddata & ~rawmask) | (rawvalue & rawmask);
+ write_raw_integer_data(data, rawfielddata, ct->ct_size);
+ return 0;
+}
+
+//1440
static Py_ssize_t get_array_length(CDataObject *cd)
{
if (cd->c_type->ct_length < 0)
@@ -49,6 +816,7 @@
}
+//1480
static void cdata_dealloc(CDataObject *cd)
{
if (cd->c_weakreflist != NULL)
@@ -60,6 +828,7 @@
#endif
}
+//1491
static void cdataowninggc_dealloc(CDataObject *cd)
{
abort();
@@ -83,6 +852,7 @@
#endif
}
+//1534
static int cdataowninggc_traverse(CDataObject *cd, visitproc visit, void *arg)
{
abort();
@@ -100,6 +870,7 @@
#endif
}
+//1548
static int cdataowninggc_clear(CDataObject *cd)
{
abort();
@@ -120,6 +891,7 @@
#endif
}
+//1599
static PyObject *cdata_repr(CDataObject *cd)
{
char *extra;
@@ -174,6 +946,7 @@
return result;
}
+//1650
static PyObject *_cdata_repr2(CDataObject *cd, char *text, PyObject *x)
{
PyObject *res, *s = PyObject_Repr(x);
@@ -185,6 +958,7 @@
return res;
}
+//1661
static PyObject *cdataowning_repr(CDataObject *cd)
{
Py_ssize_t size;
@@ -223,6 +997,253 @@
}
}
+//1815
+static Py_ssize_t cdata_length(CDataObject *cd)
+{
+ if (cd->c_type->ct_flags & CT_ARRAY) {
+ return get_array_length(cd);
+ }
+ PyErr_Format(PyExc_TypeError, "cdata of type '%s' has no len()",
+ cd->c_type->ct_name);
+ return -1;
+}
+
+//1826
+static char *_cdata_get_indexed_ptr(CDataObject *cd, PyObject *key)
+{
+ Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
+ if (i == -1 && PyErr_Occurred())
+ return NULL;
+
+ if (cd->c_type->ct_flags & CT_POINTER) {
+ if (CDataOwn_Check(cd) && i != 0) {
+ PyErr_Format(PyExc_IndexError,
+ "cdata '%s' can only be indexed by 0",
+ cd->c_type->ct_name);
+ return NULL;
+ }
+ }
+ else if (cd->c_type->ct_flags & CT_ARRAY) {
+ if (i < 0) {
+ PyErr_SetString(PyExc_IndexError,
+ "negative index not supported");
+ return NULL;
+ }
+ if (i >= get_array_length(cd)) {
+ PyErr_Format(PyExc_IndexError,
+ "index too large for cdata '%s' (expected %zd < %zd)",
+ cd->c_type->ct_name,
+ i, get_array_length(cd));
+ return NULL;
+ }
+ }
+ else {
+ PyErr_Format(PyExc_TypeError, "cdata of type '%s' cannot be indexed",
+ cd->c_type->ct_name);
+ return NULL;
+ }
+ return cd->c_data + i * cd->c_type->ct_itemdescr->ct_size;
+}
+
+//1866
+static CTypeDescrObject *
+_cdata_getslicearg(CDataObject *cd, PySliceObject *slice, Py_ssize_t bounds[])
+{
+ Py_ssize_t start, stop;
+ CTypeDescrObject *ct;
+
+ start = PyInt_AsSsize_t(slice->start);
+ if (start == -1 && PyErr_Occurred()) {
+ if (slice->start == Py_None)
+ PyErr_SetString(PyExc_IndexError, "slice start must be specified");
+ return NULL;
+ }
+ stop = PyInt_AsSsize_t(slice->stop);
+ if (stop == -1 && PyErr_Occurred()) {
+ if (slice->stop == Py_None)
+ PyErr_SetString(PyExc_IndexError, "slice stop must be specified");
+ return NULL;
+ }
+ if (slice->step != Py_None) {
+ PyErr_SetString(PyExc_IndexError, "slice with step not supported");
+ return NULL;
+ }
+ if (start > stop) {
+ PyErr_SetString(PyExc_IndexError, "slice start > stop");
+ return NULL;
+ }
+
+ ct = cd->c_type;
+ if (ct->ct_flags & CT_ARRAY) {
+ if (start < 0) {
+ PyErr_SetString(PyExc_IndexError,
+ "negative index not supported");
+ return NULL;
+ }
+ if (stop > get_array_length(cd)) {
+ PyErr_Format(PyExc_IndexError,
+ "index too large (expected %zd <= %zd)",
+ stop, get_array_length(cd));
+ return NULL;
+ }
+ ct = (CTypeDescrObject *)ct->ct_stuff;
+ }
+ else if (!(ct->ct_flags & CT_POINTER)) {
+ PyErr_Format(PyExc_TypeError, "cdata of type '%s' cannot be indexed",
+ ct->ct_name);
+ return NULL;
+ }
+
+ bounds[0] = start;
+ bounds[1] = stop - start;
+ return ct;
+}
+
+//1919
+static PyObject *cdata_slice(CDataObject *cd, PySliceObject *slice)
+{
+ Py_ssize_t bounds[2];
+ CDataObject_own_length *scd;
+ CTypeDescrObject *ct = _cdata_getslicearg(cd, slice, bounds);
+ if (ct == NULL)
+ return NULL;
+
+ if (ct->ct_stuff == NULL) {
+ if (fill_array_type(ct) < 0)
+ return NULL;
+ assert(ct->ct_stuff != NULL);
+ }
+ ct = (CTypeDescrObject *)ct->ct_stuff;
+
+ scd = (CDataObject_own_length *)PyObject_Malloc(
+ offsetof(CDataObject_own_length, alignment));
+ if (PyObject_Init((PyObject *)scd, &CData_Type) == NULL)
+ return NULL;
+ Py_INCREF(ct);
+ scd->head.c_type = ct;
+ scd->head.c_data = cd->c_data + ct->ct_itemdescr->ct_size * bounds[0];
+ scd->head.c_weakreflist = NULL;
+ scd->length = bounds[1];
+ return (PyObject *)scd;
+}
+
+//1947
+static int cdata_ass_slice(CDataObject *cd, PySliceObject *slice, PyObject *v)
+{
+ Py_ssize_t bounds[2], i, length, itemsize;
+ PyObject *it, *item;
+ PyObject *(*iternext)(PyObject *);
+ char *cdata;
+ int err;
+ CTypeDescrObject *ct = _cdata_getslicearg(cd, slice, bounds);
+ if (ct == NULL)
+ return -1;
+ ct = ct->ct_itemdescr;
+ itemsize = ct->ct_size;
+ cdata = cd->c_data + itemsize * bounds[0];
+ length = bounds[1];
+
+ if (CData_Check(v)) {
+ CTypeDescrObject *ctv = ((CDataObject *)v)->c_type;
+ if ((ctv->ct_flags & CT_ARRAY) && (ctv->ct_itemdescr == ct) &&
+ (get_array_length((CDataObject *)v) == length)) {
+ /* fast path: copying from exactly the correct type */
+ memmove(cdata, ((CDataObject *)v)->c_data, itemsize * length);
+ return 0;
+ }
+ }
+
+ /* A fast path for <char[]>[0:N] = b"somestring", which also adds
+ support for Python 3: otherwise, you get integers while enumerating
+ the string, and you can't set them to characters :-/
+ */
+ if (PyBytes_Check(v) && (ct->ct_flags & CT_PRIMITIVE_CHAR)) {
+ if (PyBytes_GET_SIZE(v) != length) {
+ PyErr_Format(PyExc_ValueError,
+ "need a string of length %zd, got %zd",
+ length, PyBytes_GET_SIZE(v));
+ return -1;
+ }
+ memcpy(cdata, PyBytes_AS_STRING(v), length);
+ return 0;
+ }
+
+ it = PyObject_GetIter(v);
+ if (it == NULL)
+ return -1;
+ iternext = *it->ob_type->tp_iternext;
+
+ for (i = 0; i < length; i++) {
+ item = iternext(it);
+ if (item == NULL) {
+ if (!PyErr_Occurred())
+ PyErr_Format(PyExc_ValueError,
+ "need %zd values to unpack, got %zd",
+ length, i);
+ goto error;
+ }
+ err = convert_from_object(cdata, ct, item);
+ Py_DECREF(item);
+ if (err < 0)
+ goto error;
+
+ cdata += itemsize;
+ }
+ item = iternext(it);
+ if (item != NULL) {
+ Py_DECREF(item);
+ PyErr_Format(PyExc_ValueError,
+ "got more than %zd values to unpack", length);
+ }
+ error:
+ Py_DECREF(it);
+ return PyErr_Occurred() ? -1 : 0;
+}
+
+//2044
+static PyObject *cdata_subscript(CDataObject *cd, PyObject *key)
+{
+ char *c;
+ if (PySlice_Check(key))
+ return cdata_slice(cd, (PySliceObject *)key);
+
+ c = _cdata_get_indexed_ptr(cd, key);
+ /* use 'mp_subscript' instead of 'sq_item' because we don't want
+ negative indexes to be corrected automatically */
+ if (c == NULL && PyErr_Occurred())
+ return NULL;
+ return convert_to_object(c, cd->c_type->ct_itemdescr);
+}
+
+//2059
+static int cdata_ass_sub(CDataObject *cd, PyObject *key, PyObject *v)
+{
+ char *c;
+ CTypeDescrObject *ctitem;
+ if (PySlice_Check(key))
+ return cdata_ass_slice(cd, (PySliceObject *)key, v);
+
+ c = _cdata_get_indexed_ptr(cd, key);
+ ctitem = cd->c_type->ct_itemdescr;
+ /* use 'mp_ass_subscript' instead of 'sq_ass_item' because we don't want
+ negative indexes to be corrected automatically */
+ if (c == NULL && PyErr_Occurred())
+ return -1;
+ if (v == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "'del x[n]' not supported for cdata objects");
+ return -1;
+ }
+ return convert_from_object(c, ctitem, v);
+}
+
+
+static PyMappingMethods CData_as_mapping = {
+ (lenfunc)cdata_length, /*mp_length*/
+ (binaryfunc)cdata_subscript, /*mp_subscript*/
+ (objobjargproc)cdata_ass_sub, /*mp_ass_subscript*/
+};
+
static PyTypeObject CData_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"zeffir.CData",
@@ -236,7 +1257,7 @@
(reprfunc)cdata_repr, /* tp_repr */
0,//&CData_as_number, /* tp_as_number */
0, /* tp_as_sequence */
- 0,//&CData_as_mapping, /* tp_as_mapping */
+ &CData_as_mapping, /* tp_as_mapping */
0,//(hashfunc)cdata_hash, /* tp_hash */
0,//(ternaryfunc)cdata_call, /* tp_call */
0, /* tp_str */
diff --git a/zeffir/ctype.c b/zeffir/ctype.c
--- a/zeffir/ctype.c
+++ b/zeffir/ctype.c
@@ -30,13 +30,12 @@
CTypeDescrObject *ct_itemdescr; /* ptrs and arrays: the item type */
PyObject *ct_stuff; /* structs: dict of the fields
- //arrays: ctypedescr of the ptr type
+ arrays: ctypedescr of the ptr type
function: tuple(abi, ctres, ctargs..)
enum: pair {"name":x},{x:"name"}
ptrs: lazily, ctypedescr of array */
- //void *ct_extra; /* structs: first field (not a ref!)
- // function types: cif_description
- // primitives: prebuilt "cif" object */
+ void *ct_extra; /* structs: first field (not a ref!)
+ function types: cif_description */
PyObject *ct_weakreflist; /* weakref support */
@@ -75,7 +74,7 @@
static PyObject *ctypedescr_repr(CTypeDescrObject *ct)
{
- return PyString_FromFormat("<ctype '%s'>", ct->ct_name);
+ return PyText_FromFormat("<ctype '%s'>", ct->ct_name);
}
static void ctypedescr_dealloc(CTypeDescrObject *ct)
diff --git a/zeffir/ffi_obj.c b/zeffir/ffi_obj.c
--- a/zeffir/ffi_obj.c
+++ b/zeffir/ffi_obj.c
@@ -121,12 +121,12 @@
/* Returns the CTypeDescrObject from the user-supplied 'arg'.
Does not return a new reference!
*/
- if ((accept & ACCEPT_STRING) && PyString_Check(arg)) {
+ if ((accept & ACCEPT_STRING) && PyText_Check(arg)) {
PyObject *x = PyDict_GetItem(ffi->types_dict, arg);
if (x != NULL && CTypeDescr_Check(x))
return (CTypeDescrObject *)x;
- CTypeDescrObject *ct = parse_c_decl(ffi, PyString_AS_STRING(arg));
+ CTypeDescrObject *ct = parse_c_decl(ffi, PyText_AS_UTF8(arg));
if (ct == NULL)
return NULL;
diff --git a/zeffir/lib_obj.c b/zeffir/lib_obj.c
--- a/zeffir/lib_obj.c
+++ b/zeffir/lib_obj.c
@@ -20,9 +20,9 @@
static PyObject *lib_repr(ZefLibObject *lib)
{
- return PyString_FromFormat("<zeffir.Lib object for '%.200s'%s>",
- lib->l_libname,
- lib->l_dl_lib == NULL ? " (closed)" : "");
+ return PyText_FromFormat("<zeffir.Lib object for '%.200s'%s>",
+ lib->l_libname,
+ lib->l_dl_lib == NULL ? " (closed)" : "");
}
static PyObject *lib_findattr(ZefLibObject *lib, PyObject *name)
@@ -40,7 +40,7 @@
"lib '%.200s' has no function,"
" global variable or constant '%.200s'",
lib->l_libname,
- PyString_Check(name) ? PyString_AS_STRING(name) : "?");
+ PyText_Check(name) ? PyText_AS_UTF8(name) : "?");
return NULL;
}
return x;
@@ -83,7 +83,7 @@
PyErr_Format(PyExc_AttributeError,
"cannot write to function or constant '%.200s'",
- PyString_Check(name) ? PyString_AS_STRING(name) : "?");
+ PyText_Check(name) ? PyText_AS_UTF8(name) : "?");
return -1;
}
@@ -152,7 +152,7 @@
return NULL;
lib->l_dl_lib = NULL;
- lib->l_libname = PyString_AS_STRING(path);
+ lib->l_libname = PyString_AsString(path);
Py_INCREF(path);
lib->l_libname_obj = path;
lib->l_dict = PyDict_New();
diff --git a/zeffir/py3support.h b/zeffir/py3support.h
new file mode 100644
--- /dev/null
+++ b/zeffir/py3support.h
@@ -0,0 +1,28 @@
+
+#if PY_MAJOR_VERSION >= 3
+# define STR_OR_BYTES "bytes"
+# define PyText_Type PyUnicode_Type
+# define PyText_Check PyUnicode_Check
+# define PyTextAny_Check PyUnicode_Check
+# define PyText_FromFormat PyUnicode_FromFormat
+# define PyText_AsUTF8 _PyUnicode_AsString /* PyUnicode_AsUTF8 in Py3.3 */
+# define PyText_AS_UTF8 _PyUnicode_AsString
+# define PyText_GetSize PyUnicode_GetSize
+# define PyText_FromString PyUnicode_FromString
+# define PyText_FromStringAndSize PyUnicode_FromStringAndSize
+# define PyText_InternInPlace PyUnicode_InternInPlace
+# define PyIntOrLong_Check PyLong_Check
+#else
+# define STR_OR_BYTES "str"
+# define PyText_Type PyString_Type
+# define PyText_Check PyString_Check
+# define PyTextAny_Check(op) (PyString_Check(op) || PyUnicode_Check(op))
+# define PyText_FromFormat PyString_FromFormat
+# define PyText_AsUTF8 PyString_AsString
+# define PyText_AS_UTF8 PyString_AS_STRING
+# define PyText_GetSize PyString_Size
+# define PyText_FromString PyString_FromString
+# define PyText_FromStringAndSize PyString_FromStringAndSize
+# define PyText_InternInPlace PyString_InternInPlace
+# define PyIntOrLong_Check(op) (PyInt_Check(op) || PyLong_Check(op))
+#endif
diff --git a/zeffir/test/test_cdata.py b/zeffir/test/test_cdata.py
--- a/zeffir/test/test_cdata.py
+++ b/zeffir/test/test_cdata.py
@@ -6,3 +6,10 @@
ffi = support.new_ffi()
p = ffi.new("short *")
assert repr(p) == "<cdata 'short *' owning 2 bytes>"
+
+def test_cdata_read_write():
+ ffi = support.new_ffi()
+ p = ffi.new("short *")
+ assert p[0] == 0
+ p[0] = 43
+ assert p[0] == 43
diff --git a/zeffir/zeffir.c b/zeffir/zeffir.c
--- a/zeffir/zeffir.c
+++ b/zeffir/zeffir.c
@@ -9,6 +9,7 @@
/* Works by including all other .c files. */
/* Allows all function and global symbols to remain static. */
+#include "py3support.h"
#include "zeffir.h"
#include "ctype.c"
#include "cdata.c"
diff --git a/zeffir/zeffir.h b/zeffir/zeffir.h
--- a/zeffir/zeffir.h
+++ b/zeffir/zeffir.h
@@ -1,5 +1,6 @@
typedef struct _crx_type_s CTypeDescrObject;
+typedef struct cfieldobject_s CFieldObject;
typedef struct ZefLibObject_s ZefLibObject;
typedef struct ZefFFIObject_s ZefFFIObject;
@@ -15,3 +16,8 @@
static int lib_close(ZefLibObject *);
static int load_creflect_main(ZefFFIObject *, ZefLibObject *);
static CTypeDescrObject *parse_c_decl(ZefFFIObject *ffi, const char *str);
+
+static int convert_from_object(char *, CTypeDescrObject *, PyObject *);
+static int convert_from_object_bitfield(char *, CFieldObject *, PyObject *);
+
+static int fill_array_type(CTypeDescrObject *ctptr);
More information about the pypy-commit
mailing list