summaryrefslogtreecommitdiff
path: root/_cffi1
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2015-05-12 11:07:25 +0200
committerArmin Rigo <arigo@tunes.org>2015-05-12 11:07:25 +0200
commitfe4bb73d2191ea7b2ee5586848e1c5bbbcbaa72b (patch)
tree5c80d5c2ee50bc8e99039c7483522e2febc08cb7 /_cffi1
parent34dbd9932de50a5de29f0fdaab9e9a06526d93a7 (diff)
downloadcffi-fe4bb73d2191ea7b2ee5586848e1c5bbbcbaa72b.tar.gz
the big Moving Files Around step
Diffstat (limited to '_cffi1')
-rw-r--r--_cffi1/__init__.py1
-rw-r--r--_cffi1/_cffi_include.h202
-rw-r--r--_cffi1/cdlopen.c347
-rw-r--r--_cffi1/cffi1_module.c183
-rw-r--r--_cffi1/cffi_opcode.py146
-rw-r--r--_cffi1/cgc.c80
-rw-r--r--_cffi1/cglob.c72
-rw-r--r--_cffi1/ffi_obj.c814
-rw-r--r--_cffi1/lib_obj.c495
-rw-r--r--_cffi1/manual.c169
-rw-r--r--_cffi1/manual2.py34
-rw-r--r--_cffi1/parse_c_type.c760
-rw-r--r--_cffi1/parse_c_type.h161
-rw-r--r--_cffi1/realize_c_type.c715
-rw-r--r--_cffi1/recompiler.py955
-rw-r--r--_cffi1/setup.py6
-rw-r--r--_cffi1/setup_manual.py5
-rw-r--r--_cffi1/setuptools_ext.py82
-rw-r--r--_cffi1/support.py19
-rw-r--r--_cffi1/test_cffi_binary.py20
-rw-r--r--_cffi1/test_dlopen.py57
-rw-r--r--_cffi1/test_ffi_obj.py180
-rw-r--r--_cffi1/test_new_ffi_1.py1658
-rw-r--r--_cffi1/test_parse_c_type.py339
-rw-r--r--_cffi1/test_realize_c_type.py48
-rw-r--r--_cffi1/test_recompiler.py745
-rw-r--r--_cffi1/test_unicode_literals.py43
-rw-r--r--_cffi1/test_verify1.py2201
-rw-r--r--_cffi1/udir.py3
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-')