diff options
| author | Armin Rigo <arigo@tunes.org> | 2015-05-12 11:07:25 +0200 |
|---|---|---|
| committer | Armin Rigo <arigo@tunes.org> | 2015-05-12 11:07:25 +0200 |
| commit | fe4bb73d2191ea7b2ee5586848e1c5bbbcbaa72b (patch) | |
| tree | 5c80d5c2ee50bc8e99039c7483522e2febc08cb7 /_cffi1 | |
| parent | 34dbd9932de50a5de29f0fdaab9e9a06526d93a7 (diff) | |
| download | cffi-fe4bb73d2191ea7b2ee5586848e1c5bbbcbaa72b.tar.gz | |
the big Moving Files Around step
Diffstat (limited to '_cffi1')
| -rw-r--r-- | _cffi1/__init__.py | 1 | ||||
| -rw-r--r-- | _cffi1/_cffi_include.h | 202 | ||||
| -rw-r--r-- | _cffi1/cdlopen.c | 347 | ||||
| -rw-r--r-- | _cffi1/cffi1_module.c | 183 | ||||
| -rw-r--r-- | _cffi1/cffi_opcode.py | 146 | ||||
| -rw-r--r-- | _cffi1/cgc.c | 80 | ||||
| -rw-r--r-- | _cffi1/cglob.c | 72 | ||||
| -rw-r--r-- | _cffi1/ffi_obj.c | 814 | ||||
| -rw-r--r-- | _cffi1/lib_obj.c | 495 | ||||
| -rw-r--r-- | _cffi1/manual.c | 169 | ||||
| -rw-r--r-- | _cffi1/manual2.py | 34 | ||||
| -rw-r--r-- | _cffi1/parse_c_type.c | 760 | ||||
| -rw-r--r-- | _cffi1/parse_c_type.h | 161 | ||||
| -rw-r--r-- | _cffi1/realize_c_type.c | 715 | ||||
| -rw-r--r-- | _cffi1/recompiler.py | 955 | ||||
| -rw-r--r-- | _cffi1/setup.py | 6 | ||||
| -rw-r--r-- | _cffi1/setup_manual.py | 5 | ||||
| -rw-r--r-- | _cffi1/setuptools_ext.py | 82 | ||||
| -rw-r--r-- | _cffi1/support.py | 19 | ||||
| -rw-r--r-- | _cffi1/test_cffi_binary.py | 20 | ||||
| -rw-r--r-- | _cffi1/test_dlopen.py | 57 | ||||
| -rw-r--r-- | _cffi1/test_ffi_obj.py | 180 | ||||
| -rw-r--r-- | _cffi1/test_new_ffi_1.py | 1658 | ||||
| -rw-r--r-- | _cffi1/test_parse_c_type.py | 339 | ||||
| -rw-r--r-- | _cffi1/test_realize_c_type.py | 48 | ||||
| -rw-r--r-- | _cffi1/test_recompiler.py | 745 | ||||
| -rw-r--r-- | _cffi1/test_unicode_literals.py | 43 | ||||
| -rw-r--r-- | _cffi1/test_verify1.py | 2201 | ||||
| -rw-r--r-- | _cffi1/udir.py | 3 |
29 files changed, 0 insertions, 10540 deletions
diff --git a/_cffi1/__init__.py b/_cffi1/__init__.py deleted file mode 100644 index a41544f..0000000 --- a/_cffi1/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .recompiler import make_c_source, recompile diff --git a/_cffi1/_cffi_include.h b/_cffi1/_cffi_include.h deleted file mode 100644 index 84cb3a9..0000000 --- a/_cffi1/_cffi_include.h +++ /dev/null @@ -1,202 +0,0 @@ -#include <Python.h> -#include <stddef.h> -#include "parse_c_type.h" - -/* this block of #ifs should be kept exactly identical between - c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py */ -#if defined(_MSC_VER) -# include <malloc.h> /* for alloca() */ -# if _MSC_VER < 1600 /* MSVC < 2010 */ - typedef __int8 int8_t; - typedef __int16 int16_t; - typedef __int32 int32_t; - typedef __int64 int64_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; - typedef unsigned __int64 uint64_t; - typedef __int8 int_least8_t; - typedef __int16 int_least16_t; - typedef __int32 int_least32_t; - typedef __int64 int_least64_t; - typedef unsigned __int8 uint_least8_t; - typedef unsigned __int16 uint_least16_t; - typedef unsigned __int32 uint_least32_t; - typedef unsigned __int64 uint_least64_t; - typedef __int8 int_fast8_t; - typedef __int16 int_fast16_t; - typedef __int32 int_fast32_t; - typedef __int64 int_fast64_t; - typedef unsigned __int8 uint_fast8_t; - typedef unsigned __int16 uint_fast16_t; - typedef unsigned __int32 uint_fast32_t; - typedef unsigned __int64 uint_fast64_t; - typedef __int64 intmax_t; - typedef unsigned __int64 uintmax_t; -# else -# include <stdint.h> -# endif -# if _MSC_VER < 1800 /* MSVC < 2013 */ - typedef unsigned char _Bool; -# endif -#else -# include <stdint.h> -# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) -# include <alloca.h> -# endif -#endif - - -/********** CPython-specific section **********/ -#ifndef PYPY_VERSION - - -#if PY_MAJOR_VERSION >= 3 -# define PyInt_FromLong PyLong_FromLong -#endif - -#define _cffi_from_c_double PyFloat_FromDouble -#define _cffi_from_c_float PyFloat_FromDouble -#define _cffi_from_c_long PyInt_FromLong -#define _cffi_from_c_ulong PyLong_FromUnsignedLong -#define _cffi_from_c_longlong PyLong_FromLongLong -#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong - -#define _cffi_to_c_double PyFloat_AsDouble -#define _cffi_to_c_float PyFloat_AsDouble - -#define _cffi_from_c_int(x, type) \ - (((type)-1) > 0 ? /* unsigned */ \ - (sizeof(type) < sizeof(long) ? \ - PyInt_FromLong((long)x) : \ - sizeof(type) == sizeof(long) ? \ - PyLong_FromUnsignedLong((unsigned long)x) : \ - PyLong_FromUnsignedLongLong((unsigned long long)x)) : \ - (sizeof(type) <= sizeof(long) ? \ - PyInt_FromLong((long)x) : \ - PyLong_FromLongLong((long long)x))) - -#define _cffi_to_c_int(o, type) \ - (sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \ - : (type)_cffi_to_c_i8(o)) : \ - sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \ - : (type)_cffi_to_c_i16(o)) : \ - sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \ - : (type)_cffi_to_c_i32(o)) : \ - sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \ - : (type)_cffi_to_c_i64(o)) : \ - (Py_FatalError("unsupported size for type " #type), (type)0)) - -#define _cffi_to_c_i8 \ - ((int(*)(PyObject *))_cffi_exports[1]) -#define _cffi_to_c_u8 \ - ((int(*)(PyObject *))_cffi_exports[2]) -#define _cffi_to_c_i16 \ - ((int(*)(PyObject *))_cffi_exports[3]) -#define _cffi_to_c_u16 \ - ((int(*)(PyObject *))_cffi_exports[4]) -#define _cffi_to_c_i32 \ - ((int(*)(PyObject *))_cffi_exports[5]) -#define _cffi_to_c_u32 \ - ((unsigned int(*)(PyObject *))_cffi_exports[6]) -#define _cffi_to_c_i64 \ - ((long long(*)(PyObject *))_cffi_exports[7]) -#define _cffi_to_c_u64 \ - ((unsigned long long(*)(PyObject *))_cffi_exports[8]) -#define _cffi_to_c_char \ - ((int(*)(PyObject *))_cffi_exports[9]) -#define _cffi_from_c_pointer \ - ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[10]) -#define _cffi_to_c_pointer \ - ((char *(*)(PyObject *, CTypeDescrObject *))_cffi_exports[11]) -#define _cffi_get_struct_layout \ - not used any more -#define _cffi_restore_errno \ - ((void(*)(void))_cffi_exports[13]) -#define _cffi_save_errno \ - ((void(*)(void))_cffi_exports[14]) -#define _cffi_from_c_char \ - ((PyObject *(*)(char))_cffi_exports[15]) -#define _cffi_from_c_deref \ - ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[16]) -#define _cffi_to_c \ - ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[17]) -#define _cffi_from_c_struct \ - ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[18]) -#define _cffi_to_c_wchar_t \ - ((wchar_t(*)(PyObject *))_cffi_exports[19]) -#define _cffi_from_c_wchar_t \ - ((PyObject *(*)(wchar_t))_cffi_exports[20]) -#define _cffi_to_c_long_double \ - ((long double(*)(PyObject *))_cffi_exports[21]) -#define _cffi_to_c__Bool \ - ((_Bool(*)(PyObject *))_cffi_exports[22]) -#define _cffi_prepare_pointer_call_argument \ - ((Py_ssize_t(*)(CTypeDescrObject *, PyObject *, char **))_cffi_exports[23]) -#define _cffi_convert_array_from_object \ - ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[24]) -#define _CFFI_NUM_EXPORTS 25 - -typedef struct _ctypedescr CTypeDescrObject; - -static void *_cffi_exports[_CFFI_NUM_EXPORTS]; - -#define _cffi_type(index) ( \ - assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \ - (CTypeDescrObject *)_cffi_types[index]) - -static PyObject *_cffi_init(char *module_name, Py_ssize_t version, - const struct _cffi_type_context_s *ctx) -{ - PyObject *module, *o_arg, *new_module; - void *raw[] = { - (void *)module_name, - (void *)version, - (void *)_cffi_exports, - (void *)ctx, - }; - - module = PyImport_ImportModule("_cffi_backend"); - if (module == NULL) - goto failure; - - o_arg = PyLong_FromVoidPtr((void *)raw); - if (o_arg == NULL) - goto failure; - - new_module = PyObject_CallMethod( - module, "_init_cffi_1_0_external_module", "O", o_arg); - - Py_DECREF(o_arg); - Py_DECREF(module); - return new_module; - - failure: - Py_XDECREF(module); - return NULL; -} - -#endif -/********** end CPython-specific section **********/ - - -#define _cffi_array_len(array) (sizeof(array) / sizeof((array)[0])) - -#define _cffi_prim_int(size, sign) \ - ((size) == sizeof(int) ? ((sign) ? _CFFI_PRIM_INT : _CFFI_PRIM_UINT) : \ - (size) == sizeof(long)? ((sign) ? _CFFI_PRIM_LONG : _CFFI_PRIM_ULONG) : \ - (size) == 1 ? ((sign) ? _CFFI_PRIM_INT8 : _CFFI_PRIM_UINT8) : \ - (size) == 2 ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) : \ - (size) == 4 ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) : \ - (size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) : \ - 0) - -#define _cffi_check_int(got, got_nonpos, expected) \ - ((got_nonpos) == (expected <= 0) && \ - (got) == (unsigned long long)expected) - -#ifdef __GNUC__ -# define _CFFI_UNUSED_FN __attribute__((unused)) -#else -# define _CFFI_UNUSED_FN /* nothing */ -#endif diff --git a/_cffi1/cdlopen.c b/_cffi1/cdlopen.c deleted file mode 100644 index 7276273..0000000 --- a/_cffi1/cdlopen.c +++ /dev/null @@ -1,347 +0,0 @@ -/* ffi.dlopen() interface with dlopen()/dlsym()/dlclose() */ - -static void *cdlopen_fetch(PyObject *libname, void *libhandle, char *symbol) -{ - void *address; - - if (libhandle == NULL) { - PyErr_Format(FFIError, "library '%s' has been closed", - PyText_AS_UTF8(libname)); - return NULL; - } - - dlerror(); /* clear error condition */ - address = dlsym(libhandle, symbol); - if (address == NULL) { - const char *error = dlerror(); - PyErr_Format(FFIError, "symbol '%s' not found in library '%s': %s", - symbol, PyText_AS_UTF8(libname), error); - } - return address; -} - -static void cdlopen_close_ignore_errors(void *libhandle) -{ - if (libhandle != NULL) - dlclose(libhandle); -} - -static int cdlopen_close(PyObject *libname, void *libhandle) -{ - if (libhandle != NULL && dlclose(libhandle) != 0) { - const char *error = dlerror(); - PyErr_Format(FFIError, "closing library '%s': %s", - PyText_AS_UTF8(libname), error); - return -1; - } - return 0; -} - -static PyObject *ffi_dlopen(PyObject *self, PyObject *args) -{ - char *filename_or_null, *printable_filename; - void *handle; - int flags = 0; - - if (PyTuple_GET_SIZE(args) == 0 || PyTuple_GET_ITEM(args, 0) == Py_None) { - PyObject *dummy; - if (!PyArg_ParseTuple(args, "|Oi:load_library", - &dummy, &flags)) - return NULL; - filename_or_null = NULL; - } - else if (!PyArg_ParseTuple(args, "et|i:load_library", - Py_FileSystemDefaultEncoding, &filename_or_null, - &flags)) - return NULL; - - if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0) - flags |= RTLD_NOW; - printable_filename = filename_or_null ? filename_or_null : "<None>"; - - handle = dlopen(filename_or_null, flags); - if (handle == NULL) { - const char *error = dlerror(); - PyErr_Format(PyExc_OSError, "cannot load library '%s': %s", - printable_filename, error); - return NULL; - } - return (PyObject *)lib_internal_new((FFIObject *)self, - printable_filename, handle); -} - -static PyObject *ffi_dlclose(PyObject *self, PyObject *args) -{ - LibObject *lib; - if (!PyArg_ParseTuple(args, "O!", &Lib_Type, &lib)) - return NULL; - - if (lib->l_libhandle == NULL) { - PyErr_Format(FFIError, "library '%s' is already closed " - "or was not created with ffi.dlopen()", - PyText_AS_UTF8(lib->l_libhandle)); - return NULL; - } - - if (cdlopen_close(lib->l_libname, lib->l_libhandle) < 0) - return NULL; - - /* Clear the dict to force further accesses to do cdlopen_fetch() - again, and fail because the library was closed. */ - PyDict_Clear(lib->l_dict); - - Py_INCREF(Py_None); - return Py_None; -} - - -static Py_ssize_t cdl_4bytes(char *src) -{ - /* read 4 bytes in little-endian order; return it as a signed integer */ - signed char *ssrc = (signed char *)src; - unsigned char *usrc = (unsigned char *)src; - return (ssrc[0] << 24) | (usrc[1] << 16) | (usrc[2] << 8) | usrc[3]; -} - -static _cffi_opcode_t cdl_opcode(char *src) -{ - return (_cffi_opcode_t)cdl_4bytes(src); -} - -typedef struct { - unsigned long long value; - int neg; -} cdl_intconst_t; - -int _cdl_realize_global_int(struct _cffi_getconst_s *gc) -{ - /* The 'address' field of 'struct _cffi_global_s' is set to point - to this function in case ffiobj_init() sees constant integers. - This fishes around after the 'ctx->globals' array, which is - initialized to contain another array, this time of - 'cdl_intconst_t' structures. We get the nth one and it tells - us what to return. - */ - cdl_intconst_t *ic; - ic = (cdl_intconst_t *)(gc->ctx->globals + gc->ctx->num_globals); - ic += gc->gindex; - gc->value = ic->value; - return ic->neg; -} - -static int ffiobj_init(PyObject *self, PyObject *args, PyObject *kwds) -{ - FFIObject *ffi; - static char *keywords[] = {"module_name", "_version", "_types", - "_globals", "_struct_unions", "_enums", - "_typenames", NULL}; - char *ffiname = NULL, *types = NULL, *building = NULL; - Py_ssize_t version = -1; - Py_ssize_t types_len = 0; - PyObject *globals = NULL, *struct_unions = NULL, *enums = NULL; - PyObject *typenames = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sns#O!O!O!O!:FFI", keywords, - &ffiname, &version, &types, &types_len, - &PyTuple_Type, &globals, - &PyTuple_Type, &struct_unions, - &PyTuple_Type, &enums, - &PyTuple_Type, &typenames)) - return -1; - - ffi = (FFIObject *)self; - if (ffi->ctx_is_nonempty) { - PyErr_SetString(PyExc_ValueError, - "cannot call FFI.__init__() more than once"); - return -1; - } - 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; - - building = PyMem_Malloc(n * sizeof(_cffi_opcode_t)); - if (building == NULL) - goto error; - ntypes = (_cffi_opcode_t *)building; - - for (i = 0; i < n; i++) { - ntypes[i] = cdl_opcode(types); - types += 4; - } - ffi->types_builder.ctx.types = ntypes; - ffi->types_builder.ctx.num_types = n; - building = NULL; - } - - if (globals != NULL) { - /* unpack a tuple alternating strings and ints, each two together - describing one global_s entry with no specified address or size. - The int is only used with integer constants. */ - struct _cffi_global_s *nglobs; - cdl_intconst_t *nintconsts; - Py_ssize_t i, n = PyTuple_GET_SIZE(globals) / 2; - - i = n * (sizeof(struct _cffi_global_s) + sizeof(cdl_intconst_t)); - building = PyMem_Malloc(i); - if (building == NULL) - goto error; - memset(building, 0, i); - nglobs = (struct _cffi_global_s *)building; - nintconsts = (cdl_intconst_t *)(nglobs + n); - - for (i = 0; i < n; i++) { - char *g = PyString_AS_STRING(PyTuple_GET_ITEM(globals, i * 2)); - nglobs[i].type_op = cdl_opcode(g); g += 4; - nglobs[i].name = g; - if (_CFFI_GETOP(nglobs[i].type_op) == _CFFI_OP_CONSTANT_INT || - _CFFI_GETOP(nglobs[i].type_op) == _CFFI_OP_ENUM) { - PyObject *o = PyTuple_GET_ITEM(globals, i * 2 + 1); - nglobs[i].address = &_cdl_realize_global_int; - if (PyInt_Check(o)) { - nintconsts[i].neg = PyInt_AS_LONG(o) <= 0; - nintconsts[i].value = (long long)PyInt_AS_LONG(o); - } - else { - nintconsts[i].neg = PyObject_RichCompareBool(o, Py_False, - Py_LE); - nintconsts[i].value = PyLong_AsUnsignedLongLongMask(o); - if (PyErr_Occurred()) - goto error; - } - } - } - 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_4bytes(s); s += 4; - nstructs[i].flags = cdl_4bytes(s); s += 4; - nstructs[i].name = s; - 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); f += 4; - nfields[nf].field_offset = (size_t)-1; - nfields[nf].field_size = cdl_4bytes(f); f += 4; - nfields[nf].name = f; - 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 (enums != NULL) { - /* unpack a tuple of strings, each of which describes one enum_s - entry */ - struct _cffi_enum_s *nenums; - Py_ssize_t i, n = PyTuple_GET_SIZE(enums); - - i = n * sizeof(struct _cffi_enum_s); - building = PyMem_Malloc(i); - if (building == NULL) - goto error; - memset(building, 0, i); - nenums = (struct _cffi_enum_s *)building; - - for (i = 0; i < n; i++) { - char *e = PyString_AS_STRING(PyTuple_GET_ITEM(enums, i)); - /* 'e' is a string describing the enum */ - nenums[i].type_index = cdl_4bytes(e); e += 4; - nenums[i].type_prim = cdl_4bytes(e); e += 4; - nenums[i].name = e; e += strlen(e) + 1; - nenums[i].enumerators = e; - } - ffi->types_builder.ctx.enums = nenums; - ffi->types_builder.ctx.num_enums = n; - building = NULL; - } - - if (typenames != NULL) { - /* unpack a tuple of strings, each of which describes one typename_s - entry */ - struct _cffi_typename_s *ntypenames; - Py_ssize_t i, n = PyTuple_GET_SIZE(typenames); - - i = n * sizeof(struct _cffi_typename_s); - building = PyMem_Malloc(i); - if (building == NULL) - goto error; - memset(building, 0, i); - ntypenames = (struct _cffi_typename_s *)building; - - for (i = 0; i < n; i++) { - char *t = PyString_AS_STRING(PyTuple_GET_ITEM(typenames, i)); - /* 't' is a string describing the typename */ - ntypenames[i].type_index = cdl_4bytes(t); t += 4; - ntypenames[i].name = t; - } - ffi->types_builder.ctx.typenames = ntypenames; - ffi->types_builder.ctx.num_typenames = n; - building = NULL; - } - - /* Above, we took directly some "char *" strings out of the strings, - typically from somewhere inside tuples. Keep them alive by - incref'ing the whole input arguments. */ - Py_INCREF(args); - Py_XINCREF(kwds); - ffi->types_builder._keepalive1 = args; - ffi->types_builder._keepalive2 = kwds; - return 0; - - error: - if (building != NULL) - PyMem_Free(building); - if (!PyErr_Occurred()) - PyErr_NoMemory(); - return -1; -} diff --git a/_cffi1/cffi1_module.c b/_cffi1/cffi1_module.c deleted file mode 100644 index 5cea0e2..0000000 --- a/_cffi1/cffi1_module.c +++ /dev/null @@ -1,183 +0,0 @@ - -#include "parse_c_type.c" -#include "realize_c_type.c" - -typedef struct FFIObject_s FFIObject; -typedef struct LibObject_s LibObject; - -static PyTypeObject FFI_Type; /* forward */ -static PyTypeObject Lib_Type; /* forward */ - -#include "ffi_obj.c" -#include "cglob.c" -#include "cgc.c" -#include "lib_obj.c" -#include "cdlopen.c" - - -static int init_ffi_lib(PyObject *m) -{ - PyObject *x; - - if (PyType_Ready(&FFI_Type) < 0) - return -1; - if (PyType_Ready(&Lib_Type) < 0) - return -1; - if (init_global_types_dict(FFI_Type.tp_dict) < 0) - return -1; - - FFIError = PyErr_NewException("ffi.error", NULL, NULL); - if (FFIError == NULL) - return -1; - if (PyDict_SetItemString(FFI_Type.tp_dict, "error", FFIError) < 0) - return -1; - if (PyDict_SetItemString(FFI_Type.tp_dict, "CType", - (PyObject *)&CTypeDescr_Type) < 0) - return -1; - if (PyDict_SetItemString(FFI_Type.tp_dict, "CData", - (PyObject *)&CData_Type) < 0) - return -1; - - x = (PyObject *)&FFI_Type; - Py_INCREF(x); - if (PyModule_AddObject(m, "FFI", x) < 0) - return -1; - x = (PyObject *)&Lib_Type; - Py_INCREF(x); - if (PyModule_AddObject(m, "Lib", x) < 0) - return -1; - - return 0; -} - -static int make_included_tuples(char *module_name, - const char *const *ctx_includes, - PyObject **included_ffis, - PyObject **included_libs) -{ - Py_ssize_t num = 0; - const char *const *p_include; - - if (ctx_includes == NULL) - return 0; - - for (p_include = ctx_includes; *p_include; p_include++) { - num++; - } - *included_ffis = PyTuple_New(num); - *included_libs = PyTuple_New(num); - if (*included_ffis == NULL || *included_libs == NULL) - goto error; - - num = 0; - for (p_include = ctx_includes; *p_include; p_include++) { - PyObject *included_ffi, *included_lib; - PyObject *m = PyImport_ImportModule(*p_include); - if (m == NULL) - goto import_error; - - included_ffi = PyObject_GetAttrString(m, "ffi"); - PyTuple_SET_ITEM(*included_ffis, num, included_ffi); - - included_lib = (included_ffi == NULL) ? NULL : - PyObject_GetAttrString(m, "lib"); - PyTuple_SET_ITEM(*included_libs, num, included_lib); - - Py_DECREF(m); - if (included_lib == NULL) - goto import_error; - - if (!FFIObject_Check(included_ffi) || - !LibObject_Check(included_lib)) - goto import_error; - num++; - } - return 0; - - import_error: - PyErr_Format(PyExc_ImportError, - "while loading %.200s: failed to import ffi, lib from %.200s", - module_name, *p_include); - error: - Py_XDECREF(*included_ffis); *included_ffis = NULL; - Py_XDECREF(*included_libs); *included_libs = NULL; - return -1; -} - -static PyObject *_my_Py_InitModule(char *module_name) -{ -#if PY_MAJOR_VERSION >= 3 - struct PyModuleDef *module_def, local_module_def = { - PyModuleDef_HEAD_INIT, - module_name, - NULL, - -1, - NULL, NULL, NULL, NULL, NULL - }; - /* note: the 'module_def' is allocated dynamically and leaks, - but anyway the C extension module can never be unloaded */ - module_def = PyMem_Malloc(sizeof(struct PyModuleDef)); - if (module_def == NULL) - return PyErr_NoMemory(); - *module_def = local_module_def; - return PyModule_Create(module_def); -#else - return Py_InitModule(module_name, NULL); -#endif -} - -#define CFFI_VERSION_MIN 0x2600 -#define CFFI_VERSION_MAX 0x260F - -static PyObject *b_init_cffi_1_0_external_module(PyObject *self, PyObject *arg) -{ - PyObject *m; - FFIObject *ffi; - LibObject *lib; - Py_ssize_t version; - char *module_name, *exports; - void **raw; - const struct _cffi_type_context_s *ctx; - - raw = (void **)PyLong_AsVoidPtr(arg); - if (raw == NULL) - return NULL; - - module_name = (char *)raw[0]; - version = (Py_ssize_t)raw[1]; - exports = (char *)raw[2]; - ctx = (const struct _cffi_type_context_s *)raw[3]; - - if (version < CFFI_VERSION_MIN || version > CFFI_VERSION_MAX) { - if (!PyErr_Occurred()) - PyErr_Format(PyExc_ImportError, - "cffi extension module '%s' has unknown version %p", - module_name, (void *)version); - return NULL; - } - - /* initialize the exports array */ - memcpy(exports, (char *)cffi_exports, sizeof(cffi_exports)); - - /* make the module object */ - m = _my_Py_InitModule(module_name); - if (m == NULL) - return NULL; - - /* build the FFI and Lib object inside this new module */ - ffi = ffi_internal_new(&FFI_Type, ctx); - Py_XINCREF(ffi); /* make the ffi object really immortal */ - if (ffi == NULL || PyModule_AddObject(m, "ffi", (PyObject *)ffi) < 0) - return NULL; - - lib = lib_internal_new(ffi, module_name, NULL); - if (lib == NULL || PyModule_AddObject(m, "lib", (PyObject *)lib) < 0) - return NULL; - - if (make_included_tuples(module_name, ctx->includes, - &ffi->types_builder.included_ffis, - &lib->l_includes) < 0) - return NULL; - - return m; -} diff --git a/_cffi1/cffi_opcode.py b/_cffi1/cffi_opcode.py deleted file mode 100644 index 1972aeb..0000000 --- a/_cffi1/cffi_opcode.py +++ /dev/null @@ -1,146 +0,0 @@ - -class CffiOp(object): - def __init__(self, op, arg): - self.op = op - self.arg = arg - def as_c_expr(self): - if self.op is None: - assert isinstance(self.arg, str) - return '(_cffi_opcode_t)(%s)' % (self.arg,) - classname = CLASS_NAME[self.op] - return '_CFFI_OP(_CFFI_OP_%s, %d)' % (classname, self.arg) - def __str__(self): - classname = CLASS_NAME.get(self.op, self.op) - return '(%s %s)' % (classname, self.arg) - -OP_PRIMITIVE = 1 -OP_POINTER = 3 -OP_ARRAY = 5 -OP_OPEN_ARRAY = 7 -OP_STRUCT_UNION = 9 -OP_ENUM = 11 -OP_FUNCTION = 13 -OP_FUNCTION_END = 15 -OP_NOOP = 17 -OP_BITFIELD = 19 -OP_TYPENAME = 21 -OP_CPYTHON_BLTN_V = 23 # varargs -OP_CPYTHON_BLTN_N = 25 # noargs -OP_CPYTHON_BLTN_O = 27 # O (i.e. a single arg) -OP_CONSTANT = 29 -OP_CONSTANT_INT = 31 -OP_GLOBAL_VAR = 33 -OP_DLOPEN = 35 - -PRIM_VOID = 0 -PRIM_BOOL = 1 -PRIM_CHAR = 2 -PRIM_SCHAR = 3 -PRIM_UCHAR = 4 -PRIM_SHORT = 5 -PRIM_USHORT = 6 -PRIM_INT = 7 -PRIM_UINT = 8 -PRIM_LONG = 9 -PRIM_ULONG = 10 -PRIM_LONGLONG = 11 -PRIM_ULONGLONG = 12 -PRIM_FLOAT = 13 -PRIM_DOUBLE = 14 -PRIM_LONGDOUBLE = 15 - -PRIM_WCHAR = 16 -PRIM_INT8 = 17 -PRIM_UINT8 = 18 -PRIM_INT16 = 19 -PRIM_UINT16 = 20 -PRIM_INT32 = 21 -PRIM_UINT32 = 22 -PRIM_INT64 = 23 -PRIM_UINT64 = 24 -PRIM_INTPTR = 25 -PRIM_UINTPTR = 26 -PRIM_PTRDIFF = 27 -PRIM_SIZE = 28 -PRIM_SSIZE = 29 -PRIM_INT_LEAST8 = 30 -PRIM_UINT_LEAST8 = 31 -PRIM_INT_LEAST16 = 32 -PRIM_UINT_LEAST16 = 33 -PRIM_INT_LEAST32 = 34 -PRIM_UINT_LEAST32 = 35 -PRIM_INT_LEAST64 = 36 -PRIM_UINT_LEAST64 = 37 -PRIM_INT_FAST8 = 38 -PRIM_UINT_FAST8 = 39 -PRIM_INT_FAST16 = 40 -PRIM_UINT_FAST16 = 41 -PRIM_INT_FAST32 = 42 -PRIM_UINT_FAST32 = 43 -PRIM_INT_FAST64 = 44 -PRIM_UINT_FAST64 = 45 -PRIM_INTMAX = 46 -PRIM_UINTMAX = 47 - -_NUM_PRIM = 48 - -PRIMITIVE_TO_INDEX = { - 'char': PRIM_CHAR, - 'short': PRIM_SHORT, - 'int': PRIM_INT, - 'long': PRIM_LONG, - 'long long': PRIM_LONGLONG, - 'signed char': PRIM_SCHAR, - 'unsigned char': PRIM_UCHAR, - 'unsigned short': PRIM_USHORT, - 'unsigned int': PRIM_UINT, - 'unsigned long': PRIM_ULONG, - 'unsigned long long': PRIM_ULONGLONG, - 'float': PRIM_FLOAT, - 'double': PRIM_DOUBLE, - 'long double': PRIM_LONGDOUBLE, - '_Bool': PRIM_BOOL, - 'wchar_t': PRIM_WCHAR, - 'int8_t': PRIM_INT8, - 'uint8_t': PRIM_UINT8, - 'int16_t': PRIM_INT16, - 'uint16_t': PRIM_UINT16, - 'int32_t': PRIM_INT32, - 'uint32_t': PRIM_UINT32, - 'int64_t': PRIM_INT64, - 'uint64_t': PRIM_UINT64, - 'intptr_t': PRIM_INTPTR, - 'uintptr_t': PRIM_UINTPTR, - 'ptrdiff_t': PRIM_PTRDIFF, - 'size_t': PRIM_SIZE, - 'ssize_t': PRIM_SSIZE, - 'int_least8_t': PRIM_INT_LEAST8, - 'uint_least8_t': PRIM_UINT_LEAST8, - 'int_least16_t': PRIM_INT_LEAST16, - 'uint_least16_t': PRIM_UINT_LEAST16, - 'int_least32_t': PRIM_INT_LEAST32, - 'uint_least32_t': PRIM_UINT_LEAST32, - 'int_least64_t': PRIM_INT_LEAST64, - 'uint_least64_t': PRIM_UINT_LEAST64, - 'int_fast8_t': PRIM_INT_FAST8, - 'uint_fast8_t': PRIM_UINT_FAST8, - 'int_fast16_t': PRIM_INT_FAST16, - 'uint_fast16_t': PRIM_UINT_FAST16, - 'int_fast32_t': PRIM_INT_FAST32, - 'uint_fast32_t': PRIM_UINT_FAST32, - 'int_fast64_t': PRIM_INT_FAST64, - 'uint_fast64_t': PRIM_UINT_FAST64, - 'intmax_t': PRIM_INTMAX, - 'uintmax_t': PRIM_UINTMAX, - } - -F_UNION = 0x01 -F_CHECK_FIELDS = 0x02 -F_PACKED = 0x04 -F_EXTERNAL = 0x08 -F_OPAQUE = 0x10 - -CLASS_NAME = {} -for _name, _value in list(globals().items()): - if _name.startswith('OP_') and isinstance(_value, int): - CLASS_NAME[_value] = _name[3:] diff --git a/_cffi1/cgc.c b/_cffi1/cgc.c deleted file mode 100644 index 2c07ff1..0000000 --- a/_cffi1/cgc.c +++ /dev/null @@ -1,80 +0,0 @@ - -/* translated to C from cffi/gc_weakref.py */ - - -static PyObject *const_name_pop; - -static PyObject *gc_wref_remove(PyObject *ffi_wref_data, PyObject *arg) -{ - PyObject *destructor, *cdata, *x; - PyObject *res = PyObject_CallMethodObjArgs(ffi_wref_data, - const_name_pop, arg, NULL); - if (res == NULL) - return NULL; - - assert(PyTuple_Check(res)); - destructor = PyTuple_GET_ITEM(res, 0); - cdata = PyTuple_GET_ITEM(res, 1); - x = PyObject_CallFunctionObjArgs(destructor, cdata, NULL); - Py_DECREF(res); - if (x == NULL) - return NULL; - Py_DECREF(x); - - Py_INCREF(Py_None); - return Py_None; -} - -static PyMethodDef remove_callback = { - "gc_wref_remove", (PyCFunction)gc_wref_remove, METH_O -}; - -static PyObject *gc_weakrefs_build(FFIObject *ffi, CDataObject *cd, - PyObject *destructor) -{ - PyObject *new_cdata, *ref = NULL, *tup = NULL; - - if (ffi->gc_wrefs == NULL) { - /* initialize */ - PyObject *data; - - if (const_name_pop == NULL) { - const_name_pop = PyText_InternFromString("pop"); - if (const_name_pop == NULL) - return NULL; - } - data = PyDict_New(); - if (data == NULL) - return NULL; - ffi->gc_wrefs = PyCFunction_New(&remove_callback, data); - Py_DECREF(data); - if (ffi->gc_wrefs == NULL) - return NULL; - } - - new_cdata = do_cast(cd->c_type, (PyObject *)cd); - if (new_cdata == NULL) - goto error; - - ref = PyWeakref_NewRef(new_cdata, ffi->gc_wrefs); - if (ref == NULL) - goto error; - - tup = PyTuple_Pack(2, destructor, cd); - if (tup == NULL) - goto error; - - /* the 'self' of the function 'gc_wrefs' is actually the data dict */ - if (PyDict_SetItem(PyCFunction_GET_SELF(ffi->gc_wrefs), ref, tup) < 0) - goto error; - - Py_DECREF(tup); - Py_DECREF(ref); - return new_cdata; - - error: - Py_XDECREF(new_cdata); - Py_XDECREF(ref); - Py_XDECREF(tup); - return NULL; -} diff --git a/_cffi1/cglob.c b/_cffi1/cglob.c deleted file mode 100644 index bb7e48d..0000000 --- a/_cffi1/cglob.c +++ /dev/null @@ -1,72 +0,0 @@ - -typedef struct { - PyObject_HEAD - - CTypeDescrObject *gs_type; - char *gs_data; - -} GlobSupportObject; - -static void glob_support_dealloc(GlobSupportObject *gs) -{ - Py_DECREF(gs->gs_type); - PyObject_Del(gs); -} - -static PyTypeObject GlobSupport_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "FFIGlobSupport", - sizeof(GlobSupportObject), - 0, - (destructor)glob_support_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ -}; - -#define GlobSupport_Check(ob) (Py_TYPE(ob) == &GlobSupport_Type) - -static PyObject *make_global_var(CTypeDescrObject *type, char *addr) -{ - GlobSupportObject *gs = PyObject_New(GlobSupportObject, &GlobSupport_Type); - if (gs == NULL) - return NULL; - - Py_INCREF(type); - gs->gs_type = type; - gs->gs_data = addr; - return (PyObject *)gs; -} - -static PyObject *read_global_var(GlobSupportObject *gs) -{ - return convert_to_object(gs->gs_data, gs->gs_type); -} - -static int write_global_var(GlobSupportObject *gs, PyObject *obj) -{ - return convert_from_object(gs->gs_data, gs->gs_type, obj); -} - -static PyObject *cg_addressof_global_var(GlobSupportObject *gs) -{ - PyObject *x, *ptrtype = new_pointer_type(gs->gs_type); - if (ptrtype == NULL) - return NULL; - - x = new_simple_cdata(gs->gs_data, (CTypeDescrObject *)ptrtype); - Py_DECREF(ptrtype); - return x; -} diff --git a/_cffi1/ffi_obj.c b/_cffi1/ffi_obj.c deleted file mode 100644 index d5644ad..0000000 --- a/_cffi1/ffi_obj.c +++ /dev/null @@ -1,814 +0,0 @@ - -/* An FFI object has methods like ffi.new(). It is also a container - for the type declarations (typedefs and structs) that you can use, - say in ffi.new(). - - CTypeDescrObjects are internally stored in the dict 'types_dict'. - The types_dict is lazily filled with CTypeDescrObjects made from - reading a _cffi_type_context_s structure. - - In "modern" mode, the FFI instance is made by the C extension - module originally created by recompile(). The _cffi_type_context_s - structure comes from global data in the C extension module. - - In "compatibility" mode, an FFI instance is created explicitly by - the user, and its _cffi_type_context_s is initially empty. You - need to call ffi.cdef() to add more information to it. -*/ - -#define FFI_COMPLEXITY_OUTPUT 1200 /* xxx should grow as needed */ - -#define FFIObject_Check(op) PyObject_TypeCheck(op, &FFI_Type) -#define LibObject_Check(ob) ((Py_TYPE(ob) == &Lib_Type)) - -struct FFIObject_s { - PyObject_HEAD - PyObject *gc_wrefs; - struct _cffi_parse_info_s info; - char ctx_is_static, ctx_is_nonempty; - builder_c_t types_builder; -}; - -static FFIObject *ffi_internal_new(PyTypeObject *ffitype, - const struct _cffi_type_context_s *static_ctx) -{ - static _cffi_opcode_t internal_output[FFI_COMPLEXITY_OUTPUT]; - - FFIObject *ffi; - if (static_ctx != NULL) { - ffi = (FFIObject *)PyObject_GC_New(FFIObject, ffitype); - /* we don't call PyObject_GC_Track() here: from _cffi_init_module() - it is not needed, because in this case the ffi object is immortal */ - } - else { - ffi = (FFIObject *)ffitype->tp_alloc(ffitype, 0); - } - if (ffi == NULL) - return NULL; - - if (init_builder_c(&ffi->types_builder, static_ctx) < 0) { - Py_DECREF(ffi); - return NULL; - } - ffi->gc_wrefs = NULL; - ffi->info.ctx = &ffi->types_builder.ctx; - ffi->info.output = internal_output; - ffi->info.output_size = FFI_COMPLEXITY_OUTPUT; - ffi->ctx_is_static = (static_ctx != NULL); - ffi->ctx_is_nonempty = (static_ctx != NULL); - return ffi; -} - -static void ffi_dealloc(FFIObject *ffi) -{ - PyObject_GC_UnTrack(ffi); - Py_XDECREF(ffi->gc_wrefs); - - free_builder_c(&ffi->types_builder, ffi->ctx_is_static); - - Py_TYPE(ffi)->tp_free((PyObject *)ffi); -} - -static int ffi_traverse(FFIObject *ffi, visitproc visit, void *arg) -{ - Py_VISIT(ffi->types_builder.types_dict); - Py_VISIT(ffi->types_builder.included_ffis); - Py_VISIT(ffi->gc_wrefs); - return 0; -} - -static PyObject *ffiobj_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - /* user-facing initialization code, for explicit FFI() calls */ - return (PyObject *)ffi_internal_new(type, NULL); -} - -/* forward, declared in cdlopen.c because it's mostly useful for this case */ -static int ffiobj_init(PyObject *self, PyObject *args, PyObject *kwds); - -#define ACCEPT_STRING 1 -#define ACCEPT_CTYPE 2 -#define ACCEPT_CDATA 4 -#define ACCEPT_ALL (ACCEPT_STRING | ACCEPT_CTYPE | ACCEPT_CDATA) -#define CONSIDER_FN_AS_FNPTR 8 - -static CTypeDescrObject *_ffi_type(FFIObject *ffi, PyObject *arg, - int accept) -{ - /* Returns the CTypeDescrObject from the user-supplied 'arg'. - Does not return a new reference! - */ - if ((accept & ACCEPT_STRING) && PyText_Check(arg)) { - PyObject *types_dict = ffi->types_builder.types_dict; - PyObject *x = PyDict_GetItem(types_dict, arg); - - if (x == NULL) { - char *input_text = PyText_AS_UTF8(arg); - int err, index = parse_c_type(&ffi->info, input_text); - if (index < 0) { - size_t num_spaces = ffi->info.error_location; - char *spaces = alloca(num_spaces + 1); - memset(spaces, ' ', num_spaces); - spaces[num_spaces] = '\0'; - PyErr_Format(FFIError, "%s\n%s\n%s^", ffi->info.error_message, - input_text, spaces); - return NULL; - } - x = realize_c_type_or_func(&ffi->types_builder, - ffi->info.output, index); - if (x == NULL) - return NULL; - - /* Cache under the name given by 'arg', in addition to the - fact that the same ct is probably already cached under - its standardized name. In a few cases, it is not, e.g. - if it is a primitive; for the purpose of this function, - the important point is the following line, which makes - sure that in any case the next _ffi_type() with the same - 'arg' will succeed early, in PyDict_GetItem() above. - */ - err = PyDict_SetItem(types_dict, arg, x); - Py_DECREF(x); /* we know it was written in types_dict (unless out - of mem), so there is at least that ref left */ - if (err < 0) - return NULL; - } - - if (CTypeDescr_Check(x)) - return (CTypeDescrObject *)x; - else if (accept & CONSIDER_FN_AS_FNPTR) - return unwrap_fn_as_fnptr(x); - else - return unexpected_fn_type(x); - } - else if ((accept & ACCEPT_CTYPE) && CTypeDescr_Check(arg)) { - return (CTypeDescrObject *)arg; - } - else if ((accept & ACCEPT_CDATA) && CData_Check(arg)) { - return ((CDataObject *)arg)->c_type; - } -#if PY_MAJOR_VERSION < 3 - else if (PyUnicode_Check(arg)) { - CTypeDescrObject *result; - arg = PyUnicode_AsASCIIString(arg); - if (arg == NULL) - return NULL; - result = _ffi_type(ffi, arg, accept); - Py_DECREF(arg); - return result; - } -#endif - else { - const char *m1 = (accept & ACCEPT_STRING) ? "string" : ""; - const char *m2 = (accept & ACCEPT_CTYPE) ? "ctype object" : ""; - const char *m3 = (accept & ACCEPT_CDATA) ? "cdata object" : ""; - const char *s12 = (*m1 && (*m2 || *m3)) ? " or " : ""; - const char *s23 = (*m2 && *m3) ? " or " : ""; - PyErr_Format(PyExc_TypeError, "expected a %s%s%s%s%s, got '%.200s'", - m1, s12, m2, s23, m3, - Py_TYPE(arg)->tp_name); - return NULL; - } -} - -PyDoc_STRVAR(ffi_sizeof_doc, -"Return the size in bytes of the argument.\n" -"It can be a string naming a C type, or a 'cdata' instance."); - -static PyObject *ffi_sizeof(FFIObject *self, PyObject *arg) -{ - Py_ssize_t size; - CTypeDescrObject *ct = _ffi_type(self, arg, ACCEPT_ALL); - if (ct == NULL) - return NULL; - - size = ct->ct_size; - - if (CData_Check(arg)) { - CDataObject *cd = (CDataObject *)arg; - if (cd->c_type->ct_flags & CT_ARRAY) - size = get_array_length(cd) * cd->c_type->ct_itemdescr->ct_size; - } - - if (size < 0) { - PyErr_Format(FFIError, "don't know the size of ctype '%s'", - ct->ct_name); - return NULL; - } - return PyInt_FromSsize_t(size); -} - -PyDoc_STRVAR(ffi_alignof_doc, -"Return the natural alignment size in bytes of the argument.\n" -"It can be a string naming a C type, or a 'cdata' instance."); - -static PyObject *ffi_alignof(FFIObject *self, PyObject *arg) -{ - int align; - CTypeDescrObject *ct = _ffi_type(self, arg, ACCEPT_ALL); - if (ct == NULL) - return NULL; - - align = get_alignment(ct); - if (align < 0) - return NULL; - return PyInt_FromLong(align); -} - -PyDoc_STRVAR(ffi_typeof_doc, -"Parse the C type given as a string and return the\n" -"corresponding <ctype> object.\n" -"It can also be used on 'cdata' instance to get its C type."); - -static PyObject *_cpyextfunc_type_index(PyObject *x); /* forward */ - -static PyObject *ffi_typeof(FFIObject *self, PyObject *arg) -{ - PyObject *x = (PyObject *)_ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CDATA); - if (x != NULL) { - Py_INCREF(x); - } - else { - x = _cpyextfunc_type_index(arg); - } - return x; -} - -PyDoc_STRVAR(ffi_new_doc, -"Allocate an instance according to the specified C type and return a\n" -"pointer to it. The specified C type must be either a pointer or an\n" -"array: ``new('X *')`` allocates an X and returns a pointer to it,\n" -"whereas ``new('X[n]')`` allocates an array of n X'es and returns an\n" -"array referencing it (which works mostly like a pointer, like in C).\n" -"You can also use ``new('X[]', n)`` to allocate an array of a\n" -"non-constant length n.\n" -"\n" -"The memory is initialized following the rules of declaring a global\n" -"variable in C: by default it is zero-initialized, but an explicit\n" -"initializer can be given which can be used to fill all or part of the\n" -"memory.\n" -"\n" -"When the returned <cdata> object goes out of scope, the memory is\n" -"freed. In other words the returned <cdata> object has ownership of\n" -"the value of type 'cdecl' that it points to. This means that the raw\n" -"data can be used as long as this object is kept alive, but must not be\n" -"used for a longer time. Be careful about that when copying the\n" -"pointer to the memory somewhere else, e.g. into another structure."); - -static PyObject *ffi_new(FFIObject *self, PyObject *args, PyObject *kwds) -{ - CTypeDescrObject *ct; - PyObject *arg, *init = Py_None; - static char *keywords[] = {"cdecl", "init", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:new", keywords, - &arg, &init)) - return NULL; - - ct = _ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CTYPE); - if (ct == NULL) - return NULL; - - return direct_newp(ct, init); -} - -PyDoc_STRVAR(ffi_cast_doc, -"Similar to a C cast: returns an instance of the named C\n" -"type initialized with the given 'source'. The source is\n" -"casted between integers or pointers of any type."); - -static PyObject *ffi_cast(FFIObject *self, PyObject *args) -{ - CTypeDescrObject *ct; - PyObject *ob, *arg; - if (!PyArg_ParseTuple(args, "OO:cast", &arg, &ob)) - return NULL; - - ct = _ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CTYPE); - if (ct == NULL) - return NULL; - - return do_cast(ct, ob); -} - -PyDoc_STRVAR(ffi_string_doc, -"Return a Python string (or unicode string) from the 'cdata'. If\n" -"'cdata' is a pointer or array of characters or bytes, returns the\n" -"null-terminated string. The returned string extends until the first\n" -"null character, or at most 'maxlen' characters. If 'cdata' is an\n" -"array then 'maxlen' defaults to its length.\n" -"\n" -"If 'cdata' is a pointer or array of wchar_t, returns a unicode string\n" -"following the same rules.\n" -"\n" -"If 'cdata' is a single character or byte or a wchar_t, returns it as a\n" -"string or unicode string.\n" -"\n" -"If 'cdata' is an enum, returns the value of the enumerator as a\n" -"string, or 'NUMBER' if the value is out of range."); - -#define ffi_string b_string /* ffi_string() => b_string() - from _cffi_backend.c */ - -PyDoc_STRVAR(ffi_buffer_doc, -"Return a read-write buffer object that references the raw C data\n" -"pointed to by the given 'cdata'. The 'cdata' must be a pointer or an\n" -"array. Can be passed to functions expecting a buffer, or directly\n" -"manipulated with:\n" -"\n" -" buf[:] get a copy of it in a regular string, or\n" -" buf[idx] as a single character\n" -" buf[:] = ...\n" -" buf[idx] = ... change the content"); - -#define ffi_buffer b_buffer /* ffi_buffer() => b_buffer() - from _cffi_backend.c */ - -PyDoc_STRVAR(ffi_offsetof_doc, -"Return the offset of the named field inside the given structure or\n" -"array, which must be given as a C type name. You can give several\n" -"field names in case of nested structures. You can also give numeric\n" -"values which correspond to array items, in case of an array type."); - -static PyObject *ffi_offsetof(FFIObject *self, PyObject *args) -{ - PyObject *arg; - CTypeDescrObject *ct; - Py_ssize_t i, offset; - - if (PyTuple_Size(args) < 2) { - PyErr_SetString(PyExc_TypeError, - "offsetof() expects at least 2 arguments"); - return NULL; - } - - arg = PyTuple_GET_ITEM(args, 0); - ct = _ffi_type(self, arg, ACCEPT_STRING|ACCEPT_CTYPE); - if (ct == NULL) - return NULL; - - offset = 0; - for (i = 1; i < PyTuple_GET_SIZE(args); i++) { - Py_ssize_t ofs1; - ct = direct_typeoffsetof(ct, PyTuple_GET_ITEM(args, i), i > 1, &ofs1); - if (ct == NULL) - return NULL; - offset += ofs1; - } - return PyInt_FromSsize_t(offset); -} - -PyDoc_STRVAR(ffi_addressof_doc, -"Limited equivalent to the '&' operator in C:\n" -"\n" -"1. ffi.addressof(<cdata 'struct-or-union'>) returns a cdata that is a\n" -"pointer to this struct or union.\n" -"\n" -"2. ffi.addressof(<cdata>, field-or-index...) returns the address of a\n" -"field or array item inside the given structure or array, recursively\n" -"in case of nested structures or arrays.\n" -"\n" -"3. ffi.addressof(<library>, \"name\") returns the address of the named\n" -"global variable."); - -static PyObject *address_of_global_var(PyObject *args); /* forward */ - -static PyObject *ffi_addressof(FFIObject *self, PyObject *args) -{ - PyObject *arg, *z, *result; - CTypeDescrObject *ct; - Py_ssize_t i, offset = 0; - int accepted_flags; - - if (PyTuple_Size(args) < 1) { - PyErr_SetString(PyExc_TypeError, - "addressof() expects at least 1 argument"); - return NULL; - } - - arg = PyTuple_GET_ITEM(args, 0); - if (LibObject_Check(arg)) { - /* case 3 in the docstring */ - return address_of_global_var(args); - } - - ct = _ffi_type(self, arg, ACCEPT_CDATA); - if (ct == NULL) - return NULL; - - if (PyTuple_GET_SIZE(args) == 1) { - /* case 1 in the docstring */ - accepted_flags = CT_STRUCT | CT_UNION | CT_ARRAY; - if ((ct->ct_flags & accepted_flags) == 0) { - PyErr_SetString(PyExc_TypeError, - "expected a cdata struct/union/array object"); - return NULL; - } - } - else { - /* case 2 in the docstring */ - accepted_flags = CT_STRUCT | CT_UNION | CT_ARRAY | CT_POINTER; - if ((ct->ct_flags & accepted_flags) == 0) { - PyErr_SetString(PyExc_TypeError, - "expected a cdata struct/union/array/pointer object"); - return NULL; - } - for (i = 1; i < PyTuple_GET_SIZE(args); i++) { - Py_ssize_t ofs1; - ct = direct_typeoffsetof(ct, PyTuple_GET_ITEM(args, i), - i > 1, &ofs1); - if (ct == NULL) - return NULL; - offset += ofs1; - } - } - - z = new_pointer_type(ct); - if (z == NULL) - return NULL; - - result = new_simple_cdata(((CDataObject *)arg)->c_data + offset, - (CTypeDescrObject *)z); - Py_DECREF(z); - return result; -} - -static PyObject *_combine_type_name_l(CTypeDescrObject *ct, - size_t extra_text_len) -{ - size_t base_name_len; - PyObject *result; - char *p; - - base_name_len = strlen(ct->ct_name); - result = PyBytes_FromStringAndSize(NULL, base_name_len + extra_text_len); - if (result == NULL) - return NULL; - - p = PyBytes_AS_STRING(result); - memcpy(p, ct->ct_name, ct->ct_name_position); - p += ct->ct_name_position; - p += extra_text_len; - memcpy(p, ct->ct_name + ct->ct_name_position, - base_name_len - ct->ct_name_position); - return result; -} - -PyDoc_STRVAR(ffi_getctype_doc, -"Return a string giving the C type 'cdecl', which may be itself a\n" -"string or a <ctype> object. If 'replace_with' is given, it gives\n" -"extra text to append (or insert for more complicated C types), like a\n" -"variable name, or '*' to get actually the C type 'pointer-to-cdecl'."); - -static PyObject *ffi_getctype(FFIObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *c_decl, *res; - char *p, *replace_with = ""; - int add_paren, add_space; - CTypeDescrObject *ct; - size_t replace_with_len; - static char *keywords[] = {"cdecl", "replace_with", NULL}; -#if PY_MAJOR_VERSION >= 3 - PyObject *u; -#endif - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s:getctype", keywords, - &c_decl, &replace_with)) - return NULL; - - ct = _ffi_type(self, c_decl, ACCEPT_STRING|ACCEPT_CTYPE); - if (ct == NULL) - return NULL; - - while (replace_with[0] != 0 && isspace(replace_with[0])) - replace_with++; - replace_with_len = strlen(replace_with); - while (replace_with_len > 0 && isspace(replace_with[replace_with_len - 1])) - replace_with_len--; - - add_paren = (replace_with[0] == '*' && - ((ct->ct_flags & CT_ARRAY) != 0)); - add_space = (!add_paren && replace_with_len > 0 && - replace_with[0] != '[' && replace_with[0] != '('); - - res = _combine_type_name_l(ct, replace_with_len + add_space + 2*add_paren); - if (res == NULL) - return NULL; - - p = PyBytes_AS_STRING(res) + ct->ct_name_position; - if (add_paren) - *p++ = '('; - if (add_space) - *p++ = ' '; - memcpy(p, replace_with, replace_with_len); - if (add_paren) - p[replace_with_len] = ')'; - -#if PY_MAJOR_VERSION >= 3 - /* bytes -> unicode string */ - u = PyUnicode_DecodeLatin1(PyBytes_AS_STRING(res), - PyBytes_GET_SIZE(res), - NULL); - Py_DECREF(res); - res = u; -#endif - - return res; -} - -PyDoc_STRVAR(ffi_new_handle_doc, -"Return a non-NULL cdata of type 'void *' that contains an opaque\n" -"reference to the argument, which can be any Python object. To cast it\n" -"back to the original object, use from_handle(). You must keep alive\n" -"the cdata object returned by new_handle()!"); - -static PyObject *ffi_new_handle(FFIObject *self, PyObject *arg) -{ - CDataObject *cd; - - cd = (CDataObject *)PyObject_GC_New(CDataObject, &CDataOwningGC_Type); - if (cd == NULL) - return NULL; - Py_INCREF(g_ct_voidp); // <ctype 'void *'> - cd->c_type = g_ct_voidp; - Py_INCREF(arg); - cd->c_data = ((char *)arg) - 42; - cd->c_weakreflist = NULL; - PyObject_GC_Track(cd); - return (PyObject *)cd; -} - -PyDoc_STRVAR(ffi_from_handle_doc, -"Cast a 'void *' back to a Python object. Must be used *only* on the\n" -"pointers returned by new_handle(), and *only* as long as the exact\n" -"cdata object returned by new_handle() is still alive (somewhere else\n" -"in the program). Failure to follow these rules will crash."); - -static PyObject *ffi_from_handle(PyObject *self, PyObject *arg) -{ - CTypeDescrObject *ct; - char *raw; - PyObject *x; - if (!CData_Check(arg)) { - PyErr_SetString(PyExc_TypeError, "expected a 'cdata' object"); - return NULL; - } - ct = ((CDataObject *)arg)->c_type; - raw = ((CDataObject *)arg)->c_data; - if (!(ct->ct_flags & CT_CAST_ANYTHING)) { - PyErr_Format(PyExc_TypeError, - "expected a 'cdata' object with a 'void *' out of " - "new_handle(), got '%s'", ct->ct_name); - return NULL; - } - if (!raw) { - PyErr_SetString(PyExc_RuntimeError, - "cannot use from_handle() on NULL pointer"); - return NULL; - } - x = (PyObject *)(raw + 42); - Py_INCREF(x); - return x; -} - -PyDoc_STRVAR(ffi_from_buffer_doc, -"Return a <cdata 'char[]'> that points to the data of the given Python\n" -"object, which must support the buffer interface. Note that this is\n" -"not meant to be used on the built-in types str, unicode, or bytearray\n" -"(you can build 'char[]' arrays explicitly) but only on objects\n" -"containing large quantities of raw data in some other format, like\n" -"'array.array' or numpy arrays."); - -static PyObject *ffi_from_buffer(PyObject *self, PyObject *arg) -{ - return direct_from_buffer(g_ct_chararray, arg); -} - -PyDoc_STRVAR(ffi_gc_doc, -"Return a new cdata object that points to the same data.\n" -"Later, when this new cdata object is garbage-collected,\n" -"'destructor(old_cdata_object)' will be called."); - -static PyObject *gc_weakrefs_build(FFIObject *ffi, CDataObject *cd, - PyObject *destructor); /* forward */ - -static PyObject *ffi_gc(FFIObject *self, PyObject *args, PyObject *kwds) -{ - CDataObject *cd; - PyObject *destructor; - static char *keywords[] = {"cdata", "destructor", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O:gc", keywords, - &CData_Type, &cd, &destructor)) - return NULL; - - return gc_weakrefs_build(self, cd, destructor); -} - -PyDoc_STRVAR(ffi_callback_doc, -"Return a callback object or a decorator making such a callback object.\n" -"'cdecl' must name a C function pointer type. The callback invokes the\n" -"specified 'python_callable' (which may be provided either directly or\n" -"via a decorator). Important: the callback object must be manually\n" -"kept alive for as long as the callback may be invoked from the C code."); - -static PyObject *_ffi_callback_decorator(PyObject *outer_args, PyObject *fn) -{ - PyObject *res, *old; - - old = PyTuple_GET_ITEM(outer_args, 1); - PyTuple_SET_ITEM(outer_args, 1, fn); - res = b_callback(NULL, outer_args); - PyTuple_SET_ITEM(outer_args, 1, old); - return res; -} - -static PyObject *ffi_callback(FFIObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *c_decl, *python_callable = Py_None, *error = Py_None; - PyObject *res; - static char *keywords[] = {"cdecl", "python_callable", "error", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", keywords, - &c_decl, &python_callable, &error)) - return NULL; - - c_decl = (PyObject *)_ffi_type(self, c_decl, ACCEPT_STRING | ACCEPT_CTYPE | - CONSIDER_FN_AS_FNPTR); - if (c_decl == NULL) - return NULL; - - args = Py_BuildValue("(OOO)", c_decl, python_callable, error); - if (args == NULL) - return NULL; - - if (python_callable != Py_None) { - res = b_callback(NULL, args); - } - else { - static PyMethodDef md = {"callback_decorator", - (PyCFunction)_ffi_callback_decorator, METH_O}; - res = PyCFunction_New(&md, args); - } - Py_DECREF(args); - return res; -} - -#ifdef MS_WIN32 -PyDoc_STRVAR(ffi_getwinerror_doc, -"Return either the GetLastError() or the error number given by the\n" -"optional 'code' argument, as a tuple '(code, message)'."); - -#define ffi_getwinerror b_getwinerror /* ffi_getwinerror() => b_getwinerror() - from misc_win32.h */ -#endif - -PyDoc_STRVAR(ffi_errno_doc, "the value of 'errno' from/to the C calls"); - -static PyObject *ffi_get_errno(PyObject *self, void *closure) -{ - /* xxx maybe think about how to make the saved errno local - to an ffi instance */ - return b_get_errno(NULL, NULL); -} - -static int ffi_set_errno(PyObject *self, PyObject *newval, void *closure) -{ - PyObject *x = b_set_errno(NULL, newval); - if (x == NULL) - return -1; - Py_DECREF(x); - return 0; -} - -PyDoc_STRVAR(ffi_dlopen_doc, -"Load and return a dynamic library identified by 'name'. The standard\n" -"C library can be loaded by passing None.\n" -"\n" -"Note that functions and types declared with 'ffi.cdef()' are not\n" -"linked to a particular library, just like C headers. In the library\n" -"we only look for the actual (untyped) symbols at the time of their\n" -"first access."); - -PyDoc_STRVAR(ffi_dlclose_doc, -"Close a library obtained with ffi.dlopen(). After this call, access to\n" -"functions or variables from the library will fail (possibly with a\n" -"segmentation fault)."); - -static PyObject *ffi_dlopen(PyObject *self, PyObject *args); /* forward */ -static PyObject *ffi_dlclose(PyObject *self, PyObject *args); /* forward */ - - -#define METH_VKW (METH_VARARGS | METH_KEYWORDS) -static PyMethodDef ffi_methods[] = { - {"addressof", (PyCFunction)ffi_addressof, METH_VARARGS, ffi_addressof_doc}, - {"alignof", (PyCFunction)ffi_alignof, METH_O, ffi_alignof_doc}, - {"buffer", (PyCFunction)ffi_buffer, METH_VARARGS, ffi_buffer_doc}, - {"callback", (PyCFunction)ffi_callback, METH_VKW, ffi_callback_doc}, - {"cast", (PyCFunction)ffi_cast, METH_VARARGS, ffi_cast_doc}, - {"dlclose", (PyCFunction)ffi_dlclose, METH_VARARGS, ffi_dlclose_doc}, - {"dlopen", (PyCFunction)ffi_dlopen, METH_VARARGS, ffi_dlopen_doc}, - {"from_buffer",(PyCFunction)ffi_from_buffer,METH_O, ffi_from_buffer_doc}, - {"from_handle",(PyCFunction)ffi_from_handle,METH_O, ffi_from_handle_doc}, - {"gc", (PyCFunction)ffi_gc, METH_VKW, ffi_gc_doc}, - {"getctype", (PyCFunction)ffi_getctype, METH_VKW, ffi_getctype_doc}, -#ifdef MS_WIN32 - {"getwinerror",(PyCFunction)ffi_getwinerror,METH_VARARGS, ffi_getwinerror_doc}, -#endif - {"new", (PyCFunction)ffi_new, METH_VKW, ffi_new_doc}, - {"new_handle", (PyCFunction)ffi_new_handle, METH_O, ffi_new_handle_doc}, - {"offsetof", (PyCFunction)ffi_offsetof, METH_VARARGS, ffi_offsetof_doc}, - {"sizeof", (PyCFunction)ffi_sizeof, METH_O, ffi_sizeof_doc}, - {"string", (PyCFunction)ffi_string, METH_VARARGS, ffi_string_doc}, - {"typeof", (PyCFunction)ffi_typeof, METH_O, ffi_typeof_doc}, - {NULL} -}; - -static PyGetSetDef ffi_getsets[] = { - {"errno", ffi_get_errno, ffi_set_errno, ffi_errno_doc}, - {NULL} -}; - -static PyTypeObject FFI_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "CompiledFFI", - sizeof(FFIObject), - 0, - (destructor)ffi_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)ffi_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - ffi_methods, /* tp_methods */ - 0, /* tp_members */ - ffi_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - ffiobj_init, /* tp_init */ - 0, /* tp_alloc */ - ffiobj_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ -}; - - -static PyObject * -_fetch_external_struct_or_union(const struct _cffi_struct_union_s *s, - PyObject *included_ffis, int recursion) -{ - Py_ssize_t i; - - if (included_ffis == NULL) - return NULL; - - if (recursion > 100) { - PyErr_SetString(PyExc_RuntimeError, - "recursion overflow in ffi.include() delegations"); - return NULL; - } - - for (i = 0; i < PyTuple_GET_SIZE(included_ffis); i++) { - FFIObject *ffi1; - const struct _cffi_struct_union_s *s1; - int sindex; - PyObject *x; - - ffi1 = (FFIObject *)PyTuple_GET_ITEM(included_ffis, i); - sindex = search_in_struct_unions(&ffi1->types_builder.ctx, s->name, - strlen(s->name)); - if (sindex < 0) /* not found at all */ - continue; - s1 = &ffi1->types_builder.ctx.struct_unions[sindex]; - if ((s1->flags & (_CFFI_F_EXTERNAL | _CFFI_F_UNION)) - == (s->flags & _CFFI_F_UNION)) { - /* s1 is not external, and the same kind (struct or union) as s */ - return _realize_c_struct_or_union(&ffi1->types_builder, sindex); - } - /* not found, look more recursively */ - x = _fetch_external_struct_or_union( - s, ffi1->types_builder.included_ffis, recursion + 1); - if (x != NULL || PyErr_Occurred()) - return x; /* either found, or got an error */ - } - return NULL; /* not found at all, leave without an error */ -} diff --git a/_cffi1/lib_obj.c b/_cffi1/lib_obj.c deleted file mode 100644 index 724317c..0000000 --- a/_cffi1/lib_obj.c +++ /dev/null @@ -1,495 +0,0 @@ - -/* A Lib object is what is in the "lib" attribute of a C extension - module originally created by recompile(). - - A Lib object is special in the sense that it has a custom - __getattr__ which returns C globals, functions and constants. It - raises AttributeError for anything else, even attrs like '__class__'. - - A Lib object has got a reference to the _cffi_type_context_s - structure, which is used to create lazily the objects returned by - __getattr__. -*/ - -struct CPyExtFunc_s { - PyMethodDef md; - int type_index; -}; -static const char cpyextfunc_doc[] = - "direct call to the C function of the same name"; - -struct LibObject_s { - PyObject_HEAD - builder_c_t *l_types_builder; /* same as the one on the ffi object */ - PyObject *l_dict; /* content, built lazily */ - PyObject *l_libname; /* some string that gives the name of the lib */ - PyObject *l_includes; /* tuple of LibObjects included here */ - FFIObject *l_ffi; /* reference back to the ffi object */ - void *l_libhandle; /* the dlopen()ed handle, if any */ -}; - -static struct CPyExtFunc_s *_cpyextfunc_get(PyObject *x) -{ - struct CPyExtFunc_s *exf; - - if (!PyCFunction_Check(x)) - return NULL; - if (!LibObject_Check(PyCFunction_GET_SELF(x))) - return NULL; - - exf = (struct CPyExtFunc_s *)(((PyCFunctionObject *)x) -> m_ml); - if (exf->md.ml_doc != cpyextfunc_doc) - return NULL; - - return exf; -} - -static PyObject *_cpyextfunc_type_index(PyObject *x) -{ - struct CPyExtFunc_s *exf; - LibObject *lib; - PyObject *tuple, *result; - - assert(PyErr_Occurred()); - exf = _cpyextfunc_get(x); - if (exf == NULL) - return NULL; /* still the same exception is set */ - - PyErr_Clear(); - - lib = (LibObject *)PyCFunction_GET_SELF(x); - tuple = realize_c_type_or_func(lib->l_types_builder, - lib->l_types_builder->ctx.types, - exf->type_index); - if (tuple == NULL) - return NULL; - - /* 'tuple' is a tuple of length 1 containing the real CT_FUNCTIONPTR - object */ - result = PyTuple_GetItem(tuple, 0); - Py_XINCREF(result); - Py_DECREF(tuple); - return result; -} - -static void cdlopen_close_ignore_errors(void *libhandle); /* forward */ -static void *cdlopen_fetch(PyObject *libname, void *libhandle, char *symbol); - -static void lib_dealloc(LibObject *lib) -{ - cdlopen_close_ignore_errors(lib->l_libhandle); - Py_DECREF(lib->l_dict); - Py_DECREF(lib->l_libname); - Py_XDECREF(lib->l_includes); - Py_DECREF(lib->l_ffi); - PyObject_Del(lib); -} - -static int lib_traverse(LibObject *lib, visitproc visit, void *arg) -{ - Py_VISIT(lib->l_dict); - Py_VISIT(lib->l_libname); - Py_VISIT(lib->l_includes); - Py_VISIT(lib->l_ffi); - return 0; -} - -static PyObject *lib_repr(LibObject *lib) -{ - return PyText_FromFormat("<Lib object for '%.200s'>", - PyText_AS_UTF8(lib->l_libname)); -} - -static PyObject *lib_build_cpython_func(LibObject *lib, - const struct _cffi_global_s *g, - const char *s, int flags) -{ - /* First make sure the argument types and return type are really - built. The C extension code can then assume that they are, - by calling _cffi_type(). - */ - CTypeDescrObject *ct; - struct CPyExtFunc_s *xfunc; - int i, type_index = _CFFI_GETARG(g->type_op); - _cffi_opcode_t *opcodes = lib->l_types_builder->ctx.types; - assert(_CFFI_GETOP(opcodes[type_index]) == _CFFI_OP_FUNCTION); - - /* return type: */ - ct = realize_c_type(lib->l_types_builder, opcodes, - _CFFI_GETARG(opcodes[type_index])); - if (ct == NULL) - return NULL; - Py_DECREF(ct); - - /* argument types: */ - i = type_index + 1; - while (_CFFI_GETOP(opcodes[i]) != _CFFI_OP_FUNCTION_END) { - ct = realize_c_type(lib->l_types_builder, opcodes, i); - if (ct == NULL) - return NULL; - Py_DECREF(ct); - i++; - } - - /* xxx the few bytes of memory we allocate here leak, but it's a - minor concern because it should only occur for CPYTHON_BLTN. - There is one per real C function in a CFFI C extension module. - CPython never unloads its C extension modules anyway. - */ - xfunc = PyMem_Malloc(sizeof(struct CPyExtFunc_s)); - if (xfunc == NULL) { - PyErr_NoMemory(); - return NULL; - } - memset((char *)xfunc, 0, sizeof(struct CPyExtFunc_s)); - xfunc->md.ml_meth = (PyCFunction)g->address; - xfunc->md.ml_flags = flags; - xfunc->md.ml_name = g->name; - xfunc->md.ml_doc = cpyextfunc_doc; - xfunc->type_index = type_index; - - return PyCFunction_NewEx(&xfunc->md, (PyObject *)lib, lib->l_libname); -} - -static PyObject *lib_build_and_cache_attr(LibObject *lib, PyObject *name, - int recursion) -{ - /* does not return a new reference! */ - PyObject *x; - int index; - const struct _cffi_global_s *g; - CTypeDescrObject *ct; - char *s = PyText_AsUTF8(name); - if (s == NULL) - return NULL; - - index = search_in_globals(&lib->l_types_builder->ctx, s, strlen(s)); - if (index < 0) { - - if (lib->l_includes != NULL) { - Py_ssize_t i; - - if (recursion > 100) { - PyErr_SetString(PyExc_RuntimeError, - "recursion overflow in ffi.include() delegations"); - return NULL; - } - - for (i = 0; i < PyTuple_GET_SIZE(lib->l_includes); i++) { - LibObject *lib1; - lib1 = (LibObject *)PyTuple_GET_ITEM(lib->l_includes, i); - x = PyDict_GetItem(lib1->l_dict, name); - if (x != NULL) { - Py_INCREF(x); - goto found; - } - x = lib_build_and_cache_attr(lib1, name, recursion + 1); - if (x != NULL) { - Py_INCREF(x); - goto found; - } - if (PyErr_Occurred()) - return NULL; - } - } - - if (recursion > 0) - return NULL; /* no error set, continue looking elsewhere */ - - PyErr_Format(PyExc_AttributeError, - "cffi library '%.200s' has no function, constant " - "or global variable named '%.200s'", - PyText_AS_UTF8(lib->l_libname), s); - return NULL; - } - - g = &lib->l_types_builder->ctx.globals[index]; - - switch (_CFFI_GETOP(g->type_op)) { - - case _CFFI_OP_CPYTHON_BLTN_V: - x = lib_build_cpython_func(lib, g, s, METH_VARARGS); - break; - - case _CFFI_OP_CPYTHON_BLTN_N: - x = lib_build_cpython_func(lib, g, s, METH_NOARGS); - break; - - case _CFFI_OP_CPYTHON_BLTN_O: - x = lib_build_cpython_func(lib, g, s, METH_O); - break; - - case _CFFI_OP_CONSTANT_INT: - case _CFFI_OP_ENUM: - { - /* a constant integer whose value, in an "unsigned long long", - is obtained by calling the function at g->address */ - x = realize_global_int(lib->l_types_builder, index); - break; - } - - case _CFFI_OP_CONSTANT: - { - /* a constant which is not of integer type */ - char *data; - ct = realize_c_type(lib->l_types_builder, - lib->l_types_builder->ctx.types, - _CFFI_GETARG(g->type_op)); - if (ct == NULL) - return NULL; - - assert(ct->ct_size > 0); - data = alloca(ct->ct_size); - ((void(*)(char*))g->address)(data); - x = convert_to_object(data, ct); - Py_DECREF(ct); - break; - } - - case _CFFI_OP_GLOBAL_VAR: - /* global variable of the exact type specified here */ - ct = realize_c_type(lib->l_types_builder, - lib->l_types_builder->ctx.types, - _CFFI_GETARG(g->type_op)); - if (ct == NULL) - return NULL; - if (g->size != ct->ct_size && g->size != 0 && ct->ct_size > 0) { - PyErr_Format(FFIError, - "global variable '%.200s' should be %zd bytes " - "according to the cdef, but is actually %zd", - s, ct->ct_size, g->size); - x = NULL; - } - else { - x = make_global_var(ct, g->address); - } - Py_DECREF(ct); - break; - - case _CFFI_OP_DLOPEN: - { - /* For dlopen(): the function or global variable of the given - 'name'. We use dlsym() to get the address of something in - the dynamic library, which we interpret as being exactly of - the specified type. If this type is a function (not a - function pointer), then we assume it is a regular function - in the dynamic library; otherwise, we assume it is a global - variable. - */ - PyObject *ct1; - void *address = cdlopen_fetch(lib->l_libname, lib->l_libhandle, s); - if (address == NULL) - return NULL; - - ct1 = realize_c_type_or_func(lib->l_types_builder, - lib->l_types_builder->ctx.types, - _CFFI_GETARG(g->type_op)); - if (ct1 == NULL) - return NULL; - - if (CTypeDescr_Check(ct1)) - x = make_global_var((CTypeDescrObject *)ct1, address); - else - x = new_simple_cdata(address, unwrap_fn_as_fnptr(ct1)); - - Py_DECREF(ct1); - break; - } - - default: - PyErr_Format(PyExc_NotImplementedError, "in lib_build_attr: op=%d", - (int)_CFFI_GETOP(g->type_op)); - return NULL; - } - - found: - if (x != NULL) { - int err = PyDict_SetItem(lib->l_dict, name, x); - Py_DECREF(x); - if (err < 0) /* else there is still one ref left in the dict */ - return NULL; - } - return x; -} - -#define LIB_GET_OR_CACHE_ADDR(x, lib, name, error) \ - do { \ - x = PyDict_GetItem(lib->l_dict, name); \ - if (x == NULL) { \ - x = lib_build_and_cache_attr(lib, name, 0); \ - if (x == NULL) { \ - error; \ - } \ - } \ - } while (0) - -static PyObject *lib_getattr(LibObject *lib, PyObject *name) -{ - PyObject *x; - LIB_GET_OR_CACHE_ADDR(x, lib, name, return NULL); - - if (GlobSupport_Check(x)) { - return read_global_var((GlobSupportObject *)x); - } - Py_INCREF(x); - return x; -} - -static int lib_setattr(LibObject *lib, PyObject *name, PyObject *val) -{ - PyObject *x; - LIB_GET_OR_CACHE_ADDR(x, lib, name, return -1); - - if (val == NULL) { - PyErr_SetString(PyExc_AttributeError, "C attribute cannot be deleted"); - return -1; - } - - if (GlobSupport_Check(x)) { - return write_global_var((GlobSupportObject *)x, val); - } - - PyErr_Format(PyExc_AttributeError, - "cannot write to function or constant '%.200s'", - PyText_Check(name) ? PyText_AS_UTF8(name) : "?"); - return -1; -} - -static PyObject *lib_dir(LibObject *lib, PyObject *noarg) -{ - const struct _cffi_global_s *g = lib->l_types_builder->ctx.globals; - int i, total = lib->l_types_builder->ctx.num_globals; - PyObject *lst = PyList_New(total); - if (lst == NULL) - return NULL; - - for (i = 0; i < total; i++) { - PyObject *s = PyText_FromString(g[i].name); - if (s == NULL) { - Py_DECREF(lst); - return NULL; - } - PyList_SET_ITEM(lst, i, s); - } - return lst; -} - -static PyMethodDef lib_methods[] = { - {"__dir__", (PyCFunction)lib_dir, METH_NOARGS}, - {NULL, NULL} /* sentinel */ -}; - -static PyTypeObject Lib_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "CompiledLib", - sizeof(LibObject), - 0, - (destructor)lib_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - (reprfunc)lib_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - (getattrofunc)lib_getattr, /* tp_getattro */ - (setattrofunc)lib_setattr, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - (traverseproc)lib_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - lib_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - offsetof(LibObject, l_dict), /* tp_dictoffset */ -}; - -static LibObject *lib_internal_new(FFIObject *ffi, char *module_name, - void *dlopen_libhandle) -{ - LibObject *lib; - PyObject *libname, *dict; - - libname = PyText_FromString(module_name); - if (libname == NULL) - goto err1; - - dict = PyDict_New(); - if (dict == NULL) - goto err2; - - lib = PyObject_New(LibObject, &Lib_Type); - if (lib == NULL) - goto err3; - - lib->l_types_builder = &ffi->types_builder; - lib->l_dict = dict; - lib->l_libname = libname; - lib->l_includes = NULL; - Py_INCREF(ffi); - lib->l_ffi = ffi; - lib->l_libhandle = dlopen_libhandle; - return lib; - - err3: - Py_DECREF(dict); - err2: - Py_DECREF(libname); - err1: - cdlopen_close_ignore_errors(dlopen_libhandle); - return NULL; -} - -static PyObject *address_of_global_var(PyObject *args) -{ - LibObject *lib; - PyObject *x, *o_varname; - char *varname; - - if (!PyArg_ParseTuple(args, "O!s", &Lib_Type, &lib, &varname)) - return NULL; - - /* rebuild a string from 'varname', to do typechecks and to force - a unicode back to a plain string */ - o_varname = PyString_FromString(varname); - if (o_varname == NULL) - return NULL; - - LIB_GET_OR_CACHE_ADDR(x, lib, o_varname, goto error); - Py_DECREF(o_varname); - if (GlobSupport_Check(x)) { - return cg_addressof_global_var((GlobSupportObject *)x); - } - else { - struct CPyExtFunc_s *exf = _cpyextfunc_get(x); - if (exf != NULL || /* an OP_CPYTHON_BLTN: '&func' is 'func' in C */ - ((CData_Check(x) && /* or, a constant functionptr cdata: same */ - (((CDataObject *)x)->c_type->ct_flags & CT_FUNCTIONPTR) != 0))) { - Py_INCREF(x); - return x; - } - else { - PyErr_Format(PyExc_AttributeError, - "cannot take the address of the constant '%.200s'", - varname); - return NULL; - } - } - - error: - Py_DECREF(o_varname); - return NULL; -} diff --git a/_cffi1/manual.c b/_cffi1/manual.c deleted file mode 100644 index 38539b8..0000000 --- a/_cffi1/manual.c +++ /dev/null @@ -1,169 +0,0 @@ -#include "_cffi_include.h" - - -#define AA (42) -#define BB (&bb) -static int bb = 16261; - -int foo42(int a, int *b) -{ - return a - *b; -} - -int foo64(int a) -{ - return ~a; -} - -struct foo_s { - int a; -}; - -/************************************************************/ - -static void *_cffi_types[] = { - _CFFI_OP(_CFFI_OP_FUNCTION, 1), - _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_INT), - _CFFI_OP(_CFFI_OP_POINTER, 1), - _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), - _CFFI_OP(_CFFI_OP_FUNCTION, 1), - _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_INT), - _CFFI_OP(_CFFI_OP_FUNCTION_END, 0), - _CFFI_OP(_CFFI_OP_STRUCT_UNION, 0), -}; - -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_foo42(PyObject *self, PyObject *args) -{ - int x0; - int * x1; - Py_ssize_t datasize; - int result; - PyObject *arg0; - PyObject *arg1; - - if (!PyArg_ParseTuple(args, "OO:foo42", &arg0, &arg1)) - return NULL; - - x0 = _cffi_to_c_int(arg0, int); - if (x0 == (int)-1 && PyErr_Occurred()) - return NULL; - - datasize = _cffi_prepare_pointer_call_argument( - _cffi_types[1], arg1, (char **)&x1); - if (datasize != 0) { - if (datasize < 0) - return NULL; - x1 = alloca(datasize); - memset((void *)x1, 0, datasize); - if (_cffi_convert_array_from_object((char *)x1, _cffi_types[1], arg1) < 0) - return NULL; - } - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = foo42(x0, x1); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - return _cffi_from_c_int(result, int); -} -#else -static int _cffi_f_foo42(int x0, int *x1) -{ - return foo42(x0, x1); -} -#endif - -#ifndef PYPY_VERSION -static PyObject * -_cffi_f_foo64(PyObject *self, PyObject *arg0) -{ - int x0; - int result; - - x0 = _cffi_to_c_int(arg0, int); - if (x0 == (int)-1 && PyErr_Occurred()) - return NULL; - - Py_BEGIN_ALLOW_THREADS - _cffi_restore_errno(); - { result = foo64(x0); } - _cffi_save_errno(); - Py_END_ALLOW_THREADS - - return _cffi_from_c_int(result, int); -} -#else -static int _cffi_f_foo64(int x0) -{ - return foo64(x0); -} -#endif - -static int _cffi_const_AA(unsigned long long *output) -{ - *output = (unsigned long long)((AA) << 0); // integer - return (AA) <= 0; -} - -static void _cffi_const_BB(char *output) -{ - *(int **)output = BB; -} - -static const struct _cffi_global_s _cffi_globals[] = { - { "AA", &_cffi_const_AA, _CFFI_OP(_CFFI_OP_CONSTANT_INT, 0) }, - { "BB", &_cffi_const_BB, _CFFI_OP(_CFFI_OP_CONSTANT, 2) }, - { "bb", &bb, _CFFI_OP(_CFFI_OP_GLOBAL_VAR, 1) }, - { "foo42", &_cffi_f_foo42, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_V, 0) }, - { "foo64", &_cffi_f_foo64, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_O, 4) }, -}; - -struct _cffi_align_foo_s { char x; struct foo_s y; }; - -static const struct _cffi_struct_union_s _cffi_struct_unions[] = { - { "foo_s", 7, 0, - sizeof(struct foo_s), - offsetof(struct _cffi_align_foo_s, y), - 1, 0 }, -}; - -static const struct _cffi_field_s _cffi_fields[] = { - { "a", offsetof(struct foo_s, a), sizeof(((struct foo_s *)0)->a), - _CFFI_OP(_CFFI_OP_NOOP, 1) }, -}; - -static const struct _cffi_type_context_s _cffi_type_context = { - _cffi_types, - _cffi_globals, - _cffi_fields, - _cffi_struct_unions, - NULL, - NULL, - 5, /* num_globals */ - 1, /* num_struct_unions */ - 0, - 0, - NULL, - 8, /* num_types */ -}; - -#ifndef PYPY_VERSION -PyMODINIT_FUNC -initmanual(void) -{ - if (_cffi_init() < 0) - return; - - _cffi_init_module("manual", &_cffi_type_context); -} -#else -PyMODINIT_FUNC -_cffi_pypyinit_manual(const void *p[]) -{ - p[0] = (const void *)0x10000f0; - p[1] = &_cffi_type_context; -} -#endif diff --git a/_cffi1/manual2.py b/_cffi1/manual2.py deleted file mode 100644 index d5c49b0..0000000 --- a/_cffi1/manual2.py +++ /dev/null @@ -1,34 +0,0 @@ -import _cffi_backend - -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\x00\x00\x01\x03', - _globals = (b'\xff\xff\xff\x0bAA',0,b'\xff\xff\xff\x0bBB',-1,b'\xff\xff\xff\x0bCC',2,b'\xff\xff\xff\x1fFOO',0x9999999999999999,b'\x00\x00\x00#close',0,b'\x00\x00\x05#stdout',0), - _struct_unions = ((b'\x00\x00\x00\x03\x00\x00\x00\x00point_s',b'\x00\x00\x01\x11\xff\xff\xff\xffx',b'\x00\x00\x01\x11\xff\xff\xff\xffy'),), - _enums = (b'\x00\x00\x00\x04\x00\x00\x00\x07myenum_e\x00AA,BB,CC',), - _typenames = (b'\x00\x00\x00\x01myint_t',), -) - - - -# trying it out -lib = ffi.dlopen(None) -assert lib.AA == 0 -assert lib.BB == -1 -assert lib.FOO == 0x9999999999999999 -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") -print ffi.new("struct point_s[CC]") -assert ffi.sizeof("struct point_s[CC]") == 2 * ffi.sizeof("struct point_s") - -print ffi.cast("enum myenum_e", 2) -print ffi.cast("myint_t", -2) -assert ffi.typeof("myint_t") == ffi.typeof("int") - -del ffi, lib diff --git a/_cffi1/parse_c_type.c b/_cffi1/parse_c_type.c deleted file mode 100644 index 25ae4b7..0000000 --- a/_cffi1/parse_c_type.c +++ /dev/null @@ -1,760 +0,0 @@ -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <errno.h> - -#define _CFFI_INTERNAL -#include "parse_c_type.h" - - -enum token_e { - TOK_STAR='*', - TOK_OPEN_PAREN='(', - TOK_CLOSE_PAREN=')', - TOK_OPEN_BRACKET='[', - TOK_CLOSE_BRACKET=']', - TOK_COMMA=',', - - TOK_START=256, - TOK_END, - TOK_ERROR, - TOK_IDENTIFIER, - TOK_INTEGER, - TOK_DOTDOTDOT, - - /* keywords */ - TOK__BOOL, - TOK_CHAR, - //TOK__COMPLEX, - TOK_CONST, - TOK_DOUBLE, - TOK_ENUM, - TOK_FLOAT, - //TOK__IMAGINARY, - TOK_INT, - TOK_LONG, - TOK_SHORT, - TOK_SIGNED, - TOK_STRUCT, - TOK_UNION, - TOK_UNSIGNED, - TOK_VOID, - TOK_VOLATILE, -}; - -typedef struct { - struct _cffi_parse_info_s *info; - const char *input, *p; - size_t size; // the next token is at 'p' and of length 'size' - enum token_e kind; - _cffi_opcode_t *output; - size_t output_index; -} token_t; - -static int is_space(char x) -{ - return (x == ' ' || x == '\f' || x == '\n' || x == '\r' || - x == '\t' || x == '\v'); -} - -static int is_ident_first(char x) -{ - return (('A' <= x && x <= 'Z') || ('a' <= x && x <= 'z') || x == '_' || - x == '$'); /* '$' in names is supported here, for the struct - names invented by cparser */ -} - -static int is_digit(char x) -{ - return ('0' <= x && x <= '9'); -} - -static int is_hex_digit(char x) -{ - return (('0' <= x && x <= '9') || - ('A' <= x && x <= 'F') || - ('a' <= x && x <= 'f')); -} - -static int is_ident_next(char x) -{ - return (is_ident_first(x) || is_digit(x)); -} - -static char get_following_char(token_t *tok) -{ - const char *p = tok->p + tok->size; - if (tok->kind == TOK_ERROR) - return 0; - while (is_space(*p)) - p++; - return *p; -} - -static int number_of_commas(token_t *tok) -{ - const char *p = tok->p; - int result = 0; - int nesting = 0; - while (1) { - switch (*p++) { - case ',': result += !nesting; break; - case '(': nesting++; break; - case ')': if ((--nesting) < 0) return result; break; - case 0: return result; - default: break; - } - } -} - -static void next_token(token_t *tok) -{ - const char *p = tok->p + tok->size; - if (tok->kind == TOK_ERROR) - return; - while (!is_ident_first(*p)) { - if (is_space(*p)) { - p++; - } - else if (is_digit(*p)) { - tok->kind = TOK_INTEGER; - tok->p = p; - tok->size = 1; - if (p[1] == 'x' || p[1] == 'X') - tok->size = 2; - while (is_hex_digit(p[tok->size])) - tok->size++; - return; - } - else if (p[0] == '.' && p[1] == '.' && p[2] == '.') { - tok->kind = TOK_DOTDOTDOT; - tok->p = p; - tok->size = 3; - return; - } - else if (*p) { - tok->kind = *p; - tok->p = p; - tok->size = 1; - return; - } - else { - tok->kind = TOK_END; - tok->p = p; - tok->size = 0; - return; - } - } - tok->kind = TOK_IDENTIFIER; - tok->p = p; - tok->size = 1; - while (is_ident_next(p[tok->size])) - tok->size++; - - switch (*p) { - case '_': - if (tok->size == 5 && !memcmp(p, "_Bool", 5)) tok->kind = TOK__BOOL; - break; - case 'c': - if (tok->size == 4 && !memcmp(p, "char", 4)) tok->kind = TOK_CHAR; - if (tok->size == 5 && !memcmp(p, "const", 5)) tok->kind = TOK_CONST; - break; - case 'd': - if (tok->size == 6 && !memcmp(p, "double", 6)) tok->kind = TOK_DOUBLE; - break; - case 'e': - if (tok->size == 4 && !memcmp(p, "enum", 4)) tok->kind = TOK_ENUM; - break; - case 'f': - if (tok->size == 5 && !memcmp(p, "float", 5)) tok->kind = TOK_FLOAT; - break; - case 'i': - if (tok->size == 3 && !memcmp(p, "int", 3)) tok->kind = TOK_INT; - break; - case 'l': - if (tok->size == 4 && !memcmp(p, "long", 4)) tok->kind = TOK_LONG; - break; - case 's': - if (tok->size == 5 && !memcmp(p, "short", 5)) tok->kind = TOK_SHORT; - if (tok->size == 6 && !memcmp(p, "signed", 6)) tok->kind = TOK_SIGNED; - if (tok->size == 6 && !memcmp(p, "struct", 6)) tok->kind = TOK_STRUCT; - break; - case 'u': - if (tok->size == 5 && !memcmp(p, "union", 5)) tok->kind = TOK_UNION; - if (tok->size == 8 && !memcmp(p,"unsigned",8)) tok->kind = TOK_UNSIGNED; - break; - case 'v': - if (tok->size == 4 && !memcmp(p, "void", 4)) tok->kind = TOK_VOID; - if (tok->size == 8 && !memcmp(p,"volatile",8)) tok->kind = TOK_VOLATILE; - break; - } -} - -static int parse_error(token_t *tok, const char *msg) -{ - if (tok->kind != TOK_ERROR) { - tok->kind = TOK_ERROR; - tok->info->error_location = tok->p - tok->input; - tok->info->error_message = msg; - } - return -1; -} - -static int write_ds(token_t *tok, _cffi_opcode_t ds) -{ - size_t index = tok->output_index; - if (index >= tok->info->output_size) { - parse_error(tok, "internal type complexity limit reached"); - return -1; - } - tok->output[index] = ds; - tok->output_index = index + 1; - return index; -} - -#define MAX_SSIZE_T (((size_t)-1) >> 1) - -static int parse_complete(token_t *tok); - -static int parse_sequel(token_t *tok, int outer) -{ - /* Emit opcodes for the "sequel", which is the optional part of a - type declaration that follows the type name, i.e. everything - with '*', '[ ]', '( )'. Returns the entry point index pointing - the innermost opcode (the one that corresponds to the complete - type). The 'outer' argument is the index of the opcode outside - this "sequel". - */ - int check_for_grouping; - _cffi_opcode_t result, *p_current; - - header: - switch (tok->kind) { - case TOK_STAR: - outer = write_ds(tok, _CFFI_OP(_CFFI_OP_POINTER, outer)); - next_token(tok); - goto header; - case TOK_CONST: - /* ignored for now */ - next_token(tok); - goto header; - case TOK_VOLATILE: - /* ignored for now */ - next_token(tok); - goto header; - default: - break; - } - - check_for_grouping = 1; - if (tok->kind == TOK_IDENTIFIER) { - next_token(tok); /* skip a potential variable name */ - check_for_grouping = 0; - } - - result = 0; - p_current = &result; - - while (tok->kind == TOK_OPEN_PAREN) { - next_token(tok); - - if ((check_for_grouping--) == 1 && (tok->kind == TOK_STAR || - tok->kind == TOK_CONST || - tok->kind == TOK_VOLATILE || - tok->kind == TOK_OPEN_BRACKET)) { - /* just parentheses for grouping. Use a OP_NOOP to simplify */ - int x; - assert(p_current == &result); - x = tok->output_index; - p_current = tok->output + x; - - write_ds(tok, _CFFI_OP(_CFFI_OP_NOOP, 0)); - - x = parse_sequel(tok, x); - result = _CFFI_OP(_CFFI_GETOP(0), x); - } - else { - /* function type */ - int arg_total, base_index, arg_next, has_ellipsis=0; - - if (tok->kind == TOK_VOID && get_following_char(tok) == ')') { - next_token(tok); - } - - /* (over-)estimate 'arg_total'. May return 1 when it is really 0 */ - arg_total = number_of_commas(tok) + 1; - - *p_current = _CFFI_OP(_CFFI_GETOP(*p_current), tok->output_index); - p_current = tok->output + tok->output_index; - - base_index = write_ds(tok, _CFFI_OP(_CFFI_OP_FUNCTION, 0)); - if (base_index < 0) - return -1; - /* reserve (arg_total + 1) slots for the arguments and the - final FUNCTION_END */ - for (arg_next = 0; arg_next <= arg_total; arg_next++) - if (write_ds(tok, _CFFI_OP(0, 0)) < 0) - return -1; - - arg_next = base_index + 1; - - if (tok->kind != TOK_CLOSE_PAREN) { - while (1) { - int arg; - _cffi_opcode_t oarg; - - if (tok->kind == TOK_DOTDOTDOT) { - has_ellipsis = 1; - next_token(tok); - break; - } - arg = parse_complete(tok); - switch (_CFFI_GETOP(tok->output[arg])) { - case _CFFI_OP_ARRAY: - case _CFFI_OP_OPEN_ARRAY: - arg = _CFFI_GETARG(tok->output[arg]); - /* fall-through */ - case _CFFI_OP_FUNCTION: - oarg = _CFFI_OP(_CFFI_OP_POINTER, arg); - break; - default: - oarg = _CFFI_OP(_CFFI_OP_NOOP, arg); - break; - } - assert(arg_next - base_index <= arg_total); - tok->output[arg_next++] = oarg; - if (tok->kind != TOK_COMMA) - break; - next_token(tok); - } - } - tok->output[arg_next] = _CFFI_OP(_CFFI_OP_FUNCTION_END, - has_ellipsis); - } - - if (tok->kind != TOK_CLOSE_PAREN) - return parse_error(tok, "expected ')'"); - next_token(tok); - } - - while (tok->kind == TOK_OPEN_BRACKET) { - *p_current = _CFFI_OP(_CFFI_GETOP(*p_current), tok->output_index); - p_current = tok->output + tok->output_index; - - next_token(tok); - if (tok->kind != TOK_CLOSE_BRACKET) { - size_t length; - int gindex; - char *endptr; - - switch (tok->kind) { - - case TOK_INTEGER: - errno = 0; -#ifndef MS_WIN32 - if (sizeof(length) > sizeof(unsigned long)) - length = strtoull(tok->p, &endptr, 0); - else -#endif - length = strtoul(tok->p, &endptr, 0); - if (endptr != tok->p + tok->size) - return parse_error(tok, "invalid number"); - if (errno == ERANGE || length > MAX_SSIZE_T) - return parse_error(tok, "number too large"); - break; - - case TOK_IDENTIFIER: - gindex = search_in_globals(tok->info->ctx, tok->p, tok->size); - if (gindex >= 0) { - const struct _cffi_global_s *g; - g = &tok->info->ctx->globals[gindex]; - if (_CFFI_GETOP(g->type_op) == _CFFI_OP_CONSTANT_INT || - _CFFI_GETOP(g->type_op) == _CFFI_OP_ENUM) { - int neg; - struct _cffi_getconst_s gc; - gc.ctx = tok->info->ctx; - gc.gindex = gindex; - neg = ((int(*)(struct _cffi_getconst_s*))g->address) - (&gc); - if (neg == 0 && gc.value > MAX_SSIZE_T) - return parse_error(tok, - "integer constant too large"); - if (neg == 0 || gc.value == 0) { - length = (size_t)gc.value; - break; - } - if (neg != 1) - return parse_error(tok, "disagreement about" - " this constant's value"); - } - } - /* fall-through to the default case */ - default: - return parse_error(tok, "expected a positive integer constant"); - } - - next_token(tok); - - write_ds(tok, _CFFI_OP(_CFFI_OP_ARRAY, 0)); - write_ds(tok, (_cffi_opcode_t)length); - } - else - write_ds(tok, _CFFI_OP(_CFFI_OP_OPEN_ARRAY, 0)); - - if (tok->kind != TOK_CLOSE_BRACKET) - return parse_error(tok, "expected ']'"); - next_token(tok); - } - - *p_current = _CFFI_OP(_CFFI_GETOP(*p_current), outer); - return _CFFI_GETARG(result); -} - - -#define MAKE_SEARCH_FUNC(FIELD) \ - static \ - int search_in_##FIELD(const struct _cffi_type_context_s *ctx, \ - const char *search, size_t search_len) \ - { \ - int left = 0, right = ctx->num_##FIELD; \ - \ - while (left < right) { \ - int middle = (left + right) / 2; \ - const char *src = ctx->FIELD[middle].name; \ - int diff = strncmp(src, search, search_len); \ - if (diff == 0 && src[search_len] == '\0') \ - return middle; \ - else if (diff >= 0) \ - right = middle; \ - else \ - left = middle + 1; \ - } \ - return -1; \ - } - -MAKE_SEARCH_FUNC(globals) -MAKE_SEARCH_FUNC(struct_unions) -MAKE_SEARCH_FUNC(typenames) -MAKE_SEARCH_FUNC(enums) - -#undef MAKE_SEARCH_FUNC - - -static -int search_standard_typename(const char *p, size_t size) -{ - if (size < 6 || p[size-2] != '_' || p[size-1] != 't') - return -1; - - switch (p[4]) { - - case '1': - if (size == 8 && !memcmp(p, "uint16", 6)) return _CFFI_PRIM_UINT16; - break; - - case '2': - if (size == 7 && !memcmp(p, "int32", 5)) return _CFFI_PRIM_INT32; - break; - - case '3': - if (size == 8 && !memcmp(p, "uint32", 6)) return _CFFI_PRIM_UINT32; - break; - - case '4': - if (size == 7 && !memcmp(p, "int64", 5)) return _CFFI_PRIM_INT64; - break; - - case '6': - if (size == 8 && !memcmp(p, "uint64", 6)) return _CFFI_PRIM_UINT64; - if (size == 7 && !memcmp(p, "int16", 5)) return _CFFI_PRIM_INT16; - break; - - case '8': - if (size == 7 && !memcmp(p, "uint8", 5)) return _CFFI_PRIM_UINT8; - break; - - case 'a': - if (size == 8 && !memcmp(p, "intmax", 6)) return _CFFI_PRIM_INTMAX; - break; - - case 'e': - if (size == 7 && !memcmp(p, "ssize", 5)) return _CFFI_PRIM_SSIZE; - break; - - case 'f': - if (size == 11 && !memcmp(p, "int_fast8", 9)) return _CFFI_PRIM_INT_FAST8; - if (size == 12 && !memcmp(p, "int_fast16", 10)) return _CFFI_PRIM_INT_FAST16; - if (size == 12 && !memcmp(p, "int_fast32", 10)) return _CFFI_PRIM_INT_FAST32; - if (size == 12 && !memcmp(p, "int_fast64", 10)) return _CFFI_PRIM_INT_FAST64; - break; - - case 'i': - if (size == 9 && !memcmp(p, "ptrdiff", 7)) return _CFFI_PRIM_PTRDIFF; - break; - - case 'l': - if (size == 12 && !memcmp(p, "int_least8", 10)) return _CFFI_PRIM_INT_LEAST8; - if (size == 13 && !memcmp(p, "int_least16", 11)) return _CFFI_PRIM_INT_LEAST16; - if (size == 13 && !memcmp(p, "int_least32", 11)) return _CFFI_PRIM_INT_LEAST32; - if (size == 13 && !memcmp(p, "int_least64", 11)) return _CFFI_PRIM_INT_LEAST64; - break; - - case 'm': - if (size == 9 && !memcmp(p, "uintmax", 7)) return _CFFI_PRIM_UINTMAX; - break; - - case 'p': - if (size == 9 && !memcmp(p, "uintptr", 7)) return _CFFI_PRIM_UINTPTR; - break; - - case 'r': - if (size == 7 && !memcmp(p, "wchar", 5)) return _CFFI_PRIM_WCHAR; - break; - - case 't': - if (size == 8 && !memcmp(p, "intptr", 6)) return _CFFI_PRIM_INTPTR; - break; - - case '_': - if (size == 6 && !memcmp(p, "size", 4)) return _CFFI_PRIM_SIZE; - if (size == 6 && !memcmp(p, "int8", 4)) return _CFFI_PRIM_INT8; - if (size >= 12) { - switch (p[10]) { - case '1': - if (size == 14 && !memcmp(p, "uint_least16", 12)) return _CFFI_PRIM_UINT_LEAST16; - break; - case '2': - if (size == 13 && !memcmp(p, "uint_fast32", 11)) return _CFFI_PRIM_UINT_FAST32; - break; - case '3': - if (size == 14 && !memcmp(p, "uint_least32", 12)) return _CFFI_PRIM_UINT_LEAST32; - break; - case '4': - if (size == 13 && !memcmp(p, "uint_fast64", 11)) return _CFFI_PRIM_UINT_FAST64; - break; - case '6': - if (size == 14 && !memcmp(p, "uint_least64", 12)) return _CFFI_PRIM_UINT_LEAST64; - if (size == 13 && !memcmp(p, "uint_fast16", 11)) return _CFFI_PRIM_UINT_FAST16; - break; - case '8': - if (size == 13 && !memcmp(p, "uint_least8", 11)) return _CFFI_PRIM_UINT_LEAST8; - break; - case '_': - if (size == 12 && !memcmp(p, "uint_fast8", 10)) return _CFFI_PRIM_UINT_FAST8; - break; - default: - break; - } - } - break; - - default: - break; - } - return -1; -} - - -static int parse_complete(token_t *tok) -{ - unsigned int t0; - _cffi_opcode_t t1; - int modifiers_length, modifiers_sign; - - qualifiers: - switch (tok->kind) { - case TOK_CONST: - /* ignored for now */ - next_token(tok); - goto qualifiers; - case TOK_VOLATILE: - /* ignored for now */ - next_token(tok); - goto qualifiers; - default: - ; - } - - modifiers_length = 0; - modifiers_sign = 0; - modifiers: - switch (tok->kind) { - - case TOK_SHORT: - if (modifiers_length != 0) - return parse_error(tok, "'short' after another 'short' or 'long'"); - modifiers_length--; - next_token(tok); - goto modifiers; - - case TOK_LONG: - if (modifiers_length < 0) - return parse_error(tok, "'long' after 'short'"); - if (modifiers_length >= 2) - return parse_error(tok, "'long long long' is too long"); - modifiers_length++; - next_token(tok); - goto modifiers; - - case TOK_SIGNED: - if (modifiers_sign) - return parse_error(tok, "multiple 'signed' or 'unsigned'"); - modifiers_sign++; - next_token(tok); - goto modifiers; - - case TOK_UNSIGNED: - if (modifiers_sign) - return parse_error(tok, "multiple 'signed' or 'unsigned'"); - modifiers_sign--; - next_token(tok); - goto modifiers; - - default: - break; - } - - if (modifiers_length || modifiers_sign) { - - switch (tok->kind) { - - case TOK_VOID: - case TOK__BOOL: - case TOK_FLOAT: - case TOK_STRUCT: - case TOK_UNION: - case TOK_ENUM: - return parse_error(tok, "invalid combination of types"); - - case TOK_DOUBLE: - if (modifiers_sign != 0 || modifiers_length != 1) - return parse_error(tok, "invalid combination of types"); - next_token(tok); - t0 = _CFFI_PRIM_LONGDOUBLE; - break; - - case TOK_CHAR: - if (modifiers_length != 0) - return parse_error(tok, "invalid combination of types"); - modifiers_length = -2; - /* fall-through */ - case TOK_INT: - next_token(tok); - /* fall-through */ - default: - if (modifiers_sign >= 0) - switch (modifiers_length) { - case -2: t0 = _CFFI_PRIM_SCHAR; break; - case -1: t0 = _CFFI_PRIM_SHORT; break; - case 1: t0 = _CFFI_PRIM_LONG; break; - case 2: t0 = _CFFI_PRIM_LONGLONG; break; - default: t0 = _CFFI_PRIM_INT; break; - } - else - switch (modifiers_length) { - case -2: t0 = _CFFI_PRIM_UCHAR; break; - case -1: t0 = _CFFI_PRIM_USHORT; break; - case 1: t0 = _CFFI_PRIM_ULONG; break; - case 2: t0 = _CFFI_PRIM_ULONGLONG; break; - default: t0 = _CFFI_PRIM_UINT; break; - } - } - t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, t0); - } - else { - switch (tok->kind) { - case TOK_INT: - t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_INT); - break; - case TOK_CHAR: - t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_CHAR); - break; - case TOK_VOID: - t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_VOID); - break; - case TOK__BOOL: - t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_BOOL); - break; - case TOK_FLOAT: - t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_FLOAT); - break; - case TOK_DOUBLE: - t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_DOUBLE); - break; - case TOK_IDENTIFIER: - { - int n = search_in_typenames(tok->info->ctx, tok->p, tok->size); - if (n >= 0) { - t1 = _CFFI_OP(_CFFI_OP_TYPENAME, n); - break; - } - n = search_standard_typename(tok->p, tok->size); - if (n >= 0) { - t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, n); - break; - } - return parse_error(tok, "undefined type name"); - } - case TOK_STRUCT: - case TOK_UNION: - { - int n, kind = tok->kind; - next_token(tok); - if (tok->kind != TOK_IDENTIFIER) - return parse_error(tok, "struct or union name expected"); - - n = search_in_struct_unions(tok->info->ctx, tok->p, tok->size); - if (n < 0) - return parse_error(tok, "undefined struct/union name"); - if (((tok->info->ctx->struct_unions[n].flags & _CFFI_F_UNION) != 0) - ^ (kind == TOK_UNION)) - return parse_error(tok, "wrong kind of tag: struct vs union"); - - t1 = _CFFI_OP(_CFFI_OP_STRUCT_UNION, n); - break; - } - case TOK_ENUM: - { - int n; - next_token(tok); - if (tok->kind != TOK_IDENTIFIER) - return parse_error(tok, "enum name expected"); - - n = search_in_enums(tok->info->ctx, tok->p, tok->size); - if (n < 0) - return parse_error(tok, "undefined enum name"); - - t1 = _CFFI_OP(_CFFI_OP_ENUM, n); - break; - } - default: - return parse_error(tok, "identifier expected"); - } - next_token(tok); - } - - return parse_sequel(tok, write_ds(tok, t1)); -} - - -static -int parse_c_type(struct _cffi_parse_info_s *info, const char *input) -{ - int result; - token_t token; - - token.info = info; - token.kind = TOK_START; - token.input = input; - token.p = input; - token.size = 0; - token.output = info->output; - token.output_index = 0; - - next_token(&token); - result = parse_complete(&token); - - if (token.kind != TOK_END) - return parse_error(&token, "unexpected symbol"); - return result; -} diff --git a/_cffi1/parse_c_type.h b/_cffi1/parse_c_type.h deleted file mode 100644 index 2320803..0000000 --- a/_cffi1/parse_c_type.h +++ /dev/null @@ -1,161 +0,0 @@ - -/* See doc/parse_c_type.rst in the source of CFFI for more information */ - -typedef void *_cffi_opcode_t; - -#define _CFFI_OP(opcode, arg) (_cffi_opcode_t)(opcode | (((uintptr_t)(arg)) << 8)) -#define _CFFI_GETOP(cffi_opcode) ((unsigned char)(uintptr_t)cffi_opcode) -#define _CFFI_GETARG(cffi_opcode) (((uintptr_t)cffi_opcode) >> 8) - -#define _CFFI_OP_PRIMITIVE 1 -#define _CFFI_OP_POINTER 3 -#define _CFFI_OP_ARRAY 5 -#define _CFFI_OP_OPEN_ARRAY 7 -#define _CFFI_OP_STRUCT_UNION 9 -#define _CFFI_OP_ENUM 11 -#define _CFFI_OP_FUNCTION 13 -#define _CFFI_OP_FUNCTION_END 15 -#define _CFFI_OP_NOOP 17 -#define _CFFI_OP_BITFIELD 19 -#define _CFFI_OP_TYPENAME 21 -#define _CFFI_OP_CPYTHON_BLTN_V 23 // varargs -#define _CFFI_OP_CPYTHON_BLTN_N 25 // noargs -#define _CFFI_OP_CPYTHON_BLTN_O 27 // O (i.e. a single arg) -#define _CFFI_OP_CONSTANT 29 -#define _CFFI_OP_CONSTANT_INT 31 -#define _CFFI_OP_GLOBAL_VAR 33 -#define _CFFI_OP_DLOPEN 35 - -#define _CFFI_PRIM_VOID 0 -#define _CFFI_PRIM_BOOL 1 -#define _CFFI_PRIM_CHAR 2 -#define _CFFI_PRIM_SCHAR 3 -#define _CFFI_PRIM_UCHAR 4 -#define _CFFI_PRIM_SHORT 5 -#define _CFFI_PRIM_USHORT 6 -#define _CFFI_PRIM_INT 7 -#define _CFFI_PRIM_UINT 8 -#define _CFFI_PRIM_LONG 9 -#define _CFFI_PRIM_ULONG 10 -#define _CFFI_PRIM_LONGLONG 11 -#define _CFFI_PRIM_ULONGLONG 12 -#define _CFFI_PRIM_FLOAT 13 -#define _CFFI_PRIM_DOUBLE 14 -#define _CFFI_PRIM_LONGDOUBLE 15 - -#define _CFFI_PRIM_WCHAR 16 -#define _CFFI_PRIM_INT8 17 -#define _CFFI_PRIM_UINT8 18 -#define _CFFI_PRIM_INT16 19 -#define _CFFI_PRIM_UINT16 20 -#define _CFFI_PRIM_INT32 21 -#define _CFFI_PRIM_UINT32 22 -#define _CFFI_PRIM_INT64 23 -#define _CFFI_PRIM_UINT64 24 -#define _CFFI_PRIM_INTPTR 25 -#define _CFFI_PRIM_UINTPTR 26 -#define _CFFI_PRIM_PTRDIFF 27 -#define _CFFI_PRIM_SIZE 28 -#define _CFFI_PRIM_SSIZE 29 -#define _CFFI_PRIM_INT_LEAST8 30 -#define _CFFI_PRIM_UINT_LEAST8 31 -#define _CFFI_PRIM_INT_LEAST16 32 -#define _CFFI_PRIM_UINT_LEAST16 33 -#define _CFFI_PRIM_INT_LEAST32 34 -#define _CFFI_PRIM_UINT_LEAST32 35 -#define _CFFI_PRIM_INT_LEAST64 36 -#define _CFFI_PRIM_UINT_LEAST64 37 -#define _CFFI_PRIM_INT_FAST8 38 -#define _CFFI_PRIM_UINT_FAST8 39 -#define _CFFI_PRIM_INT_FAST16 40 -#define _CFFI_PRIM_UINT_FAST16 41 -#define _CFFI_PRIM_INT_FAST32 42 -#define _CFFI_PRIM_UINT_FAST32 43 -#define _CFFI_PRIM_INT_FAST64 44 -#define _CFFI_PRIM_UINT_FAST64 45 -#define _CFFI_PRIM_INTMAX 46 -#define _CFFI_PRIM_UINTMAX 47 - -#define _CFFI__NUM_PRIM 48 - - -struct _cffi_global_s { - const char *name; - void *address; - _cffi_opcode_t type_op; - size_t size; // 0 if unknown -}; - -struct _cffi_getconst_s { - unsigned long long value; - const struct _cffi_type_context_s *ctx; - int gindex; -}; - -struct _cffi_struct_union_s { - const char *name; - int type_index; // -> _cffi_types, on a OP_STRUCT_UNION - int flags; // _CFFI_F_* flags below - size_t size; - int alignment; - int first_field_index; // -> _cffi_fields array - int num_fields; -}; -#define _CFFI_F_UNION 0x01 // is a union, not a struct -#define _CFFI_F_CHECK_FIELDS 0x02 // complain if fields are not in the - // "standard layout" or if some are missing -#define _CFFI_F_PACKED 0x04 // for CHECK_FIELDS, assume a packed struct -#define _CFFI_F_EXTERNAL 0x08 // in some other ffi.include() -#define _CFFI_F_OPAQUE 0x10 // opaque - -struct _cffi_field_s { - const char *name; - size_t field_offset; - size_t field_size; - _cffi_opcode_t field_type_op; -}; - -struct _cffi_enum_s { - const char *name; - int type_index; // -> _cffi_types, on a OP_ENUM - int type_prim; // _CFFI_PRIM_xxx - const char *enumerators; // comma-delimited string -}; - -struct _cffi_typename_s { - const char *name; - int type_index; /* if opaque, points to a possibly artificial - OP_STRUCT which is itself opaque */ -}; - -struct _cffi_type_context_s { - _cffi_opcode_t *types; - const struct _cffi_global_s *globals; - const struct _cffi_field_s *fields; - const struct _cffi_struct_union_s *struct_unions; - const struct _cffi_enum_s *enums; - const struct _cffi_typename_s *typenames; - int num_globals; - int num_struct_unions; - int num_enums; - int num_typenames; - const char *const *includes; - int num_types; - int flags; /* future extension */ -}; - -struct _cffi_parse_info_s { - const struct _cffi_type_context_s *ctx; - _cffi_opcode_t *output; - unsigned int output_size; - size_t error_location; - const char *error_message; -}; - -#ifdef _CFFI_INTERNAL -static int parse_c_type(struct _cffi_parse_info_s *info, const char *input); -static int search_in_globals(const struct _cffi_type_context_s *ctx, - const char *search, size_t search_len); -static int search_in_struct_unions(const struct _cffi_type_context_s *ctx, - const char *search, size_t search_len); -#endif diff --git a/_cffi1/realize_c_type.c b/_cffi1/realize_c_type.c deleted file mode 100644 index 61be3da..0000000 --- a/_cffi1/realize_c_type.c +++ /dev/null @@ -1,715 +0,0 @@ - -typedef struct { - struct _cffi_type_context_s ctx; /* inlined substructure */ - PyObject *types_dict; - PyObject *included_ffis; - PyObject *_keepalive1; - PyObject *_keepalive2; -} builder_c_t; - - -static PyObject *all_primitives[_CFFI__NUM_PRIM]; -static CTypeDescrObject *g_ct_voidp, *g_ct_chararray; - -static PyObject *build_primitive_type(int num); /* forward */ - -#define get_primitive_type(num) \ - (all_primitives[num] != NULL ? all_primitives[num] \ - : build_primitive_type(num)) - -static int init_global_types_dict(PyObject *ffi_type_dict) -{ - int err; - PyObject *ct_void, *ct_char, *ct2, *pnull; - /* XXX some leaks in case these functions fail, but well, - MemoryErrors during importing an extension module are kind - of bad anyway */ - - ct_void = get_primitive_type(_CFFI_PRIM_VOID); // 'void' - if (ct_void == NULL) - return -1; - - ct2 = new_pointer_type((CTypeDescrObject *)ct_void); // 'void *' - if (ct2 == NULL) - return -1; - g_ct_voidp = (CTypeDescrObject *)ct2; - - ct_char = get_primitive_type(_CFFI_PRIM_CHAR); // 'char' - if (ct_char == NULL) - return -1; - - ct2 = new_pointer_type((CTypeDescrObject *)ct_char); // 'char *' - if (ct2 == NULL) - return -1; - - ct2 = new_array_type((CTypeDescrObject *)ct2, -1); // 'char[]' - if (ct2 == NULL) - return -1; - g_ct_chararray = (CTypeDescrObject *)ct2; - - pnull = new_simple_cdata(NULL, g_ct_voidp); - if (pnull == NULL) - return -1; - err = PyDict_SetItemString(ffi_type_dict, "NULL", pnull); - Py_DECREF(pnull); - return err; -} - -static void free_builder_c(builder_c_t *builder, int ctx_is_static) -{ - if (!ctx_is_static) { - int i; - const void *mem[] = {builder->ctx.types, - builder->ctx.globals, - builder->ctx.struct_unions, - //builder->ctx.fields: allocated with struct_unions - builder->ctx.enums, - builder->ctx.typenames}; - for (i = 0; i < sizeof(mem) / sizeof(*mem); i++) { - if (mem[i] != NULL) - PyMem_Free((void *)mem[i]); - } - } - Py_XDECREF(builder->included_ffis); - Py_XDECREF(builder->types_dict); - Py_XDECREF(builder->_keepalive1); - Py_XDECREF(builder->_keepalive2); -} - -static int init_builder_c(builder_c_t *builder, - const struct _cffi_type_context_s *ctx) -{ - PyObject *ldict = PyDict_New(); - if (ldict == NULL) - return -1; - - if (ctx) - builder->ctx = *ctx; - else - memset(&builder->ctx, 0, sizeof(builder->ctx)); - - builder->types_dict = ldict; - builder->included_ffis = NULL; - builder->_keepalive1 = NULL; - builder->_keepalive2 = NULL; - return 0; -} - -static PyObject *build_primitive_type(int num) -{ - /* XXX too many translations between here and new_primitive_type() */ - static const char *primitive_name[] = { - NULL, - "_Bool", - "char", - "signed char", - "unsigned char", - "short", - "unsigned short", - "int", - "unsigned int", - "long", - "unsigned long", - "long long", - "unsigned long long", - "float", - "double", - "long double", - "wchar_t", - "int8_t", - "uint8_t", - "int16_t", - "uint16_t", - "int32_t", - "uint32_t", - "int64_t", - "uint64_t", - "intptr_t", - "uintptr_t", - "ptrdiff_t", - "size_t", - "ssize_t", - "int_least8_t", - "uint_least8_t", - "int_least16_t", - "uint_least16_t", - "int_least32_t", - "uint_least32_t", - "int_least64_t", - "uint_least64_t", - "int_fast8_t", - "uint_fast8_t", - "int_fast16_t", - "uint_fast16_t", - "int_fast32_t", - "uint_fast32_t", - "int_fast64_t", - "uint_fast64_t", - "intmax_t", - "uintmax_t", - }; - PyObject *x; - - if (num == _CFFI_PRIM_VOID) { - x = new_void_type(); - } - else if (0 <= num && - num < sizeof(primitive_name) / sizeof(*primitive_name) && - primitive_name[num] != NULL) { - x = new_primitive_type(primitive_name[num]); - } - else { - PyErr_Format(PyExc_NotImplementedError, "prim=%d", num); - return NULL; - } - - all_primitives[num] = x; - return x; -} - -static PyObject *realize_global_int(builder_c_t *builder, int gindex) -{ - int neg; - char got[64]; - unsigned long long value; - struct _cffi_getconst_s gc; - const struct _cffi_global_s *g = &builder->ctx.globals[gindex]; - gc.ctx = &builder->ctx; - gc.gindex = gindex; - /* note: we cast g->address to this function type; we do the same - in parse_c_type:parse_sequel() too. Note that the called function - may be declared simply with "unsigned long long *" as argument, - which is fine as it is the first field in _cffi_getconst_s. */ - assert(&gc.value == (unsigned long long *)&gc); - neg = ((int(*)(struct _cffi_getconst_s *))g->address)(&gc); - value = gc.value; - - switch (neg) { - - case 0: - if (value <= (unsigned long long)LONG_MAX) - return PyInt_FromLong((long)value); - else - return PyLong_FromUnsignedLongLong(value); - - case 1: - if ((long long)value >= (long long)LONG_MIN) - return PyInt_FromLong((long)value); - else - return PyLong_FromLongLong((long long)value); - - default: - break; - } - if (neg == 2) - sprintf(got, "%llu (0x%llx)", value, value); - else - sprintf(got, "%lld", (long long)value); - PyErr_Format(FFIError, "the C compiler says '%.200s' is equal to %s, " - "but the cdef disagrees", g->name, got); - return NULL; -} - -static CTypeDescrObject * -unwrap_fn_as_fnptr(PyObject *x) -{ - assert(PyTuple_Check(x)); - return (CTypeDescrObject *)PyTuple_GET_ITEM(x, 0); -} - -static CTypeDescrObject * -unexpected_fn_type(PyObject *x) -{ - CTypeDescrObject *ct = unwrap_fn_as_fnptr(x); - char *text1 = ct->ct_name; - char *text2 = text1 + ct->ct_name_position + 1; - assert(text2[-3] == '('); - text2[-3] = '\0'; - PyErr_Format(FFIError, "the type '%s%s' is a function type, not a " - "pointer-to-function type", text1, text2); - text2[-3] = '('; - return NULL; -} - -static PyObject * -realize_c_type_or_func(builder_c_t *builder, - _cffi_opcode_t opcodes[], int index); /* forward */ - - -/* Interpret an opcodes[] array. If opcodes == ctx->types, store all - the intermediate types back in the opcodes[]. Returns a new - reference. -*/ -static CTypeDescrObject * -realize_c_type(builder_c_t *builder, _cffi_opcode_t opcodes[], int index) -{ - PyObject *x = realize_c_type_or_func(builder, opcodes, index); - if (x == NULL || CTypeDescr_Check(x)) - return (CTypeDescrObject *)x; - else - return unexpected_fn_type(x); -} - -static void _realize_name(char *target, const char *prefix, const char *srcname) -{ - /* "xyz" => "struct xyz" - "$xyz" => "xyz" - "$1" => "struct $1" - */ - if (srcname[0] == '$' && srcname[1] != '$' && - !('0' <= srcname[1] && srcname[1] <= '9')) { - strcpy(target, &srcname[1]); - } - else { - strcpy(target, prefix); - strcat(target, srcname); - } -} - -static void _unrealize_name(char *target, const char *srcname) -{ - /* reverse of _realize_name() */ - if (strncmp(srcname, "struct ", 7) == 0) { - strcpy(target, &srcname[7]); - } - else if (strncmp(srcname, "union ", 6) == 0) { - strcpy(target, &srcname[6]); - } - else if (strncmp(srcname, "enum ", 5) == 0) { - strcpy(target, &srcname[5]); - } - else { - strcpy(target, "$"); - strcat(target, srcname); - } -} - -static PyObject * /* forward */ -_fetch_external_struct_or_union(const struct _cffi_struct_union_s *s, - PyObject *included_ffis, int recursion); - -static PyObject * -_realize_c_struct_or_union(builder_c_t *builder, int sindex) -{ - PyObject *x; - _cffi_opcode_t op2; - const struct _cffi_struct_union_s *s; - - s = &builder->ctx.struct_unions[sindex]; - op2 = builder->ctx.types[s->type_index]; - if ((((uintptr_t)op2) & 1) == 0) { - x = (PyObject *)op2; /* found already in the "primary" slot */ - Py_INCREF(x); - } - else { - CTypeDescrObject *ct = NULL; - - if (!(s->flags & _CFFI_F_EXTERNAL)) { - int flags = (s->flags & _CFFI_F_UNION) ? CT_UNION : CT_STRUCT; - char *name = alloca(8 + strlen(s->name)); - _realize_name(name, - (s->flags & _CFFI_F_UNION) ? "union " : "struct ", - s->name); - if (strcmp(name, "struct _IO_FILE") == 0) - flags |= CT_IS_FILE; - - x = new_struct_or_union_type(name, flags); - if (x == NULL) - return NULL; - - if (!(s->flags & _CFFI_F_OPAQUE)) { - assert(s->first_field_index >= 0); - ct = (CTypeDescrObject *)x; - ct->ct_size = (Py_ssize_t)s->size; - ct->ct_length = s->alignment; /* may be -1 */ - ct->ct_flags &= ~CT_IS_OPAQUE; - ct->ct_flags |= CT_LAZY_FIELD_LIST; - ct->ct_extra = builder; - } - else - assert(s->first_field_index < 0); - } - else { - assert(s->first_field_index < 0); - x = _fetch_external_struct_or_union(s, builder->included_ffis, 0); - if (x == NULL) { - if (!PyErr_Occurred()) - PyErr_Format(FFIError, "'%s %.200s' should come from " - "ffi.include() but was not found", - (s->flags & _CFFI_F_UNION) ? "union" - : "struct", s->name); - return NULL; - } - if (!(s->flags & _CFFI_F_OPAQUE)) { - if (((CTypeDescrObject *)x)->ct_flags & CT_IS_OPAQUE) { - const char *prefix = (s->flags & _CFFI_F_UNION) ? "union" - : "struct"; - PyErr_Format(PyExc_NotImplementedError, - "'%s %.200s' is opaque in the ffi.include(), " - "but no longer in the ffi doing the include " - "(workaround: don't use ffi.include() but " - "duplicate the declarations of everything " - "using %s %.200s)", - prefix, s->name, prefix, s->name); - Py_DECREF(x); - return NULL; - } - } - } - - /* Update the "primary" OP_STRUCT_UNION slot */ - assert((((uintptr_t)x) & 1) == 0); - assert(builder->ctx.types[s->type_index] == op2); - Py_INCREF(x); - builder->ctx.types[s->type_index] = x; - - if (ct != NULL && s->size == (size_t)-2) { - /* oops, this struct is unnamed and we couldn't generate - a C expression to get its size. We have to rely on - complete_struct_or_union() to compute it now. */ - if (do_realize_lazy_struct(ct) < 0) { - builder->ctx.types[s->type_index] = op2; - return NULL; - } - } - } - return x; -} - -static PyObject * -realize_c_type_or_func(builder_c_t *builder, - _cffi_opcode_t opcodes[], int index) -{ - PyObject *x, *y, *z; - _cffi_opcode_t op = opcodes[index]; - Py_ssize_t length = -1; - - if ((((uintptr_t)op) & 1) == 0) { - x = (PyObject *)op; - Py_INCREF(x); - return x; - } - - switch (_CFFI_GETOP(op)) { - - case _CFFI_OP_PRIMITIVE: - x = get_primitive_type(_CFFI_GETARG(op)); - Py_XINCREF(x); - break; - - case _CFFI_OP_POINTER: - y = realize_c_type_or_func(builder, opcodes, _CFFI_GETARG(op)); - if (y == NULL) - return NULL; - if (CTypeDescr_Check(y)) { - x = new_pointer_type((CTypeDescrObject *)y); - } - else { - assert(PyTuple_Check(y)); /* from _CFFI_OP_FUNCTION */ - x = PyTuple_GET_ITEM(y, 0); - Py_INCREF(x); - } - Py_DECREF(y); - break; - - case _CFFI_OP_ARRAY: - length = (Py_ssize_t)opcodes[index + 1]; - /* fall-through */ - case _CFFI_OP_OPEN_ARRAY: - y = (PyObject *)realize_c_type(builder, opcodes, _CFFI_GETARG(op)); - if (y == NULL) - return NULL; - z = new_pointer_type((CTypeDescrObject *)y); - Py_DECREF(y); - if (z == NULL) - return NULL; - x = new_array_type((CTypeDescrObject *)z, length); - Py_DECREF(z); - break; - - case _CFFI_OP_STRUCT_UNION: - x = _realize_c_struct_or_union(builder, _CFFI_GETARG(op)); - break; - - case _CFFI_OP_ENUM: - { - const struct _cffi_enum_s *e; - _cffi_opcode_t op2; - - e = &builder->ctx.enums[_CFFI_GETARG(op)]; - op2 = builder->ctx.types[e->type_index]; - if ((((uintptr_t)op2) & 1) == 0) { - x = (PyObject *)op2; - Py_INCREF(x); - } - else { - PyObject *enumerators = NULL, *enumvalues = NULL, *tmp; - Py_ssize_t i, j, n = 0; - const char *p; - int gindex; - PyObject *args; - PyObject *basetd = get_primitive_type(e->type_prim); - if (basetd == NULL) - return NULL; - - if (*e->enumerators != '\0') { - n++; - for (p = e->enumerators; *p != '\0'; p++) - n += (*p == ','); - } - enumerators = PyTuple_New(n); - if (enumerators == NULL) - return NULL; - - enumvalues = PyTuple_New(n); - if (enumvalues == NULL) { - Py_DECREF(enumerators); - return NULL; - } - - p = e->enumerators; - for (i = 0; i < n; i++) { - j = 0; - while (p[j] != ',' && p[j] != '\0') - j++; - tmp = PyText_FromStringAndSize(p, j); - if (tmp == NULL) - break; - PyTuple_SET_ITEM(enumerators, i, tmp); - - gindex = search_in_globals(&builder->ctx, p, j); - assert(gindex >= 0); - assert(builder->ctx.globals[gindex].type_op == - _CFFI_OP(_CFFI_OP_ENUM, -1)); - - tmp = realize_global_int(builder, gindex); - if (tmp == NULL) - break; - PyTuple_SET_ITEM(enumvalues, i, tmp); - - p += j + 1; - } - - args = NULL; - if (!PyErr_Occurred()) { - char *name = alloca(6 + strlen(e->name)); - _realize_name(name, "enum ", e->name); - args = Py_BuildValue("(sOOO)", name, enumerators, - enumvalues, basetd); - } - Py_DECREF(enumerators); - Py_DECREF(enumvalues); - if (args == NULL) - return NULL; - - x = b_new_enum_type(NULL, args); - Py_DECREF(args); - if (x == NULL) - return NULL; - - /* Update the "primary" _CFFI_OP_ENUM slot, which - may be the same or a different slot than the "current" one */ - assert((((uintptr_t)x) & 1) == 0); - assert(builder->ctx.types[e->type_index] == op2); - Py_INCREF(x); - builder->ctx.types[e->type_index] = x; - - /* Done, leave without updating the "current" slot because - it may be done already above. If not, never mind, the - next call to realize_c_type() will do it. */ - return x; - } - break; - } - - case _CFFI_OP_FUNCTION: - { - PyObject *fargs; - int i, base_index, num_args, ellipsis; - - y = (PyObject *)realize_c_type(builder, opcodes, _CFFI_GETARG(op)); - if (y == NULL) - return NULL; - - base_index = index + 1; - num_args = 0; - while (_CFFI_GETOP(opcodes[base_index + num_args]) != - _CFFI_OP_FUNCTION_END) - num_args++; - - ellipsis = _CFFI_GETARG(opcodes[base_index + num_args]) & 1; - - fargs = PyTuple_New(num_args); - if (fargs == NULL) { - Py_DECREF(y); - return NULL; - } - - for (i = 0; i < num_args; i++) { - z = (PyObject *)realize_c_type(builder, opcodes, base_index + i); - if (z == NULL) { - Py_DECREF(fargs); - Py_DECREF(y); - return NULL; - } - PyTuple_SET_ITEM(fargs, i, z); - } - - z = new_function_type(fargs, (CTypeDescrObject *)y, ellipsis, - FFI_DEFAULT_ABI); - Py_DECREF(fargs); - Py_DECREF(y); - if (z == NULL) - return NULL; - - x = PyTuple_Pack(1, z); /* hack: hide the CT_FUNCTIONPTR. it will - be revealed again by the OP_POINTER */ - Py_DECREF(z); - break; - } - - case _CFFI_OP_NOOP: - x = realize_c_type_or_func(builder, opcodes, _CFFI_GETARG(op)); - break; - - case _CFFI_OP_TYPENAME: - { - /* essential: the TYPENAME opcode resolves the type index looked - up in the 'ctx->typenames' array, but it does so in 'ctx->types' - instead of in 'opcodes'! */ - int type_index = builder->ctx.typenames[_CFFI_GETARG(op)].type_index; - x = realize_c_type_or_func(builder, builder->ctx.types, type_index); - break; - } - - default: - PyErr_Format(PyExc_NotImplementedError, "op=%d", (int)_CFFI_GETOP(op)); - return NULL; - } - - if (x != NULL && opcodes == builder->ctx.types && opcodes[index] != x) { - assert((((uintptr_t)x) & 1) == 0); - assert((((uintptr_t)opcodes[index]) & 1) == 1); - Py_INCREF(x); - opcodes[index] = x; - } - return x; -}; - -static int do_realize_lazy_struct(CTypeDescrObject *ct) -{ - /* This is called by force_lazy_struct() in _cffi_backend.c */ - assert(ct->ct_flags & (CT_STRUCT | CT_UNION)); - - if (ct->ct_flags & CT_LAZY_FIELD_LIST) { - builder_c_t *builder; - char *p; - int n, i, sflags; - const struct _cffi_struct_union_s *s; - const struct _cffi_field_s *fld; - PyObject *fields, *args, *res; - - assert(!(ct->ct_flags & CT_IS_OPAQUE)); - - builder = ct->ct_extra; - assert(builder != NULL); - - p = alloca(2 + strlen(ct->ct_name)); - _unrealize_name(p, ct->ct_name); - - n = search_in_struct_unions(&builder->ctx, p, strlen(p)); - if (n < 0) - Py_FatalError("lost a struct/union!"); - - s = &builder->ctx.struct_unions[n]; - fld = &builder->ctx.fields[s->first_field_index]; - - /* XXX painfully build all the Python objects that are the args - to b_complete_struct_or_union() */ - - fields = PyList_New(s->num_fields); - if (fields == NULL) - return -1; - - for (i = 0; i < s->num_fields; i++, fld++) { - _cffi_opcode_t op = fld->field_type_op; - int fbitsize = -1; - PyObject *f; - CTypeDescrObject *ctf; - - switch (_CFFI_GETOP(op)) { - - case _CFFI_OP_BITFIELD: - assert(fld->field_size >= 0); - fbitsize = (int)fld->field_size; - /* fall-through */ - case _CFFI_OP_NOOP: - ctf = realize_c_type(builder, builder->ctx.types, - _CFFI_GETARG(op)); - break; - - default: - Py_DECREF(fields); - PyErr_Format(PyExc_NotImplementedError, "field op=%d", - (int)_CFFI_GETOP(op)); - return -1; - } - - if (fld->field_offset == (size_t)-1) { - /* unnamed struct, with field positions and sizes entirely - determined by complete_struct_or_union() and not checked. - Or, bitfields (field_size >= 0), similarly not checked. */ - assert(fld->field_size == (size_t)-1 || fbitsize >= 0); - } - else if (detect_custom_layout(ct, SF_STD_FIELD_POS, - ctf->ct_size, fld->field_size, - "wrong size for field '", - fld->name, "'") < 0) { - Py_DECREF(fields); - return -1; - } - - f = Py_BuildValue("(sOin)", fld->name, ctf, - fbitsize, (Py_ssize_t)fld->field_offset); - if (f == NULL) { - Py_DECREF(fields); - return -1; - } - PyList_SET_ITEM(fields, i, f); - } - - sflags = 0; - if (s->flags & _CFFI_F_CHECK_FIELDS) - sflags |= SF_STD_FIELD_POS; - if (s->flags & _CFFI_F_PACKED) - sflags |= SF_PACKED; - - args = Py_BuildValue("(OOOnii)", ct, fields, Py_None, - (Py_ssize_t)s->size, - s->alignment, - sflags); - Py_DECREF(fields); - if (args == NULL) - return -1; - - ct->ct_extra = NULL; - ct->ct_flags |= CT_IS_OPAQUE; - res = b_complete_struct_or_union(NULL, args); - ct->ct_flags &= ~CT_IS_OPAQUE; - Py_DECREF(args); - - if (res == NULL) { - ct->ct_extra = builder; - return -1; - } - - assert(ct->ct_stuff != NULL); - ct->ct_flags &= ~CT_LAZY_FIELD_LIST; - Py_DECREF(res); - return 1; - } - else { - assert(ct->ct_flags & CT_IS_OPAQUE); - return 0; - } -} diff --git a/_cffi1/recompiler.py b/_cffi1/recompiler.py deleted file mode 100644 index cf9398d..0000000 --- a/_cffi1/recompiler.py +++ /dev/null @@ -1,955 +0,0 @@ -import os, sys, io -from cffi import ffiplatform, model -from .cffi_opcode import * - - -class Recompiler: - - def __init__(self, ffi, module_name): - self.ffi = ffi - self.module_name = module_name - - def collect_type_table(self): - self._typesdict = {} - self._generate("collecttype") - # - all_decls = sorted(self._typesdict, key=str) - # - # prepare all FUNCTION bytecode sequences first - self.cffi_types = [] - for tp in all_decls: - if tp.is_raw_function: - assert self._typesdict[tp] is None - self._typesdict[tp] = len(self.cffi_types) - self.cffi_types.append(tp) # placeholder - for tp1 in tp.args: - assert isinstance(tp1, (model.VoidType, - model.PrimitiveType, - model.PointerType, - model.StructOrUnionOrEnum, - model.FunctionPtrType)) - if self._typesdict[tp1] is None: - self._typesdict[tp1] = len(self.cffi_types) - self.cffi_types.append(tp1) # placeholder - self.cffi_types.append('END') # placeholder - # - # prepare all OTHER bytecode sequences - for tp in all_decls: - if not tp.is_raw_function and self._typesdict[tp] is None: - self._typesdict[tp] = len(self.cffi_types) - self.cffi_types.append(tp) # placeholder - if tp.is_array_type and tp.length is not None: - self.cffi_types.append('LEN') # placeholder - assert None not in self._typesdict.values() - # - # collect all structs and unions and enums - self._struct_unions = {} - self._enums = {} - for tp in all_decls: - if isinstance(tp, model.StructOrUnion): - self._struct_unions[tp] = None - elif isinstance(tp, model.EnumType): - self._enums[tp] = None - for i, tp in enumerate(sorted(self._struct_unions, - key=lambda tp: tp.name)): - self._struct_unions[tp] = i - for i, tp in enumerate(sorted(self._enums, - key=lambda tp: tp.name)): - self._enums[tp] = i - # - # emit all bytecode sequences now - for tp in all_decls: - method = getattr(self, '_emit_bytecode_' + tp.__class__.__name__) - method(tp, self._typesdict[tp]) - # - # consistency check - for op in self.cffi_types: - assert isinstance(op, CffiOp) - - def _do_collect_type(self, tp): - if not isinstance(tp, model.BaseTypeByIdentity): - if isinstance(tp, tuple): - for x in tp: - self._do_collect_type(x) - return - if tp not in self._typesdict: - self._typesdict[tp] = None - if isinstance(tp, model.FunctionPtrType): - self._do_collect_type(tp.as_raw_function()) - elif isinstance(tp, model.StructOrUnion): - if tp.fldtypes is not None and ( - tp not in self.ffi._parser._included_declarations): - for name1, tp1, _ in tp.enumfields(): - self._do_collect_type(self._field_type(tp, name1, tp1)) - else: - for _, x in tp._get_items(): - self._do_collect_type(x) - - def _get_declarations(self): - return sorted(self.ffi._parser._declarations.items()) - - def _generate(self, step_name): - for name, tp in self._get_declarations(): - kind, realname = name.split(' ', 1) - try: - method = getattr(self, '_generate_cpy_%s_%s' % (kind, - step_name)) - except AttributeError: - raise ffiplatform.VerificationError( - "not implemented in recompile(): %r" % name) - try: - method(tp, realname) - except Exception as e: - model.attach_exception_info(e, name) - raise - - # ---------- - - def _prnt(self, what=''): - self._f.write(what + '\n') - - def _gettypenum(self, type): - # a KeyError here is a bug. please report it! :-) - return self._typesdict[type] - - def _rel_readlines(self, filename): - g = open(os.path.join(os.path.dirname(__file__), filename), 'r') - lines = g.readlines() - g.close() - return lines - - def write_source_to_f(self, f, preamble): - self._f = f - prnt = self._prnt - # - # first the '#include' (actually done by inlining the file's content) - lines = self._rel_readlines('_cffi_include.h') - i = lines.index('#include "parse_c_type.h"\n') - lines[i:i+1] = self._rel_readlines('parse_c_type.h') - prnt(''.join(lines)) - # - # then paste the C source given by the user, verbatim. - prnt('/************************************************************/') - prnt() - prnt(preamble) - prnt() - prnt('/************************************************************/') - prnt() - # - # the declaration of '_cffi_types' - prnt('static void *_cffi_types[] = {') - self.cffi_types = tuple(self.cffi_types) # don't change any more - typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()]) - for i, op in enumerate(self.cffi_types): - comment = '' - if i in typeindex2type: - comment = ' // ' + typeindex2type[i]._get_c_name() - prnt('/* %2d */ %s,%s' % (i, op.as_c_expr(), comment)) - if not self.cffi_types: - prnt(' 0') - prnt('};') - prnt() - # - # call generate_cpy_xxx_decl(), for every xxx found from - # ffi._parser._declarations. This generates all the functions. - self._seen_constants = set() - self._generate("decl") - # - # the declaration of '_cffi_globals' and '_cffi_typenames' - ALL_STEPS = ["global", "field", "struct_union", "enum", "typename"] - nums = {} - self._lsts = {} - for step_name in ALL_STEPS: - self._lsts[step_name] = [] - self._seen_struct_unions = set() - self._generate("ctx") - self._add_missing_struct_unions() - for step_name in ALL_STEPS: - lst = self._lsts[step_name] - nums[step_name] = len(lst) - if nums[step_name] > 0: - lst.sort() # sort by name, which is at the start of each line - prnt('static const struct _cffi_%s_s _cffi_%ss[] = {' % ( - step_name, step_name)) - if step_name == 'field': - self._fix_final_field_list(lst) - for line in lst: - prnt(line) - if all(line.startswith('#') for line in lst): - prnt(' { 0 }') - prnt('};') - prnt() - # - # check for a possible internal inconsistency: _cffi_struct_unions - # should have been generated with exactly self._struct_unions - lst = self._lsts["struct_union"] - for tp, i in self._struct_unions.items(): - assert i < len(lst) - assert lst[i].startswith(' { "%s"' % tp.name) - assert len(lst) == len(self._struct_unions) - # same with enums - lst = self._lsts["enum"] - for tp, i in self._enums.items(): - assert i < len(lst) - assert lst[i].startswith(' { "%s"' % tp.name) - assert len(lst) == len(self._enums) - # - # the declaration of '_cffi_includes' - if self.ffi._included_ffis: - prnt('static const char * const _cffi_includes[] = {') - for ffi_to_include in self.ffi._included_ffis: - if not hasattr(ffi_to_include, '_recompiler_module_name'): - raise ffiplatform.VerificationError( - "this ffi includes %r, but the latter has not been " - "turned into a C module" % (ffi_to_include,)) - prnt(' "%s",' % (ffi_to_include._recompiler_module_name,)) - prnt(' NULL') - prnt('};') - prnt() - # - # the declaration of '_cffi_type_context' - prnt('static const struct _cffi_type_context_s _cffi_type_context = {') - prnt(' _cffi_types,') - for step_name in ALL_STEPS: - if nums[step_name] > 0: - prnt(' _cffi_%ss,' % step_name) - else: - prnt(' NULL, /* no %ss */' % step_name) - for step_name in ALL_STEPS: - if step_name != "field": - prnt(' %d, /* num_%ss */' % (nums[step_name], step_name)) - if self.ffi._included_ffis: - prnt(' _cffi_includes,') - else: - prnt(' NULL, /* no includes */') - prnt(' %d, /* num_types */' % (len(self.cffi_types),)) - prnt(' 0, /* flags */') - prnt('};') - prnt() - # - # the init function - base_module_name = self.module_name.split('.')[-1] - prnt('#ifdef PYPY_VERSION') - prnt('PyMODINIT_FUNC') - prnt('_cffi_pypyinit_%s(const void *p[])' % (base_module_name,)) - prnt('{') - prnt(' p[0] = (const void *)0x2600;') - prnt(' p[1] = &_cffi_type_context;') - prnt('}') - # on Windows, distutils insists on putting init_cffi_xyz in - # 'export_symbols', so instead of fighting it, just give up and - # give it one - prnt('# ifdef _MSC_VER') - prnt(' PyMODINIT_FUNC') - prnt('# if PY_MAJOR_VERSION >= 3') - prnt(' PyInit_%s(void) { return -1; }' % (base_module_name,)) - prnt('# else') - prnt(' init%s(void) { }' % (base_module_name,)) - prnt('# endif') - prnt('# endif') - prnt('#elif PY_MAJOR_VERSION >= 3') - prnt('PyMODINIT_FUNC') - prnt('PyInit_%s(void)' % (base_module_name,)) - prnt('{') - prnt(' return _cffi_init("%s", 0x2600, &_cffi_type_context);' % ( - self.module_name,)) - prnt('}') - prnt('#else') - prnt('PyMODINIT_FUNC') - prnt('init%s(void)' % (base_module_name,)) - prnt('{') - prnt(' _cffi_init("%s", 0x2600, &_cffi_type_context);' % ( - self.module_name,)) - prnt('}') - prnt('#endif') - self.ffi._recompiler_module_name = self.module_name - - # ---------- - - def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode): - extraarg = '' - if isinstance(tp, model.PrimitiveType): - if tp.is_integer_type() and tp.name != '_Bool': - converter = '_cffi_to_c_int' - extraarg = ', %s' % tp.name - else: - converter = '(%s)_cffi_to_c_%s' % (tp.get_c_name(''), - tp.name.replace(' ', '_')) - errvalue = '-1' - # - elif isinstance(tp, model.PointerType): - self._convert_funcarg_to_c_ptr_or_array(tp, fromvar, - tovar, errcode) - return - # - elif isinstance(tp, (model.StructOrUnion, model.EnumType)): - # a struct (not a struct pointer) as a function argument - self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)' - % (tovar, self._gettypenum(tp), fromvar)) - self._prnt(' %s;' % errcode) - return - # - elif isinstance(tp, model.FunctionPtrType): - converter = '(%s)_cffi_to_c_pointer' % tp.get_c_name('') - extraarg = ', _cffi_type(%d)' % self._gettypenum(tp) - errvalue = 'NULL' - # - else: - raise NotImplementedError(tp) - # - self._prnt(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg)) - self._prnt(' if (%s == (%s)%s && PyErr_Occurred())' % ( - tovar, tp.get_c_name(''), errvalue)) - self._prnt(' %s;' % errcode) - - def _extra_local_variables(self, tp, localvars): - if isinstance(tp, model.PointerType): - localvars.add('Py_ssize_t datasize') - - def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode): - self._prnt(' datasize = _cffi_prepare_pointer_call_argument(') - self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % ( - self._gettypenum(tp), fromvar, tovar)) - self._prnt(' if (datasize != 0) {') - self._prnt(' if (datasize < 0)') - self._prnt(' %s;' % errcode) - self._prnt(' %s = alloca((size_t)datasize);' % (tovar,)) - self._prnt(' memset((void *)%s, 0, (size_t)datasize);' % (tovar,)) - self._prnt(' if (_cffi_convert_array_from_object(' - '(char *)%s, _cffi_type(%d), %s) < 0)' % ( - tovar, self._gettypenum(tp), fromvar)) - self._prnt(' %s;' % errcode) - self._prnt(' }') - - def _convert_expr_from_c(self, tp, var, context): - if isinstance(tp, model.PrimitiveType): - if tp.is_integer_type(): - return '_cffi_from_c_int(%s, %s)' % (var, tp.name) - elif tp.name != 'long double': - return '_cffi_from_c_%s(%s)' % (tp.name.replace(' ', '_'), var) - else: - return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - elif isinstance(tp, (model.PointerType, model.FunctionPtrType)): - return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - elif isinstance(tp, model.ArrayType): - return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( - var, self._gettypenum(model.PointerType(tp.item))) - elif isinstance(tp, model.StructType): - if tp.fldnames is None: - raise TypeError("'%s' is used as %s, but is opaque" % ( - tp._get_c_name(), context)) - return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - elif isinstance(tp, model.EnumType): - return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % ( - var, self._gettypenum(tp)) - else: - raise NotImplementedError(tp) - - # ---------- - # typedefs - - def _generate_cpy_typedef_collecttype(self, tp, name): - self._do_collect_type(tp) - - def _generate_cpy_typedef_decl(self, tp, name): - pass - - def _typedef_ctx(self, tp, name): - type_index = self._typesdict[tp] - self._lsts["typename"].append( - ' { "%s", %d },' % (name, type_index)) - - def _generate_cpy_typedef_ctx(self, tp, name): - self._typedef_ctx(tp, name) - if getattr(tp, "origin", None) == "unknown_type": - self._struct_ctx(tp, tp.name, approxname=None) - elif isinstance(tp, model.NamedPointerType): - self._struct_ctx(tp.totype, tp.totype.name, approxname=tp.name, - named_ptr=tp) - - # ---------- - # function declarations - - def _generate_cpy_function_collecttype(self, tp, name): - self._do_collect_type(tp.as_raw_function()) - if tp.ellipsis: - self._do_collect_type(tp) - - def _generate_cpy_function_decl(self, tp, name): - assert isinstance(tp, model.FunctionPtrType) - if tp.ellipsis: - # cannot support vararg functions better than this: check for its - # exact type (including the fixed arguments), and build it as a - # constant function pointer (no CPython wrapper) - self._generate_cpy_constant_decl(tp, name) - return - prnt = self._prnt - numargs = len(tp.args) - if numargs == 0: - argname = 'noarg' - elif numargs == 1: - argname = 'arg0' - else: - argname = 'args' - # - prnt('#ifndef PYPY_VERSION') # ------------------------------ - # - prnt('static PyObject *') - prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname)) - prnt('{') - # - context = 'argument of %s' % name - for i, type in enumerate(tp.args): - arg = type.get_c_name(' x%d' % i, context) - prnt(' %s;' % arg) - # - localvars = set() - for type in tp.args: - self._extra_local_variables(type, localvars) - for decl in localvars: - prnt(' %s;' % (decl,)) - # - if not isinstance(tp.result, model.VoidType): - result_code = 'result = ' - context = 'result of %s' % name - result_decl = ' %s;' % tp.result.get_c_name(' result', context) - prnt(result_decl) - else: - result_decl = None - result_code = '' - # - if len(tp.args) > 1: - rng = range(len(tp.args)) - for i in rng: - prnt(' PyObject *arg%d;' % i) - prnt() - prnt(' if (!PyArg_ParseTuple(args, "%s:%s", %s))' % ( - 'O' * numargs, name, ', '.join(['&arg%d' % i for i in rng]))) - prnt(' return NULL;') - prnt() - # - for i, type in enumerate(tp.args): - self._convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i, - 'return NULL') - prnt() - # - prnt(' Py_BEGIN_ALLOW_THREADS') - prnt(' _cffi_restore_errno();') - call_arguments = ['x%d' % i for i in range(len(tp.args))] - call_arguments = ', '.join(call_arguments) - prnt(' { %s%s(%s); }' % (result_code, name, call_arguments)) - prnt(' _cffi_save_errno();') - prnt(' Py_END_ALLOW_THREADS') - prnt() - # - prnt(' (void)self; /* unused */') - if numargs == 0: - prnt(' (void)noarg; /* unused */') - if result_code: - prnt(' return %s;' % - self._convert_expr_from_c(tp.result, 'result', 'result type')) - else: - prnt(' Py_INCREF(Py_None);') - prnt(' return Py_None;') - prnt('}') - # - prnt('#else') # ------------------------------ - # - # the PyPy version: need to replace struct/union arguments with - # pointers, and if the result is a struct/union, insert a first - # arg that is a pointer to the result. - arguments = [] - call_arguments = [] - context = 'argument of %s' % name - for i, type in enumerate(tp.args): - indirection = '' - if isinstance(type, model.StructOrUnion): - indirection = '*' - arg = type.get_c_name(' %sx%d' % (indirection, i), context) - arguments.append(arg) - call_arguments.append('%sx%d' % (indirection, i)) - tp_result = tp.result - if isinstance(tp_result, model.StructOrUnion): - context = 'result of %s' % name - arg = tp_result.get_c_name(' *result', context) - arguments.insert(0, arg) - tp_result = model.void_type - result_decl = None - result_code = '*result = ' - repr_arguments = ', '.join(arguments) - repr_arguments = repr_arguments or 'void' - name_and_arguments = '_cffi_f_%s(%s)' % (name, repr_arguments) - prnt('static %s' % (tp_result.get_c_name(name_and_arguments),)) - prnt('{') - if result_decl: - prnt(result_decl) - call_arguments = ', '.join(call_arguments) - prnt(' { %s%s(%s); }' % (result_code, name, call_arguments)) - if result_decl: - prnt(' return result;') - prnt('}') - # - prnt('#endif') # ------------------------------ - prnt() - - def _generate_cpy_function_ctx(self, tp, name): - if tp.ellipsis: - self._generate_cpy_constant_ctx(tp, name) - return - type_index = self._typesdict[tp.as_raw_function()] - numargs = len(tp.args) - if numargs == 0: - meth_kind = 'N' # 'METH_NOARGS' - elif numargs == 1: - meth_kind = 'O' # 'METH_O' - else: - meth_kind = 'V' # 'METH_VARARGS' - self._lsts["global"].append( - ' { "%s", _cffi_f_%s, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_%s, %d), 0 },' - % (name, name, meth_kind, type_index)) - - # ---------- - # named structs or unions - - def _field_type(self, tp_struct, field_name, tp_field): - if isinstance(tp_field, model.ArrayType) and tp_field.length == '...': - ptr_struct_name = tp_struct.get_c_name('*') - actual_length = '_cffi_array_len(((%s)0)->%s)' % ( - ptr_struct_name, field_name) - tp_field = tp_field.resolve_length(actual_length) - return tp_field - - def _struct_collecttype(self, tp): - self._do_collect_type(tp) - - def _struct_decl(self, tp, cname, approxname): - if tp.fldtypes is None: - return - prnt = self._prnt - checkfuncname = '_cffi_checkfld_%s' % (approxname,) - prnt('_CFFI_UNUSED_FN') - prnt('static void %s(%s *p)' % (checkfuncname, cname)) - prnt('{') - prnt(' /* only to generate compile-time warnings or errors */') - prnt(' (void)p;') - for fname, ftype, fbitsize in tp.enumfields(): - if (isinstance(ftype, model.PrimitiveType) - and ftype.is_integer_type()) or fbitsize >= 0: - # accept all integers, but complain on float or double - prnt(' (void)((p->%s) << 1);' % fname) - else: - # only accept exactly the type declared. - try: - prnt(' { %s = &p->%s; (void)tmp; }' % ( - ftype.get_c_name('*tmp', 'field %r'%fname), fname)) - except ffiplatform.VerificationError as e: - prnt(' /* %s */' % str(e)) # cannot verify it, ignore - prnt('}') - prnt('struct _cffi_align_%s { char x; %s y; };' % (approxname, cname)) - prnt() - - def _struct_ctx(self, tp, cname, approxname, named_ptr=None): - type_index = self._typesdict[tp] - reason_for_not_expanding = None - flags = [] - if isinstance(tp, model.UnionType): - flags.append("_CFFI_F_UNION") - if tp.fldtypes is None: - flags.append("_CFFI_F_OPAQUE") - reason_for_not_expanding = "opaque" - if (tp not in self.ffi._parser._included_declarations and - (named_ptr is None or - named_ptr not in self.ffi._parser._included_declarations)): - if tp.fldtypes is None: - pass # opaque - elif tp.partial or tp.has_anonymous_struct_fields(): - pass # field layout obtained silently from the C compiler - else: - flags.append("_CFFI_F_CHECK_FIELDS") - if tp.packed: - flags.append("_CFFI_F_PACKED") - else: - flags.append("_CFFI_F_EXTERNAL") - reason_for_not_expanding = "external" - flags = '|'.join(flags) or '0' - if reason_for_not_expanding is None: - c_field = [approxname] - enumfields = list(tp.enumfields()) - for fldname, fldtype, fbitsize in enumfields: - fldtype = self._field_type(tp, fldname, fldtype) - spaces = " " * len(fldname) - # cname is None for _add_missing_struct_unions() only - op = '_CFFI_OP_NOOP' - if fbitsize >= 0: - op = '_CFFI_OP_BITFIELD' - size = '%d /* bits */' % fbitsize - elif cname is None or ( - isinstance(fldtype, model.ArrayType) and - fldtype.length is None): - size = '(size_t)-1' - else: - size = 'sizeof(((%s)0)->%s)' % ( - tp.get_c_name('*') if named_ptr is None - else named_ptr.name, - fldname) - if cname is None or fbitsize >= 0: - offset = '(size_t)-1' - elif named_ptr is not None: - offset = '((char *)&((%s)0)->%s) - (char *)0' % ( - named_ptr.name, fldname) - else: - offset = 'offsetof(%s, %s)' % (tp.get_c_name(''), fldname) - c_field.append( - ' { "%s", %s,\n' % (fldname, offset) + - ' %s %s,\n' % (spaces, size) + - ' %s _CFFI_OP(%s, %s) },' % ( - spaces, op, self._typesdict[fldtype])) - self._lsts["field"].append('\n'.join(c_field)) - # - if cname is None: # unknown name, for _add_missing_struct_unions - size_align = (' (size_t)-2, -2, /* unnamed */\n' + - ' _cffi_FIELDS_FOR_%s, %d },' % (approxname, - len(enumfields),)) - else: - if named_ptr is not None: - size = 'sizeof(*(%s)0)' % (named_ptr.name,) - align = '-1 /* unknown alignment */' - else: - size = 'sizeof(%s)' % (cname,) - align = 'offsetof(struct _cffi_align_%s, y)' % (approxname,) - size_align = ('\n' + - ' %s,\n' % (size,) + - ' %s,\n' % (align,) + - ' _cffi_FIELDS_FOR_%s, %d },' % (approxname, - len(enumfields),)) - else: - size_align = ' (size_t)-1, -1, -1, 0 /* %s */ },' % ( - reason_for_not_expanding,) - self._lsts["struct_union"].append( - ' { "%s", %d, %s,' % (tp.name, type_index, flags) + size_align) - self._seen_struct_unions.add(tp) - - def _add_missing_struct_unions(self): - # not very nice, but some struct declarations might be missing - # because they don't have any known C name. Check that they are - # not partial (we can't complete or verify them!) and emit them - # anonymously. - for tp in list(self._struct_unions): - if tp not in self._seen_struct_unions: - if tp.partial: - raise NotImplementedError("internal inconsistency: %r is " - "partial but was not seen at " - "this point" % (tp,)) - if tp.name.startswith('$') and tp.name[1:].isdigit(): - approxname = tp.name[1:] - elif tp.name == '_IO_FILE' and tp.forcename == 'FILE': - approxname = 'FILE' - self._typedef_ctx(tp, 'FILE') - else: - raise NotImplementedError("internal inconsistency: %r" % - (tp,)) - self._struct_ctx(tp, None, approxname) - - def _fix_final_field_list(self, lst): - count = 0 - for i in range(len(lst)): - struct_fields = lst[i] - pname = struct_fields.split('\n')[0] - define_macro = '#define _cffi_FIELDS_FOR_%s %d' % (pname, count) - lst[i] = define_macro + struct_fields[len(pname):] - count += lst[i].count('\n { "') - - def _generate_cpy_struct_collecttype(self, tp, name): - self._struct_collecttype(tp) - _generate_cpy_union_collecttype = _generate_cpy_struct_collecttype - - def _struct_names(self, tp): - cname = tp.get_c_name('') - if ' ' in cname: - return cname, cname.replace(' ', '_') - else: - return cname, '_' + cname - - def _generate_cpy_struct_decl(self, tp, name): - self._struct_decl(tp, *self._struct_names(tp)) - _generate_cpy_union_decl = _generate_cpy_struct_decl - - def _generate_cpy_struct_ctx(self, tp, name): - self._struct_ctx(tp, *self._struct_names(tp)) - _generate_cpy_union_ctx = _generate_cpy_struct_ctx - - # ---------- - # 'anonymous' declarations. These are produced for anonymous structs - # or unions; the 'name' is obtained by a typedef. - - def _generate_cpy_anonymous_collecttype(self, tp, name): - if isinstance(tp, model.EnumType): - self._generate_cpy_enum_collecttype(tp, name) - else: - self._struct_collecttype(tp) - - def _generate_cpy_anonymous_decl(self, tp, name): - if isinstance(tp, model.EnumType): - self._generate_cpy_enum_decl(tp) - else: - self._struct_decl(tp, name, 'typedef_' + name) - - def _generate_cpy_anonymous_ctx(self, tp, name): - if isinstance(tp, model.EnumType): - self._enum_ctx(tp, name) - else: - self._struct_ctx(tp, name, 'typedef_' + name) - - # ---------- - # constants, declared with "static const ..." - - def _generate_cpy_const(self, is_int, name, tp=None, category='const', - check_value=None): - if (category, name) in self._seen_constants: - raise ffiplatform.VerificationError( - "duplicate declaration of %s '%s'" % (category, name)) - self._seen_constants.add((category, name)) - # - prnt = self._prnt - funcname = '_cffi_%s_%s' % (category, name) - if is_int: - prnt('static int %s(unsigned long long *o)' % funcname) - prnt('{') - prnt(' int n = (%s) <= 0;' % (name,)) - prnt(' *o = (unsigned long long)((%s) << 0);' - ' /* check that we get an integer */' % (name,)) - if check_value is not None: - if check_value > 0: - check_value = '%dU' % (check_value,) - prnt(' if (!_cffi_check_int(*o, n, %s))' % (check_value,)) - prnt(' n |= 2;') - prnt(' return n;') - prnt('}') - else: - assert check_value is None - prnt('static void %s(char *o)' % funcname) - prnt('{') - prnt(' *(%s)o = %s;' % (tp.get_c_name('*'), name)) - prnt('}') - prnt() - - def _generate_cpy_constant_collecttype(self, tp, name): - is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() - if not is_int: - self._do_collect_type(tp) - - def _generate_cpy_constant_decl(self, tp, name): - is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type() - self._generate_cpy_const(is_int, name, tp) - - def _generate_cpy_constant_ctx(self, tp, name): - if isinstance(tp, model.PrimitiveType) and tp.is_integer_type(): - type_op = '_CFFI_OP(_CFFI_OP_CONSTANT_INT, -1)' - else: - type_index = self._typesdict[tp] - type_op = '_CFFI_OP(_CFFI_OP_CONSTANT, %d)' % type_index - self._lsts["global"].append( - ' { "%s", _cffi_const_%s, %s, 0 },' % (name, name, type_op)) - - # ---------- - # enums - - def _generate_cpy_enum_collecttype(self, tp, name): - self._do_collect_type(tp) - - def _generate_cpy_enum_decl(self, tp, name=None): - for enumerator in tp.enumerators: - self._generate_cpy_const(True, enumerator) - - def _enum_ctx(self, tp, cname): - type_index = self._typesdict[tp] - type_op = '_CFFI_OP(_CFFI_OP_ENUM, -1)' - for enumerator in tp.enumerators: - self._lsts["global"].append( - ' { "%s", _cffi_const_%s, %s, 0 },' % - (enumerator, enumerator, type_op)) - # - if cname is not None and '$' not in cname: - size = "sizeof(%s)" % cname - signed = "((%s)-1) <= 0" % cname - else: - basetp = tp.build_baseinttype(self.ffi, []) - size = self.ffi.sizeof(basetp) - signed = int(int(self.ffi.cast(basetp, -1)) < 0) - allenums = ",".join(tp.enumerators) - self._lsts["enum"].append( - ' { "%s", %d, _cffi_prim_int(%s, %s),\n' - ' "%s" },' % (tp.name, type_index, size, signed, allenums)) - - def _generate_cpy_enum_ctx(self, tp, name): - self._enum_ctx(tp, tp._get_c_name()) - - # ---------- - # macros: for now only for integers - - def _generate_cpy_macro_collecttype(self, tp, name): - pass - - def _generate_cpy_macro_decl(self, tp, name): - if tp == '...': - check_value = None - else: - check_value = tp # an integer - self._generate_cpy_const(True, name, check_value=check_value) - - def _generate_cpy_macro_ctx(self, tp, name): - self._lsts["global"].append( - ' { "%s", _cffi_const_%s,' - ' _CFFI_OP(_CFFI_OP_CONSTANT_INT, -1), 0 },' % (name, name)) - - # ---------- - # global variables - - def _global_type(self, tp, global_name): - if isinstance(tp, model.ArrayType) and tp.length == '...': - actual_length = '_cffi_array_len(%s)' % (global_name,) - tp = tp.resolve_length(actual_length) - return tp - - def _generate_cpy_variable_collecttype(self, tp, name): - self._do_collect_type(self._global_type(tp, name)) - - def _generate_cpy_variable_decl(self, tp, name): - pass - - def _generate_cpy_variable_ctx(self, tp, name): - tp = self._global_type(tp, name) - type_index = self._typesdict[tp] - if tp.sizeof_enabled(): - size = "sizeof(%s)" % (name,) - else: - size = "0" - self._lsts["global"].append( - ' { "%s", &%s, _CFFI_OP(_CFFI_OP_GLOBAL_VAR, %d), %s },' - % (name, name, type_index, size)) - - # ---------- - # emitting the opcodes for individual types - - def _emit_bytecode_VoidType(self, tp, index): - self.cffi_types[index] = CffiOp(OP_PRIMITIVE, PRIM_VOID) - - def _emit_bytecode_PrimitiveType(self, tp, index): - prim_index = PRIMITIVE_TO_INDEX[tp.name] - self.cffi_types[index] = CffiOp(OP_PRIMITIVE, prim_index) - - def _emit_bytecode_RawFunctionType(self, tp, index): - self.cffi_types[index] = CffiOp(OP_FUNCTION, self._typesdict[tp.result]) - index += 1 - for tp1 in tp.args: - realindex = self._typesdict[tp1] - if index != realindex: - if isinstance(tp1, model.PrimitiveType): - self._emit_bytecode_PrimitiveType(tp1, index) - else: - self.cffi_types[index] = CffiOp(OP_NOOP, realindex) - index += 1 - self.cffi_types[index] = CffiOp(OP_FUNCTION_END, int(tp.ellipsis)) - - def _emit_bytecode_PointerType(self, tp, index): - self.cffi_types[index] = CffiOp(OP_POINTER, self._typesdict[tp.totype]) - - _emit_bytecode_ConstPointerType = _emit_bytecode_PointerType - _emit_bytecode_NamedPointerType = _emit_bytecode_PointerType - - def _emit_bytecode_FunctionPtrType(self, tp, index): - raw = tp.as_raw_function() - self.cffi_types[index] = CffiOp(OP_POINTER, self._typesdict[raw]) - - def _emit_bytecode_ArrayType(self, tp, index): - item_index = self._typesdict[tp.item] - if tp.length is None: - self.cffi_types[index] = CffiOp(OP_OPEN_ARRAY, item_index) - elif tp.length == '...': - raise ffiplatform.VerificationError( - "type %s badly placed: the '...' array length can only be " - "used on global arrays or on fields of structures" % ( - str(tp).replace('/*...*/', '...'),)) - else: - assert self.cffi_types[index + 1] == 'LEN' - self.cffi_types[index] = CffiOp(OP_ARRAY, item_index) - self.cffi_types[index + 1] = CffiOp(None, str(tp.length)) - - def _emit_bytecode_StructType(self, tp, index): - struct_index = self._struct_unions[tp] - self.cffi_types[index] = CffiOp(OP_STRUCT_UNION, struct_index) - _emit_bytecode_UnionType = _emit_bytecode_StructType - - def _emit_bytecode_EnumType(self, tp, index): - enum_index = self._enums[tp] - self.cffi_types[index] = CffiOp(OP_ENUM, enum_index) - - -if sys.version_info >= (3,): - NativeIO = io.StringIO -else: - class NativeIO(io.BytesIO): - def write(self, s): - if isinstance(s, unicode): - s = s.encode('ascii') - super(NativeIO, self).write(s) - -def make_c_source(ffi, module_name, preamble, target_c_file): - recompiler = Recompiler(ffi, module_name) - recompiler.collect_type_table() - f = NativeIO() - recompiler.write_source_to_f(f, preamble) - output = f.getvalue() - try: - with open(target_c_file, 'r') as f1: - if f1.read(len(output) + 1) != output: - raise IOError - return False # already up-to-date - except IOError: - with open(target_c_file, 'w') as f1: - f1.write(output) - return True - -def _get_extension(module_name, c_file, kwds): - source_name = ffiplatform.maybe_relative_path(c_file) - return ffiplatform.get_extension(source_name, module_name, **kwds) - -def recompile(ffi, module_name, preamble, tmpdir='.', - call_c_compiler=True, c_file=None, **kwds): - if not isinstance(module_name, str): - module_name = module_name.encode('ascii') - if ffi._windows_unicode: - ffi._apply_windows_unicode(kwds) - if c_file is None: - c_file = os.path.join(tmpdir, module_name + '.c') - ext = _get_extension(module_name, c_file, kwds) - updated = make_c_source(ffi, module_name, preamble, c_file) - if call_c_compiler: - outputfilename = ffiplatform.compile(tmpdir, ext) - return outputfilename - else: - return ext, updated - -def verify(ffi, module_name, preamble, *args, **kwds): - from _cffi1.udir import udir - import imp - assert module_name not in sys.modules, "module name conflict: %r" % ( - module_name,) - kwds.setdefault('tmpdir', str(udir)) - outputfilename = recompile(ffi, module_name, preamble, *args, **kwds) - module = imp.load_dynamic(module_name, outputfilename) - # - # hack hack hack: copy all *bound methods* from module.ffi back to the - # ffi instance. Then calls like ffi.new() will invoke module.ffi.new(). - for name in dir(module.ffi): - if not name.startswith('_'): - attr = getattr(module.ffi, name) - if attr is not getattr(ffi, name, object()): - setattr(ffi, name, attr) - def typeof_disabled(*args, **kwds): - raise NotImplementedError - ffi._typeof = typeof_disabled - return module.lib diff --git a/_cffi1/setup.py b/_cffi1/setup.py deleted file mode 100644 index f786ace..0000000 --- a/_cffi1/setup.py +++ /dev/null @@ -1,6 +0,0 @@ -from distutils.core import setup -from distutils.extension import Extension -setup(name='realize_c_type', - ext_modules=[Extension(name='realize_c_type', - sources=['realize_c_type.c', - 'parse_c_type.c'])]) diff --git a/_cffi1/setup_manual.py b/_cffi1/setup_manual.py deleted file mode 100644 index 2569bb4..0000000 --- a/_cffi1/setup_manual.py +++ /dev/null @@ -1,5 +0,0 @@ -from distutils.core import setup -from distutils.extension import Extension -setup(name='manual', - ext_modules=[Extension(name='manual', - sources=['manual.c'])]) diff --git a/_cffi1/setuptools_ext.py b/_cffi1/setuptools_ext.py deleted file mode 100644 index d42de50..0000000 --- a/_cffi1/setuptools_ext.py +++ /dev/null @@ -1,82 +0,0 @@ -try: - basestring -except NameError: - # Python 3.x - basestring = str - -def error(msg): - from distutils.errors import DistutilsSetupError - raise DistutilsSetupError(msg) - - -def add_cffi_module(dist, mod_spec): - import os - from cffi.api import FFI - from _cffi1 import recompiler - from distutils.core import Extension - from distutils.command.build_ext import build_ext - from distutils.dir_util import mkpath - from distutils import log - - if not isinstance(mod_spec, basestring): - error("argument to 'cffi_modules=...' must be a str or a list of str," - " not %r" % (type(mod_spec).__name__,)) - mod_spec = str(mod_spec) - try: - build_mod_name, ffi_var_name = mod_spec.split(':') - except ValueError: - error("%r must be of the form 'build_mod_name:ffi_variable'" % - (mod_spec,)) - mod = __import__(build_mod_name, None, None, [ffi_var_name]) - try: - ffi = getattr(mod, ffi_var_name) - except AttributeError: - error("%r: object %r not found in module" % (mod_spec, - ffi_var_name)) - if not isinstance(ffi, FFI): - ffi = ffi() # maybe it's a function instead of directly an ffi - if not isinstance(ffi, FFI): - error("%r is not an FFI instance (got %r)" % (mod_spec, - type(ffi).__name__)) - if not hasattr(ffi, '_assigned_source'): - error("%r: the set_source() method was not called" % (mod_spec,)) - module_name = ffi._recompiler_module_name - source, kwds = ffi._assigned_source - if ffi._windows_unicode: - kwds = kwds.copy() - ffi._apply_windows_unicode(kwds) - - allsources = ['$PLACEHOLDER'] - allsources.extend(kwds.get('sources', [])) - ext = Extension(name=module_name, sources=allsources, **kwds) - - def make_mod(tmpdir): - file_name = module_name + '.c' - log.info("generating cffi module %r" % file_name) - mkpath(tmpdir) - c_file = os.path.join(tmpdir, file_name) - updated = recompiler.make_c_source(ffi, module_name, source, c_file) - if not updated: - log.info("already up-to-date") - return c_file - - if dist.ext_modules is None: - dist.ext_modules = [] - dist.ext_modules.append(ext) - - base_class = dist.cmdclass.get('build_ext', build_ext) - class build_ext_make_mod(base_class): - def run(self): - if ext.sources[0] == '$PLACEHOLDER': - ext.sources[0] = make_mod(self.build_temp) - base_class.run(self) - dist.cmdclass['build_ext'] = build_ext_make_mod - - -def cffi_modules(dist, attr, value): - assert attr == 'cffi_modules' - if isinstance(value, basestring): - value = [value] - - for cffi_module in value: - add_cffi_module(dist, cffi_module) diff --git a/_cffi1/support.py b/_cffi1/support.py deleted file mode 100644 index 17c56cd..0000000 --- a/_cffi1/support.py +++ /dev/null @@ -1,19 +0,0 @@ -import sys - -if sys.version_info < (3,): - __all__ = ['u'] - - class U(object): - def __add__(self, other): - return eval('u'+repr(other).replace(r'\\u', r'\u') - .replace(r'\\U', r'\U')) - u = U() - assert u+'a\x00b' == eval(r"u'a\x00b'") - assert u+'a\u1234b' == eval(r"u'a\u1234b'") - assert u+'a\U00012345b' == eval(r"u'a\U00012345b'") - -else: - __all__ = ['u', 'unicode', 'long'] - u = "" - unicode = str - long = int diff --git a/_cffi1/test_cffi_binary.py b/_cffi1/test_cffi_binary.py deleted file mode 100644 index 25953db..0000000 --- a/_cffi1/test_cffi_binary.py +++ /dev/null @@ -1,20 +0,0 @@ -import py, sys, os -import _cffi_backend - -def test_no_unknown_exported_symbols(): - if not hasattr(_cffi_backend, '__file__'): - py.test.skip("_cffi_backend module is built-in") - if not sys.platform.startswith('linux'): - py.test.skip("linux-only") - g = os.popen("objdump -T '%s'" % _cffi_backend.__file__, 'r') - for line in g: - if not line.startswith('0'): - continue - if '*UND*' in line: - continue - name = line.split()[-1] - if name.startswith('_') or name.startswith('.'): - continue - if name not in ('init_cffi_backend', 'PyInit__cffi_backend'): - raise Exception("Unexpected exported name %r" % (name,)) - g.close() diff --git a/_cffi1/test_dlopen.py b/_cffi1/test_dlopen.py deleted file mode 100644 index 4056ff6..0000000 --- a/_cffi1/test_dlopen.py +++ /dev/null @@ -1,57 +0,0 @@ -import py -py.test.skip("later") - -from cffi1 import FFI -import math - - -def test_cdef_struct(): - ffi = FFI() - ffi.cdef("struct foo_s { int a, b; };") - assert ffi.sizeof("struct foo_s") == 8 - -def test_cdef_union(): - ffi = FFI() - ffi.cdef("union foo_s { int a, b; };") - assert ffi.sizeof("union foo_s") == 4 - -def test_cdef_struct_union(): - ffi = FFI() - ffi.cdef("union bar_s { int a; }; struct foo_s { int b; };") - assert ffi.sizeof("union bar_s") == 4 - assert ffi.sizeof("struct foo_s") == 4 - -def test_cdef_struct_typename_1(): - ffi = FFI() - ffi.cdef("typedef struct { int a; } t1; typedef struct { t1* m; } t2;") - assert ffi.sizeof("t2") == ffi.sizeof("void *") - assert ffi.sizeof("t1") == 4 - -def test_cdef_struct_typename_2(): - ffi = FFI() - ffi.cdef("typedef struct { int a; } *p1; typedef struct { p1 m; } *p2;") - p2 = ffi.new("p2") - assert ffi.sizeof(p2[0]) == ffi.sizeof("void *") - assert ffi.sizeof(p2[0].m) == ffi.sizeof("void *") - -def test_cdef_struct_anon_1(): - ffi = FFI() - ffi.cdef("typedef struct { int a; } t1; struct foo_s { t1* m; };") - assert ffi.sizeof("struct foo_s") == ffi.sizeof("void *") - -def test_cdef_struct_anon_2(): - ffi = FFI() - ffi.cdef("typedef struct { int a; } *p1; struct foo_s { p1 m; };") - assert ffi.sizeof("struct foo_s") == ffi.sizeof("void *") - -def test_cdef_struct_anon_3(): - ffi = FFI() - ffi.cdef("typedef struct { int a; } **pp; struct foo_s { pp m; };") - assert ffi.sizeof("struct foo_s") == ffi.sizeof("void *") - -def test_math_sin(): - ffi = FFI() - ffi.cdef("double sin(double);") - m = ffi.dlopen('m') - x = m.sin(1.23) - assert x == math.sin(1.23) diff --git a/_cffi1/test_ffi_obj.py b/_cffi1/test_ffi_obj.py deleted file mode 100644 index 2def7e6..0000000 --- a/_cffi1/test_ffi_obj.py +++ /dev/null @@ -1,180 +0,0 @@ -import py -import _cffi_backend as _cffi1_backend - - -def test_ffi_new(): - ffi = _cffi1_backend.FFI() - p = ffi.new("int *") - p[0] = -42 - assert p[0] == -42 - -def test_ffi_subclass(): - class FOO(_cffi1_backend.FFI): - def __init__(self, x): - self.x = x - foo = FOO(42) - assert foo.x == 42 - p = foo.new("int *") - assert p[0] == 0 - -def test_ffi_no_argument(): - py.test.raises(TypeError, _cffi1_backend.FFI, 42) - -def test_ffi_cache_type(): - ffi = _cffi1_backend.FFI() - t1 = ffi.typeof("int **") - t2 = ffi.typeof("int *") - assert t2.item is t1.item.item - assert t2 is t1.item - assert ffi.typeof("int[][10]") is ffi.typeof("int[][10]") - assert ffi.typeof("int(*)()") is ffi.typeof("int(*)()") - -def test_ffi_cache_type_globally(): - ffi1 = _cffi1_backend.FFI() - ffi2 = _cffi1_backend.FFI() - t1 = ffi1.typeof("int *") - t2 = ffi2.typeof("int *") - assert t1 is t2 - -def test_ffi_invalid(): - ffi = _cffi1_backend.FFI() - # array of 10 times an "int[]" is invalid - py.test.raises(ValueError, ffi.typeof, "int[10][]") - -def test_ffi_docstrings(): - # check that all methods of the FFI class have a docstring. - check_type = type(_cffi1_backend.FFI.new) - for methname in dir(_cffi1_backend.FFI): - if not methname.startswith('_'): - method = getattr(_cffi1_backend.FFI, methname) - if isinstance(method, check_type): - assert method.__doc__, "method FFI.%s() has no docstring" % ( - methname,) - -def test_ffi_NULL(): - NULL = _cffi1_backend.FFI.NULL - assert _cffi1_backend.FFI().typeof(NULL).cname == "void *" - -def test_ffi_no_attr(): - ffi = _cffi1_backend.FFI() - py.test.raises(AttributeError, "ffi.no_such_name") - py.test.raises(AttributeError, "ffi.no_such_name = 42") - py.test.raises(AttributeError, "del ffi.no_such_name") - -def test_ffi_string(): - ffi = _cffi1_backend.FFI() - p = ffi.new("char[]", init=b"foobar\x00baz") - assert ffi.string(p) == b"foobar" - -def test_ffi_errno(): - # xxx not really checking errno, just checking that we can read/write it - ffi = _cffi1_backend.FFI() - ffi.errno = 42 - assert ffi.errno == 42 - -def test_ffi_alignof(): - ffi = _cffi1_backend.FFI() - assert ffi.alignof("int") == 4 - assert ffi.alignof("int[]") == 4 - assert ffi.alignof("int[41]") == 4 - assert ffi.alignof("short[41]") == 2 - assert ffi.alignof(ffi.new("int[41]")) == 4 - assert ffi.alignof(ffi.new("int[]", 41)) == 4 - -def test_ffi_sizeof(): - ffi = _cffi1_backend.FFI() - assert ffi.sizeof("int") == 4 - py.test.raises(ffi.error, ffi.sizeof, "int[]") - assert ffi.sizeof("int[41]") == 41 * 4 - assert ffi.sizeof(ffi.new("int[41]")) == 41 * 4 - assert ffi.sizeof(ffi.new("int[]", 41)) == 41 * 4 - -def test_ffi_callback(): - ffi = _cffi1_backend.FFI() - assert ffi.callback("int(int)", lambda x: x + 42)(10) == 52 - assert ffi.callback("int(*)(int)", lambda x: x + 42)(10) == 52 - assert ffi.callback("int(int)", lambda x: x + "", -66)(10) == -66 - assert ffi.callback("int(int)", lambda x: x + "", error=-66)(10) == -66 - -def test_ffi_callback_decorator(): - ffi = _cffi1_backend.FFI() - assert ffi.callback(ffi.typeof("int(*)(int)"))(lambda x: x + 42)(10) == 52 - deco = ffi.callback("int(int)", error=-66) - assert deco(lambda x: x + "")(10) == -66 - assert deco(lambda x: x + 42)(10) == 52 - -def test_ffi_getctype(): - ffi = _cffi1_backend.FFI() - assert ffi.getctype("int") == "int" - assert ffi.getctype("int", 'x') == "int x" - assert ffi.getctype("int*") == "int *" - assert ffi.getctype("int*", '') == "int *" - assert ffi.getctype("int*", 'x') == "int * x" - assert ffi.getctype("int", '*') == "int *" - assert ffi.getctype("int", replace_with=' * x ') == "int * x" - assert ffi.getctype(ffi.typeof("int*"), '*') == "int * *" - assert ffi.getctype("int", '[5]') == "int[5]" - assert ffi.getctype("int[5]", '[6]') == "int[6][5]" - assert ffi.getctype("int[5]", '(*)') == "int(*)[5]" - # special-case for convenience: automatically put '()' around '*' - assert ffi.getctype("int[5]", '*') == "int(*)[5]" - assert ffi.getctype("int[5]", '*foo') == "int(*foo)[5]" - assert ffi.getctype("int[5]", ' ** foo ') == "int(** foo)[5]" - -def test_addressof(): - ffi = _cffi1_backend.FFI() - a = ffi.new("int[10]") - b = ffi.addressof(a, 5) - b[2] = -123 - assert a[7] == -123 - -def test_handle(): - ffi = _cffi1_backend.FFI() - x = [2, 4, 6] - xp = ffi.new_handle(x) - assert ffi.typeof(xp) == ffi.typeof("void *") - assert ffi.from_handle(xp) is x - yp = ffi.new_handle([6, 4, 2]) - assert ffi.from_handle(yp) == [6, 4, 2] - -def test_ffi_cast(): - ffi = _cffi1_backend.FFI() - assert ffi.cast("int(*)(int)", 0) == ffi.NULL - ffi.callback("int(int)") # side-effect of registering this string - py.test.raises(ffi.error, ffi.cast, "int(int)", 0) - -def test_ffi_invalid_type(): - ffi = _cffi1_backend.FFI() - e = py.test.raises(ffi.error, ffi.cast, "", 0) - assert str(e.value) == ("identifier expected\n" - "\n" - "^") - e = py.test.raises(ffi.error, ffi.cast, "struct struct", 0) - assert str(e.value) == ("struct or union name expected\n" - "struct struct\n" - " ^") - e = py.test.raises(ffi.error, ffi.cast, "struct never_heard_of_s", 0) - assert str(e.value) == ("undefined struct/union name\n" - "struct never_heard_of_s\n" - " ^") - -def test_ffi_buffer(): - ffi = _cffi1_backend.FFI() - a = ffi.new("signed char[]", [5, 6, 7]) - assert ffi.buffer(a)[:] == b'\x05\x06\x07' - -def test_ffi_from_buffer(): - import array - ffi = _cffi1_backend.FFI() - a = array.array('H', [10000, 20000, 30000]) - c = ffi.from_buffer(a) - assert ffi.typeof(c) is ffi.typeof("char[]") - ffi.cast("unsigned short *", c)[1] += 500 - assert list(a) == [10000, 20500, 30000] - -def test_ffi_types(): - CData = _cffi1_backend.FFI.CData - CType = _cffi1_backend.FFI.CType - ffi = _cffi1_backend.FFI() - assert isinstance(ffi.cast("int", 42), CData) - assert isinstance(ffi.typeof("int"), CType) diff --git a/_cffi1/test_new_ffi_1.py b/_cffi1/test_new_ffi_1.py deleted file mode 100644 index c1fc6bb..0000000 --- a/_cffi1/test_new_ffi_1.py +++ /dev/null @@ -1,1658 +0,0 @@ -import py -import platform, imp -import sys, os, ctypes -import cffi -from .udir import udir -from .recompiler import recompile -from .support import * - -SIZE_OF_INT = ctypes.sizeof(ctypes.c_int) -SIZE_OF_LONG = ctypes.sizeof(ctypes.c_long) -SIZE_OF_SHORT = ctypes.sizeof(ctypes.c_short) -SIZE_OF_PTR = ctypes.sizeof(ctypes.c_void_p) -SIZE_OF_WCHAR = ctypes.sizeof(ctypes.c_wchar) - - -def setup_module(): - global ffi, construction_params - ffi1 = cffi.FFI() - DEFS = r""" - struct repr { short a, b, c; }; - struct simple { int a; short b, c; }; - struct array { int a[2]; char b[3]; }; - struct recursive { int value; struct recursive *next; }; - union simple_u { int a; short b, c; }; - union init_u { char a; int b; }; - struct four_s { int a; short b, c, d; }; - union four_u { int a; short b, c, d; }; - struct string { const char *name; }; - struct ustring { const wchar_t *name; }; - struct voidp { void *p; int *q; short *r; }; - struct ab { int a, b; }; - struct abc { int a, b, c; }; - - enum foq { A0, B0, CC0, D0 }; - enum bar { A1, B1=-2, CC1, D1, E1 }; - enum baz { A2=0x1000, B2=0x2000 }; - enum foo2 { A3, B3, C3, D3 }; - struct bar_with_e { enum foo2 e; }; - enum noncont { A4, B4=42, C4 }; - enum etypes {A5='!', B5='\'', C5=0x10, D5=010, E5=- 0x10, F5=-010}; - typedef enum { Value0 = 0 } e_t, *pe_t; - enum e_noninj { AA3=0, BB3=0, CC3=0, DD3=0 }; - enum e_prev { AA4, BB4=2, CC4=4, DD4=BB4, EE4, FF4=CC4, GG4=FF4 }; - - struct nesting { struct abc d, e; }; - struct array2 { int a, b; int c[99]; }; - struct align { char a; short b; char c; }; - struct bitfield { int a:10, b:20, c:3; }; - typedef enum { AA2, BB2, CC2 } foo_e_t; - typedef struct { foo_e_t f:2; } bfenum_t; - typedef struct { int a; } anon_foo_t; - typedef struct { char b, c; } anon_bar_t; - typedef struct named_foo_s { int a; } named_foo_t, *named_foo_p; - typedef struct { int a; } unnamed_foo_t, *unnamed_foo_p; - struct nonpacked { char a; int b; }; - struct array0 { int len; short data[0]; }; - struct array_no_length { int x; int a[]; }; - - struct nested_anon { - struct { int a, b; }; - union { int c, d; }; - }; - struct nested_field_ofs_s { - struct { int a; char b; }; - union { char c; }; - }; - union nested_anon_u { - struct { int a, b; }; - union { int c, d; }; - }; - struct abc50 { int a, b; int c[50]; }; - struct ints_and_bitfield { int a,b,c,d,e; int x:1; }; - """ - DEFS_PACKED = """ - struct is_packed { char a; int b; } /*here*/; - """ - if sys.platform == "win32": - DEFS = DEFS.replace('data[0]', 'data[1]') # not supported - CCODE = (DEFS + "\n#pragma pack(push,1)\n" + DEFS_PACKED + - "\n#pragma pack(pop)\n") - else: - CCODE = (DEFS + - DEFS_PACKED.replace('/*here*/', '__attribute__((packed))')) - - ffi1.cdef(DEFS) - ffi1.cdef(DEFS_PACKED, packed=True) - - outputfilename = recompile(ffi1, "test_new_ffi_1", CCODE, - tmpdir=str(udir)) - module = imp.load_dynamic("test_new_ffi_1", outputfilename) - ffi = module.ffi - construction_params = (ffi1, CCODE) - - -class TestNewFFI1: - - def test_integer_ranges(self): - for (c_type, size) in [('char', 1), - ('short', 2), - ('short int', 2), - ('', 4), - ('int', 4), - ('long', SIZE_OF_LONG), - ('long int', SIZE_OF_LONG), - ('long long', 8), - ('long long int', 8), - ]: - for unsigned in [None, False, True]: - c_decl = {None: '', - False: 'signed ', - True: 'unsigned '}[unsigned] + c_type - if c_decl == 'char' or c_decl == '': - continue - self._test_int_type(ffi, c_decl, size, unsigned) - - def test_fixedsize_int(self): - for size in [1, 2, 4, 8]: - self._test_int_type(ffi, 'int%d_t' % (8*size), size, False) - self._test_int_type(ffi, 'uint%d_t' % (8*size), size, True) - self._test_int_type(ffi, 'intptr_t', SIZE_OF_PTR, False) - self._test_int_type(ffi, 'uintptr_t', SIZE_OF_PTR, True) - self._test_int_type(ffi, 'ptrdiff_t', SIZE_OF_PTR, False) - self._test_int_type(ffi, 'size_t', SIZE_OF_PTR, True) - self._test_int_type(ffi, 'ssize_t', SIZE_OF_PTR, False) - - def _test_int_type(self, ffi, c_decl, size, unsigned): - if unsigned: - min = 0 - max = (1 << (8*size)) - 1 - else: - min = -(1 << (8*size-1)) - max = (1 << (8*size-1)) - 1 - min = int(min) - max = int(max) - p = ffi.cast(c_decl, min) - assert p != min # no __eq__(int) - assert bool(p) is True - assert int(p) == min - p = ffi.cast(c_decl, max) - assert int(p) == max - p = ffi.cast(c_decl, long(max)) - assert int(p) == max - q = ffi.cast(c_decl, min - 1) - assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max - q = ffi.cast(c_decl, long(min - 1)) - assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max - assert q != p - assert int(q) == int(p) - assert hash(q) != hash(p) # unlikely - c_decl_ptr = '%s *' % c_decl - py.test.raises(OverflowError, ffi.new, c_decl_ptr, min - 1) - py.test.raises(OverflowError, ffi.new, c_decl_ptr, max + 1) - py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(min - 1)) - py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(max + 1)) - assert ffi.new(c_decl_ptr, min)[0] == min - assert ffi.new(c_decl_ptr, max)[0] == max - assert ffi.new(c_decl_ptr, long(min))[0] == min - assert ffi.new(c_decl_ptr, long(max))[0] == max - - def test_new_unsupported_type(self): - e = py.test.raises(TypeError, ffi.new, "int") - assert str(e.value) == "expected a pointer or array ctype, got 'int'" - - def test_new_single_integer(self): - p = ffi.new("int *") # similar to ffi.new("int[1]") - assert p[0] == 0 - p[0] = -123 - assert p[0] == -123 - p = ffi.new("int *", -42) - assert p[0] == -42 - assert repr(p) == "<cdata 'int *' owning %d bytes>" % SIZE_OF_INT - - def test_new_array_no_arg(self): - p = ffi.new("int[10]") - # the object was zero-initialized: - for i in range(10): - assert p[i] == 0 - - def test_array_indexing(self): - p = ffi.new("int[10]") - p[0] = 42 - p[9] = 43 - assert p[0] == 42 - assert p[9] == 43 - py.test.raises(IndexError, "p[10]") - py.test.raises(IndexError, "p[10] = 44") - py.test.raises(IndexError, "p[-1]") - py.test.raises(IndexError, "p[-1] = 44") - - def test_new_array_args(self): - # this tries to be closer to C: where we say "int x[5] = {10, 20, ..}" - # then here we must enclose the items in a list - p = ffi.new("int[5]", [10, 20, 30, 40, 50]) - assert p[0] == 10 - assert p[1] == 20 - assert p[2] == 30 - assert p[3] == 40 - assert p[4] == 50 - p = ffi.new("int[4]", [25]) - assert p[0] == 25 - assert p[1] == 0 # follow C convention rather than LuaJIT's - assert p[2] == 0 - assert p[3] == 0 - p = ffi.new("int[4]", [ffi.cast("int", -5)]) - assert p[0] == -5 - assert repr(p) == "<cdata 'int[4]' owning %d bytes>" % (4*SIZE_OF_INT) - - def test_new_array_varsize(self): - p = ffi.new("int[]", 10) # a single integer is the length - assert p[9] == 0 - py.test.raises(IndexError, "p[10]") - # - py.test.raises(TypeError, ffi.new, "int[]") - # - p = ffi.new("int[]", [-6, -7]) # a list is all the items, like C - assert p[0] == -6 - assert p[1] == -7 - py.test.raises(IndexError, "p[2]") - assert repr(p) == "<cdata 'int[]' owning %d bytes>" % (2*SIZE_OF_INT) - # - p = ffi.new("int[]", 0) - py.test.raises(IndexError, "p[0]") - py.test.raises(ValueError, ffi.new, "int[]", -1) - assert repr(p) == "<cdata 'int[]' owning 0 bytes>" - - def test_pointer_init(self): - n = ffi.new("int *", 24) - a = ffi.new("int *[10]", [ffi.NULL, ffi.NULL, n, n, ffi.NULL]) - for i in range(10): - if i not in (2, 3): - assert a[i] == ffi.NULL - assert a[2] == a[3] == n - - def test_cannot_cast(self): - a = ffi.new("short int[10]") - e = py.test.raises(TypeError, ffi.new, "long int **", a) - msg = str(e.value) - assert "'short[10]'" in msg and "'long *'" in msg - - def test_new_pointer_to_array(self): - a = ffi.new("int[4]", [100, 102, 104, 106]) - p = ffi.new("int **", a) - assert p[0] == ffi.cast("int *", a) - assert p[0][2] == 104 - p = ffi.cast("int *", a) - assert p[0] == 100 - assert p[1] == 102 - assert p[2] == 104 - assert p[3] == 106 - # keepalive: a - - def test_pointer_direct(self): - p = ffi.cast("int*", 0) - assert p is not None - assert bool(p) is False - assert p == ffi.cast("int*", 0) - assert p != None - assert repr(p) == "<cdata 'int *' NULL>" - a = ffi.new("int[]", [123, 456]) - p = ffi.cast("int*", a) - assert bool(p) is True - assert p == ffi.cast("int*", a) - assert p != ffi.cast("int*", 0) - assert p[0] == 123 - assert p[1] == 456 - - def test_repr(self): - typerepr = "<ctype '%s'>" - p = ffi.cast("short unsigned int", 0) - assert repr(p) == "<cdata 'unsigned short' 0>" - assert repr(ffi.typeof(p)) == typerepr % "unsigned short" - p = ffi.cast("unsigned short int", 0) - assert repr(p) == "<cdata 'unsigned short' 0>" - assert repr(ffi.typeof(p)) == typerepr % "unsigned short" - p = ffi.cast("int*", 0) - assert repr(p) == "<cdata 'int *' NULL>" - assert repr(ffi.typeof(p)) == typerepr % "int *" - # - p = ffi.new("int*") - assert repr(p) == "<cdata 'int *' owning %d bytes>" % SIZE_OF_INT - assert repr(ffi.typeof(p)) == typerepr % "int *" - p = ffi.new("int**") - assert repr(p) == "<cdata 'int * *' owning %d bytes>" % SIZE_OF_PTR - assert repr(ffi.typeof(p)) == typerepr % "int * *" - p = ffi.new("int [2]") - assert repr(p) == "<cdata 'int[2]' owning %d bytes>" % (2*SIZE_OF_INT) - assert repr(ffi.typeof(p)) == typerepr % "int[2]" - p = ffi.new("int*[2][3]") - assert repr(p) == "<cdata 'int *[2][3]' owning %d bytes>" % ( - 6*SIZE_OF_PTR) - assert repr(ffi.typeof(p)) == typerepr % "int *[2][3]" - p = ffi.new("struct repr *") - assert repr(p) == "<cdata 'struct repr *' owning %d bytes>" % ( - 3*SIZE_OF_SHORT) - assert repr(ffi.typeof(p)) == typerepr % "struct repr *" - # - q = ffi.cast("short", -123) - assert repr(q) == "<cdata 'short' -123>" - assert repr(ffi.typeof(q)) == typerepr % "short" - p = ffi.new("int*") - q = ffi.cast("short*", p) - assert repr(q).startswith("<cdata 'short *' 0x") - assert repr(ffi.typeof(q)) == typerepr % "short *" - p = ffi.new("int [2]") - q = ffi.cast("int*", p) - assert repr(q).startswith("<cdata 'int *' 0x") - assert repr(ffi.typeof(q)) == typerepr % "int *" - p = ffi.new("struct repr*") - q = ffi.cast("struct repr *", p) - assert repr(q).startswith("<cdata 'struct repr *' 0x") - assert repr(ffi.typeof(q)) == typerepr % "struct repr *" - prevrepr = repr(q) - q = q[0] - assert repr(q) == prevrepr.replace(' *', ' &') - assert repr(ffi.typeof(q)) == typerepr % "struct repr" - - def test_new_array_of_array(self): - p = ffi.new("int[3][4]") - p[0][0] = 10 - p[2][3] = 33 - assert p[0][0] == 10 - assert p[2][3] == 33 - py.test.raises(IndexError, "p[1][-1]") - - def test_constructor_array_of_array(self): - p = ffi.new("int[3][2]", [[10, 11], [12, 13], [14, 15]]) - assert p[2][1] == 15 - - def test_new_array_of_pointer_1(self): - n = ffi.new("int*", 99) - p = ffi.new("int*[4]") - p[3] = n - a = p[3] - assert repr(a).startswith("<cdata 'int *' 0x") - assert a[0] == 99 - - def test_new_array_of_pointer_2(self): - n = ffi.new("int[1]", [99]) - p = ffi.new("int*[4]") - p[3] = n - a = p[3] - assert repr(a).startswith("<cdata 'int *' 0x") - assert a[0] == 99 - - def test_char(self): - assert ffi.new("char*", b"\xff")[0] == b'\xff' - assert ffi.new("char*")[0] == b'\x00' - assert int(ffi.cast("char", 300)) == 300 - 256 - assert bool(ffi.cast("char", 0)) - py.test.raises(TypeError, ffi.new, "char*", 32) - py.test.raises(TypeError, ffi.new, "char*", u+"x") - py.test.raises(TypeError, ffi.new, "char*", b"foo") - # - p = ffi.new("char[]", [b'a', b'b', b'\x9c']) - assert len(p) == 3 - assert p[0] == b'a' - assert p[1] == b'b' - assert p[2] == b'\x9c' - p[0] = b'\xff' - assert p[0] == b'\xff' - p = ffi.new("char[]", b"abcd") - assert len(p) == 5 - assert p[4] == b'\x00' # like in C, with: char[] p = "abcd"; - # - p = ffi.new("char[4]", b"ab") - assert len(p) == 4 - assert [p[i] for i in range(4)] == [b'a', b'b', b'\x00', b'\x00'] - p = ffi.new("char[2]", b"ab") - assert len(p) == 2 - assert [p[i] for i in range(2)] == [b'a', b'b'] - py.test.raises(IndexError, ffi.new, "char[2]", b"abc") - - def check_wchar_t(self, ffi): - try: - ffi.cast("wchar_t", 0) - except NotImplementedError: - py.test.skip("NotImplementedError: wchar_t") - - def test_wchar_t(self): - self.check_wchar_t(ffi) - assert ffi.new("wchar_t*", u+'x')[0] == u+'x' - assert ffi.new("wchar_t*", u+'\u1234')[0] == u+'\u1234' - if SIZE_OF_WCHAR > 2: - assert ffi.new("wchar_t*", u+'\U00012345')[0] == u+'\U00012345' - else: - py.test.raises(TypeError, ffi.new, "wchar_t*", u+'\U00012345') - assert ffi.new("wchar_t*")[0] == u+'\x00' - assert int(ffi.cast("wchar_t", 300)) == 300 - assert bool(ffi.cast("wchar_t", 0)) - py.test.raises(TypeError, ffi.new, "wchar_t*", 32) - py.test.raises(TypeError, ffi.new, "wchar_t*", "foo") - # - p = ffi.new("wchar_t[]", [u+'a', u+'b', u+'\u1234']) - assert len(p) == 3 - assert p[0] == u+'a' - assert p[1] == u+'b' and type(p[1]) is unicode - assert p[2] == u+'\u1234' - p[0] = u+'x' - assert p[0] == u+'x' and type(p[0]) is unicode - p[1] = u+'\u1357' - assert p[1] == u+'\u1357' - p = ffi.new("wchar_t[]", u+"abcd") - assert len(p) == 5 - assert p[4] == u+'\x00' - p = ffi.new("wchar_t[]", u+"a\u1234b") - assert len(p) == 4 - assert p[1] == u+'\u1234' - # - p = ffi.new("wchar_t[]", u+'\U00023456') - if SIZE_OF_WCHAR == 2: - assert sys.maxunicode == 0xffff - assert len(p) == 3 - assert p[0] == u+'\ud84d' - assert p[1] == u+'\udc56' - assert p[2] == u+'\x00' - else: - assert len(p) == 2 - assert p[0] == u+'\U00023456' - assert p[1] == u+'\x00' - # - p = ffi.new("wchar_t[4]", u+"ab") - assert len(p) == 4 - assert [p[i] for i in range(4)] == [u+'a', u+'b', u+'\x00', u+'\x00'] - p = ffi.new("wchar_t[2]", u+"ab") - assert len(p) == 2 - assert [p[i] for i in range(2)] == [u+'a', u+'b'] - py.test.raises(IndexError, ffi.new, "wchar_t[2]", u+"abc") - - def test_none_as_null_doesnt_work(self): - p = ffi.new("int*[1]") - assert p[0] is not None - assert p[0] != None - assert p[0] == ffi.NULL - assert repr(p[0]) == "<cdata 'int *' NULL>" - # - n = ffi.new("int*", 99) - p = ffi.new("int*[]", [n]) - assert p[0][0] == 99 - py.test.raises(TypeError, "p[0] = None") - p[0] = ffi.NULL - assert p[0] == ffi.NULL - - def test_float(self): - p = ffi.new("float[]", [-2, -2.5]) - assert p[0] == -2.0 - assert p[1] == -2.5 - p[1] += 17.75 - assert p[1] == 15.25 - # - p = ffi.new("float*", 15.75) - assert p[0] == 15.75 - py.test.raises(TypeError, int, p) - py.test.raises(TypeError, float, p) - p[0] = 0.0 - assert bool(p) is True - # - p = ffi.new("float*", 1.1) - f = p[0] - assert f != 1.1 # because of rounding effect - assert abs(f - 1.1) < 1E-7 - # - INF = 1E200 * 1E200 - assert 1E200 != INF - p[0] = 1E200 - assert p[0] == INF # infinite, not enough precision - - def test_struct_simple(self): - s = ffi.new("struct simple*") - assert s.a == s.b == s.c == 0 - s.b = -23 - assert s.b == -23 - py.test.raises(OverflowError, "s.b = 32768") - # - s = ffi.new("struct simple*", [-2, -3]) - assert s.a == -2 - assert s.b == -3 - assert s.c == 0 - py.test.raises((AttributeError, TypeError), "del s.a") - assert repr(s) == "<cdata 'struct simple *' owning %d bytes>" % ( - SIZE_OF_INT + 2 * SIZE_OF_SHORT) - # - py.test.raises(ValueError, ffi.new, "struct simple*", [1, 2, 3, 4]) - - def test_constructor_struct_from_dict(self): - s = ffi.new("struct simple*", {'b': 123, 'c': 456}) - assert s.a == 0 - assert s.b == 123 - assert s.c == 456 - py.test.raises(KeyError, ffi.new, "struct simple*", {'d': 456}) - - def test_struct_pointer(self): - s = ffi.new("struct simple*") - assert s[0].a == s[0].b == s[0].c == 0 - s[0].b = -23 - assert s[0].b == s.b == -23 - py.test.raises(OverflowError, "s[0].b = -32769") - py.test.raises(IndexError, "s[1]") - - def test_struct_opaque(self): - py.test.raises(ffi.error, ffi.new, "struct baz*") - # should 'ffi.new("struct baz **") work? it used to, but it was - # not particularly useful... - py.test.raises(ffi.error, ffi.new, "struct baz**") - - def test_pointer_to_struct(self): - s = ffi.new("struct simple *") - s.a = -42 - assert s[0].a == -42 - p = ffi.new("struct simple **", s) - assert p[0].a == -42 - assert p[0][0].a == -42 - p[0].a = -43 - assert s.a == -43 - assert s[0].a == -43 - p[0][0].a = -44 - assert s.a == -44 - assert s[0].a == -44 - s.a = -45 - assert p[0].a == -45 - assert p[0][0].a == -45 - s[0].a = -46 - assert p[0].a == -46 - assert p[0][0].a == -46 - - def test_constructor_struct_of_array(self): - s = ffi.new("struct array *", [[10, 11], [b'a', b'b', b'c']]) - assert s.a[1] == 11 - assert s.b[2] == b'c' - s.b[1] = b'X' - assert s.b[0] == b'a' - assert s.b[1] == b'X' - assert s.b[2] == b'c' - - def test_recursive_struct(self): - s = ffi.new("struct recursive*") - t = ffi.new("struct recursive*") - s.value = 123 - s.next = t - t.value = 456 - assert s.value == 123 - assert s.next.value == 456 - - def test_union_simple(self): - u = ffi.new("union simple_u*") - assert u.a == u.b == u.c == 0 - u.b = -23 - assert u.b == -23 - assert u.a != 0 - py.test.raises(OverflowError, "u.b = 32768") - # - u = ffi.new("union simple_u*", [-2]) - assert u.a == -2 - py.test.raises((AttributeError, TypeError), "del u.a") - assert repr(u) == "<cdata 'union simple_u *' owning %d bytes>" % ( - SIZE_OF_INT,) - - def test_union_opaque(self): - py.test.raises(ffi.error, ffi.new, "union baz*") - # should 'ffi.new("union baz **") work? it used to, but it was - # not particularly useful... - py.test.raises(ffi.error, ffi.new, "union baz**") - - def test_union_initializer(self): - py.test.raises(TypeError, ffi.new, "union init_u*", b'A') - py.test.raises(TypeError, ffi.new, "union init_u*", 5) - py.test.raises(ValueError, ffi.new, "union init_u*", [b'A', 5]) - u = ffi.new("union init_u*", [b'A']) - assert u.a == b'A' - py.test.raises(TypeError, ffi.new, "union init_u*", [1005]) - u = ffi.new("union init_u*", {'b': 12345}) - assert u.b == 12345 - u = ffi.new("union init_u*", []) - assert u.a == b'\x00' - assert u.b == 0 - - def test_sizeof_type(self): - for c_type, expected_size in [ - ('char', 1), - ('unsigned int', 4), - ('char *', SIZE_OF_PTR), - ('int[5]', 20), - ('struct four_s', 12), - ('union four_u', 4), - ]: - size = ffi.sizeof(c_type) - assert size == expected_size, (size, expected_size, ctype) - - def test_sizeof_cdata(self): - assert ffi.sizeof(ffi.new("short*")) == SIZE_OF_PTR - assert ffi.sizeof(ffi.cast("short", 123)) == SIZE_OF_SHORT - # - a = ffi.new("int[]", [10, 11, 12, 13, 14]) - assert len(a) == 5 - assert ffi.sizeof(a) == 5 * SIZE_OF_INT - - def test_string_from_char_pointer(self): - x = ffi.new("char*", b"x") - assert str(x) == repr(x) - assert ffi.string(x) == b"x" - assert ffi.string(ffi.new("char*", b"\x00")) == b"" - py.test.raises(TypeError, ffi.new, "char*", unicode("foo")) - - def test_unicode_from_wchar_pointer(self): - self.check_wchar_t(ffi) - x = ffi.new("wchar_t*", u+"x") - assert unicode(x) == unicode(repr(x)) - assert ffi.string(x) == u+"x" - assert ffi.string(ffi.new("wchar_t*", u+"\x00")) == u+"" - - def test_string_from_char_array(self): - p = ffi.new("char[]", b"hello.") - p[5] = b'!' - assert ffi.string(p) == b"hello!" - p[6] = b'?' - assert ffi.string(p) == b"hello!?" - p[3] = b'\x00' - assert ffi.string(p) == b"hel" - assert ffi.string(p, 2) == b"he" - py.test.raises(IndexError, "p[7] = b'X'") - # - a = ffi.new("char[]", b"hello\x00world") - assert len(a) == 12 - p = ffi.cast("char *", a) - assert ffi.string(p) == b'hello' - - def test_string_from_wchar_array(self): - self.check_wchar_t(ffi) - assert ffi.string(ffi.cast("wchar_t", "x")) == u+"x" - assert ffi.string(ffi.cast("wchar_t", u+"x")) == u+"x" - x = ffi.cast("wchar_t", "x") - assert str(x) == repr(x) - assert ffi.string(x) == u+"x" - # - p = ffi.new("wchar_t[]", u+"hello.") - p[5] = u+'!' - assert ffi.string(p) == u+"hello!" - p[6] = u+'\u04d2' - assert ffi.string(p) == u+"hello!\u04d2" - p[3] = u+'\x00' - assert ffi.string(p) == u+"hel" - assert ffi.string(p, 123) == u+"hel" - py.test.raises(IndexError, "p[7] = u+'X'") - # - a = ffi.new("wchar_t[]", u+"hello\x00world") - assert len(a) == 12 - p = ffi.cast("wchar_t *", a) - assert ffi.string(p) == u+'hello' - assert ffi.string(p, 123) == u+'hello' - assert ffi.string(p, 5) == u+'hello' - assert ffi.string(p, 2) == u+'he' - - def test_fetch_const_char_p_field(self): - # 'const' is ignored so far, in the declaration of 'struct string' - t = ffi.new("const char[]", b"testing") - s = ffi.new("struct string*", [t]) - assert type(s.name) not in (bytes, str, unicode) - assert ffi.string(s.name) == b"testing" - py.test.raises(TypeError, "s.name = None") - s.name = ffi.NULL - assert s.name == ffi.NULL - - def test_fetch_const_wchar_p_field(self): - # 'const' is ignored so far - self.check_wchar_t(ffi) - t = ffi.new("const wchar_t[]", u+"testing") - s = ffi.new("struct ustring*", [t]) - assert type(s.name) not in (bytes, str, unicode) - assert ffi.string(s.name) == u+"testing" - s.name = ffi.NULL - assert s.name == ffi.NULL - - def test_voidp(self): - py.test.raises(TypeError, ffi.new, "void*") - p = ffi.new("void **") - assert p[0] == ffi.NULL - a = ffi.new("int[]", [10, 11, 12]) - p = ffi.new("void **", a) - vp = p[0] - py.test.raises(TypeError, "vp[0]") - py.test.raises(TypeError, ffi.new, "short **", a) - # - s = ffi.new("struct voidp *") - s.p = a # works - s.q = a # works - py.test.raises(TypeError, "s.r = a") # fails - b = ffi.cast("int *", a) - s.p = b # works - s.q = b # works - py.test.raises(TypeError, "s.r = b") # fails - - def test_functionptr_simple(self): - py.test.raises(TypeError, ffi.callback, "int(*)(int)", 0) - def cb(n): - return n + 1 - cb.__qualname__ = 'cb' - p = ffi.callback("int(*)(int)", cb) - res = p(41) # calling an 'int(*)(int)', i.e. a function pointer - assert res == 42 and type(res) is int - res = p(ffi.cast("int", -41)) - assert res == -40 and type(res) is int - assert repr(p).startswith( - "<cdata 'int(*)(int)' calling <function cb at 0x") - assert ffi.typeof(p) is ffi.typeof("int(*)(int)") - q = ffi.new("int(**)(int)", p) - assert repr(q) == "<cdata 'int(* *)(int)' owning %d bytes>" % ( - SIZE_OF_PTR) - py.test.raises(TypeError, "q(43)") - res = q[0](43) - assert res == 44 - q = ffi.cast("int(*)(int)", p) - assert repr(q).startswith("<cdata 'int(*)(int)' 0x") - res = q(45) - assert res == 46 - - def test_functionptr_advanced(self): - t = ffi.typeof("int(*(*)(int))(int)") - assert repr(t) == "<ctype '%s'>" % "int(*(*)(int))(int)" - - def test_functionptr_voidptr_return(self): - def cb(): - return ffi.NULL - p = ffi.callback("void*(*)()", cb) - res = p() - assert res is not None - assert res == ffi.NULL - int_ptr = ffi.new('int*') - void_ptr = ffi.cast('void*', int_ptr) - def cb(): - return void_ptr - p = ffi.callback("void*(*)()", cb) - res = p() - assert res == void_ptr - - def test_functionptr_intptr_return(self): - def cb(): - return ffi.NULL - p = ffi.callback("int*(*)()", cb) - res = p() - assert res == ffi.NULL - int_ptr = ffi.new('int*') - def cb(): - return int_ptr - p = ffi.callback("int*(*)()", cb) - res = p() - assert repr(res).startswith("<cdata 'int *' 0x") - assert res == int_ptr - int_array_ptr = ffi.new('int[1]') - def cb(): - return int_array_ptr - p = ffi.callback("int*(*)()", cb) - res = p() - assert repr(res).startswith("<cdata 'int *' 0x") - assert res == int_array_ptr - - def test_functionptr_void_return(self): - def foo(): - pass - foo_cb = ffi.callback("void foo()", foo) - result = foo_cb() - assert result is None - - def test_char_cast(self): - p = ffi.cast("int", b'\x01') - assert ffi.typeof(p) is ffi.typeof("int") - assert int(p) == 1 - p = ffi.cast("int", ffi.cast("char", b"a")) - assert int(p) == ord("a") - p = ffi.cast("int", ffi.cast("char", b"\x80")) - assert int(p) == 0x80 # "char" is considered unsigned in this case - p = ffi.cast("int", b"\x81") - assert int(p) == 0x81 - - def test_wchar_cast(self): - self.check_wchar_t(ffi) - p = ffi.cast("int", ffi.cast("wchar_t", u+'\u1234')) - assert int(p) == 0x1234 - p = ffi.cast("long long", ffi.cast("wchar_t", -1)) - if SIZE_OF_WCHAR == 2: # 2 bytes, unsigned - assert int(p) == 0xffff - elif platform.machine() == 'aarch64': # 4 bytes, unsigned - assert int(p) == 0xffffffff - else: # 4 bytes, signed - assert int(p) == -1 - p = ffi.cast("int", u+'\u1234') - assert int(p) == 0x1234 - - def test_cast_array_to_charp(self): - a = ffi.new("short int[]", [0x1234, 0x5678]) - p = ffi.cast("char*", a) - data = b''.join([p[i] for i in range(4)]) - if sys.byteorder == 'little': - assert data == b'\x34\x12\x78\x56' - else: - assert data == b'\x12\x34\x56\x78' - - def test_cast_between_pointers(self): - a = ffi.new("short int[]", [0x1234, 0x5678]) - p = ffi.cast("short*", a) - p2 = ffi.cast("int*", p) - q = ffi.cast("char*", p2) - data = b''.join([q[i] for i in range(4)]) - if sys.byteorder == 'little': - assert data == b'\x34\x12\x78\x56' - else: - assert data == b'\x12\x34\x56\x78' - - def test_cast_pointer_and_int(self): - a = ffi.new("short int[]", [0x1234, 0x5678]) - l1 = ffi.cast("intptr_t", a) - p = ffi.cast("short*", a) - l2 = ffi.cast("intptr_t", p) - assert int(l1) == int(l2) != 0 - q = ffi.cast("short*", l1) - assert q == ffi.cast("short*", int(l1)) - assert q[0] == 0x1234 - assert int(ffi.cast("intptr_t", ffi.NULL)) == 0 - - def test_cast_functionptr_and_int(self): - def cb(n): - return n + 1 - a = ffi.callback("int(*)(int)", cb) - p = ffi.cast("void *", a) - assert p - b = ffi.cast("int(*)(int)", p) - assert b(41) == 42 - assert a == b - assert hash(a) == hash(b) - - def test_callback_crash(self): - def cb(n): - raise Exception - a = ffi.callback("int(*)(int)", cb, error=42) - res = a(1) # and the error reported to stderr - assert res == 42 - - def test_structptr_argument(self): - def cb(p): - return p[0].a * 1000 + p[0].b * 100 + p[1].a * 10 + p[1].b - a = ffi.callback("int(*)(struct ab[])", cb) - res = a([[5, 6], {'a': 7, 'b': 8}]) - assert res == 5678 - res = a([[5], {'b': 8}]) - assert res == 5008 - - def test_array_argument_as_list(self): - seen = [] - def cb(argv): - seen.append(ffi.string(argv[0])) - seen.append(ffi.string(argv[1])) - a = ffi.callback("void(*)(char *[])", cb) - a([ffi.new("char[]", b"foobar"), ffi.new("char[]", b"baz")]) - assert seen == [b"foobar", b"baz"] - - def test_cast_float(self): - a = ffi.cast("float", 12) - assert float(a) == 12.0 - a = ffi.cast("float", 12.5) - assert float(a) == 12.5 - a = ffi.cast("float", b"A") - assert float(a) == ord("A") - a = ffi.cast("int", 12.9) - assert int(a) == 12 - a = ffi.cast("char", 66.9 + 256) - assert ffi.string(a) == b"B" - # - a = ffi.cast("float", ffi.cast("int", 12)) - assert float(a) == 12.0 - a = ffi.cast("float", ffi.cast("double", 12.5)) - assert float(a) == 12.5 - a = ffi.cast("float", ffi.cast("char", b"A")) - assert float(a) == ord("A") - a = ffi.cast("int", ffi.cast("double", 12.9)) - assert int(a) == 12 - a = ffi.cast("char", ffi.cast("double", 66.9 + 256)) - assert ffi.string(a) == b"B" - - def test_enum(self): - # enum foq { A0, B0, CC0, D0 }; - assert ffi.string(ffi.cast("enum foq", 0)) == "A0" - assert ffi.string(ffi.cast("enum foq", 2)) == "CC0" - assert ffi.string(ffi.cast("enum foq", 3)) == "D0" - assert ffi.string(ffi.cast("enum foq", 4)) == "4" - # enum bar { A1, B1=-2, CC1, D1, E1 }; - assert ffi.string(ffi.cast("enum bar", 0)) == "A1" - assert ffi.string(ffi.cast("enum bar", -2)) == "B1" - assert ffi.string(ffi.cast("enum bar", -1)) == "CC1" - assert ffi.string(ffi.cast("enum bar", 1)) == "E1" - assert ffi.cast("enum bar", -2) != ffi.cast("enum bar", -2) - assert ffi.cast("enum foq", 0) != ffi.cast("enum bar", 0) - assert ffi.cast("enum bar", 0) != ffi.cast("int", 0) - assert repr(ffi.cast("enum bar", -1)) == "<cdata 'enum bar' -1: CC1>" - assert repr(ffi.cast("enum foq", -1)) == ( # enums are unsigned, if - "<cdata 'enum foq' 4294967295>") or ( # they contain no neg value - sys.platform == "win32") # (but not on msvc) - # enum baz { A2=0x1000, B2=0x2000 }; - assert ffi.string(ffi.cast("enum baz", 0x1000)) == "A2" - assert ffi.string(ffi.cast("enum baz", 0x2000)) == "B2" - - def test_enum_in_struct(self): - # enum foo2 { A3, B3, C3, D3 }; - # struct bar_with_e { enum foo2 e; }; - s = ffi.new("struct bar_with_e *") - s.e = 0 - assert s.e == 0 - s.e = 3 - assert s.e == 3 - assert s[0].e == 3 - s[0].e = 2 - assert s.e == 2 - assert s[0].e == 2 - s.e = ffi.cast("enum foo2", -1) - assert s.e in (4294967295, -1) # two choices - assert s[0].e in (4294967295, -1) - s.e = s.e - py.test.raises(TypeError, "s.e = 'B3'") - py.test.raises(TypeError, "s.e = '2'") - py.test.raises(TypeError, "s.e = '#2'") - py.test.raises(TypeError, "s.e = '#7'") - - def test_enum_non_contiguous(self): - # enum noncont { A4, B4=42, C4 }; - assert ffi.string(ffi.cast("enum noncont", 0)) == "A4" - assert ffi.string(ffi.cast("enum noncont", 42)) == "B4" - assert ffi.string(ffi.cast("enum noncont", 43)) == "C4" - invalid_value = ffi.cast("enum noncont", 2) - assert int(invalid_value) == 2 - assert ffi.string(invalid_value) == "2" - - def test_enum_char_hex_oct(self): - # enum etypes {A5='!', B5='\'', C5=0x10, D5=010, E5=- 0x10, F5=-010}; - assert ffi.string(ffi.cast("enum etypes", ord('!'))) == "A5" - assert ffi.string(ffi.cast("enum etypes", ord("'"))) == "B5" - assert ffi.string(ffi.cast("enum etypes", 16)) == "C5" - assert ffi.string(ffi.cast("enum etypes", 8)) == "D5" - assert ffi.string(ffi.cast("enum etypes", -16)) == "E5" - assert ffi.string(ffi.cast("enum etypes", -8)) == "F5" - - def test_array_of_struct(self): - s = ffi.new("struct ab[1]") - py.test.raises(AttributeError, 's.b') - py.test.raises(AttributeError, 's.b = 412') - s[0].b = 412 - assert s[0].b == 412 - py.test.raises(IndexError, 's[1]') - - def test_pointer_to_array(self): - p = ffi.new("int(**)[5]") - assert repr(p) == "<cdata 'int(* *)[5]' owning %d bytes>" % SIZE_OF_PTR - - def test_iterate_array(self): - a = ffi.new("char[]", b"hello") - assert list(a) == [b"h", b"e", b"l", b"l", b"o", b"\0"] - assert list(iter(a)) == [b"h", b"e", b"l", b"l", b"o", b"\0"] - # - py.test.raises(TypeError, iter, ffi.cast("char *", a)) - py.test.raises(TypeError, list, ffi.cast("char *", a)) - py.test.raises(TypeError, iter, ffi.new("int *")) - py.test.raises(TypeError, list, ffi.new("int *")) - - def test_offsetof(self): - # struct abc { int a, b, c; }; - assert ffi.offsetof("struct abc", "a") == 0 - assert ffi.offsetof("struct abc", "b") == 4 - assert ffi.offsetof("struct abc", "c") == 8 - - def test_offsetof_nested(self): - # struct nesting { struct abc d, e; }; - assert ffi.offsetof("struct nesting", "e") == 12 - py.test.raises(KeyError, ffi.offsetof, "struct nesting", "e.a") - assert ffi.offsetof("struct nesting", "e", "a") == 12 - assert ffi.offsetof("struct nesting", "e", "b") == 16 - assert ffi.offsetof("struct nesting", "e", "c") == 20 - - def test_offsetof_array(self): - assert ffi.offsetof("int[]", 51) == 51 * ffi.sizeof("int") - assert ffi.offsetof("int *", 51) == 51 * ffi.sizeof("int") - # struct array2 { int a, b; int c[99]; }; - assert ffi.offsetof("struct array2", "c") == 2 * ffi.sizeof("int") - assert ffi.offsetof("struct array2", "c", 0) == 2 * ffi.sizeof("int") - assert ffi.offsetof("struct array2", "c", 51) == 53 * ffi.sizeof("int") - - def test_alignof(self): - # struct align { char a; short b; char c; }; - assert ffi.alignof("int") == 4 - assert ffi.alignof("double") in (4, 8) - assert ffi.alignof("struct align") == 2 - - def test_bitfield(self): - # struct bitfield { int a:10, b:20, c:3; }; - assert ffi.sizeof("struct bitfield") == 8 - s = ffi.new("struct bitfield *") - s.a = 511 - py.test.raises(OverflowError, "s.a = 512") - py.test.raises(OverflowError, "s[0].a = 512") - assert s.a == 511 - s.a = -512 - py.test.raises(OverflowError, "s.a = -513") - py.test.raises(OverflowError, "s[0].a = -513") - assert s.a == -512 - s.c = 3 - assert s.c == 3 - py.test.raises(OverflowError, "s.c = 4") - py.test.raises(OverflowError, "s[0].c = 4") - s.c = -4 - assert s.c == -4 - - def test_bitfield_enum(self): - # typedef enum { AA1, BB1, CC1 } foo_e_t; - # typedef struct { foo_e_t f:2; } bfenum_t; - if sys.platform == "win32": - py.test.skip("enums are not unsigned") - s = ffi.new("bfenum_t *") - s.f = 2 - assert s.f == 2 - - def test_anonymous_struct(self): - # typedef struct { int a; } anon_foo_t; - # typedef struct { char b, c; } anon_bar_t; - f = ffi.new("anon_foo_t *", [12345]) - b = ffi.new("anon_bar_t *", [b"B", b"C"]) - assert f.a == 12345 - assert b.b == b"B" - assert b.c == b"C" - assert repr(b).startswith("<cdata 'anon_bar_t *'") - - def test_struct_with_two_usages(self): - # typedef struct named_foo_s { int a; } named_foo_t, *named_foo_p; - # typedef struct { int a; } unnamed_foo_t, *unnamed_foo_p; - f = ffi.new("named_foo_t *", [12345]) - ps = ffi.new("named_foo_p[]", [f]) - f = ffi.new("unnamed_foo_t *", [12345]) - ps = ffi.new("unnamed_foo_p[]", [f]) - - def test_pointer_arithmetic(self): - s = ffi.new("short[]", list(range(100, 110))) - p = ffi.cast("short *", s) - assert p[2] == 102 - assert p+1 == p+1 - assert p+1 != p+0 - assert p == p+0 == p-0 - assert (p+1)[0] == 101 - assert (p+19)[-10] == 109 - assert (p+5) - (p+1) == 4 - assert p == s+0 - assert p+1 == s+1 - - def test_pointer_comparison(self): - s = ffi.new("short[]", list(range(100))) - p = ffi.cast("short *", s) - assert (p < s) is False - assert (p <= s) is True - assert (p == s) is True - assert (p != s) is False - assert (p > s) is False - assert (p >= s) is True - assert (s < p) is False - assert (s <= p) is True - assert (s == p) is True - assert (s != p) is False - assert (s > p) is False - assert (s >= p) is True - q = p + 1 - assert (q < s) is False - assert (q <= s) is False - assert (q == s) is False - assert (q != s) is True - assert (q > s) is True - assert (q >= s) is True - assert (s < q) is True - assert (s <= q) is True - assert (s == q) is False - assert (s != q) is True - assert (s > q) is False - assert (s >= q) is False - assert (q < p) is False - assert (q <= p) is False - assert (q == p) is False - assert (q != p) is True - assert (q > p) is True - assert (q >= p) is True - assert (p < q) is True - assert (p <= q) is True - assert (p == q) is False - assert (p != q) is True - assert (p > q) is False - assert (p >= q) is False - # - assert (None == s) is False - assert (None != s) is True - assert (s == None) is False - assert (s != None) is True - assert (None == q) is False - assert (None != q) is True - assert (q == None) is False - assert (q != None) is True - - def test_no_integer_comparison(self): - x = ffi.cast("int", 123) - y = ffi.cast("int", 456) - py.test.raises(TypeError, "x < y") - # - z = ffi.cast("double", 78.9) - py.test.raises(TypeError, "x < z") - py.test.raises(TypeError, "z < y") - - def test_ffi_buffer_ptr(self): - a = ffi.new("short *", 100) - try: - b = ffi.buffer(a) - except NotImplementedError as e: - py.test.skip(str(e)) - content = b[:] - assert len(content) == len(b) == 2 - if sys.byteorder == 'little': - assert content == b'\x64\x00' - assert b[0] == b'\x64' - b[0] = b'\x65' - else: - assert content == b'\x00\x64' - assert b[1] == b'\x64' - b[1] = b'\x65' - assert a[0] == 101 - - def test_ffi_buffer_array(self): - a = ffi.new("int[]", list(range(100, 110))) - try: - b = ffi.buffer(a) - except NotImplementedError as e: - py.test.skip(str(e)) - content = b[:] - if sys.byteorder == 'little': - assert content.startswith(b'\x64\x00\x00\x00\x65\x00\x00\x00') - b[4] = b'\x45' - else: - assert content.startswith(b'\x00\x00\x00\x64\x00\x00\x00\x65') - b[7] = b'\x45' - assert len(content) == 4 * 10 - assert a[1] == 0x45 - - def test_ffi_buffer_ptr_size(self): - a = ffi.new("short *", 0x4243) - try: - b = ffi.buffer(a, 1) - except NotImplementedError as e: - py.test.skip(str(e)) - content = b[:] - assert len(content) == 1 - if sys.byteorder == 'little': - assert content == b'\x43' - b[0] = b'\x62' - assert a[0] == 0x4262 - else: - assert content == b'\x42' - b[0] = b'\x63' - assert a[0] == 0x6343 - - def test_ffi_buffer_array_size(self): - a1 = ffi.new("int[]", list(range(100, 110))) - a2 = ffi.new("int[]", list(range(100, 115))) - try: - ffi.buffer(a1) - except NotImplementedError as e: - py.test.skip(str(e)) - assert ffi.buffer(a1)[:] == ffi.buffer(a2, 4*10)[:] - - def test_ffi_buffer_with_file(self): - import tempfile, os, array - fd, filename = tempfile.mkstemp() - f = os.fdopen(fd, 'r+b') - a = ffi.new("int[]", list(range(1005))) - try: - ffi.buffer(a, 512) - except NotImplementedError as e: - py.test.skip(str(e)) - f.write(ffi.buffer(a, 1000 * ffi.sizeof("int"))) - f.seek(0) - assert f.read() == array.array('i', range(1000)).tostring() - f.seek(0) - b = ffi.new("int[]", 1005) - f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int"))) - assert list(a)[:1000] + [0] * (len(a)-1000) == list(b) - f.close() - os.unlink(filename) - - def test_ffi_buffer_with_io(self): - import io, array - f = io.BytesIO() - a = ffi.new("int[]", list(range(1005))) - try: - ffi.buffer(a, 512) - except NotImplementedError as e: - py.test.skip(str(e)) - f.write(ffi.buffer(a, 1000 * ffi.sizeof("int"))) - f.seek(0) - assert f.read() == array.array('i', range(1000)).tostring() - f.seek(0) - b = ffi.new("int[]", 1005) - f.readinto(ffi.buffer(b, 1000 * ffi.sizeof("int"))) - assert list(a)[:1000] + [0] * (len(a)-1000) == list(b) - f.close() - - def test_array_in_struct(self): - # struct array { int a[2]; char b[3]; }; - p = ffi.new("struct array *") - p.a[1] = 5 - assert p.a[1] == 5 - assert repr(p.a).startswith("<cdata 'int[2]' 0x") - - def test_struct_containing_array_varsize_workaround(self): - if sys.platform == "win32": - py.test.skip("array of length 0 not supported") - # struct array0 { int len; short data[0]; }; - p = ffi.new("char[]", ffi.sizeof("struct array0") + 7 * SIZE_OF_SHORT) - q = ffi.cast("struct array0 *", p) - assert q.len == 0 - # 'q.data' gets not a 'short[0]', but just a 'short *' instead - assert repr(q.data).startswith("<cdata 'short *' 0x") - assert q.data[6] == 0 - q.data[6] = 15 - assert q.data[6] == 15 - - def test_new_struct_containing_array_varsize(self): - py.test.skip("later?") - ffi.cdef("struct foo_s { int len; short data[]; };") - p = ffi.new("struct foo_s *", 10) # a single integer is the length - assert p.len == 0 - assert p.data[9] == 0 - py.test.raises(IndexError, "p.data[10]") - - def test_ffi_typeof_getcname(self): - assert ffi.getctype("int") == "int" - assert ffi.getctype("int", 'x') == "int x" - assert ffi.getctype("int*") == "int *" - assert ffi.getctype("int*", '') == "int *" - assert ffi.getctype("int*", 'x') == "int * x" - assert ffi.getctype("int", '*') == "int *" - assert ffi.getctype("int", ' * x ') == "int * x" - assert ffi.getctype(ffi.typeof("int*"), '*') == "int * *" - assert ffi.getctype("int", '[5]') == "int[5]" - assert ffi.getctype("int[5]", '[6]') == "int[6][5]" - assert ffi.getctype("int[5]", '(*)') == "int(*)[5]" - # special-case for convenience: automatically put '()' around '*' - assert ffi.getctype("int[5]", '*') == "int(*)[5]" - assert ffi.getctype("int[5]", '*foo') == "int(*foo)[5]" - assert ffi.getctype("int[5]", ' ** foo ') == "int(** foo)[5]" - - def test_array_of_func_ptr(self): - f = ffi.cast("int(*)(int)", 42) - assert f != ffi.NULL - py.test.raises(ffi.error, ffi.cast, "int(int)", 42) - py.test.raises(ffi.error, ffi.new, "int([5])(int)") - a = ffi.new("int(*[5])(int)", [f]) - assert ffi.getctype(ffi.typeof(a)) == "int(*[5])(int)" - assert len(a) == 5 - assert a[0] == f - assert a[1] == ffi.NULL - py.test.raises(TypeError, ffi.cast, "int(*)(int)[5]", 0) - # - def cb(n): - return n + 1 - f = ffi.callback("int(*)(int)", cb) - a = ffi.new("int(*[5])(int)", [f, f]) - assert a[1](42) == 43 - - def test_callback_as_function_argument(self): - # In C, function arguments can be declared with a function type, - # which is automatically replaced with the ptr-to-function type. - def cb(a, b): - return chr(ord(a) + ord(b)).encode() - f = ffi.callback("char cb(char, char)", cb) - assert f(b'A', b'\x01') == b'B' - def g(callback): - return callback(b'A', b'\x01') - g = ffi.callback("char g(char cb(char, char))", g) - assert g(f) == b'B' - - def test_vararg_callback(self): - py.test.skip("callback with '...'") - def cb(i, va_list): - j = ffi.va_arg(va_list, "int") - k = ffi.va_arg(va_list, "long long") - return i * 2 + j * 3 + k * 5 - f = ffi.callback("long long cb(long i, ...)", cb) - res = f(10, ffi.cast("int", 100), ffi.cast("long long", 1000)) - assert res == 20 + 300 + 5000 - - def test_callback_decorator(self): - # - @ffi.callback("long(long, long)", error=42) - def cb(a, b): - return a - b - # - assert cb(-100, -10) == -90 - sz = ffi.sizeof("long") - assert cb((1 << (sz*8-1)) - 1, -10) == 42 - - def test_anonymous_enum(self): - # typedef enum { Value0 = 0 } e_t, *pe_t; - assert ffi.getctype("e_t*") == 'e_t *' - assert ffi.getctype("pe_t") == 'e_t *' - assert ffi.getctype("foo_e_t*") == 'foo_e_t *' - - def test_new_ctype(self): - p = ffi.new("int *") - py.test.raises(TypeError, ffi.new, p) - p = ffi.new(ffi.typeof("int *"), 42) - assert p[0] == 42 - - def test_enum_with_non_injective_mapping(self): - # enum e_noninj { AA3=0, BB3=0, CC3=0, DD3=0 }; - e = ffi.cast("enum e_noninj", 0) - assert ffi.string(e) == "AA3" # pick the first one arbitrarily - - def test_enum_refer_previous_enum_value(self): - # enum e_prev { AA4, BB4=2, CC4=4, DD4=BB4, EE4, FF4=CC4, GG4=FF4 }; - assert ffi.string(ffi.cast("enum e_prev", 2)) == "BB4" - assert ffi.string(ffi.cast("enum e_prev", 3)) == "EE4" - assert ffi.sizeof("char[DD4]") == 2 - assert ffi.sizeof("char[EE4]") == 3 - assert ffi.sizeof("char[FF4]") == 4 - assert ffi.sizeof("char[GG4]") == 4 - - def test_nested_anonymous_struct(self): - # struct nested_anon { - # struct { int a, b; }; - # union { int c, d; }; - # }; - assert ffi.sizeof("struct nested_anon") == 3 * SIZE_OF_INT - p = ffi.new("struct nested_anon *", [1, 2, 3]) - assert p.a == 1 - assert p.b == 2 - assert p.c == 3 - assert p.d == 3 - p.d = 17 - assert p.c == 17 - p.b = 19 - assert p.a == 1 - assert p.b == 19 - assert p.c == 17 - assert p.d == 17 - p = ffi.new("struct nested_anon *", {'b': 12, 'd': 14}) - assert p.a == 0 - assert p.b == 12 - assert p.c == 14 - assert p.d == 14 - - def test_nested_field_offset_align(self): - # struct nested_field_ofs_s { - # struct { int a; char b; }; - # union { char c; }; - # }; - assert ffi.offsetof("struct nested_field_ofs_s", "c") == 2 * SIZE_OF_INT - assert ffi.sizeof("struct nested_field_ofs_s") == 3 * SIZE_OF_INT - - def test_nested_anonymous_union(self): - # union nested_anon_u { - # struct { int a, b; }; - # union { int c, d; }; - # }; - assert ffi.sizeof("union nested_anon_u") == 2 * SIZE_OF_INT - p = ffi.new("union nested_anon_u *", [5]) - assert p.a == 5 - assert p.b == 0 - assert p.c == 5 - assert p.d == 5 - p.d = 17 - assert p.c == 17 - assert p.a == 17 - p.b = 19 - assert p.a == 17 - assert p.b == 19 - assert p.c == 17 - assert p.d == 17 - p = ffi.new("union nested_anon_u *", {'d': 14}) - assert p.a == 14 - assert p.b == 0 - assert p.c == 14 - assert p.d == 14 - p = ffi.new("union nested_anon_u *", {'b': 12}) - assert p.a == 0 - assert p.b == 12 - assert p.c == 0 - assert p.d == 0 - # we cannot specify several items in the dict, even though - # in theory in this particular case it would make sense - # to give both 'a' and 'b' - - def test_cast_to_array_type(self): - p = ffi.new("int[4]", [-5]) - q = ffi.cast("int[3]", p) - assert q[0] == -5 - assert repr(q).startswith("<cdata 'int[3]' 0x") - - def test_gc(self): - p = ffi.new("int *", 123) - seen = [] - def destructor(p1): - assert p1 is p - assert p1[0] == 123 - seen.append(1) - q = ffi.gc(p, destructor=destructor) - import gc; gc.collect() - assert seen == [] - del q - import gc; gc.collect(); gc.collect(); gc.collect() - assert seen == [1] - - def test_CData_CType(self): - assert isinstance(ffi.cast("int", 0), ffi.CData) - assert isinstance(ffi.new("int *"), ffi.CData) - assert not isinstance(ffi.typeof("int"), ffi.CData) - assert not isinstance(ffi.cast("int", 0), ffi.CType) - assert not isinstance(ffi.new("int *"), ffi.CType) - - def test_CData_CType_2(self): - assert isinstance(ffi.typeof("int"), ffi.CType) - - def test_bool(self): - assert int(ffi.cast("_Bool", 0.1)) == 1 - assert int(ffi.cast("_Bool", -0.0)) == 0 - assert int(ffi.cast("_Bool", b'\x02')) == 1 - assert int(ffi.cast("_Bool", b'\x00')) == 0 - assert int(ffi.cast("_Bool", b'\x80')) == 1 - assert ffi.new("_Bool *", False)[0] == 0 - assert ffi.new("_Bool *", 1)[0] == 1 - py.test.raises(OverflowError, ffi.new, "_Bool *", 2) - py.test.raises(TypeError, ffi.string, ffi.cast("_Bool", 2)) - - def test_addressof(self): - p = ffi.new("struct ab *") - a = ffi.addressof(p[0]) - assert repr(a).startswith("<cdata 'struct ab *' 0x") - assert a == p - py.test.raises(TypeError, ffi.addressof, p) - py.test.raises((AttributeError, TypeError), ffi.addressof, 5) - py.test.raises(TypeError, ffi.addressof, ffi.cast("int", 5)) - - def test_addressof_field(self): - p = ffi.new("struct ab *") - b = ffi.addressof(p[0], 'b') - assert repr(b).startswith("<cdata 'int *' 0x") - assert int(ffi.cast("uintptr_t", b)) == ( - int(ffi.cast("uintptr_t", p)) + ffi.sizeof("int")) - assert b == ffi.addressof(p, 'b') - assert b != ffi.addressof(p, 'a') - - def test_addressof_field_nested(self): - # struct nesting { struct abc d, e; }; - p = ffi.new("struct nesting *") - py.test.raises(KeyError, ffi.addressof, p[0], 'e.b') - a = ffi.addressof(p[0], 'e', 'b') - assert int(ffi.cast("uintptr_t", a)) == ( - int(ffi.cast("uintptr_t", p)) + - ffi.sizeof("struct abc") + ffi.sizeof("int")) - - def test_addressof_anonymous_struct(self): - # typedef struct { int a; } anon_foo_t; - p = ffi.new("anon_foo_t *") - a = ffi.addressof(p[0]) - assert a == p - - def test_addressof_array(self): - p = ffi.new("int[52]") - p0 = ffi.addressof(p) - assert p0 == p - assert ffi.typeof(p0) is ffi.typeof("int(*)[52]") - py.test.raises(TypeError, ffi.addressof, p0) - # - p1 = ffi.addressof(p, 25) - assert ffi.typeof(p1) is ffi.typeof("int *") - assert (p1 - p) == 25 - assert ffi.addressof(p, 0) == p - - def test_addressof_pointer(self): - array = ffi.new("int[50]") - p = ffi.cast("int *", array) - py.test.raises(TypeError, ffi.addressof, p) - assert ffi.addressof(p, 0) == p - assert ffi.addressof(p, 25) == p + 25 - assert ffi.typeof(ffi.addressof(p, 25)) == ffi.typeof(p) - # - array = ffi.new("struct ab[50]") - p = ffi.cast("int *", array) - py.test.raises(TypeError, ffi.addressof, p) - assert ffi.addressof(p, 0) == p - assert ffi.addressof(p, 25) == p + 25 - assert ffi.typeof(ffi.addressof(p, 25)) == ffi.typeof(p) - - def test_addressof_array_in_struct(self): - # struct abc50 { int a, b; int c[50]; }; - p = ffi.new("struct abc50 *") - p1 = ffi.addressof(p, "c", 25) - assert ffi.typeof(p1) is ffi.typeof("int *") - assert p1 == ffi.cast("int *", p) + 27 - assert ffi.addressof(p, "c") == ffi.cast("int *", p) + 2 - assert ffi.addressof(p, "c", 0) == ffi.cast("int *", p) + 2 - p2 = ffi.addressof(p, 1) - assert ffi.typeof(p2) is ffi.typeof("struct abc50 *") - assert p2 == p + 1 - - def test_multiple_independent_structs(self): - CDEF2 = "struct ab { int x; };" - ffi2 = cffi.FFI(); ffi2.cdef(CDEF2) - outputfilename = recompile(ffi2, "test_multiple_independent_structs", - CDEF2, tmpdir=str(udir)) - module = imp.load_dynamic("test_multiple_independent_structs", - outputfilename) - ffi1 = module.ffi - foo1 = ffi1.new("struct ab *", [10]) - foo2 = ffi .new("struct ab *", [20, 30]) - assert foo1.x == 10 - assert foo2.a == 20 - assert foo2.b == 30 - - def test_include_struct_union_enum_typedef(self): - #py.test.xfail("ffi.include") - ffi1, CCODE = construction_params - ffi2 = cffi.FFI() - ffi2.include(ffi1) - outputfilename = recompile(ffi2, - "test_include_struct_union_enum_typedef", - CCODE, tmpdir=str(udir)) - module = imp.load_dynamic("test_include_struct_union_enum_typedef", - outputfilename) - ffi2 = module.ffi - # - p = ffi2.new("struct nonpacked *", [b'A', -43141]) - assert p.a == b'A' - assert p.b == -43141 - # - p = ffi.new("union simple_u *", [-52525]) - assert p.a == -52525 - # - p = ffi.cast("enum foq", 2) - assert ffi.string(p) == "CC0" - assert ffi2.sizeof("char[CC0]") == 2 - # - p = ffi.new("anon_foo_t *", [-52526]) - assert p.a == -52526 - p = ffi.new("named_foo_p", [-52527]) - assert p.a == -52527 - - def test_struct_packed(self): - # struct nonpacked { char a; int b; }; - # struct is_packed { char a; int b; } __attribute__((packed)); - assert ffi.sizeof("struct nonpacked") == 8 - assert ffi.sizeof("struct is_packed") == 5 - assert ffi.alignof("struct nonpacked") == 4 - assert ffi.alignof("struct is_packed") == 1 - s = ffi.new("struct is_packed[2]") - s[0].b = 42623381 - s[0].a = b'X' - s[1].b = -4892220 - s[1].a = b'Y' - assert s[0].b == 42623381 - assert s[0].a == b'X' - assert s[1].b == -4892220 - assert s[1].a == b'Y' - - def test_not_supported_bitfield_in_result(self): - # struct ints_and_bitfield { int a,b,c,d,e; int x:1; }; - e = py.test.raises(NotImplementedError, ffi.callback, - "struct ints_and_bitfield foo(void)", lambda: 42) - assert str(e.value) == ("struct ints_and_bitfield(*)(): " - "callback with unsupported argument or return type or with '...'") - - def test_inspecttype(self): - assert ffi.typeof("long").kind == "primitive" - assert ffi.typeof("long(*)(long, long**, ...)").cname == ( - "long(*)(long, long * *, ...)") - assert ffi.typeof("long(*)(long, long**, ...)").ellipsis is True - - def test_new_handle(self): - o = [2, 3, 4] - p = ffi.new_handle(o) - assert ffi.typeof(p) == ffi.typeof("void *") - assert ffi.from_handle(p) is o - assert ffi.from_handle(ffi.cast("char *", p)) is o - py.test.raises(RuntimeError, ffi.from_handle, ffi.NULL) - - def test_struct_array_no_length(self): - # struct array_no_length { int x; int a[]; }; - p = ffi.new("struct array_no_length *", [100, [200, 300, 400]]) - assert p.x == 100 - assert ffi.typeof(p.a) is ffi.typeof("int *") # no length available - assert p.a[0] == 200 - assert p.a[1] == 300 - assert p.a[2] == 400 - - def test_from_buffer(self): - import array - a = array.array('H', [10000, 20000, 30000]) - c = ffi.from_buffer(a) - assert ffi.typeof(c) is ffi.typeof("char[]") - ffi.cast("unsigned short *", c)[1] += 500 - assert list(a) == [10000, 20500, 30000] - - def test_all_primitives(self): - from .cffi_opcode import PRIMITIVE_TO_INDEX - assert set(PRIMITIVE_TO_INDEX) == set([ - "char", - "short", - "int", - "long", - "long long", - "signed char", - "unsigned char", - "unsigned short", - "unsigned int", - "unsigned long", - "unsigned long long", - "float", - "double", - "long double", - "wchar_t", - "_Bool", - "int8_t", - "uint8_t", - "int16_t", - "uint16_t", - "int32_t", - "uint32_t", - "int64_t", - "uint64_t", - "int_least8_t", - "uint_least8_t", - "int_least16_t", - "uint_least16_t", - "int_least32_t", - "uint_least32_t", - "int_least64_t", - "uint_least64_t", - "int_fast8_t", - "uint_fast8_t", - "int_fast16_t", - "uint_fast16_t", - "int_fast32_t", - "uint_fast32_t", - "int_fast64_t", - "uint_fast64_t", - "intptr_t", - "uintptr_t", - "intmax_t", - "uintmax_t", - "ptrdiff_t", - "size_t", - "ssize_t", - ]) - for name in PRIMITIVE_TO_INDEX: - x = ffi.sizeof(name) - assert 1 <= x <= 16 - - def test_emit_c_code(self): - ffi = cffi.FFI() - ffi.set_source("foobar", "??") - c_file = str(udir.join('test_emit_c_code')) - ffi.emit_c_code(c_file) - assert os.path.isfile(c_file) diff --git a/_cffi1/test_parse_c_type.py b/_cffi1/test_parse_c_type.py deleted file mode 100644 index 77537ed..0000000 --- a/_cffi1/test_parse_c_type.py +++ /dev/null @@ -1,339 +0,0 @@ -import sys, re, os, py -import cffi -from . import cffi_opcode - -local_dir = os.path.dirname(__file__) - -r_macro = re.compile(r"#define \w+[(][^\n]*|#include [^\n]*") -r_define = re.compile(r"(#define \w+) [^\n]*") -r_ifdefs = re.compile(r"(#ifdef |#endif)[^\n]*") -header = open(os.path.join(local_dir, 'parse_c_type.h')).read() -header = r_macro.sub(r"", header) -header = r_define.sub(r"\1 ...", header) -header = r_ifdefs.sub(r"", header) - -ffi = cffi.FFI() -ffi.cdef(header) - -lib = ffi.verify(open(os.path.join(local_dir, 'parse_c_type.c')).read(), - include_dirs=[local_dir]) - -class ParseError(Exception): - pass - -struct_names = ["bar_s", "foo", "foo_", "foo_s", "foo_s1", "foo_s12"] -assert struct_names == sorted(struct_names) - -enum_names = ["ebar_s", "efoo", "efoo_", "efoo_s", "efoo_s1", "efoo_s12"] -assert enum_names == sorted(enum_names) - -identifier_names = ["id", "id0", "id05", "id05b", "tail"] -assert identifier_names == sorted(identifier_names) - -global_names = ["FIVE", "NEG", "ZERO"] -assert global_names == sorted(global_names) - -ctx = ffi.new("struct _cffi_type_context_s *") -c_struct_names = [ffi.new("char[]", _n.encode('ascii')) for _n in struct_names] -ctx_structs = ffi.new("struct _cffi_struct_union_s[]", len(struct_names)) -for _i in range(len(struct_names)): - ctx_structs[_i].name = c_struct_names[_i] -ctx_structs[3].flags = lib._CFFI_F_UNION -ctx.struct_unions = ctx_structs -ctx.num_struct_unions = len(struct_names) - -c_enum_names = [ffi.new("char[]", _n.encode('ascii')) for _n in enum_names] -ctx_enums = ffi.new("struct _cffi_enum_s[]", len(enum_names)) -for _i in range(len(enum_names)): - ctx_enums[_i].name = c_enum_names[_i] -ctx.enums = ctx_enums -ctx.num_enums = len(enum_names) - -c_identifier_names = [ffi.new("char[]", _n.encode('ascii')) - for _n in identifier_names] -ctx_identifiers = ffi.new("struct _cffi_typename_s[]", len(identifier_names)) -for _i in range(len(identifier_names)): - ctx_identifiers[_i].name = c_identifier_names[_i] - ctx_identifiers[_i].type_index = 100 + _i -ctx.typenames = ctx_identifiers -ctx.num_typenames = len(identifier_names) - -@ffi.callback("int(unsigned long long *)") -def fetch_constant_five(p): - p[0] = 5 - return 0 -@ffi.callback("int(unsigned long long *)") -def fetch_constant_zero(p): - p[0] = 0 - return 1 -@ffi.callback("int(unsigned long long *)") -def fetch_constant_neg(p): - p[0] = 123321 - return 1 - -ctx_globals = ffi.new("struct _cffi_global_s[]", len(global_names)) -c_glob_names = [ffi.new("char[]", _n.encode('ascii')) for _n in global_names] -for _i, _fn in enumerate([fetch_constant_five, - fetch_constant_neg, - fetch_constant_zero]): - ctx_globals[_i].name = c_glob_names[_i] - ctx_globals[_i].address = _fn - ctx_globals[_i].type_op = ffi.cast("_cffi_opcode_t", - cffi_opcode.OP_CONSTANT_INT if _i != 1 - else cffi_opcode.OP_ENUM) -ctx.globals = ctx_globals -ctx.num_globals = len(global_names) - - -def parse(input): - out = ffi.new("_cffi_opcode_t[]", 100) - info = ffi.new("struct _cffi_parse_info_s *") - info.ctx = ctx - info.output = out - info.output_size = len(out) - for j in range(len(out)): - out[j] = ffi.cast("void *", -424242) - res = lib.parse_c_type(info, input.encode('ascii')) - if res < 0: - raise ParseError(ffi.string(info.error_message).decode('ascii'), - info.error_location) - assert 0 <= res < len(out) - result = [] - for j in range(len(out)): - if out[j] == ffi.cast("void *", -424242): - assert res < j - break - i = int(ffi.cast("intptr_t", out[j])) - if j == res: - result.append('->') - result.append(i) - return result - -def parsex(input): - result = parse(input) - def str_if_int(x): - if isinstance(x, str): - return x - return '%d,%d' % (x & 255, x >> 8) - return ' '.join(map(str_if_int, result)) - -def parse_error(input, expected_msg, expected_location): - e = py.test.raises(ParseError, parse, input) - assert e.value.args[0] == expected_msg - assert e.value.args[1] == expected_location - -def make_getter(name): - opcode = getattr(lib, '_CFFI_OP_' + name) - def getter(value): - return opcode | (value << 8) - return getter - -Prim = make_getter('PRIMITIVE') -Pointer = make_getter('POINTER') -Array = make_getter('ARRAY') -OpenArray = make_getter('OPEN_ARRAY') -NoOp = make_getter('NOOP') -Func = make_getter('FUNCTION') -FuncEnd = make_getter('FUNCTION_END') -Struct = make_getter('STRUCT_UNION') -Enum = make_getter('ENUM') -Typename = make_getter('TYPENAME') - - -def test_simple(): - for simple_type, expected in [ - ("int", lib._CFFI_PRIM_INT), - ("signed int", lib._CFFI_PRIM_INT), - (" long ", lib._CFFI_PRIM_LONG), - ("long int", lib._CFFI_PRIM_LONG), - ("unsigned short", lib._CFFI_PRIM_USHORT), - ("long double", lib._CFFI_PRIM_LONGDOUBLE), - ]: - assert parse(simple_type) == ['->', Prim(expected)] - -def test_array(): - assert parse("int[5]") == [Prim(lib._CFFI_PRIM_INT), '->', Array(0), 5] - assert parse("int[]") == [Prim(lib._CFFI_PRIM_INT), '->', OpenArray(0)] - assert parse("int[5][8]") == [Prim(lib._CFFI_PRIM_INT), - '->', Array(3), - 5, - Array(0), - 8] - assert parse("int[][8]") == [Prim(lib._CFFI_PRIM_INT), - '->', OpenArray(2), - Array(0), - 8] - -def test_pointer(): - assert parse("int*") == [Prim(lib._CFFI_PRIM_INT), '->', Pointer(0)] - assert parse("int***") == [Prim(lib._CFFI_PRIM_INT), - Pointer(0), Pointer(1), '->', Pointer(2)] - -def test_grouping(): - assert parse("int*[]") == [Prim(lib._CFFI_PRIM_INT), - Pointer(0), '->', OpenArray(1)] - assert parse("int**[][8]") == [Prim(lib._CFFI_PRIM_INT), - Pointer(0), Pointer(1), - '->', OpenArray(4), Array(2), 8] - assert parse("int(*)[]") == [Prim(lib._CFFI_PRIM_INT), - NoOp(3), '->', Pointer(1), OpenArray(0)] - assert parse("int(*)[][8]") == [Prim(lib._CFFI_PRIM_INT), - NoOp(3), '->', Pointer(1), - OpenArray(4), Array(0), 8] - assert parse("int**(**)") == [Prim(lib._CFFI_PRIM_INT), - Pointer(0), Pointer(1), - NoOp(2), Pointer(3), '->', Pointer(4)] - assert parse("int**(**)[]") == [Prim(lib._CFFI_PRIM_INT), - Pointer(0), Pointer(1), - NoOp(6), Pointer(3), '->', Pointer(4), - OpenArray(2)] - -def test_simple_function(): - assert parse("int()") == [Prim(lib._CFFI_PRIM_INT), - '->', Func(0), FuncEnd(0), 0] - assert parse("int(int)") == [Prim(lib._CFFI_PRIM_INT), - '->', Func(0), NoOp(4), FuncEnd(0), - Prim(lib._CFFI_PRIM_INT)] - assert parse("int(long, char)") == [ - Prim(lib._CFFI_PRIM_INT), - '->', Func(0), NoOp(5), NoOp(6), FuncEnd(0), - Prim(lib._CFFI_PRIM_LONG), - Prim(lib._CFFI_PRIM_CHAR)] - assert parse("int(int*)") == [Prim(lib._CFFI_PRIM_INT), - '->', Func(0), NoOp(5), FuncEnd(0), - Prim(lib._CFFI_PRIM_INT), - Pointer(4)] - assert parse("int*(void)") == [Prim(lib._CFFI_PRIM_INT), - Pointer(0), - '->', Func(1), FuncEnd(0), 0] - assert parse("int(int, ...)") == [Prim(lib._CFFI_PRIM_INT), - '->', Func(0), NoOp(5), FuncEnd(1), 0, - Prim(lib._CFFI_PRIM_INT)] - -def test_internal_function(): - assert parse("int(*)()") == [Prim(lib._CFFI_PRIM_INT), - NoOp(3), '->', Pointer(1), - Func(0), FuncEnd(0), 0] - assert parse("int(*())[]") == [Prim(lib._CFFI_PRIM_INT), - NoOp(6), Pointer(1), - '->', Func(2), FuncEnd(0), 0, - OpenArray(0)] - assert parse("int(char(*)(long, short))") == [ - Prim(lib._CFFI_PRIM_INT), - '->', Func(0), NoOp(6), FuncEnd(0), - Prim(lib._CFFI_PRIM_CHAR), - NoOp(7), Pointer(5), - Func(4), NoOp(11), NoOp(12), FuncEnd(0), - Prim(lib._CFFI_PRIM_LONG), - Prim(lib._CFFI_PRIM_SHORT)] - -def test_fix_arg_types(): - assert parse("int(char(long, short))") == [ - Prim(lib._CFFI_PRIM_INT), - '->', Func(0), Pointer(5), FuncEnd(0), - Prim(lib._CFFI_PRIM_CHAR), - Func(4), NoOp(9), NoOp(10), FuncEnd(0), - Prim(lib._CFFI_PRIM_LONG), - Prim(lib._CFFI_PRIM_SHORT)] - assert parse("int(char[])") == [ - Prim(lib._CFFI_PRIM_INT), - '->', Func(0), Pointer(4), FuncEnd(0), - Prim(lib._CFFI_PRIM_CHAR), - OpenArray(4)] - -def test_enum(): - for i in range(len(enum_names)): - assert parse("enum %s" % (enum_names[i],)) == ['->', Enum(i)] - assert parse("enum %s*" % (enum_names[i],)) == [Enum(i), - '->', Pointer(0)] - -def test_error(): - parse_error("short short int", "'short' after another 'short' or 'long'", 6) - parse_error("long long long", "'long long long' is too long", 10) - parse_error("short long", "'long' after 'short'", 6) - parse_error("signed unsigned int", "multiple 'signed' or 'unsigned'", 7) - parse_error("unsigned signed int", "multiple 'signed' or 'unsigned'", 9) - parse_error("long char", "invalid combination of types", 5) - parse_error("short char", "invalid combination of types", 6) - parse_error("signed void", "invalid combination of types", 7) - parse_error("unsigned struct", "invalid combination of types", 9) - # - parse_error("", "identifier expected", 0) - parse_error("]", "identifier expected", 0) - parse_error("*", "identifier expected", 0) - parse_error("int ]**", "unexpected symbol", 4) - parse_error("char char", "unexpected symbol", 5) - parse_error("int(int]", "expected ')'", 7) - parse_error("int(*]", "expected ')'", 5) - parse_error("int(]", "identifier expected", 4) - parse_error("int[?]", "expected a positive integer constant", 4) - parse_error("int[24)", "expected ']'", 6) - parse_error("struct", "struct or union name expected", 6) - parse_error("struct 24", "struct or union name expected", 7) - parse_error("int[5](*)", "unexpected symbol", 6) - parse_error("int a(*)", "identifier expected", 6) - parse_error("int[123456789012345678901234567890]", "number too large", 4) - -def test_number_too_large(): - num_max = sys.maxsize - assert parse("char[%d]" % num_max) == [Prim(lib._CFFI_PRIM_CHAR), - '->', Array(0), num_max] - parse_error("char[%d]" % (num_max + 1), "number too large", 5) - -def test_complexity_limit(): - parse_error("int" + "[]" * 2500, "internal type complexity limit reached", - 202) - -def test_struct(): - for i in range(len(struct_names)): - if i == 3: - tag = "union" - else: - tag = "struct" - assert parse("%s %s" % (tag, struct_names[i])) == ['->', Struct(i)] - assert parse("%s %s*" % (tag, struct_names[i])) == [Struct(i), - '->', Pointer(0)] - -def test_exchanging_struct_union(): - parse_error("union %s" % (struct_names[0],), - "wrong kind of tag: struct vs union", 6) - parse_error("struct %s" % (struct_names[3],), - "wrong kind of tag: struct vs union", 7) - -def test_identifier(): - for i in range(len(identifier_names)): - assert parse("%s" % (identifier_names[i])) == ['->', Typename(i)] - assert parse("%s*" % (identifier_names[i])) == [Typename(i), - '->', Pointer(0)] - -def test_cffi_opcode_sync(): - import cffi.model - for name in dir(lib): - if name.startswith('_CFFI_'): - assert getattr(cffi_opcode, name[6:]) == getattr(lib, name) - assert sorted(cffi_opcode.PRIMITIVE_TO_INDEX.keys()) == ( - sorted(cffi.model.PrimitiveType.ALL_PRIMITIVE_TYPES.keys())) - -def test_array_length_from_constant(): - parse_error("int[UNKNOWN]", "expected a positive integer constant", 4) - assert parse("int[FIVE]") == [Prim(lib._CFFI_PRIM_INT), '->', Array(0), 5] - assert parse("int[ZERO]") == [Prim(lib._CFFI_PRIM_INT), '->', Array(0), 0] - parse_error("int[NEG]", "expected a positive integer constant", 4) - -def test_various_constant_exprs(): - def array(n): - return [Prim(lib._CFFI_PRIM_CHAR), '->', Array(0), n] - assert parse("char[21]") == array(21) - assert parse("char[0x10]") == array(16) - assert parse("char[0X21]") == array(33) - assert parse("char[0Xb]") == array(11) - assert parse("char[0x1C]") == array(0x1C) - assert parse("char[0xc6]") == array(0xC6) - assert parse("char[010]") == array(8) - assert parse("char[021]") == array(17) - parse_error("char[08]", "invalid number", 5) - parse_error("char[1C]", "invalid number", 5) - parse_error("char[0C]", "invalid number", 5) - # not supported (really obscure): - # "char[+5]" - # "char['A']" diff --git a/_cffi1/test_realize_c_type.py b/_cffi1/test_realize_c_type.py deleted file mode 100644 index 784db5d..0000000 --- a/_cffi1/test_realize_c_type.py +++ /dev/null @@ -1,48 +0,0 @@ -import py - - -def check(input, expected_output=None, expected_ffi_error=False): - import _cffi_backend - ffi = _cffi_backend.FFI() - if not expected_ffi_error: - ct = ffi.typeof(input) - assert isinstance(ct, ffi.CType) - assert ct.cname == (expected_output or input) - else: - e = py.test.raises(ffi.error, ffi.typeof, input) - if isinstance(expected_ffi_error, str): - assert str(e.value) == expected_ffi_error - -def test_void(): - check("void", "void") - check(" void ", "void") - -def test_int_star(): - check("int") - check("int *") - check("int*", "int *") - check("long int", "long") - check("long") - -def test_noop(): - check("int(*)", "int *") - -def test_array(): - check("int[6]") - -def test_funcptr(): - check("int(*)(long)") - check("int(long)", expected_ffi_error="the type 'int(long)' is a" - " function type, not a pointer-to-function type") - check("int(void)", expected_ffi_error="the type 'int()' is a" - " function type, not a pointer-to-function type") - -def test_funcptr_rewrite_args(): - check("int(*)(int(int))", "int(*)(int(*)(int))") - check("int(*)(long[])", "int(*)(long *)") - check("int(*)(long[5])", "int(*)(long *)") - -def test_all_primitives(): - from . import cffi_opcode - for name in cffi_opcode.PRIMITIVE_TO_INDEX: - check(name, name) diff --git a/_cffi1/test_recompiler.py b/_cffi1/test_recompiler.py deleted file mode 100644 index 6241d7e..0000000 --- a/_cffi1/test_recompiler.py +++ /dev/null @@ -1,745 +0,0 @@ -import sys, os, py -from cffi import FFI, VerificationError -from _cffi1 import recompiler -from _cffi1.udir import udir -from _cffi1.support import u - - -def check_type_table(input, expected_output, included=None): - ffi = FFI() - if included: - ffi1 = FFI() - ffi1.cdef(included) - ffi.include(ffi1) - ffi.cdef(input) - recomp = recompiler.Recompiler(ffi, 'testmod') - recomp.collect_type_table() - assert ''.join(map(str, recomp.cffi_types)) == expected_output - -def verify(ffi, module_name, *args, **kwds): - kwds.setdefault('undef_macros', ['NDEBUG']) - return recompiler.verify(ffi, '_CFFI_' + module_name, *args, **kwds) - - -def test_type_table_func(): - check_type_table("double sin(double);", - "(FUNCTION 1)(PRIMITIVE 14)(FUNCTION_END 0)") - check_type_table("float sin(double);", - "(FUNCTION 3)(PRIMITIVE 14)(FUNCTION_END 0)(PRIMITIVE 13)") - check_type_table("float sin(void);", - "(FUNCTION 2)(FUNCTION_END 0)(PRIMITIVE 13)") - check_type_table("double sin(float); double cos(float);", - "(FUNCTION 3)(PRIMITIVE 13)(FUNCTION_END 0)(PRIMITIVE 14)") - check_type_table("double sin(float); double cos(double);", - "(FUNCTION 1)(PRIMITIVE 14)(FUNCTION_END 0)" # cos - "(FUNCTION 1)(PRIMITIVE 13)(FUNCTION_END 0)") # sin - check_type_table("float sin(double); float cos(float);", - "(FUNCTION 4)(PRIMITIVE 14)(FUNCTION_END 0)" # sin - "(FUNCTION 4)(PRIMITIVE 13)(FUNCTION_END 0)") # cos - -def test_type_table_use_noop_for_repeated_args(): - check_type_table("double sin(double *, double *);", - "(FUNCTION 4)(POINTER 4)(NOOP 1)(FUNCTION_END 0)" - "(PRIMITIVE 14)") - check_type_table("double sin(double *, double *, double);", - "(FUNCTION 3)(POINTER 3)(NOOP 1)(PRIMITIVE 14)" - "(FUNCTION_END 0)") - -def test_type_table_dont_use_noop_for_primitives(): - check_type_table("double sin(double, double);", - "(FUNCTION 1)(PRIMITIVE 14)(PRIMITIVE 14)(FUNCTION_END 0)") - -def test_type_table_funcptr_as_argument(): - check_type_table("int sin(double(float));", - "(FUNCTION 6)(PRIMITIVE 13)(FUNCTION_END 0)" - "(FUNCTION 7)(POINTER 0)(FUNCTION_END 0)" - "(PRIMITIVE 14)(PRIMITIVE 7)") - -def test_type_table_variadic_function(): - check_type_table("int sin(int, ...);", - "(FUNCTION 1)(PRIMITIVE 7)(FUNCTION_END 1)(POINTER 0)") - -def test_type_table_array(): - check_type_table("int a[100];", - "(PRIMITIVE 7)(ARRAY 0)(None 100)") - -def test_type_table_typedef(): - check_type_table("typedef int foo_t;", - "(PRIMITIVE 7)") - -def test_type_table_prebuilt_type(): - check_type_table("int32_t f(void);", - "(FUNCTION 2)(FUNCTION_END 0)(PRIMITIVE 21)") - -def test_type_table_struct_opaque(): - check_type_table("struct foo_s;", - "(STRUCT_UNION 0)") - -def test_type_table_struct(): - check_type_table("struct foo_s { int a; long b; };", - "(PRIMITIVE 7)(PRIMITIVE 9)(STRUCT_UNION 0)") - -def test_type_table_union(): - check_type_table("union foo_u { int a; long b; };", - "(PRIMITIVE 7)(PRIMITIVE 9)(STRUCT_UNION 0)") - -def test_type_table_struct_used(): - check_type_table("struct foo_s { int a; long b; }; int f(struct foo_s*);", - "(FUNCTION 3)(POINTER 5)(FUNCTION_END 0)" - "(PRIMITIVE 7)(PRIMITIVE 9)" - "(STRUCT_UNION 0)") - -def test_type_table_anonymous_struct_with_typedef(): - check_type_table("typedef struct { int a; long b; } foo_t;", - "(STRUCT_UNION 0)(PRIMITIVE 7)(PRIMITIVE 9)") - -def test_type_table_enum(): - check_type_table("enum foo_e { AA, BB, ... };", - "(ENUM 0)") - -def test_type_table_include_1(): - check_type_table("foo_t sin(foo_t);", - "(FUNCTION 1)(PRIMITIVE 14)(FUNCTION_END 0)", - included="typedef double foo_t;") - -def test_type_table_include_2(): - check_type_table("struct foo_s *sin(struct foo_s *);", - "(FUNCTION 1)(POINTER 3)(FUNCTION_END 0)(STRUCT_UNION 0)", - included="struct foo_s { int x, y; };") - - -def test_math_sin(): - import math - ffi = FFI() - ffi.cdef("float sin(double); double cos(double);") - lib = verify(ffi, 'test_math_sin', '#include <math.h>') - assert lib.cos(1.43) == math.cos(1.43) - -def test_repr_lib(): - ffi = FFI() - lib = verify(ffi, 'test_repr_lib', '') - assert repr(lib) == "<Lib object for '_CFFI_test_repr_lib'>" - -def test_funcarg_ptr(): - ffi = FFI() - ffi.cdef("int foo(int *);") - lib = verify(ffi, 'test_funcarg_ptr', 'int foo(int *p) { return *p; }') - assert lib.foo([-12345]) == -12345 - -def test_funcres_ptr(): - ffi = FFI() - ffi.cdef("int *foo(void);") - lib = verify(ffi, 'test_funcres_ptr', - 'int *foo(void) { static int x=-12345; return &x; }') - assert lib.foo()[0] == -12345 - -def test_global_var_array(): - ffi = FFI() - ffi.cdef("int a[100];") - lib = verify(ffi, 'test_global_var_array', 'int a[100] = { 9999 };') - lib.a[42] = 123456 - assert lib.a[42] == 123456 - assert lib.a[0] == 9999 - -def test_verify_typedef(): - ffi = FFI() - ffi.cdef("typedef int **foo_t;") - lib = verify(ffi, 'test_verify_typedef', 'typedef int **foo_t;') - assert ffi.sizeof("foo_t") == ffi.sizeof("void *") - -def test_verify_typedef_dotdotdot(): - ffi = FFI() - ffi.cdef("typedef ... foo_t;") - verify(ffi, 'test_verify_typedef_dotdotdot', 'typedef int **foo_t;') - -def test_verify_typedef_star_dotdotdot(): - ffi = FFI() - ffi.cdef("typedef ... *foo_t;") - verify(ffi, 'test_verify_typedef_star_dotdotdot', 'typedef int **foo_t;') - -def test_global_var_int(): - ffi = FFI() - ffi.cdef("int a, b, c;") - lib = verify(ffi, 'test_global_var_int', 'int a = 999, b, c;') - assert lib.a == 999 - lib.a -= 1001 - assert lib.a == -2 - lib.a = -2147483648 - assert lib.a == -2147483648 - py.test.raises(OverflowError, "lib.a = 2147483648") - py.test.raises(OverflowError, "lib.a = -2147483649") - lib.b = 525 # try with the first access being in setattr, too - assert lib.b == 525 - py.test.raises(AttributeError, "del lib.a") - py.test.raises(AttributeError, "del lib.c") - py.test.raises(AttributeError, "del lib.foobarbaz") - -def test_macro(): - ffi = FFI() - ffi.cdef("#define FOOBAR ...") - lib = verify(ffi, 'test_macro', "#define FOOBAR (-6912)") - assert lib.FOOBAR == -6912 - py.test.raises(AttributeError, "lib.FOOBAR = 2") - -def test_macro_check_value(): - # the value '-0x80000000' in C sources does not have a clear meaning - # to me; it appears to have a different effect than '-2147483648'... - # Moreover, on 32-bits, -2147483648 is actually equal to - # -2147483648U, which in turn is equal to 2147483648U and so positive. - vals = ['42', '-42', '0x80000000', '-2147483648', - '0', '9223372036854775809ULL', - '-9223372036854775807LL'] - if sys.maxsize <= 2**32: - vals.remove('-2147483648') - ffi = FFI() - cdef_lines = ['#define FOO_%d_%d %s' % (i, j, vals[i]) - for i in range(len(vals)) - for j in range(len(vals))] - ffi.cdef('\n'.join(cdef_lines)) - - verify_lines = ['#define FOO_%d_%d %s' % (i, j, vals[j]) # [j], not [i] - for i in range(len(vals)) - for j in range(len(vals))] - lib = verify(ffi, 'test_macro_check_value_ok', - '\n'.join(verify_lines)) - # - for j in range(len(vals)): - c_got = int(vals[j].replace('U', '').replace('L', ''), 0) - c_compiler_msg = str(c_got) - if c_got > 0: - c_compiler_msg += ' (0x%x)' % (c_got,) - # - for i in range(len(vals)): - attrname = 'FOO_%d_%d' % (i, j) - if i == j: - x = getattr(lib, attrname) - assert x == c_got - else: - e = py.test.raises(ffi.error, getattr, lib, attrname) - assert str(e.value) == ( - "the C compiler says '%s' is equal to " - "%s, but the cdef disagrees" % (attrname, c_compiler_msg)) - -def test_constant(): - ffi = FFI() - ffi.cdef("static const int FOOBAR;") - lib = verify(ffi, 'test_constant', "#define FOOBAR (-6912)") - assert lib.FOOBAR == -6912 - py.test.raises(AttributeError, "lib.FOOBAR = 2") - -def test_constant_nonint(): - ffi = FFI() - ffi.cdef("static const double FOOBAR;") - lib = verify(ffi, 'test_constant_nonint', "#define FOOBAR (-6912.5)") - assert lib.FOOBAR == -6912.5 - py.test.raises(AttributeError, "lib.FOOBAR = 2") - -def test_constant_ptr(): - ffi = FFI() - ffi.cdef("static double *const FOOBAR;") - lib = verify(ffi, 'test_constant_ptr', "#define FOOBAR NULL") - assert lib.FOOBAR == ffi.NULL - assert ffi.typeof(lib.FOOBAR) == ffi.typeof("double *") - -def test_dir(): - ffi = FFI() - ffi.cdef("int ff(int); int aa; static const int my_constant;") - lib = verify(ffi, 'test_dir', """ - #define my_constant (-45) - int aa; - int ff(int x) { return x+aa; } - """) - lib.aa = 5 - assert dir(lib) == ['aa', 'ff', 'my_constant'] - -def test_verify_opaque_struct(): - ffi = FFI() - ffi.cdef("struct foo_s;") - lib = verify(ffi, 'test_verify_opaque_struct', "struct foo_s;") - assert ffi.typeof("struct foo_s").cname == "struct foo_s" - -def test_verify_opaque_union(): - ffi = FFI() - ffi.cdef("union foo_s;") - lib = verify(ffi, 'test_verify_opaque_union', "union foo_s;") - assert ffi.typeof("union foo_s").cname == "union foo_s" - -def test_verify_struct(): - ffi = FFI() - ffi.cdef("""struct foo_s { int b; short a; ...; }; - struct bar_s { struct foo_s *f; };""") - lib = verify(ffi, 'test_verify_struct', - """struct foo_s { short a; int b; }; - struct bar_s { struct foo_s *f; };""") - ffi.typeof("struct bar_s *") - p = ffi.new("struct foo_s *", {'a': -32768, 'b': -2147483648}) - assert p.a == -32768 - assert p.b == -2147483648 - py.test.raises(OverflowError, "p.a -= 1") - py.test.raises(OverflowError, "p.b -= 1") - q = ffi.new("struct bar_s *", {'f': p}) - assert q.f == p - # - assert ffi.offsetof("struct foo_s", "a") == 0 - assert ffi.offsetof("struct foo_s", "b") == 4 - assert ffi.offsetof(u+"struct foo_s", u+"b") == 4 - # - py.test.raises(TypeError, ffi.addressof, p) - assert ffi.addressof(p[0]) == p - assert ffi.typeof(ffi.addressof(p[0])) is ffi.typeof("struct foo_s *") - assert ffi.typeof(ffi.addressof(p, "b")) is ffi.typeof("int *") - assert ffi.addressof(p, "b")[0] == p.b - -def test_verify_exact_field_offset(): - ffi = FFI() - ffi.cdef("""struct foo_s { int b; short a; };""") - lib = verify(ffi, 'test_verify_exact_field_offset', - """struct foo_s { short a; int b; };""") - e = py.test.raises(ffi.error, ffi.new, "struct foo_s *", []) # lazily - assert str(e.value) == ("struct foo_s: wrong offset for field 'b' (cdef " - 'says 0, but C compiler says 4). fix it or use "...;" ' - "in the cdef for struct foo_s to make it flexible") - -def test_type_caching(): - ffi1 = FFI(); ffi1.cdef("struct foo_s;") - ffi2 = FFI(); ffi2.cdef("struct foo_s;") # different one! - lib1 = verify(ffi1, 'test_type_caching_1', 'struct foo_s;') - lib2 = verify(ffi2, 'test_type_caching_2', 'struct foo_s;') - # shared types - assert ffi1.typeof("long") is ffi2.typeof("long") - assert ffi1.typeof("long**") is ffi2.typeof("long * *") - assert ffi1.typeof("long(*)(int, ...)") is ffi2.typeof("long(*)(int, ...)") - # non-shared types - assert ffi1.typeof("struct foo_s") is not ffi2.typeof("struct foo_s") - assert ffi1.typeof("struct foo_s *") is not ffi2.typeof("struct foo_s *") - assert ffi1.typeof("struct foo_s*(*)()") is not ( - ffi2.typeof("struct foo_s*(*)()")) - assert ffi1.typeof("void(*)(struct foo_s*)") is not ( - ffi2.typeof("void(*)(struct foo_s*)")) - -def test_verify_enum(): - ffi = FFI() - ffi.cdef("""enum e1 { B1, A1, ... }; enum e2 { B2, A2, ... };""") - lib = verify(ffi, 'test_verify_enum', - "enum e1 { A1, B1, C1=%d };" % sys.maxsize + - "enum e2 { A2, B2, C2 };") - ffi.typeof("enum e1") - ffi.typeof("enum e2") - assert lib.A1 == 0 - assert lib.B1 == 1 - assert lib.A2 == 0 - assert lib.B2 == 1 - assert ffi.sizeof("enum e1") == ffi.sizeof("long") - assert ffi.sizeof("enum e2") == ffi.sizeof("int") - assert repr(ffi.cast("enum e1", 0)) == "<cdata 'enum e1' 0: A1>" - -def test_duplicate_enum(): - ffi = FFI() - ffi.cdef("enum e1 { A1, ... }; enum e2 { A1, ... };") - py.test.raises(VerificationError, verify, ffi, 'test_duplicate_enum', - "enum e1 { A1 }; enum e2 { B1 };") - -def test_dotdotdot_length_of_array_field(): - ffi = FFI() - ffi.cdef("struct foo_s { int a[...]; int b[...]; };") - verify(ffi, 'test_dotdotdot_length_of_array_field', - "struct foo_s { int a[42]; int b[11]; };") - assert ffi.sizeof("struct foo_s") == (42 + 11) * 4 - p = ffi.new("struct foo_s *") - assert p.a[41] == p.b[10] == 0 - py.test.raises(IndexError, "p.a[42]") - py.test.raises(IndexError, "p.b[11]") - -def test_dotdotdot_global_array(): - ffi = FFI() - ffi.cdef("int aa[...]; int bb[...];") - lib = verify(ffi, 'test_dotdotdot_global_array', - "int aa[41]; int bb[12];") - assert ffi.sizeof(lib.aa) == 41 * 4 - assert ffi.sizeof(lib.bb) == 12 * 4 - assert lib.aa[40] == lib.bb[11] == 0 - py.test.raises(IndexError, "lib.aa[41]") - py.test.raises(IndexError, "lib.bb[12]") - -def test_misdeclared_field_1(): - ffi = FFI() - ffi.cdef("struct foo_s { int a[5]; };") - verify(ffi, 'test_misdeclared_field_1', - "struct foo_s { int a[6]; };") - assert ffi.sizeof("struct foo_s") == 24 # found by the actual C code - p = ffi.new("struct foo_s *") - # lazily build the fields and boom: - e = py.test.raises(ffi.error, "p.a") - assert str(e.value).startswith("struct foo_s: wrong size for field 'a' " - "(cdef says 20, but C compiler says 24)") - -def test_open_array_in_struct(): - ffi = FFI() - ffi.cdef("struct foo_s { int b; int a[]; };") - verify(ffi, 'test_open_array_in_struct', - "struct foo_s { int b; int a[]; };") - assert ffi.sizeof("struct foo_s") == 4 - p = ffi.new("struct foo_s *", [5, [10, 20, 30]]) - assert p.a[2] == 30 - -def test_math_sin_type(): - ffi = FFI() - ffi.cdef("double sin(double);") - lib = verify(ffi, 'test_math_sin_type', '#include <math.h>') - # 'lib.sin' is typed as a <built-in method> object on lib - assert ffi.typeof(lib.sin).cname == "double(*)(double)" - # 'x' is another <built-in method> object on lib, made very indirectly - x = type(lib).__dir__.__get__(lib) - py.test.raises(TypeError, ffi.typeof, x) - -def test_verify_anonymous_struct_with_typedef(): - ffi = FFI() - ffi.cdef("typedef struct { int a; long b; ...; } foo_t;") - verify(ffi, 'test_verify_anonymous_struct_with_typedef', - "typedef struct { long b; int hidden, a; } foo_t;") - p = ffi.new("foo_t *", {'b': 42}) - assert p.b == 42 - assert repr(p).startswith("<cdata 'foo_t *' ") - -def test_verify_anonymous_struct_with_star_typedef(): - ffi = FFI() - ffi.cdef("typedef struct { int a; long b; } *foo_t;") - verify(ffi, 'test_verify_anonymous_struct_with_star_typedef', - "typedef struct { int a; long b; } *foo_t;") - p = ffi.new("foo_t", {'b': 42}) - assert p.b == 42 - -def test_verify_anonymous_enum_with_typedef(): - ffi = FFI() - ffi.cdef("typedef enum { AA, ... } e1;") - lib = verify(ffi, 'test_verify_anonymous_enum_with_typedef1', - "typedef enum { BB, CC, AA } e1;") - assert lib.AA == 2 - assert ffi.sizeof("e1") == ffi.sizeof("int") - assert repr(ffi.cast("e1", 2)) == "<cdata 'e1' 2: AA>" - # - ffi = FFI() - ffi.cdef("typedef enum { AA=%d } e1;" % sys.maxsize) - lib = verify(ffi, 'test_verify_anonymous_enum_with_typedef2', - "typedef enum { AA=%d } e1;" % sys.maxsize) - assert lib.AA == sys.maxsize - assert ffi.sizeof("e1") == ffi.sizeof("long") - -def test_unique_types(): - CDEF = "struct foo_s; union foo_u; enum foo_e { AA };" - ffi1 = FFI(); ffi1.cdef(CDEF); verify(ffi1, "test_unique_types_1", CDEF) - ffi2 = FFI(); ffi2.cdef(CDEF); verify(ffi2, "test_unique_types_2", CDEF) - # - assert ffi1.typeof("char") is ffi2.typeof("char ") - assert ffi1.typeof("long") is ffi2.typeof("signed long int") - assert ffi1.typeof("double *") is ffi2.typeof("double*") - assert ffi1.typeof("int ***") is ffi2.typeof(" int * * *") - assert ffi1.typeof("int[]") is ffi2.typeof("signed int[]") - assert ffi1.typeof("signed int*[17]") is ffi2.typeof("int *[17]") - assert ffi1.typeof("void") is ffi2.typeof("void") - assert ffi1.typeof("int(*)(int,int)") is ffi2.typeof("int(*)(int,int)") - # - # these depend on user-defined data, so should not be shared - for name in ["struct foo_s", - "union foo_u *", - "enum foo_e", - "struct foo_s *(*)()", - "void(*)(struct foo_s *)", - "struct foo_s *(*[5])[8]", - ]: - assert ffi1.typeof(name) is not ffi2.typeof(name) - # sanity check: twice 'ffi1' - assert ffi1.typeof("struct foo_s*") is ffi1.typeof("struct foo_s *") - -def test_module_name_in_package(): - ffi = FFI() - ffi.cdef("int foo(int);") - recompiler.recompile(ffi, "test_module_name_in_package.mymod", - "int foo(int x) { return x + 32; }", - tmpdir=str(udir)) - old_sys_path = sys.path[:] - try: - package_dir = udir.join('test_module_name_in_package') - assert os.path.isdir(str(package_dir)) - assert len(os.listdir(str(package_dir))) > 0 - package_dir.join('__init__.py').write('') - # - sys.path.insert(0, str(udir)) - import test_module_name_in_package.mymod - assert test_module_name_in_package.mymod.lib.foo(10) == 42 - assert test_module_name_in_package.mymod.__name__ == ( - 'test_module_name_in_package.mymod') - finally: - sys.path[:] = old_sys_path - -def test_bad_size_of_global_1(): - ffi = FFI() - ffi.cdef("short glob;") - lib = verify(ffi, "test_bad_size_of_global_1", "long glob;") - py.test.raises(ffi.error, "lib.glob") - -def test_bad_size_of_global_2(): - ffi = FFI() - ffi.cdef("int glob[10];") - lib = verify(ffi, "test_bad_size_of_global_2", "int glob[9];") - e = py.test.raises(ffi.error, "lib.glob") - assert str(e.value) == ("global variable 'glob' should be 40 bytes " - "according to the cdef, but is actually 36") - -def test_unspecified_size_of_global(): - ffi = FFI() - ffi.cdef("int glob[];") - lib = verify(ffi, "test_unspecified_size_of_global", "int glob[10];") - lib.glob # does not crash - -def test_include_1(): - ffi1 = FFI() - ffi1.cdef("typedef double foo_t;") - verify(ffi1, "test_include_1_parent", "typedef double foo_t;") - ffi = FFI() - ffi.include(ffi1) - ffi.cdef("foo_t ff1(foo_t);") - lib = verify(ffi, "test_include_1", "double ff1(double x) { return 42.5; }") - assert lib.ff1(0) == 42.5 - assert ffi1.typeof("foo_t") is ffi.typeof("foo_t") is ffi.typeof("double") - -def test_include_1b(): - ffi1 = FFI() - ffi1.cdef("int foo1(int);") - lib1 = verify(ffi1, "test_include_1b_parent", - "int foo1(int x) { return x + 10; }") - ffi = FFI() - ffi.include(ffi1) - ffi.cdef("int foo2(int);") - lib = verify(ffi, "test_include_1b", "int foo2(int x) { return x - 5; }") - assert lib.foo2(42) == 37 - assert lib.foo1(42) == 52 - assert lib.foo1 is lib1.foo1 - -def test_include_2(): - ffi1 = FFI() - ffi1.cdef("struct foo_s { int x, y; };") - verify(ffi1, "test_include_2_parent", "struct foo_s { int x, y; };") - ffi = FFI() - ffi.include(ffi1) - ffi.cdef("struct foo_s *ff2(struct foo_s *);") - lib = verify(ffi, "test_include_2", - "struct foo_s { int x, y; }; //usually from a #include\n" - "struct foo_s *ff2(struct foo_s *p) { p->y++; return p; }") - p = ffi.new("struct foo_s *") - p.y = 41 - q = lib.ff2(p) - assert q == p - assert p.y == 42 - assert ffi1.typeof("struct foo_s") is ffi.typeof("struct foo_s") - -def test_include_3(): - ffi1 = FFI() - ffi1.cdef("typedef short sshort_t;") - verify(ffi1, "test_include_3_parent", "typedef short sshort_t;") - ffi = FFI() - ffi.include(ffi1) - ffi.cdef("sshort_t ff3(sshort_t);") - lib = verify(ffi, "test_include_3", - "typedef short sshort_t; //usually from a #include\n" - "sshort_t ff3(sshort_t x) { return x + 42; }") - assert lib.ff3(10) == 52 - assert ffi.typeof(ffi.cast("sshort_t", 42)) is ffi.typeof("short") - assert ffi1.typeof("sshort_t") is ffi.typeof("sshort_t") - -def test_include_4(): - ffi1 = FFI() - ffi1.cdef("typedef struct { int x; } mystruct_t;") - verify(ffi1, "test_include_4_parent", - "typedef struct { int x; } mystruct_t;") - ffi = FFI() - ffi.include(ffi1) - ffi.cdef("mystruct_t *ff4(mystruct_t *);") - lib = verify(ffi, "test_include_4", - "typedef struct {int x; } mystruct_t; //usually from a #include\n" - "mystruct_t *ff4(mystruct_t *p) { p->x += 42; return p; }") - p = ffi.new("mystruct_t *", [10]) - q = lib.ff4(p) - assert q == p - assert p.x == 52 - assert ffi1.typeof("mystruct_t") is ffi.typeof("mystruct_t") - -def test_include_5(): - ffi1 = FFI() - ffi1.cdef("typedef struct { int x[2]; int y; } *mystruct_p;") - verify(ffi1, "test_include_5_parent", - "typedef struct { int x[2]; int y; } *mystruct_p;") - ffi = FFI() - ffi.include(ffi1) - ffi.cdef("mystruct_p ff5(mystruct_p);") - lib = verify(ffi, "test_include_5", - "typedef struct {int x[2]; int y; } *mystruct_p; //usually #include\n" - "mystruct_p ff5(mystruct_p p) { p->x[1] += 42; return p; }") - assert ffi.alignof(ffi.typeof("mystruct_p").item) == 4 - assert ffi1.typeof("mystruct_p") is ffi.typeof("mystruct_p") - p = ffi.new("mystruct_p", [[5, 10], -17]) - q = lib.ff5(p) - assert q == p - assert p.x[0] == 5 - assert p.x[1] == 52 - assert p.y == -17 - assert ffi.alignof(ffi.typeof(p[0])) == 4 - -def test_include_6(): - ffi1 = FFI() - ffi1.cdef("typedef ... mystruct_t;") - verify(ffi1, "test_include_6_parent", - "typedef struct _mystruct_s mystruct_t;") - ffi = FFI() - ffi.include(ffi1) - ffi.cdef("mystruct_t *ff6(void); int ff6b(mystruct_t *);") - lib = verify(ffi, "test_include_6", - "typedef struct _mystruct_s mystruct_t; //usually from a #include\n" - "struct _mystruct_s { int x; };\n" - "static mystruct_t result_struct = { 42 };\n" - "mystruct_t *ff6(void) { return &result_struct; }\n" - "int ff6b(mystruct_t *p) { return p->x; }") - p = lib.ff6() - assert ffi.cast("int *", p)[0] == 42 - assert lib.ff6b(p) == 42 - -def test_include_7(): - ffi1 = FFI() - ffi1.cdef("typedef ... mystruct_t;\n" - "int ff7b(mystruct_t *);") - verify(ffi1, "test_include_7_parent", - "typedef struct { int x; } mystruct_t;\n" - "int ff7b(mystruct_t *p) { return p->x; }") - ffi = FFI() - ffi.include(ffi1) - ffi.cdef("mystruct_t *ff7(void);") - lib = verify(ffi, "test_include_7", - "typedef struct { int x; } mystruct_t; //usually from a #include\n" - "static mystruct_t result_struct = { 42 };" - "mystruct_t *ff7(void) { return &result_struct; }") - p = lib.ff7() - assert ffi.cast("int *", p)[0] == 42 - assert lib.ff7b(p) == 42 - -def test_include_8(): - ffi1 = FFI() - ffi1.cdef("struct foo_s;") - verify(ffi1, "test_include_8_parent", "struct foo_s;") - ffi = FFI() - ffi.include(ffi1) - ffi.cdef("struct foo_s { int x, y; };") - verify(ffi, "test_include_8", "struct foo_s { int x, y; };") - e = py.test.raises(NotImplementedError, ffi.new, "struct foo_s *") - assert str(e.value) == ( - "'struct foo_s' is opaque in the ffi.include(), but no longer in " - "the ffi doing the include (workaround: don't use ffi.include() but" - " duplicate the declarations of everything using struct foo_s)") - -def test_unicode_libraries(): - try: - unicode - except NameError: - py.test.skip("for python 2.x") - # - import math - lib_m = "m" - if sys.platform == 'win32': - #there is a small chance this fails on Mingw via environ $CC - import distutils.ccompiler - if distutils.ccompiler.get_default_compiler() == 'msvc': - lib_m = 'msvcrt' - ffi = FFI() - ffi.cdef(unicode("float sin(double); double cos(double);")) - lib = verify(ffi, 'test_math_sin_unicode', unicode('#include <math.h>'), - libraries=[unicode(lib_m)]) - assert lib.cos(1.43) == math.cos(1.43) - -def test_incomplete_struct_as_arg(): - ffi = FFI() - ffi.cdef("struct foo_s { int x; ...; }; int f(int, struct foo_s);") - lib = verify(ffi, "test_incomplete_struct_as_arg", - "struct foo_s { int a, x, z; };\n" - "int f(int b, struct foo_s s) { return s.x * b; }") - s = ffi.new("struct foo_s *", [21]) - assert s.x == 21 - assert ffi.sizeof(s[0]) == 12 - assert ffi.offsetof(ffi.typeof(s), 'x') == 4 - assert lib.f(2, s[0]) == 42 - assert ffi.typeof(lib.f) == ffi.typeof("int(*)(int, struct foo_s)") - -def test_incomplete_struct_as_result(): - ffi = FFI() - ffi.cdef("struct foo_s { int x; ...; }; struct foo_s f(int);") - lib = verify(ffi, "test_incomplete_struct_as_result", - "struct foo_s { int a, x, z; };\n" - "struct foo_s f(int x) { struct foo_s r; r.x = x * 2; return r; }") - s = lib.f(21) - assert s.x == 42 - assert ffi.typeof(lib.f) == ffi.typeof("struct foo_s(*)(int)") - -def test_incomplete_struct_as_both(): - ffi = FFI() - ffi.cdef("struct foo_s { int x; ...; }; struct bar_s { int y; ...; };\n" - "struct foo_s f(int, struct bar_s);") - lib = verify(ffi, "test_incomplete_struct_as_both", - "struct foo_s { int a, x, z; };\n" - "struct bar_s { int b, c, y, d; };\n" - "struct foo_s f(int x, struct bar_s b) {\n" - " struct foo_s r; r.x = x * b.y; return r;\n" - "}") - b = ffi.new("struct bar_s *", [7]) - s = lib.f(6, b[0]) - assert s.x == 42 - assert ffi.typeof(lib.f) == ffi.typeof( - "struct foo_s(*)(int, struct bar_s)") - s = lib.f(14, {'y': -3}) - assert s.x == -42 - -def test_name_of_unnamed_struct(): - ffi = FFI() - ffi.cdef("typedef struct { int x; } foo_t;\n" - "typedef struct { int y; } *bar_p;\n" - "typedef struct { int y; } **baz_pp;\n") - verify(ffi, "test_name_of_unnamed_struct", - "typedef struct { int x; } foo_t;\n" - "typedef struct { int y; } *bar_p;\n" - "typedef struct { int y; } **baz_pp;\n") - assert repr(ffi.typeof("foo_t")) == "<ctype 'foo_t'>" - assert repr(ffi.typeof("bar_p")) == "<ctype 'struct $1 *'>" - assert repr(ffi.typeof("baz_pp")) == "<ctype 'struct $2 * *'>" - -def test_address_of_global_var(): - ffi = FFI() - ffi.cdef(""" - long bottom, bottoms[2]; - long FetchRectBottom(void); - long FetchRectBottoms1(void); - #define FOOBAR 42 - """) - lib = verify(ffi, "test_address_of_global_var", """ - long bottom, bottoms[2]; - long FetchRectBottom(void) { return bottom; } - long FetchRectBottoms1(void) { return bottoms[1]; } - #define FOOBAR 42 - """) - lib.bottom = 300 - assert lib.FetchRectBottom() == 300 - lib.bottom += 1 - assert lib.FetchRectBottom() == 301 - lib.bottoms[1] = 500 - assert lib.FetchRectBottoms1() == 500 - lib.bottoms[1] += 2 - assert lib.FetchRectBottoms1() == 502 - # - p = ffi.addressof(lib, 'bottom') - assert ffi.typeof(p) == ffi.typeof("long *") - assert p[0] == 301 - p[0] += 1 - assert lib.FetchRectBottom() == 302 - p = ffi.addressof(lib, 'bottoms') - assert ffi.typeof(p) == ffi.typeof("long(*)[2]") - assert p[0] == lib.bottoms - # - py.test.raises(AttributeError, ffi.addressof, lib, 'unknown_var') - py.test.raises(AttributeError, ffi.addressof, lib, "FOOBAR") - assert ffi.addressof(lib, 'FetchRectBottom') == lib.FetchRectBottom diff --git a/_cffi1/test_unicode_literals.py b/_cffi1/test_unicode_literals.py deleted file mode 100644 index e9825db..0000000 --- a/_cffi1/test_unicode_literals.py +++ /dev/null @@ -1,43 +0,0 @@ -# -# ---------------------------------------------- -# WARNING, ALL LITERALS IN THIS FILE ARE UNICODE -# ---------------------------------------------- -# -from __future__ import unicode_literals -# -# -# -from _cffi_backend import FFI - - -def test_cast(): - ffi = FFI() - assert int(ffi.cast("int", 3.14)) == 3 # unicode literal - -def test_new(): - ffi = FFI() - assert ffi.new("int[]", [3, 4, 5])[2] == 5 # unicode literal - -def test_typeof(): - ffi = FFI() - tp = ffi.typeof("int[51]") # unicode literal - assert tp.length == 51 - -def test_sizeof(): - ffi = FFI() - assert ffi.sizeof("int[51]") == 51 * 4 # unicode literal - -def test_alignof(): - ffi = FFI() - assert ffi.alignof("int[51]") == 4 # unicode literal - -def test_getctype(): - ffi = FFI() - assert ffi.getctype("int**") == "int * *" # unicode literal - assert type(ffi.getctype("int**")) is str - -def test_callback(): - ffi = FFI() - cb = ffi.callback("int(int)", # unicode literal - lambda x: x + 42) - assert cb(5) == 47 diff --git a/_cffi1/test_verify1.py b/_cffi1/test_verify1.py deleted file mode 100644 index 9aeb974..0000000 --- a/_cffi1/test_verify1.py +++ /dev/null @@ -1,2201 +0,0 @@ -import sys, math, py -from cffi import FFI, VerificationError, VerificationMissing, model -from . import recompiler -from .support import * -import _cffi_backend - -lib_m = ['m'] -if sys.platform == 'win32': - #there is a small chance this fails on Mingw via environ $CC - import distutils.ccompiler - if distutils.ccompiler.get_default_compiler() == 'msvc': - lib_m = ['msvcrt'] - extra_compile_args = [] # no obvious -Werror equivalent on MSVC -else: - if (sys.platform == 'darwin' and - [int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]): - # assume a standard clang or gcc - extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion'] - # special things for clang - extra_compile_args.append('-Qunused-arguments') - else: - # assume a standard gcc - extra_compile_args = ['-Werror', '-Wall', '-Wextra', '-Wconversion'] - -class FFI(FFI): - error = _cffi_backend.FFI.error - _extra_compile_args = extra_compile_args - _verify_counter = 0 - - def verify(self, preamble='', *args, **kwds): - FFI._verify_counter += 1 - return recompiler.verify(self, 'verify%d' % FFI._verify_counter, - preamble, *args, - extra_compile_args=self._extra_compile_args, - **kwds) - -class FFI_warnings_not_error(FFI): - _extra_compile_args = [] - - -def test_missing_function(ffi=None): - # uses the FFI hacked above with '-Werror' - if ffi is None: - ffi = FFI() - ffi.cdef("void some_completely_unknown_function();") - try: - lib = ffi.verify() - except (VerificationError, OSError, ImportError): - pass # expected case: we get a VerificationError - else: - # but depending on compiler and loader details, maybe - # 'lib' could actually be imported but will fail if we - # actually try to call the unknown function... Hard - # to test anything more. - pass - -def test_missing_function_import_error(): - # uses the original FFI that just gives a warning during compilation - test_missing_function(ffi=FFI_warnings_not_error()) - -def test_simple_case(): - ffi = FFI() - ffi.cdef("double sin(double x);") - lib = ffi.verify('#include <math.h>', libraries=lib_m) - assert lib.sin(1.23) == math.sin(1.23) - -def _Wconversion(cdef, source, **kargs): - if sys.platform == 'win32': - py.test.skip("needs GCC or Clang") - ffi = FFI() - ffi.cdef(cdef) - py.test.raises(VerificationError, ffi.verify, source, **kargs) - extra_compile_args_orig = extra_compile_args[:] - extra_compile_args.remove('-Wconversion') - try: - lib = ffi.verify(source, **kargs) - finally: - extra_compile_args[:] = extra_compile_args_orig - return lib - -def test_Wconversion_unsigned(): - _Wconversion("unsigned foo(void);", - "int foo(void) { return -1;}") - -def test_Wconversion_integer(): - _Wconversion("short foo(void);", - "long long foo(void) { return 1<<sizeof(short);}") - -def test_Wconversion_floating(): - lib = _Wconversion("float sin(double);", - "#include <math.h>", libraries=lib_m) - res = lib.sin(1.23) - assert res != math.sin(1.23) # not exact, because of double->float - assert abs(res - math.sin(1.23)) < 1E-5 - -def test_Wconversion_float2int(): - _Wconversion("int sinf(float);", - "#include <math.h>", libraries=lib_m) - -def test_Wconversion_double2int(): - _Wconversion("int sin(double);", - "#include <math.h>", libraries=lib_m) - -def test_rounding_1(): - ffi = FFI() - ffi.cdef("double sinf(float x);") - lib = ffi.verify('#include <math.h>', libraries=lib_m) - res = lib.sinf(1.23) - assert res != math.sin(1.23) # not exact, because of double->float - assert abs(res - math.sin(1.23)) < 1E-5 - -def test_rounding_2(): - ffi = FFI() - ffi.cdef("double sin(float x);") - lib = ffi.verify('#include <math.h>', libraries=lib_m) - res = lib.sin(1.23) - assert res != math.sin(1.23) # not exact, because of double->float - assert abs(res - math.sin(1.23)) < 1E-5 - -def test_strlen_exact(): - ffi = FFI() - ffi.cdef("size_t strlen(const char *s);") - lib = ffi.verify("#include <string.h>") - assert lib.strlen(b"hi there!") == 9 - -def test_strlen_approximate(): - lib = _Wconversion("int strlen(char *s);", - "#include <string.h>") - assert lib.strlen(b"hi there!") == 9 - -def test_return_approximate(): - for typename in ['short', 'int', 'long', 'long long']: - ffi = FFI() - ffi.cdef("%s foo(signed char x);" % typename) - lib = ffi.verify("signed char foo(signed char x) { return x;}") - assert lib.foo(-128) == -128 - assert lib.foo(+127) == +127 - -def test_strlen_array_of_char(): - ffi = FFI() - ffi.cdef("size_t strlen(char[]);") - lib = ffi.verify("#include <string.h>") - assert lib.strlen(b"hello") == 5 - -def test_longdouble(): - ffi = FFI() - ffi.cdef("long double sinl(long double x);") - lib = ffi.verify('#include <math.h>', libraries=lib_m) - for input in [1.23, - ffi.cast("double", 1.23), - ffi.cast("long double", 1.23)]: - x = lib.sinl(input) - assert repr(x).startswith("<cdata 'long double'") - assert (float(x) - math.sin(1.23)) < 1E-10 - -def test_longdouble_precision(): - # Test that we don't loose any precision of 'long double' when - # passing through Python and CFFI. - ffi = FFI() - ffi.cdef("long double step1(long double x);") - SAME_SIZE = ffi.sizeof("long double") == ffi.sizeof("double") - lib = ffi.verify(""" - long double step1(long double x) - { - return 4*x-x*x; - } - """) - def do(cast_to_double): - x = 0.9789 - for i in range(10000): - x = lib.step1(x) - if cast_to_double: - x = float(x) - return float(x) - - more_precise = do(False) - less_precise = do(True) - if SAME_SIZE: - assert more_precise == less_precise - else: - assert abs(more_precise - less_precise) > 0.1 - # Check the particular results on Intel - import platform - if (platform.machine().startswith('i386') or - platform.machine().startswith('x86')): - assert abs(more_precise - 0.656769) < 0.001 - assert abs(less_precise - 3.99091) < 0.001 - else: - py.test.skip("don't know the very exact precision of 'long double'") - - -all_primitive_types = model.PrimitiveType.ALL_PRIMITIVE_TYPES -if sys.platform == 'win32': - all_primitive_types = all_primitive_types.copy() - del all_primitive_types['ssize_t'] -all_integer_types = sorted(tp for tp in all_primitive_types - if all_primitive_types[tp] == 'i') -all_float_types = sorted(tp for tp in all_primitive_types - if all_primitive_types[tp] == 'f') - -def all_signed_integer_types(ffi): - return [x for x in all_integer_types if int(ffi.cast(x, -1)) < 0] - -def all_unsigned_integer_types(ffi): - return [x for x in all_integer_types if int(ffi.cast(x, -1)) > 0] - - -def test_primitive_category(): - for typename in all_primitive_types: - tp = model.PrimitiveType(typename) - C = tp.is_char_type() - F = tp.is_float_type() - I = tp.is_integer_type() - assert C == (typename in ('char', 'wchar_t')) - assert F == (typename in ('float', 'double', 'long double')) - assert I + F + C == 1 # one and only one of them is true - -def test_all_integer_and_float_types(): - typenames = [] - for typename in all_primitive_types: - if (all_primitive_types[typename] == 'c' or - typename == '_Bool' or typename == 'long double'): - pass - else: - typenames.append(typename) - # - ffi = FFI() - ffi.cdef('\n'.join(["%s foo_%s(%s);" % (tp, tp.replace(' ', '_'), tp) - for tp in typenames])) - lib = ffi.verify('\n'.join(["%s foo_%s(%s x) { return (%s)(x+1); }" % - (tp, tp.replace(' ', '_'), tp, tp) - for tp in typenames])) - for typename in typenames: - foo = getattr(lib, 'foo_%s' % typename.replace(' ', '_')) - assert foo(42) == 43 - if sys.version < '3': - assert foo(long(44)) == 45 - assert foo(ffi.cast(typename, 46)) == 47 - py.test.raises(TypeError, foo, ffi.NULL) - # - # check for overflow cases - if all_primitive_types[typename] == 'f': - continue - for value in [-2**80, -2**40, -2**20, -2**10, -2**5, -1, - 2**5, 2**10, 2**20, 2**40, 2**80]: - overflows = int(ffi.cast(typename, value)) != value - if overflows: - py.test.raises(OverflowError, foo, value) - else: - assert foo(value) == value + 1 - -def test_var_signed_integer_types(): - ffi = FFI() - lst = all_signed_integer_types(ffi) - csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_')) - for tp in lst]) - ffi.cdef(csource) - lib = ffi.verify(csource) - for tp in lst: - varname = 'somevar_%s' % tp.replace(' ', '_') - sz = ffi.sizeof(tp) - max = (1 << (8*sz-1)) - 1 - min = -(1 << (8*sz-1)) - setattr(lib, varname, max) - assert getattr(lib, varname) == max - setattr(lib, varname, min) - assert getattr(lib, varname) == min - py.test.raises(OverflowError, setattr, lib, varname, max+1) - py.test.raises(OverflowError, setattr, lib, varname, min-1) - -def test_var_unsigned_integer_types(): - ffi = FFI() - lst = all_unsigned_integer_types(ffi) - csource = "\n".join(["%s somevar_%s;" % (tp, tp.replace(' ', '_')) - for tp in lst]) - ffi.cdef(csource) - lib = ffi.verify(csource) - for tp in lst: - varname = 'somevar_%s' % tp.replace(' ', '_') - sz = ffi.sizeof(tp) - if tp != '_Bool': - max = (1 << (8*sz)) - 1 - else: - max = 1 - setattr(lib, varname, max) - assert getattr(lib, varname) == max - setattr(lib, varname, 0) - assert getattr(lib, varname) == 0 - py.test.raises(OverflowError, setattr, lib, varname, max+1) - py.test.raises(OverflowError, setattr, lib, varname, -1) - -def test_fn_signed_integer_types(): - ffi = FFI() - lst = all_signed_integer_types(ffi) - cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp) - for tp in lst]) - ffi.cdef(cdefsrc) - verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" % - (tp, tp.replace(' ', '_'), tp) for tp in lst]) - lib = ffi.verify(verifysrc) - for tp in lst: - fnname = 'somefn_%s' % tp.replace(' ', '_') - sz = ffi.sizeof(tp) - max = (1 << (8*sz-1)) - 1 - min = -(1 << (8*sz-1)) - fn = getattr(lib, fnname) - assert fn(max) == max - assert fn(min) == min - py.test.raises(OverflowError, fn, max + 1) - py.test.raises(OverflowError, fn, min - 1) - -def test_fn_unsigned_integer_types(): - ffi = FFI() - lst = all_unsigned_integer_types(ffi) - cdefsrc = "\n".join(["%s somefn_%s(%s);" % (tp, tp.replace(' ', '_'), tp) - for tp in lst]) - ffi.cdef(cdefsrc) - verifysrc = "\n".join(["%s somefn_%s(%s x) { return x; }" % - (tp, tp.replace(' ', '_'), tp) for tp in lst]) - lib = ffi.verify(verifysrc) - for tp in lst: - fnname = 'somefn_%s' % tp.replace(' ', '_') - sz = ffi.sizeof(tp) - if tp != '_Bool': - max = (1 << (8*sz)) - 1 - else: - max = 1 - fn = getattr(lib, fnname) - assert fn(max) == max - assert fn(0) == 0 - py.test.raises(OverflowError, fn, max + 1) - py.test.raises(OverflowError, fn, -1) - -def test_char_type(): - ffi = FFI() - ffi.cdef("char foo(char);") - lib = ffi.verify("char foo(char x) { return ++x; }") - assert lib.foo(b"A") == b"B" - py.test.raises(TypeError, lib.foo, b"bar") - py.test.raises(TypeError, lib.foo, "bar") - -def test_wchar_type(): - ffi = FFI() - if ffi.sizeof('wchar_t') == 2: - uniexample1 = u+'\u1234' - uniexample2 = u+'\u1235' - else: - uniexample1 = u+'\U00012345' - uniexample2 = u+'\U00012346' - # - ffi.cdef("wchar_t foo(wchar_t);") - lib = ffi.verify("wchar_t foo(wchar_t x) { return x+1; }") - assert lib.foo(uniexample1) == uniexample2 - -def test_no_argument(): - ffi = FFI() - ffi.cdef("int foo(void);") - lib = ffi.verify("int foo(void) { return 42; }") - assert lib.foo() == 42 - -def test_two_arguments(): - ffi = FFI() - ffi.cdef("int foo(int, int);") - lib = ffi.verify("int foo(int a, int b) { return a - b; }") - assert lib.foo(40, -2) == 42 - -def test_macro(): - ffi = FFI() - ffi.cdef("int foo(int, int);") - lib = ffi.verify("#define foo(a, b) ((a) * (b))") - assert lib.foo(-6, -7) == 42 - -def test_ptr(): - ffi = FFI() - ffi.cdef("int *foo(int *);") - lib = ffi.verify("int *foo(int *a) { return a; }") - assert lib.foo(ffi.NULL) == ffi.NULL - p = ffi.new("int *", 42) - q = ffi.new("int *", 42) - assert lib.foo(p) == p - assert lib.foo(q) != p - -def test_bogus_ptr(): - ffi = FFI() - ffi.cdef("int *foo(int *);") - lib = ffi.verify("int *foo(int *a) { return a; }") - py.test.raises(TypeError, lib.foo, ffi.new("short *", 42)) - - -def test_verify_typedefs(): - py.test.skip("ignored so far") - types = ['signed char', 'unsigned char', 'int', 'long'] - for cdefed in types: - for real in types: - ffi = FFI() - ffi.cdef("typedef %s foo_t;" % cdefed) - if cdefed == real: - ffi.verify("typedef %s foo_t;" % real) - else: - py.test.raises(VerificationError, ffi.verify, - "typedef %s foo_t;" % real) - -def test_nondecl_struct(): - ffi = FFI() - ffi.cdef("typedef struct foo_s foo_t; int bar(foo_t *);") - lib = ffi.verify("typedef struct foo_s foo_t;\n" - "int bar(foo_t *f) { (void)f; return 42; }\n") - assert lib.bar(ffi.NULL) == 42 - -def test_ffi_full_struct(): - def check(verified_code): - ffi = FFI() - ffi.cdef("struct foo_s { char x; int y; long *z; };") - ffi.verify(verified_code) - ffi.new("struct foo_s *", {}) - - check("struct foo_s { char x; int y; long *z; };") - # - if sys.platform != 'win32': # XXX fixme: only gives warnings - py.test.raises(VerificationError, check, - "struct foo_s { char x; int y; int *z; };") - # - py.test.raises(VerificationError, check, - "struct foo_s { int y; long *z; };") # cdef'ed field x is missing - # - e = py.test.raises(FFI.error, check, - "struct foo_s { int y; char x; long *z; };") - assert str(e.value).startswith( - "struct foo_s: wrong offset for field 'x'" - " (cdef says 0, but C compiler says 4)") - # - e = py.test.raises(FFI.error, check, - "struct foo_s { char x; int y; long *z; char extra; };") - assert str(e.value).startswith( - "struct foo_s: wrong total size" - " (cdef says %d, but C compiler says %d)" % ( - 8 + FFI().sizeof('long *'), - 8 + FFI().sizeof('long *') * 2)) - # - # a corner case that we cannot really detect, but where it has no - # bad consequences: the size is the same, but there is an extra field - # that replaces what is just padding in our declaration above - check("struct foo_s { char x, extra; int y; long *z; };") - # - e = py.test.raises(FFI.error, check, - "struct foo_s { char x; short pad; short y; long *z; };") - assert str(e.value).startswith( - "struct foo_s: wrong size for field 'y'" - " (cdef says 4, but C compiler says 2)") - -def test_ffi_nonfull_struct(): - ffi = FFI() - ffi.cdef(""" - struct foo_s { - int x; - ...; - }; - """) - py.test.raises(VerificationMissing, ffi.sizeof, 'struct foo_s') - py.test.raises(VerificationMissing, ffi.offsetof, 'struct foo_s', 'x') - py.test.raises(VerificationMissing, ffi.new, 'struct foo_s *') - ffi.verify(""" - struct foo_s { - int a, b, x, c, d, e; - }; - """) - assert ffi.sizeof('struct foo_s') == 6 * ffi.sizeof('int') - assert ffi.offsetof('struct foo_s', 'x') == 2 * ffi.sizeof('int') - -def test_ffi_nonfull_alignment(): - ffi = FFI() - ffi.cdef("struct foo_s { char x; ...; };") - ffi.verify("struct foo_s { int a, b; char x; };") - assert ffi.sizeof('struct foo_s') == 3 * ffi.sizeof('int') - assert ffi.alignof('struct foo_s') == ffi.sizeof('int') - -def _check_field_match(typename, real, expect_mismatch): - ffi = FFI() - testing_by_size = (expect_mismatch == 'by_size') - if testing_by_size: - expect_mismatch = ffi.sizeof(typename) != ffi.sizeof(real) - ffi.cdef("struct foo_s { %s x; ...; };" % typename) - try: - ffi.verify("struct foo_s { %s x; };" % real) - ffi.new("struct foo_s *", []) # because some mismatches show up lazily - except (VerificationError, ffi.error): - if not expect_mismatch: - if testing_by_size and typename != real: - print("ignoring mismatch between %s* and %s* even though " - "they have the same size" % (typename, real)) - return - raise AssertionError("unexpected mismatch: %s should be accepted " - "as equal to %s" % (typename, real)) - else: - if expect_mismatch: - raise AssertionError("mismatch not detected: " - "%s != %s" % (typename, real)) - -def test_struct_bad_sized_integer(): - for typename in ['int8_t', 'int16_t', 'int32_t', 'int64_t']: - for real in ['int8_t', 'int16_t', 'int32_t', 'int64_t']: - _check_field_match(typename, real, "by_size") - -def test_struct_bad_sized_float(): - for typename in all_float_types: - for real in all_float_types: - _check_field_match(typename, real, "by_size") - -def test_struct_signedness_ignored(): - _check_field_match("int", "unsigned int", expect_mismatch=False) - _check_field_match("unsigned short", "signed short", expect_mismatch=False) - -def test_struct_float_vs_int(): - if sys.platform == 'win32': - py.test.skip("XXX fixme: only gives warnings") - ffi = FFI() - for typename in all_signed_integer_types(ffi): - for real in all_float_types: - _check_field_match(typename, real, expect_mismatch=True) - for typename in all_float_types: - for real in all_signed_integer_types(ffi): - _check_field_match(typename, real, expect_mismatch=True) - -def test_struct_array_field(): - ffi = FFI() - ffi.cdef("struct foo_s { int a[17]; ...; };") - ffi.verify("struct foo_s { int x; int a[17]; int y; };") - assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int') - s = ffi.new("struct foo_s *") - assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int') - -def test_struct_array_no_length(): - ffi = FFI() - ffi.cdef("struct foo_s { int a[]; int y; ...; };\n" - "int bar(struct foo_s *);\n") - lib = ffi.verify("struct foo_s { int x; int a[17]; int y; };\n" - "int bar(struct foo_s *f) { return f->a[14]; }\n") - assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int') - s = ffi.new("struct foo_s *") - assert ffi.typeof(s.a) is ffi.typeof('int *') # because no length - s.a[14] = 4242 - assert lib.bar(s) == 4242 - # with no declared length, out-of-bound accesses are not detected - s.a[17] = -521 - assert s.y == s.a[17] == -521 - # - s = ffi.new("struct foo_s *", {'a': list(range(17))}) - assert s.a[16] == 16 - # overflows at construction time not detected either - s = ffi.new("struct foo_s *", {'a': list(range(18))}) - assert s.y == s.a[17] == 17 - -def test_struct_array_guess_length(): - ffi = FFI() - ffi.cdef("struct foo_s { int a[...]; };") - ffi.verify("struct foo_s { int x; int a[17]; int y; };") - assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int') - s = ffi.new("struct foo_s *") - assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int') - py.test.raises(IndexError, 's.a[17]') - -def test_struct_array_c99_1(): - if sys.platform == 'win32': - py.test.skip("requires C99") - ffi = FFI() - ffi.cdef("struct foo_s { int x; int a[]; };") - ffi.verify("struct foo_s { int x; int a[]; };") - assert ffi.sizeof('struct foo_s') == 1 * ffi.sizeof('int') - s = ffi.new("struct foo_s *", [424242, 4]) - assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int') # the same in C - assert s.a[3] == 0 - s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]]) - assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int') - assert s.a[3] == -10 - s = ffi.new("struct foo_s *") - assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int') - s = ffi.new("struct foo_s *", [424242]) - assert ffi.sizeof(s[0]) == 1 * ffi.sizeof('int') - -def test_struct_array_c99_2(): - if sys.platform == 'win32': - py.test.skip("requires C99") - ffi = FFI() - ffi.cdef("struct foo_s { int x; int a[]; ...; };") - ffi.verify("struct foo_s { int x, y; int a[]; };") - assert ffi.sizeof('struct foo_s') == 2 * ffi.sizeof('int') - s = ffi.new("struct foo_s *", [424242, 4]) - assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int') - assert s.a[3] == 0 - s = ffi.new("struct foo_s *", [424242, [-40, -30, -20, -10]]) - assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int') - assert s.a[3] == -10 - s = ffi.new("struct foo_s *") - assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int') - s = ffi.new("struct foo_s *", [424242]) - assert ffi.sizeof(s[0]) == 2 * ffi.sizeof('int') - -def test_struct_ptr_to_array_field(): - ffi = FFI() - ffi.cdef("struct foo_s { int (*a)[17]; ...; }; struct bar_s { ...; };") - ffi.verify("struct foo_s { int x; int (*a)[17]; int y; };\n" - "struct bar_s { int x; int *a; int y; };") - assert ffi.sizeof('struct foo_s') == ffi.sizeof("struct bar_s") - s = ffi.new("struct foo_s *") - assert ffi.sizeof(s.a) == ffi.sizeof('int(*)[17]') == ffi.sizeof("int *") - -def test_struct_with_bitfield_exact(): - ffi = FFI() - ffi.cdef("struct foo_s { int a:2, b:3; };") - ffi.verify("struct foo_s { int a:2, b:3; };") - s = ffi.new("struct foo_s *") - s.b = 3 - py.test.raises(OverflowError, "s.b = 4") - assert s.b == 3 - -def test_struct_with_bitfield_enum(): - ffi = FFI() - code = """ - typedef enum { AA, BB, CC } foo_e; - typedef struct { foo_e f:2; } foo_s; - """ - ffi.cdef(code) - ffi.verify(code) - s = ffi.new("foo_s *") - s.f = 1 - assert s.f == 1 - if int(ffi.cast("foo_e", -1)) < 0: - two = -2 - else: - two = 2 - s.f = two - assert s.f == two - -def test_unsupported_struct_with_bitfield_ellipsis(): - ffi = FFI() - py.test.raises(NotImplementedError, ffi.cdef, - "struct foo_s { int a:2, b:3; ...; };") - -def test_global_constants(): - ffi = FFI() - # use 'static const int', as generally documented, although in this - # case the 'static' is completely ignored. - ffi.cdef("static const int AA, BB, CC, DD;") - lib = ffi.verify("#define AA 42\n" - "#define BB (-43) // blah\n" - "#define CC (22*2) /* foobar */\n" - "#define DD ((unsigned int)142) /* foo\nbar */\n") - assert lib.AA == 42 - assert lib.BB == -43 - assert lib.CC == 44 - assert lib.DD == 142 - -def test_global_const_int_size(): - # integer constants: ignore the declared type, always just use the value - for value in [-2**63, -2**31, -2**15, - 2**15-1, 2**15, 2**31-1, 2**31, 2**32-1, 2**32, - 2**63-1, 2**63, 2**64-1]: - ffi = FFI() - if value == int(ffi.cast("long long", value)): - if value < 0: - vstr = '(-%dLL-1)' % (~value,) - else: - vstr = '%dLL' % value - elif value == int(ffi.cast("unsigned long long", value)): - vstr = '%dULL' % value - else: - raise AssertionError(value) - ffi.cdef("static const unsigned short AA;") - lib = ffi.verify("#define AA %s\n" % vstr) - assert lib.AA == value - assert type(lib.AA) is type(int(lib.AA)) - -def test_global_constants_non_int(): - ffi = FFI() - ffi.cdef("static char *const PP;") - lib = ffi.verify('static char *const PP = "testing!";\n') - assert ffi.typeof(lib.PP) == ffi.typeof("char *") - assert ffi.string(lib.PP) == b"testing!" - -def test_nonfull_enum(): - ffi = FFI() - ffi.cdef("enum ee { EE1, EE2, EE3, ... \n \t };") - py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE2') - ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };") - assert ffi.string(ffi.cast('enum ee', 11)) == "EE2" - assert ffi.string(ffi.cast('enum ee', -10)) == "EE3" - # - # try again - ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };") - assert ffi.string(ffi.cast('enum ee', 11)) == "EE2" - # - assert ffi.typeof("enum ee").relements == {'EE1': 10, 'EE2': 11, 'EE3': -10} - assert ffi.typeof("enum ee").elements == {10: 'EE1', 11: 'EE2', -10: 'EE3'} - -def test_full_enum(): - ffi = FFI() - ffi.cdef("enum ee { EE1, EE2, EE3 };") - ffi.verify("enum ee { EE1, EE2, EE3 };") - py.test.raises(VerificationError, ffi.verify, "enum ee { EE1, EE2 };") - # disabled: for now, we always accept and fix transparently constant values - #e = py.test.raises(VerificationError, ffi.verify, - # "enum ee { EE1, EE3, EE2 };") - #assert str(e.value) == 'enum ee: EE2 has the real value 2, not 1' - # extra items cannot be seen and have no bad consequence anyway - lib = ffi.verify("enum ee { EE1, EE2, EE3, EE4 };") - assert lib.EE3 == 2 - -def test_enum_usage(): - ffi = FFI() - ffi.cdef("enum ee { EE1,EE2 }; typedef struct { enum ee x; } *sp;") - lib = ffi.verify("enum ee { EE1,EE2 }; typedef struct { enum ee x; } *sp;") - assert lib.EE2 == 1 - s = ffi.new("sp", [lib.EE2]) - assert s.x == 1 - s.x = 17 - assert s.x == 17 - -def test_anonymous_enum(): - ffi = FFI() - ffi.cdef("enum { EE1 }; enum { EE2, EE3 };") - lib = ffi.verify("enum { EE1 }; enum { EE2, EE3 };") - assert lib.EE1 == 0 - assert lib.EE2 == 0 - assert lib.EE3 == 1 - -def test_nonfull_anonymous_enum(): - ffi = FFI() - ffi.cdef("enum { EE1, ... }; enum { EE3, ... };") - lib = ffi.verify("enum { EE2, EE1 }; enum { EE3 };") - assert lib.EE1 == 1 - assert lib.EE3 == 0 - -def test_nonfull_enum_syntax2(): - ffi = FFI() - ffi.cdef("enum ee { EE1, EE2=\t..., EE3 };") - py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE1') - ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };") - assert ffi.string(ffi.cast('enum ee', 11)) == 'EE2' - assert ffi.string(ffi.cast('enum ee', -10)) == 'EE3' - # - ffi = FFI() - ffi.cdef("enum ee { EE1, EE2=\t... };") - py.test.raises(VerificationMissing, ffi.cast, 'enum ee', 'EE1') - ffi.verify("enum ee { EE1=10, EE2, EE3=-10, EE4 };") - assert ffi.string(ffi.cast('enum ee', 11)) == 'EE2' - # - ffi = FFI() - ffi.cdef("enum ee2 { EE4=..., EE5=..., ... };") - ffi.verify("enum ee2 { EE4=-1234-5, EE5 }; ") - assert ffi.string(ffi.cast('enum ee2', -1239)) == 'EE4' - assert ffi.string(ffi.cast('enum ee2', -1238)) == 'EE5' - -def test_get_set_errno(): - ffi = FFI() - ffi.cdef("int foo(int);") - lib = ffi.verify(""" - static int foo(int x) - { - errno += 1; - return x * 7; - } - """) - ffi.errno = 15 - assert lib.foo(6) == 42 - assert ffi.errno == 16 - -def test_define_int(): - ffi = FFI() - ffi.cdef("#define FOO ...\n" - "\t#\tdefine\tBAR\t...\t\n" - "#define BAZ ...\n") - lib = ffi.verify("#define FOO 42\n" - "#define BAR (-44)\n" - "#define BAZ 0xffffffffffffffffULL\n") - assert lib.FOO == 42 - assert lib.BAR == -44 - assert lib.BAZ == 0xffffffffffffffff - -def test_access_variable(): - ffi = FFI() - ffi.cdef("int foo(void);\n" - "int somenumber;") - lib = ffi.verify(""" - static int somenumber = 2; - static int foo(void) { - return somenumber * 7; - } - """) - assert lib.somenumber == 2 - assert lib.foo() == 14 - lib.somenumber = -6 - assert lib.foo() == -42 - assert lib.somenumber == -6 - lib.somenumber = 2 # reset for the next run, if any - -def test_access_address_of_variable(): - # access the address of 'somenumber': need a trick - ffi = FFI() - ffi.cdef("int somenumber; static int *const somenumberptr;") - lib = ffi.verify(""" - static int somenumber = 2; - #define somenumberptr (&somenumber) - """) - assert lib.somenumber == 2 - lib.somenumberptr[0] = 42 - assert lib.somenumber == 42 - lib.somenumber = 2 # reset for the next run, if any - -def test_access_array_variable(length=5): - ffi = FFI() - ffi.cdef("int foo(int);\n" - "int somenumber[%s];" % (length,)) - lib = ffi.verify(""" - static int somenumber[] = {2, 2, 3, 4, 5}; - static int foo(int i) { - return somenumber[i] * 7; - } - """) - if length == '': - # a global variable of an unknown array length is implicitly - # transformed into a global pointer variable, because we can only - # work with array instances whose length we know. using a pointer - # instead of an array gives the correct effects. - assert repr(lib.somenumber).startswith("<cdata 'int *' 0x") - py.test.raises(TypeError, len, lib.somenumber) - else: - assert repr(lib.somenumber).startswith("<cdata 'int[%s]' 0x" % length) - assert len(lib.somenumber) == 5 - assert lib.somenumber[3] == 4 - assert lib.foo(3) == 28 - lib.somenumber[3] = -6 - assert lib.foo(3) == -42 - assert lib.somenumber[3] == -6 - assert lib.somenumber[4] == 5 - lib.somenumber[3] = 4 # reset for the next run, if any - -def test_access_array_variable_length_hidden(): - test_access_array_variable(length='') - -def test_access_struct_variable(): - ffi = FFI() - ffi.cdef("struct foo { int x; ...; };\n" - "int foo(int);\n" - "struct foo stuff;") - lib = ffi.verify(""" - struct foo { int x, y, z; }; - static struct foo stuff = {2, 5, 8}; - static int foo(int i) { - switch (i) { - case 0: return stuff.x * 7; - case 1: return stuff.y * 7; - case 2: return stuff.z * 7; - } - return -1; - } - """) - assert lib.stuff.x == 2 - assert lib.foo(0) == 14 - assert lib.foo(1) == 35 - assert lib.foo(2) == 56 - lib.stuff.x = -6 - assert lib.foo(0) == -42 - assert lib.foo(1) == 35 - lib.stuff.x = 2 # reset for the next run, if any - -def test_access_callback(): - ffi = FFI() - ffi.cdef("int (*cb)(int);\n" - "int foo(int);\n" - "void reset_cb(void);") - lib = ffi.verify(""" - static int g(int x) { return x * 7; } - static int (*cb)(int); - static int foo(int i) { return cb(i) - 1; } - static void reset_cb(void) { cb = g; } - """) - lib.reset_cb() - assert lib.foo(6) == 41 - my_callback = ffi.callback("int(*)(int)", lambda n: n * 222) - lib.cb = my_callback - assert lib.foo(4) == 887 - -def test_access_callback_function_typedef(): - ffi = FFI() - ffi.cdef("typedef int mycallback_t(int);\n" - "mycallback_t *cb;\n" - "int foo(int);\n" - "void reset_cb(void);") - lib = ffi.verify(""" - static int g(int x) { return x * 7; } - static int (*cb)(int); - static int foo(int i) { return cb(i) - 1; } - static void reset_cb(void) { cb = g; } - """) - lib.reset_cb() - assert lib.foo(6) == 41 - my_callback = ffi.callback("int(*)(int)", lambda n: n * 222) - lib.cb = my_callback - assert lib.foo(4) == 887 - -def test_call_with_struct_ptr(): - ffi = FFI() - ffi.cdef("typedef struct { int x; ...; } foo_t; int foo(foo_t *);") - lib = ffi.verify(""" - typedef struct { int y, x; } foo_t; - static int foo(foo_t *f) { return f->x * 7; } - """) - f = ffi.new("foo_t *") - f.x = 6 - assert lib.foo(f) == 42 - -def test_unknown_type(): - ffi = FFI() - ffi.cdef(""" - typedef ... token_t; - int foo(token_t *); - #define TOKEN_SIZE ... - """) - lib = ffi.verify(""" - typedef float token_t; - static int foo(token_t *tk) { - if (!tk) - return -42; - *tk += 1.601f; - return (int)*tk; - } - #define TOKEN_SIZE sizeof(token_t) - """) - # we cannot let ffi.new("token_t *") work, because we don't know ahead of - # time if it's ok to ask 'sizeof(token_t)' in the C code or not. - # See test_unknown_type_2. Workaround. - tkmem = ffi.new("char[]", lib.TOKEN_SIZE) # zero-initialized - tk = ffi.cast("token_t *", tkmem) - results = [lib.foo(tk) for i in range(6)] - assert results == [1, 3, 4, 6, 8, 9] - assert lib.foo(ffi.NULL) == -42 - -def test_unknown_type_2(): - ffi = FFI() - ffi.cdef("typedef ... token_t;") - lib = ffi.verify("typedef struct token_s token_t;") - # assert did not crash, even though 'sizeof(token_t)' is not valid in C. - -def test_unknown_type_3(): - ffi = FFI() - ffi.cdef(""" - typedef ... *token_p; - token_p foo(token_p); - """) - lib = ffi.verify(""" - typedef struct _token_s *token_p; - token_p foo(token_p arg) { - if (arg) - return (token_p)0x12347; - else - return (token_p)0x12345; - } - """) - p = lib.foo(ffi.NULL) - assert int(ffi.cast("intptr_t", p)) == 0x12345 - q = lib.foo(p) - assert int(ffi.cast("intptr_t", q)) == 0x12347 - -def test_varargs(): - ffi = FFI() - ffi.cdef("int foo(int x, ...);") - lib = ffi.verify(""" - int foo(int x, ...) { - va_list vargs; - va_start(vargs, x); - x -= va_arg(vargs, int); - x -= va_arg(vargs, int); - va_end(vargs); - return x; - } - """) - assert lib.foo(50, ffi.cast("int", 5), ffi.cast("int", 3)) == 42 - -def test_varargs_exact(): - if sys.platform == 'win32': - py.test.skip("XXX fixme: only gives warnings") - ffi = FFI() - ffi.cdef("int foo(int x, ...);") - py.test.raises(VerificationError, ffi.verify, """ - int foo(long long x, ...) { - return x; - } - """) - -def test_varargs_struct(): - ffi = FFI() - ffi.cdef("struct foo_s { char a; int b; }; int foo(int x, ...);") - lib = ffi.verify(""" - struct foo_s { - char a; int b; - }; - int foo(int x, ...) { - va_list vargs; - struct foo_s s; - va_start(vargs, x); - s = va_arg(vargs, struct foo_s); - va_end(vargs); - return s.a - s.b; - } - """) - s = ffi.new("struct foo_s *", [b'B', 1]) - assert lib.foo(50, s[0]) == ord('A') - -def test_autofilled_struct_as_argument(): - ffi = FFI() - ffi.cdef("struct foo_s { long a; double b; ...; };\n" - "int foo(struct foo_s);") - lib = ffi.verify(""" - struct foo_s { - double b; - long a; - }; - int foo(struct foo_s s) { - return (int)s.a - (int)s.b; - } - """) - s = ffi.new("struct foo_s *", [100, 1]) - assert lib.foo(s[0]) == 99 - assert lib.foo([100, 1]) == 99 - -def test_autofilled_struct_as_argument_dynamic(): - ffi = FFI() - ffi.cdef("struct foo_s { long a; ...; };\n" - "int (*foo)(struct foo_s);") - lib = ffi.verify(""" - struct foo_s { - double b; - long a; - }; - int foo1(struct foo_s s) { - return (int)s.a - (int)s.b; - } - int (*foo)(struct foo_s s) = &foo1; - """) - e = py.test.raises(NotImplementedError, lib.foo, "?") - msg = ("ctype 'struct foo_s' not supported as argument (it is a struct " - 'declared with "...;", but the C calling convention may depend ' - 'on the missing fields)') - assert str(e.value) == msg - -def test_func_returns_struct(): - ffi = FFI() - ffi.cdef(""" - struct foo_s { int aa, bb; }; - struct foo_s foo(int a, int b); - """) - lib = ffi.verify(""" - struct foo_s { int aa, bb; }; - struct foo_s foo(int a, int b) { - struct foo_s r; - r.aa = a*a; - r.bb = b*b; - return r; - } - """) - s = lib.foo(6, 7) - assert repr(s) == "<cdata 'struct foo_s' owning 8 bytes>" - assert s.aa == 36 - assert s.bb == 49 - -def test_func_as_funcptr(): - ffi = FFI() - ffi.cdef("int *(*const fooptr)(void);") - lib = ffi.verify(""" - int *foo(void) { - return (int*)"foobar"; - } - int *(*fooptr)(void) = foo; - """) - foochar = ffi.cast("char *(*)(void)", lib.fooptr) - s = foochar() - assert ffi.string(s) == b"foobar" - -def test_funcptr_as_argument(): - ffi = FFI() - ffi.cdef(""" - void qsort(void *base, size_t nel, size_t width, - int (*compar)(const void *, const void *)); - """) - ffi.verify("#include <stdlib.h>") - -def test_func_as_argument(): - ffi = FFI() - ffi.cdef(""" - void qsort(void *base, size_t nel, size_t width, - int compar(const void *, const void *)); - """) - ffi.verify("#include <stdlib.h>") - -def test_array_as_argument(): - ffi = FFI() - ffi.cdef(""" - size_t strlen(char string[]); - """) - ffi.verify("#include <string.h>") - -def test_enum_as_argument(): - ffi = FFI() - ffi.cdef(""" - enum foo_e { AA, BB, ... }; - int foo_func(enum foo_e); - """) - lib = ffi.verify(""" - enum foo_e { AA, CC, BB }; - int foo_func(enum foo_e e) { return (int)e; } - """) - assert lib.foo_func(lib.BB) == 2 - py.test.raises(TypeError, lib.foo_func, "BB") - -def test_enum_as_function_result(): - ffi = FFI() - ffi.cdef(""" - enum foo_e { AA, BB, ... }; - enum foo_e foo_func(int x); - """) - lib = ffi.verify(""" - enum foo_e { AA, CC, BB }; - enum foo_e foo_func(int x) { return (enum foo_e)x; } - """) - assert lib.foo_func(lib.BB) == lib.BB == 2 - -def test_enum_values(): - ffi = FFI() - ffi.cdef("enum enum1_e { AA, BB };") - lib = ffi.verify("enum enum1_e { AA, BB };") - assert lib.AA == 0 - assert lib.BB == 1 - assert ffi.string(ffi.cast("enum enum1_e", 1)) == 'BB' - -def test_typedef_complete_enum(): - ffi = FFI() - ffi.cdef("typedef enum { AA, BB } enum1_t;") - lib = ffi.verify("typedef enum { AA, BB } enum1_t;") - assert ffi.string(ffi.cast("enum1_t", 1)) == 'BB' - assert lib.AA == 0 - assert lib.BB == 1 - -def test_typedef_broken_complete_enum(): - # xxx this is broken in old cffis, but works with recompiler.py - ffi = FFI() - ffi.cdef("typedef enum { AA, BB } enum1_t;") - lib = ffi.verify("typedef enum { AA, CC, BB } enum1_t;") - assert lib.AA == 0 - assert lib.BB == 2 - -def test_typedef_incomplete_enum(): - ffi = FFI() - ffi.cdef("typedef enum { AA, BB, ... } enum1_t;") - lib = ffi.verify("typedef enum { AA, CC, BB } enum1_t;") - assert ffi.string(ffi.cast("enum1_t", 1)) == '1' - assert ffi.string(ffi.cast("enum1_t", 2)) == 'BB' - assert lib.AA == 0 - assert lib.BB == 2 - -def test_typedef_enum_as_argument(): - ffi = FFI() - ffi.cdef(""" - typedef enum { AA, BB, ... } foo_t; - int foo_func(foo_t); - """) - lib = ffi.verify(""" - typedef enum { AA, CC, BB } foo_t; - int foo_func(foo_t e) { return (int)e; } - """) - assert lib.foo_func(lib.BB) == lib.BB == 2 - py.test.raises(TypeError, lib.foo_func, "BB") - -def test_typedef_enum_as_function_result(): - ffi = FFI() - ffi.cdef(""" - typedef enum { AA, BB, ... } foo_t; - foo_t foo_func(int x); - """) - lib = ffi.verify(""" - typedef enum { AA, CC, BB } foo_t; - foo_t foo_func(int x) { return (foo_t)x; } - """) - assert lib.foo_func(lib.BB) == lib.BB == 2 - -def test_function_typedef(): - ffi = FFI() - ffi.cdef(""" - typedef double func_t(double); - func_t sin; - """) - lib = ffi.verify('#include <math.h>', libraries=lib_m) - assert lib.sin(1.23) == math.sin(1.23) - -def test_callback_calling_convention(): - py.test.skip("later") - if sys.platform != 'win32': - py.test.skip("Windows only") - ffi = FFI() - ffi.cdef(""" - int call1(int(*__cdecl cb)(int)); - int call2(int(*__stdcall cb)(int)); - """) - lib = ffi.verify(""" - int call1(int(*__cdecl cb)(int)) { - return cb(42) + 1; - } - int call2(int(*__stdcall cb)(int)) { - return cb(-42) - 6; - } - """) - xxx - -def test_opaque_integer_as_function_result(): - #import platform - #if platform.machine().startswith('sparc'): - # py.test.skip('Breaks horribly on sparc (SIGILL + corrupted stack)') - #elif platform.machine() == 'mips64' and sys.maxsize > 2**32: - # py.test.skip('Segfaults on mips64el') - # XXX bad abuse of "struct { ...; }". It only works a bit by chance - # anyway. XXX think about something better :-( - ffi = FFI() - ffi.cdef(""" - typedef struct { ...; } myhandle_t; - myhandle_t foo(void); - """) - lib = ffi.verify(""" - typedef short myhandle_t; - myhandle_t foo(void) { return 42; } - """) - h = lib.foo() - assert ffi.sizeof(h) == ffi.sizeof("short") - -def test_return_partial_struct(): - ffi = FFI() - ffi.cdef(""" - typedef struct { int x; ...; } foo_t; - foo_t foo(void); - """) - lib = ffi.verify(""" - typedef struct { int y, x; } foo_t; - foo_t foo(void) { foo_t r = { 45, 81 }; return r; } - """) - h = lib.foo() - assert ffi.sizeof(h) == 2 * ffi.sizeof("int") - assert h.x == 81 - -def test_take_and_return_partial_structs(): - ffi = FFI() - ffi.cdef(""" - typedef struct { int x; ...; } foo_t; - foo_t foo(foo_t, foo_t); - """) - lib = ffi.verify(""" - typedef struct { int y, x; } foo_t; - foo_t foo(foo_t a, foo_t b) { - foo_t r = { 100, a.x * 5 + b.x * 7 }; - return r; - } - """) - args = ffi.new("foo_t[3]") - args[0].x = 1000 - args[2].x = -498 - h = lib.foo(args[0], args[2]) - assert ffi.sizeof(h) == 2 * ffi.sizeof("int") - assert h.x == 1000 * 5 - 498 * 7 - -def test_cannot_name_struct_type(): - ffi = FFI() - ffi.cdef("typedef struct { int x; } **sp; void foo(sp);") - e = py.test.raises(VerificationError, ffi.verify, - "typedef struct { int x; } **sp; void foo(sp x) { }") - assert 'in argument of foo: unknown type name' in str(e.value) - -def test_dont_check_unnamable_fields(): - ffi = FFI() - ffi.cdef("struct foo_s { struct { int x; } someone; };") - ffi.verify("struct foo_s { struct { int x; } someone; };") - # assert did not crash - -def test_nested_anonymous_struct_exact(): - if sys.platform == 'win32': - py.test.skip("nested anonymous struct/union") - ffi = FFI() - ffi.cdef(""" - struct foo_s { struct { int a; char b; }; union { char c, d; }; }; - """) - assert ffi.offsetof("struct foo_s", "c") == 2 * ffi.sizeof("int") - assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int") - ffi.verify(""" - struct foo_s { struct { int a; char b; }; union { char c, d; }; }; - """) - p = ffi.new("struct foo_s *") - assert ffi.sizeof(p[0]) == 3 * ffi.sizeof("int") # with alignment - p.a = 1234567 - p.b = b'X' - p.c = b'Y' - assert p.a == 1234567 - assert p.b == b'X' - assert p.c == b'Y' - assert p.d == b'Y' - -def test_nested_anonymous_struct_exact_error(): - if sys.platform == 'win32': - py.test.skip("nested anonymous struct/union") - ffi = FFI() - ffi.cdef(""" - struct foo_s { struct { int a; char b; }; union { char c, d; }; }; - """) - py.test.raises(VerificationError, ffi.verify, """ - struct foo_s { struct { int a; short b; }; union { char c, d; }; }; - """) - # works fine now - #py.test.raises(VerificationError, ffi.verify, """ - # struct foo_s { struct { int a; char e, b; }; union { char c, d; }; }; - #""") - -def test_nested_anonymous_struct_inexact_1(): - ffi = FFI() - ffi.cdef(""" - struct foo_s { struct { char b; ...; }; union { char c, d; }; }; - """) - ffi.verify(""" - struct foo_s { int a, padding; char c, d, b; }; - """) - assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int") - -def test_nested_anonymous_struct_inexact_2(): - ffi = FFI() - ffi.cdef(""" - struct foo_s { union { char c, d; }; struct { int a; char b; }; ...; }; - """) - ffi.verify(""" - struct foo_s { int a, padding; char c, d, b; }; - """) - assert ffi.sizeof("struct foo_s") == 3 * ffi.sizeof("int") - -def test_ffi_union(): - ffi = FFI() - ffi.cdef("union foo_u { char x; long *z; };") - ffi.verify("union foo_u { char x; int y; long *z; };") - -def test_ffi_union_partial(): - ffi = FFI() - ffi.cdef("union foo_u { char x; ...; };") - ffi.verify("union foo_u { char x; int y; };") - assert ffi.sizeof("union foo_u") == 4 - -def test_ffi_union_with_partial_struct(): - ffi = FFI() - ffi.cdef("struct foo_s { int x; ...; }; union foo_u { struct foo_s s; };") - ffi.verify("struct foo_s { int a; int x; }; " - "union foo_u { char b[32]; struct foo_s s; };") - assert ffi.sizeof("struct foo_s") == 8 - assert ffi.sizeof("union foo_u") == 32 - -def test_ffi_union_partial_2(): - ffi = FFI() - ffi.cdef("typedef union { char x; ...; } u1;") - ffi.verify("typedef union { char x; int y; } u1;") - assert ffi.sizeof("u1") == 4 - -def test_ffi_union_with_partial_struct_2(): - ffi = FFI() - ffi.cdef("typedef struct { int x; ...; } s1;" - "typedef union { s1 s; } u1;") - ffi.verify("typedef struct { int a; int x; } s1; " - "typedef union { char b[32]; s1 s; } u1;") - assert ffi.sizeof("s1") == 8 - assert ffi.sizeof("u1") == 32 - assert ffi.offsetof("u1", "s") == 0 - -def test_ffi_struct_packed(): - if sys.platform == 'win32': - py.test.skip("needs a GCC extension") - ffi = FFI() - ffi.cdef("struct foo_s { int b; ...; };") - ffi.verify(""" - struct foo_s { - char a; - int b; - } __attribute__((packed)); - """) - -def test_tmpdir(): - import tempfile, os - from testing.udir import udir - tmpdir = tempfile.mkdtemp(dir=str(udir)) - ffi = FFI() - ffi.cdef("int foo(int);") - lib = ffi.verify("int foo(int a) { return a + 42; }", tmpdir=tmpdir) - assert os.listdir(tmpdir) - assert lib.foo(100) == 142 - -def test_relative_to(): - py.test.skip("not available") - import tempfile, os - from testing.udir import udir - tmpdir = tempfile.mkdtemp(dir=str(udir)) - ffi = FFI() - ffi.cdef("int foo(int);") - f = open(os.path.join(tmpdir, 'foo.h'), 'w') - f.write("int foo(int a) { return a + 42; }\n") - f.close() - lib = ffi.verify('#include "foo.h"', - include_dirs=['.'], - relative_to=os.path.join(tmpdir, 'x')) - assert lib.foo(100) == 142 - -def test_bug1(): - ffi = FFI() - ffi.cdef(""" - typedef struct tdlhandle_s { ...; } *tdl_handle_t; - typedef struct my_error_code_ { - tdl_handle_t *rh; - } my_error_code_t; - """) - ffi.verify(""" - typedef struct tdlhandle_s { int foo; } *tdl_handle_t; - typedef struct my_error_code_ { - tdl_handle_t *rh; - } my_error_code_t; - """) - -def test_bool(): - if sys.platform == 'win32': - py.test.skip("_Bool not in MSVC") - ffi = FFI() - ffi.cdef("struct foo_s { _Bool x; };" - "_Bool foo(_Bool);") - lib = ffi.verify(""" - struct foo_s { _Bool x; }; - int foo(int arg) { - return !arg; - } - """) - p = ffi.new("struct foo_s *") - p.x = 1 - assert p.x == 1 - py.test.raises(OverflowError, "p.x = -1") - py.test.raises(TypeError, "p.x = 0.0") - assert lib.foo(1) == 0 - assert lib.foo(0) == 1 - py.test.raises(OverflowError, lib.foo, 42) - py.test.raises(TypeError, lib.foo, 0.0) - assert int(ffi.cast("_Bool", long(1))) == 1 - assert int(ffi.cast("_Bool", long(0))) == 0 - assert int(ffi.cast("_Bool", long(-1))) == 1 - assert int(ffi.cast("_Bool", 10**200)) == 1 - assert int(ffi.cast("_Bool", 10**40000)) == 1 - # - class Foo(object): - def __int__(self): - self.seen = 1 - return result - f = Foo() - f.seen = 0 - result = 42 - assert int(ffi.cast("_Bool", f)) == 1 - assert f.seen - f.seen = 0 - result = 0 - assert int(ffi.cast("_Bool", f)) == 0 - assert f.seen - # - py.test.raises(TypeError, ffi.cast, "_Bool", []) - -def test_bool_on_long_double(): - if sys.platform == 'win32': - py.test.skip("_Bool not in MSVC") - f = 1E-250 - if f == 0.0 or f*f != 0.0: - py.test.skip("unexpected precision") - ffi = FFI() - ffi.cdef("long double square(long double f); _Bool opposite(_Bool);") - lib = ffi.verify("long double square(long double f) { return f*f; }\n" - "_Bool opposite(_Bool x) { return !x; }") - f0 = lib.square(0.0) - f2 = lib.square(f) - f3 = lib.square(f * 2.0) - if repr(f2) == repr(f3): - py.test.skip("long double doesn't have enough precision") - assert float(f0) == float(f2) == float(f3) == 0.0 # too tiny for 'double' - assert int(ffi.cast("_Bool", f2)) == 1 - assert int(ffi.cast("_Bool", f3)) == 1 - assert int(ffi.cast("_Bool", f0)) == 0 - py.test.raises(TypeError, lib.opposite, f2) - -def test_cannot_pass_float(): - for basetype in ['char', 'short', 'int', 'long', 'long long']: - for sign in ['signed', 'unsigned']: - type = '%s %s' % (sign, basetype) - ffi = FFI() - ffi.cdef("struct foo_s { %s x; };\n" - "int foo(%s);" % (type, type)) - lib = ffi.verify(""" - struct foo_s { %s x; }; - int foo(%s arg) { - return !arg; - } - """ % (type, type)) - p = ffi.new("struct foo_s *") - py.test.raises(TypeError, "p.x = 0.0") - assert lib.foo(42) == 0 - assert lib.foo(0) == 1 - py.test.raises(TypeError, lib.foo, 0.0) - -def test_cast_from_int_type_to_bool(): - ffi = FFI() - for basetype in ['char', 'short', 'int', 'long', 'long long']: - for sign in ['signed', 'unsigned']: - type = '%s %s' % (sign, basetype) - assert int(ffi.cast("_Bool", ffi.cast(type, 42))) == 1 - assert int(ffi.cast("bool", ffi.cast(type, 42))) == 1 - assert int(ffi.cast("_Bool", ffi.cast(type, 0))) == 0 - -def test_addressof(): - ffi = FFI() - ffi.cdef(""" - struct point_s { int x, y; }; - struct foo_s { int z; struct point_s point; }; - struct point_s sum_coord(struct point_s *); - """) - lib = ffi.verify(""" - struct point_s { int x, y; }; - struct foo_s { int z; struct point_s point; }; - struct point_s sum_coord(struct point_s *point) { - struct point_s r; - r.x = point->x + point->y; - r.y = point->x - point->y; - return r; - } - """) - p = ffi.new("struct foo_s *") - p.point.x = 16 - p.point.y = 9 - py.test.raises(TypeError, lib.sum_coord, p.point) - res = lib.sum_coord(ffi.addressof(p.point)) - assert res.x == 25 - assert res.y == 7 - res2 = lib.sum_coord(ffi.addressof(res)) - assert res2.x == 32 - assert res2.y == 18 - py.test.raises(TypeError, lib.sum_coord, res2) - -def test_callback_in_thread(): - py.test.xfail("adapt or remove") - if sys.platform == 'win32': - py.test.skip("pthread only") - import os, subprocess, imp - arg = os.path.join(os.path.dirname(__file__), 'callback_in_thread.py') - g = subprocess.Popen([sys.executable, arg, - os.path.dirname(imp.find_module('cffi')[1])]) - result = g.wait() - assert result == 0 - -def test_keepalive_lib(): - py.test.xfail("adapt or remove") - ffi = FFI() - ffi.cdef("int foobar(void);") - lib = ffi.verify("int foobar(void) { return 42; }") - func = lib.foobar - ffi_r = weakref.ref(ffi) - lib_r = weakref.ref(lib) - del ffi - import gc; gc.collect() # lib stays alive - assert lib_r() is not None - assert ffi_r() is not None - assert func() == 42 - -def test_keepalive_ffi(): - py.test.xfail("adapt or remove") - ffi = FFI() - ffi.cdef("int foobar(void);") - lib = ffi.verify("int foobar(void) { return 42; }") - func = lib.foobar - ffi_r = weakref.ref(ffi) - lib_r = weakref.ref(lib) - del lib - import gc; gc.collect() # ffi stays alive - assert ffi_r() is not None - assert lib_r() is not None - assert func() == 42 - -def test_FILE_stored_in_stdout(): - if not sys.platform.startswith('linux'): - py.test.skip("likely, we cannot assign to stdout") - ffi = FFI() - ffi.cdef("int printf(const char *, ...); FILE *setstdout(FILE *);") - lib = ffi.verify(""" - #include <stdio.h> - FILE *setstdout(FILE *f) { - FILE *result = stdout; - stdout = f; - return result; - } - """) - import os - fdr, fdw = os.pipe() - fw1 = os.fdopen(fdw, 'wb', 256) - old_stdout = lib.setstdout(fw1) - try: - # - fw1.write(b"X") - r = lib.printf(b"hello, %d!\n", ffi.cast("int", 42)) - fw1.close() - assert r == len("hello, 42!\n") - # - finally: - lib.setstdout(old_stdout) - # - result = os.read(fdr, 256) - os.close(fdr) - # the 'X' might remain in the user-level buffer of 'fw1' and - # end up showing up after the 'hello, 42!\n' - assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX" - -def test_FILE_stored_explicitly(): - ffi = FFI() - ffi.cdef("int myprintf(const char *, int); FILE *myfile;") - lib = ffi.verify(""" - #include <stdio.h> - FILE *myfile; - int myprintf(const char *out, int value) { - return fprintf(myfile, out, value); - } - """) - import os - fdr, fdw = os.pipe() - fw1 = os.fdopen(fdw, 'wb', 256) - lib.myfile = ffi.cast("FILE *", fw1) - # - fw1.write(b"X") - r = lib.myprintf(b"hello, %d!\n", ffi.cast("int", 42)) - fw1.close() - assert r == len("hello, 42!\n") - # - result = os.read(fdr, 256) - os.close(fdr) - # the 'X' might remain in the user-level buffer of 'fw1' and - # end up showing up after the 'hello, 42!\n' - assert result == b"Xhello, 42!\n" or result == b"hello, 42!\nX" - -def test_global_array_with_missing_length(): - ffi = FFI() - ffi.cdef("int fooarray[];") - lib = ffi.verify("int fooarray[50];") - assert repr(lib.fooarray).startswith("<cdata 'int *'") - -def test_global_array_with_dotdotdot_length(): - ffi = FFI() - ffi.cdef("int fooarray[...];") - lib = ffi.verify("int fooarray[50];") - assert repr(lib.fooarray).startswith("<cdata 'int[50]'") - -def test_bad_global_array_with_dotdotdot_length(): - py.test.xfail("was detected only because 23 bytes cannot be divided by 4; " - "redo more generally") - ffi = FFI() - ffi.cdef("int fooarray[...];") - py.test.raises(VerificationError, ffi.verify, "char fooarray[23];") - -def test_struct_containing_struct(): - ffi = FFI() - ffi.cdef("struct foo_s { ...; }; struct bar_s { struct foo_s f; ...; };") - ffi.verify("struct foo_s { int x; }; struct bar_s { struct foo_s f; };") - # - ffi = FFI() - ffi.cdef("struct foo_s { struct bar_s f; ...; }; struct bar_s { ...; };") - ffi.verify("struct bar_s { int x; }; struct foo_s { struct bar_s f; };") - -def test_struct_returned_by_func(): - ffi = FFI() - ffi.cdef("typedef ... foo_t; foo_t myfunc(void);") - e = py.test.raises(TypeError, ffi.verify, - "typedef struct { int x; } foo_t; " - "foo_t myfunc(void) { foo_t x = { 42 }; return x; }") - assert str(e.value) == ( - "function myfunc: 'foo_t' is used as result type, but is opaque") - -def test_include(): - ffi1 = FFI() - ffi1.cdef("typedef struct { int x; ...; } foo_t;") - ffi1.verify("typedef struct { int y, x; } foo_t;") - ffi2 = FFI() - ffi2.include(ffi1) - ffi2.cdef("int myfunc(foo_t *);") - lib = ffi2.verify("typedef struct { int y, x; } foo_t;" - "int myfunc(foo_t *p) { return 42 * p->x; }") - res = lib.myfunc(ffi2.new("foo_t *", {'x': 10})) - assert res == 420 - res = lib.myfunc(ffi1.new("foo_t *", {'x': -10})) - assert res == -420 - -def test_include_enum(): - ffi1 = FFI() - ffi1.cdef("enum foo_e { AA, ... };") - lib1 = ffi1.verify("enum foo_e { CC, BB, AA };") - ffi2 = FFI() - ffi2.include(ffi1) - ffi2.cdef("int myfunc(enum foo_e);") - lib2 = ffi2.verify("enum foo_e { CC, BB, AA };" - "int myfunc(enum foo_e x) { return (int)x; }") - res = lib2.myfunc(lib2.AA) - assert res == 2 - -def test_named_pointer_as_argument(): - ffi = FFI() - ffi.cdef("typedef struct { int x; } *mystruct_p;\n" - "mystruct_p ff5a(mystruct_p);") - lib = ffi.verify("typedef struct { int x; } *mystruct_p;\n" - "mystruct_p ff5a(mystruct_p p) { p->x += 40; return p; }") - p = ffi.new("mystruct_p", [-2]) - q = lib.ff5a(p) - assert q == p - assert p.x == 38 - -def test_enum_size(): - cases = [('123', 4, 4294967295), - ('4294967295U', 4, 4294967295), - ('-123', 4, -1), - ('-2147483647-1', 4, -1), - ] - if FFI().sizeof("long") == 8: - cases += [('4294967296L', 8, 2**64-1), - ('%dUL' % (2**64-1), 8, 2**64-1), - ('-2147483649L', 8, -1), - ('%dL-1L' % (1-2**63), 8, -1)] - for hidden_value, expected_size, expected_minus1 in cases: - if sys.platform == 'win32' and 'U' in hidden_value: - continue # skipped on Windows - ffi = FFI() - ffi.cdef("enum foo_e { AA, BB, ... };") - lib = ffi.verify("enum foo_e { AA, BB=%s };" % hidden_value) - assert lib.AA == 0 - assert lib.BB == eval(hidden_value.replace('U', '').replace('L', '')) - assert ffi.sizeof("enum foo_e") == expected_size - if sys.platform != 'win32': - assert int(ffi.cast("enum foo_e", -1)) == expected_minus1 - # test with the large value hidden: - # disabled so far, doesn't work -## for hidden_value, expected_size, expected_minus1 in cases: -## ffi = FFI() -## ffi.cdef("enum foo_e { AA, BB, ... };") -## lib = ffi.verify("enum foo_e { AA, BB=%s };" % hidden_value) -## assert lib.AA == 0 -## assert ffi.sizeof("enum foo_e") == expected_size -## assert int(ffi.cast("enum foo_e", -1)) == expected_minus1 - -def test_enum_bug118(): - maxulong = 256 ** FFI().sizeof("unsigned long") - 1 - for c2, c2c in [(-1, ''), - (-1, ''), - (0xffffffff, 'U'), - (maxulong, 'UL'), - (-int(maxulong / 3), 'L')]: - if c2c and sys.platform == 'win32': - continue # enums may always be signed with MSVC - ffi = FFI() - ffi.cdef("enum foo_e { AA };") - lib = ffi.verify("enum foo_e { AA=%s%s };" % (c2, c2c)) - assert lib.AA == c2 - -def test_string_to_voidp_arg(): - ffi = FFI() - ffi.cdef("int myfunc(void *);") - lib = ffi.verify("int myfunc(void *p) { return ((signed char *)p)[0]; }") - res = lib.myfunc(b"hi!") - assert res == ord(b"h") - p = ffi.new("char[]", b"gah") - res = lib.myfunc(p) - assert res == ord(b"g") - res = lib.myfunc(ffi.cast("void *", p)) - assert res == ord(b"g") - res = lib.myfunc(ffi.cast("int *", p)) - assert res == ord(b"g") - -def test_callback_indirection(): - ffi = FFI() - ffi.cdef(""" - int (*python_callback)(int how_many, int *values); - int (*const c_callback)(int,...); /* pass this ptr to C routines */ - int some_c_function(int(*cb)(int,...)); - """) - lib = ffi.verify(""" - #include <stdarg.h> - #ifdef _WIN32 - #include <malloc.h> - #define alloca _alloca - #else - # ifdef __FreeBSD__ - # include <stdlib.h> - # else - # include <alloca.h> - # endif - #endif - static int (*python_callback)(int how_many, int *values); - static int c_callback(int how_many, ...) { - va_list ap; - /* collect the "..." arguments into the values[] array */ - int i, *values = alloca((size_t)how_many * sizeof(int)); - va_start(ap, how_many); - for (i=0; i<how_many; i++) - values[i] = va_arg(ap, int); - va_end(ap); - return python_callback(how_many, values); - } - int some_c_function(int(*cb)(int,...)) { - int result = cb(2, 10, 20); - result += cb(3, 30, 40, 50); - return result; - } - """) - seen = [] - @ffi.callback("int(int, int*)") - def python_callback(how_many, values): - seen.append([values[i] for i in range(how_many)]) - return 42 - lib.python_callback = python_callback - - res = lib.some_c_function(lib.c_callback) - assert res == 84 - assert seen == [[10, 20], [30, 40, 50]] - -def test_floatstar_argument(): - ffi = FFI() - ffi.cdef("float sum3floats(float *);") - lib = ffi.verify(""" - float sum3floats(float *f) { - return f[0] + f[1] + f[2]; - } - """) - assert lib.sum3floats((1.5, 2.5, 3.5)) == 7.5 - p = ffi.new("float[]", (1.5, 2.5, 3.5)) - assert lib.sum3floats(p) == 7.5 - -def test_charstar_argument(): - ffi = FFI() - ffi.cdef("char sum3chars(char *);") - lib = ffi.verify(""" - char sum3chars(char *f) { - return (char)(f[0] + f[1] + f[2]); - } - """) - assert lib.sum3chars((b'\x10', b'\x20', b'\x30')) == b'\x60' - p = ffi.new("char[]", b'\x10\x20\x30') - assert lib.sum3chars(p) == b'\x60' - -def test_passing_string_or_NULL(): - ffi = FFI() - ffi.cdef("int seeme1(char *); int seeme2(int *);") - lib = ffi.verify(""" - int seeme1(char *x) { - return (x == NULL); - } - int seeme2(int *x) { - return (x == NULL); - } - """) - assert lib.seeme1(b"foo") == 0 - assert lib.seeme1(ffi.NULL) == 1 - assert lib.seeme2([42, 43]) == 0 - assert lib.seeme2(ffi.NULL) == 1 - py.test.raises(TypeError, lib.seeme1, None) - py.test.raises(TypeError, lib.seeme2, None) - py.test.raises(TypeError, lib.seeme1, 0.0) - py.test.raises(TypeError, lib.seeme2, 0.0) - py.test.raises(TypeError, lib.seeme1, 0) - py.test.raises(TypeError, lib.seeme2, 0) - zeroL = 99999999999999999999 - zeroL -= 99999999999999999999 - py.test.raises(TypeError, lib.seeme2, zeroL) - -def test_typeof_function(): - ffi = FFI() - ffi.cdef("int foo(int, char);") - lib = ffi.verify("int foo(int x, char y) { (void)x; (void)y; return 42; }") - ctype = ffi.typeof(lib.foo) - assert len(ctype.args) == 2 - assert ctype.result == ffi.typeof("int") - -def test_call_with_voidstar_arg(): - ffi = FFI() - ffi.cdef("int f(void *);") - lib = ffi.verify("int f(void *x) { return ((char*)x)[0]; }") - assert lib.f(b"foobar") == ord(b"f") - -def test_dir(): - ffi = FFI() - ffi.cdef("""void somefunc(void); - extern int somevar, somearray[2]; - static char *const sv2; - enum my_e { AA, BB, ... }; - #define FOO ...""") - lib = ffi.verify("""void somefunc(void) { } - int somevar, somearray[2]; - #define sv2 "text" - enum my_e { AA, BB }; - #define FOO 42""") - assert dir(lib) == ['AA', 'BB', 'FOO', 'somearray', - 'somefunc', 'somevar', 'sv2'] - -def test_typeof_func_with_struct_argument(): - ffi = FFI() - ffi.cdef("""struct s { int a; }; int foo(struct s);""") - lib = ffi.verify("""struct s { int a; }; - int foo(struct s x) { return x.a; }""") - s = ffi.new("struct s *", [-1234]) - m = lib.foo(s[0]) - assert m == -1234 - assert repr(ffi.typeof(lib.foo)) == "<ctype 'int(*)(struct s)'>" - -def test_bug_const_char_ptr_array_1(): - ffi = FFI() - ffi.cdef("""const char *a[...];""") - lib = ffi.verify("""const char *a[5];""") - assert repr(ffi.typeof(lib.a)) == "<ctype 'char *[5]'>" - -def test_bug_const_char_ptr_array_2(): - ffi = FFI_warnings_not_error() # ignore warnings - ffi.cdef("""const int a[];""") - lib = ffi.verify("""const int a[5];""") - assert repr(ffi.typeof(lib.a)) == "<ctype 'int *'>" - -def _test_various_calls(force_libffi): - cdef_source = """ - int xvalue; - long long ivalue, rvalue; - float fvalue; - double dvalue; - long double Dvalue; - signed char tf_bb(signed char x, signed char c); - unsigned char tf_bB(signed char x, unsigned char c); - short tf_bh(signed char x, short c); - unsigned short tf_bH(signed char x, unsigned short c); - int tf_bi(signed char x, int c); - unsigned int tf_bI(signed char x, unsigned int c); - long tf_bl(signed char x, long c); - unsigned long tf_bL(signed char x, unsigned long c); - long long tf_bq(signed char x, long long c); - unsigned long long tf_bQ(signed char x, unsigned long long c); - float tf_bf(signed char x, float c); - double tf_bd(signed char x, double c); - long double tf_bD(signed char x, long double c); - """ - if force_libffi: - cdef_source = (cdef_source - .replace('tf_', '(*const tf_') - .replace('(signed char x', ')(signed char x')) - ffi = FFI() - ffi.cdef(cdef_source) - lib = ffi.verify(""" - int xvalue; - long long ivalue, rvalue; - float fvalue; - double dvalue; - long double Dvalue; - - typedef signed char b_t; - typedef unsigned char B_t; - typedef short h_t; - typedef unsigned short H_t; - typedef int i_t; - typedef unsigned int I_t; - typedef long l_t; - typedef unsigned long L_t; - typedef long long q_t; - typedef unsigned long long Q_t; - typedef float f_t; - typedef double d_t; - typedef long double D_t; - #define S(letter) xvalue = (int)x; letter##value = (letter##_t)c; - #define R(letter) return (letter##_t)rvalue; - - signed char tf_bb(signed char x, signed char c) { S(i) R(b) } - unsigned char tf_bB(signed char x, unsigned char c) { S(i) R(B) } - short tf_bh(signed char x, short c) { S(i) R(h) } - unsigned short tf_bH(signed char x, unsigned short c) { S(i) R(H) } - int tf_bi(signed char x, int c) { S(i) R(i) } - unsigned int tf_bI(signed char x, unsigned int c) { S(i) R(I) } - long tf_bl(signed char x, long c) { S(i) R(l) } - unsigned long tf_bL(signed char x, unsigned long c) { S(i) R(L) } - long long tf_bq(signed char x, long long c) { S(i) R(q) } - unsigned long long tf_bQ(signed char x, unsigned long long c) { S(i) R(Q) } - float tf_bf(signed char x, float c) { S(f) R(f) } - double tf_bd(signed char x, double c) { S(d) R(d) } - long double tf_bD(signed char x, long double c) { S(D) R(D) } - """) - lib.rvalue = 0x7182838485868788 - for kind, cname in [('b', 'signed char'), - ('B', 'unsigned char'), - ('h', 'short'), - ('H', 'unsigned short'), - ('i', 'int'), - ('I', 'unsigned int'), - ('l', 'long'), - ('L', 'unsigned long'), - ('q', 'long long'), - ('Q', 'unsigned long long'), - ('f', 'float'), - ('d', 'double'), - ('D', 'long double')]: - sign = +1 if 'unsigned' in cname else -1 - lib.xvalue = 0 - lib.ivalue = 0 - lib.fvalue = 0 - lib.dvalue = 0 - lib.Dvalue = 0 - fun = getattr(lib, 'tf_b' + kind) - res = fun(-42, sign * 99) - if kind == 'D': - res = float(res) - assert res == int(ffi.cast(cname, 0x7182838485868788)) - assert lib.xvalue == -42 - if kind in 'fdD': - assert float(getattr(lib, kind + 'value')) == -99.0 - else: - assert lib.ivalue == sign * 99 - -def test_various_calls_direct(): - _test_various_calls(force_libffi=False) - -def test_various_calls_libffi(): - _test_various_calls(force_libffi=True) - -def test_ptr_to_opaque(): - ffi = FFI() - ffi.cdef("typedef ... foo_t; int f1(foo_t*); foo_t *f2(int);") - lib = ffi.verify(""" - #include <stdlib.h> - typedef struct { int x; } foo_t; - int f1(foo_t* p) { - int x = p->x; - free(p); - return x; - } - foo_t *f2(int x) { - foo_t *p = malloc(sizeof(foo_t)); - p->x = x; - return p; - } - """) - p = lib.f2(42) - x = lib.f1(p) - assert x == 42 - -def _run_in_multiple_threads(test1): - test1() - import sys - try: - import thread - except ImportError: - import _thread as thread - errors = [] - def wrapper(lock): - try: - test1() - except: - errors.append(sys.exc_info()) - lock.release() - locks = [] - for i in range(10): - _lock = thread.allocate_lock() - _lock.acquire() - thread.start_new_thread(wrapper, (_lock,)) - locks.append(_lock) - for _lock in locks: - _lock.acquire() - if errors: - raise errors[0][1] - -def test_errno_working_even_with_pypys_jit(): - ffi = FFI() - ffi.cdef("int f(int);") - lib = ffi.verify(""" - #include <errno.h> - int f(int x) { return (errno = errno + x); } - """) - @_run_in_multiple_threads - def test1(): - ffi.errno = 0 - for i in range(10000): - e = lib.f(1) - assert e == i + 1 - assert ffi.errno == e - for i in range(10000): - ffi.errno = i - e = lib.f(42) - assert e == i + 42 - -def test_getlasterror_working_even_with_pypys_jit(): - if sys.platform != 'win32': - py.test.skip("win32-only test") - ffi = FFI() - ffi.cdef("void SetLastError(DWORD);") - lib = ffi.dlopen("Kernel32.dll") - @_run_in_multiple_threads - def test1(): - for i in range(10000): - n = (1 << 29) + i - lib.SetLastError(n) - assert ffi.getwinerror()[0] == n - -def test_verify_dlopen_flags(): - if not hasattr(sys, 'setdlopenflags'): - py.test.skip("requires sys.setdlopenflags()") - # Careful with RTLD_GLOBAL. If by chance the FFI is not deleted - # promptly, like on PyPy, then other tests may see the same - # exported symbols as well. So we must not export a simple name - # like 'foo'! - old = sys.getdlopenflags() - try: - ffi1 = FFI() - ffi1.cdef("int foo_verify_dlopen_flags;") - - sys.setdlopenflags(ffi1.RTLD_GLOBAL | ffi1.RTLD_LAZY) - lib1 = ffi1.verify("int foo_verify_dlopen_flags;") - lib2 = get_second_lib() - - lib1.foo_verify_dlopen_flags = 42 - assert lib2.foo_verify_dlopen_flags == 42 - lib2.foo_verify_dlopen_flags += 1 - assert lib1.foo_verify_dlopen_flags == 43 - finally: - sys.setdlopenflags(old) - -def get_second_lib(): - # Hack, using modulename makes the test fail - ffi2 = FFI() - ffi2.cdef("int foo_verify_dlopen_flags;") - lib2 = ffi2.verify("int foo_verify_dlopen_flags;", - flags=ffi2.RTLD_GLOBAL | ffi2.RTLD_LAZY) - return lib2 - -def test_consider_not_implemented_function_type(): - ffi = FFI() - ffi.cdef("typedef union { int a; float b; } Data;" - "typedef struct { int a:2; } MyStr;" - "typedef void (*foofunc_t)(Data);" - "typedef Data (*bazfunc_t)(void);" - "typedef MyStr (*barfunc_t)(void);") - fooptr = ffi.cast("foofunc_t", 123) - bazptr = ffi.cast("bazfunc_t", 123) - barptr = ffi.cast("barfunc_t", 123) - # assert did not crash so far - e = py.test.raises(NotImplementedError, fooptr, ffi.new("Data *")) - assert str(e.value) == ( - "ctype 'Data' (size 4) not supported as argument") - e = py.test.raises(NotImplementedError, bazptr) - assert str(e.value) == ( - "ctype 'Data' (size 4) not supported as return value") - e = py.test.raises(NotImplementedError, barptr) - assert str(e.value) == ( - "ctype 'MyStr' not supported as return value " - "(it is a struct with bit fields)") - -def test_verify_extra_arguments(): - ffi = FFI() - ffi.cdef("#define ABA ...") - lib = ffi.verify("", define_macros=[('ABA', '42')]) - assert lib.ABA == 42 - -def test_implicit_unicode_on_windows(): - from cffi import FFIError - if sys.platform != 'win32': - py.test.skip("win32-only test") - ffi = FFI() - e = py.test.raises(FFIError, ffi.cdef, "int foo(LPTSTR);") - assert str(e.value) == ("The Windows type 'LPTSTR' is only available after" - " you call ffi.set_unicode()") - for with_unicode in [True, False]: - ffi = FFI() - ffi.set_unicode(with_unicode) - ffi.cdef(""" - DWORD GetModuleFileName(HMODULE hModule, LPTSTR lpFilename, - DWORD nSize); - """) - lib = ffi.verify(""" - #include <windows.h> - """, libraries=['Kernel32']) - outbuf = ffi.new("TCHAR[]", 200) - n = lib.GetModuleFileName(ffi.NULL, outbuf, 500) - assert 0 < n < 500 - for i in range(n): - #print repr(outbuf[i]) - assert ord(outbuf[i]) != 0 - assert ord(outbuf[n]) == 0 - assert ord(outbuf[0]) < 128 # should be a letter, or '\' - -def test_define_known_value(): - ffi = FFI() - ffi.cdef("#define FOO 0x123") - lib = ffi.verify("#define FOO 0x123") - assert lib.FOO == 0x123 - -def test_define_wrong_value(): - ffi = FFI() - ffi.cdef("#define FOO 123") - lib = ffi.verify("#define FOO 124") # used to complain - e = py.test.raises(ffi.error, "lib.FOO") - assert str(e.value) == ("the C compiler says 'FOO' is equal to 124 (0x7c)," - " but the cdef disagrees") diff --git a/_cffi1/udir.py b/_cffi1/udir.py deleted file mode 100644 index bbdd744..0000000 --- a/_cffi1/udir.py +++ /dev/null @@ -1,3 +0,0 @@ -import py - -udir = py.path.local.make_numbered_dir(prefix = 'cffi1-') |
