aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorarcadia-devtools <arcadia-devtools@yandex-team.ru>2022-07-05 16:12:08 +0300
committerarcadia-devtools <arcadia-devtools@yandex-team.ru>2022-07-05 16:12:08 +0300
commitabfeb6ada0ba12078673d7ae3ec6d30f4d495198 (patch)
treea231d11fbd8797f99ba18cdfd6372e480ee35e45
parent19faef2e52f1f3ab4ba7675f354554ffc9712c98 (diff)
downloadydb-abfeb6ada0ba12078673d7ae3ec6d30f4d495198.tar.gz
intermediate changes
ref:f2015db1a1c46f10e1e26fd57a923c66d3c80954
-rw-r--r--contrib/python/cffi/.dist-info/METADATA5
-rw-r--r--contrib/python/cffi/.dist-info/entry_points.txt1
-rw-r--r--contrib/python/cffi/.yandex_meta/yamaker.yaml22
-rw-r--r--contrib/python/cffi/c/_cffi_backend.c44
-rw-r--r--contrib/python/cffi/c/libffi_msvc/ffi.c495
-rw-r--r--contrib/python/cffi/c/libffi_msvc/ffi.h322
-rw-r--r--contrib/python/cffi/c/libffi_msvc/ffi_common.h77
-rw-r--r--contrib/python/cffi/c/libffi_msvc/fficonfig.h96
-rw-r--r--contrib/python/cffi/c/libffi_msvc/ffitarget.h85
-rw-r--r--contrib/python/cffi/c/libffi_msvc/prep_cif.c184
-rw-r--r--contrib/python/cffi/c/libffi_msvc/types.c104
-rw-r--r--contrib/python/cffi/c/libffi_msvc/win32.c162
-rw-r--r--contrib/python/cffi/c/libffi_msvc/win64.asm156
-rw-r--r--contrib/python/cffi/c/libffi_msvc/win64.objbin1176 -> 0 bytes
-rw-r--r--contrib/python/cffi/c/test_c.py4575
-rw-r--r--contrib/python/cffi/cffi/__init__.py4
-rw-r--r--contrib/python/cffi/cffi/_embedding.h5
-rw-r--r--contrib/python/cffi/cffi/recompiler.py4
-rw-r--r--contrib/python/cffi/patches/01-arcadia.patch118
-rw-r--r--contrib/python/cffi/patches/02-fix-ya.make.patch22
20 files changed, 206 insertions, 6275 deletions
diff --git a/contrib/python/cffi/.dist-info/METADATA b/contrib/python/cffi/.dist-info/METADATA
index b708a09f610..538e679147a 100644
--- a/contrib/python/cffi/.dist-info/METADATA
+++ b/contrib/python/cffi/.dist-info/METADATA
@@ -1,12 +1,11 @@
Metadata-Version: 2.1
Name: cffi
-Version: 1.15.0
+Version: 1.15.1
Summary: Foreign Function Interface for Python calling C code.
Home-page: http://cffi.readthedocs.org
Author: Armin Rigo, Maciej Fijalkowski
Author-email: python-cffi@googlegroups.com
License: MIT
-Platform: UNKNOWN
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
@@ -33,5 +32,3 @@ Contact
-------
`Mailing list <https://groups.google.com/forum/#!forum/python-cffi>`_
-
-
diff --git a/contrib/python/cffi/.dist-info/entry_points.txt b/contrib/python/cffi/.dist-info/entry_points.txt
index eee7e0fb1f4..4b0274f2333 100644
--- a/contrib/python/cffi/.dist-info/entry_points.txt
+++ b/contrib/python/cffi/.dist-info/entry_points.txt
@@ -1,3 +1,2 @@
[distutils.setup_keywords]
cffi_modules = cffi.setuptools_ext:cffi_modules
-
diff --git a/contrib/python/cffi/.yandex_meta/yamaker.yaml b/contrib/python/cffi/.yandex_meta/yamaker.yaml
new file mode 100644
index 00000000000..63a9e8792e2
--- /dev/null
+++ b/contrib/python/cffi/.yandex_meta/yamaker.yaml
@@ -0,0 +1,22 @@
+additional_requirements:
+- contrib/restricted/libffi
+copy:
+- c/*
+exclude:
+- c/libffi_*
+- c/test_c.py
+exclude_from_macros:
+- c/call_python.c
+- c/cdlopen.c
+- c/cffi1_module.c
+- c/cglob.c
+- c/commontypes.c
+- c/ffi_obj.c
+- c/lib_obj.c
+- c/parse_c_type.c
+- c/realize_c_type.c
+- gen/*
+- lsan.supp
+keep:
+- gen/*
+- lsan.supp
diff --git a/contrib/python/cffi/c/_cffi_backend.c b/contrib/python/cffi/c/_cffi_backend.c
index a92402b6a22..58f6666f026 100644
--- a/contrib/python/cffi/c/_cffi_backend.c
+++ b/contrib/python/cffi/c/_cffi_backend.c
@@ -2,7 +2,7 @@
#include <Python.h>
#include "structmember.h"
-#define CFFI_VERSION "1.15.0"
+#define CFFI_VERSION "1.15.1"
#ifdef MS_WIN32
#include <windows.h>
@@ -2196,7 +2196,7 @@ static PyObject *_frombuf_repr(CDataObject *cd, const char *cd_type_name)
}
}
-static PyObject *cdataowning_repr(CDataObject *cd)
+static Py_ssize_t cdataowning_size_bytes(CDataObject *cd)
{
Py_ssize_t size = _cdata_var_byte_size(cd);
if (size < 0) {
@@ -2207,6 +2207,12 @@ static PyObject *cdataowning_repr(CDataObject *cd)
else
size = cd->c_type->ct_size;
}
+ return size;
+}
+
+static PyObject *cdataowning_repr(CDataObject *cd)
+{
+ Py_ssize_t size = cdataowning_size_bytes(cd);
return PyText_FromFormat("<cdata '%s' owning %zd bytes>",
cd->c_type->ct_name, size);
}
@@ -4602,7 +4608,7 @@ static PyObject *get_unique_type(CTypeDescrObject *x,
array [ctype, length]
funcptr [ctresult, ellipsis+abi, num_args, ctargs...]
*/
- PyObject *key, *y;
+ PyObject *key, *y, *res;
void *pkey;
key = PyBytes_FromStringAndSize(NULL, keylength * sizeof(void *));
@@ -4634,8 +4640,9 @@ static PyObject *get_unique_type(CTypeDescrObject *x,
/* the 'value' in unique_cache doesn't count as 1, but don't use
Py_DECREF(x) here because it will confuse debug builds into thinking
there was an extra DECREF in total. */
- ((PyObject *)x)->ob_refcnt--;
- return (PyObject *)x;
+ res = (PyObject *)x;
+ Py_SET_REFCNT(res, Py_REFCNT(res) - 1);
+ return res;
error:
Py_DECREF(x);
@@ -5664,7 +5671,8 @@ static ffi_type *fb_fill_type(struct funcbuilder_s *fb, CTypeDescrObject *ct,
}
}
-#define ALIGN_ARG(n) ((n) + 7) & ~7
+#define ALIGN_TO(n, a) ((n) + ((a)-1)) & ~((a)-1)
+#define ALIGN_ARG(n) ALIGN_TO(n, 8)
static int fb_build(struct funcbuilder_s *fb, PyObject *fargs,
CTypeDescrObject *fresult)
@@ -5689,10 +5697,12 @@ static int fb_build(struct funcbuilder_s *fb, PyObject *fargs,
/* exchange data size */
/* first, enough room for an array of 'nargs' pointers */
exchange_offset = nargs * sizeof(void*);
+ /* then enough room for the result --- which means at least
+ sizeof(ffi_arg), according to the ffi docs, but we also
+ align according to the result type, for issue #531 */
+ exchange_offset = ALIGN_TO(exchange_offset, fb->rtype->alignment);
exchange_offset = ALIGN_ARG(exchange_offset);
cif_descr->exchange_offset_arg[0] = exchange_offset;
- /* then enough room for the result --- which means at least
- sizeof(ffi_arg), according to the ffi docs */
i = fb->rtype->size;
if (i < (Py_ssize_t)sizeof(ffi_arg))
i = sizeof(ffi_arg);
@@ -5720,6 +5730,7 @@ static int fb_build(struct funcbuilder_s *fb, PyObject *fargs,
if (fb->atypes != NULL) {
fb->atypes[i] = atype;
/* exchange data size */
+ exchange_offset = ALIGN_TO(exchange_offset, atype->alignment);
exchange_offset = ALIGN_ARG(exchange_offset);
cif_descr->exchange_offset_arg[1 + i] = exchange_offset;
exchange_offset += atype->size;
@@ -5736,6 +5747,7 @@ static int fb_build(struct funcbuilder_s *fb, PyObject *fargs,
}
#undef ALIGN_ARG
+#undef ALIGN_TO
static void fb_cat_name(struct funcbuilder_s *fb, const char *piece,
int piecelen)
@@ -7009,12 +7021,14 @@ b_buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
/* this is the constructor of the type implemented in minibuffer.h */
CDataObject *cd;
Py_ssize_t size = -1;
+ int explicit_size;
static char *keywords[] = {"cdata", "size", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|n:buffer", keywords,
&CData_Type, &cd, &size))
return NULL;
+ explicit_size = size >= 0;
if (size < 0)
size = _cdata_var_byte_size(cd);
@@ -7038,6 +7052,20 @@ b_buffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
cd->c_type->ct_name);
return NULL;
}
+
+ if (explicit_size && CDataOwn_Check(cd)) {
+ Py_ssize_t size_max = cdataowning_size_bytes(cd);
+ if (size > size_max) {
+ char msg[256];
+ sprintf(msg, "ffi.buffer(cdata, bytes): creating a buffer of %llu "
+ "bytes over a cdata that owns only %llu bytes. This "
+ "will crash if you access the extra memory",
+ (unsigned PY_LONG_LONG)size,
+ (unsigned PY_LONG_LONG)size_max);
+ if (PyErr_WarnEx(PyExc_UserWarning, msg, 1))
+ return NULL;
+ }
+ }
/*WRITE(cd->c_data, size)*/
return minibuffer_new(cd->c_data, size, (PyObject *)cd);
}
diff --git a/contrib/python/cffi/c/libffi_msvc/ffi.c b/contrib/python/cffi/c/libffi_msvc/ffi.c
deleted file mode 100644
index 581d6599826..00000000000
--- a/contrib/python/cffi/c/libffi_msvc/ffi.c
+++ /dev/null
@@ -1,495 +0,0 @@
-/* -----------------------------------------------------------------------
- ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc.
- Copyright (c) 2002 Ranjit Mathew
- Copyright (c) 2002 Bo Thorsen
- Copyright (c) 2002 Roger Sayle
-
- x86 Foreign Function Interface
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- ``Software''), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- ----------------------------------------------------------------------- */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-#include <stdlib.h>
-
-/* ffi_prep_args is called by the assembly routine once stack space
- has been allocated for the function's arguments */
-
-extern void Py_FatalError(const char *msg);
-
-/*@-exportheader@*/
-void ffi_prep_args(char *stack, extended_cif *ecif)
-/*@=exportheader@*/
-{
- unsigned int i;
- void **p_argv;
- char *argp;
- ffi_type **p_arg;
-
- argp = stack;
- if (ecif->cif->flags == FFI_TYPE_STRUCT)
- {
- *(void **) argp = ecif->rvalue;
- argp += sizeof(void *);
- }
-
- p_argv = ecif->avalue;
-
- for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
- i != 0;
- i--, p_arg++)
- {
- size_t z;
-
- /* Align if necessary */
- if ((sizeof(void *) - 1) & (size_t) argp)
- argp = (char *) ALIGN(argp, sizeof(void *));
-
- z = (*p_arg)->size;
- if (z < sizeof(int))
- {
- z = sizeof(int);
- switch ((*p_arg)->type)
- {
- case FFI_TYPE_SINT8:
- *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT8:
- *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
- break;
-
- case FFI_TYPE_SINT16:
- *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT16:
- *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
- break;
-
- case FFI_TYPE_SINT32:
- *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
- break;
-
- case FFI_TYPE_UINT32:
- *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
- break;
-
- case FFI_TYPE_STRUCT:
- *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
- break;
-
- default:
- FFI_ASSERT(0);
- }
- }
-#ifdef _WIN64
- else if (z != 1 && z != 2 && z != 4 && z != 8)
- {
- /* On Win64, if a single argument takes more than 8 bytes,
- then it is always passed by reference. */
- *(void **)argp = *p_argv;
- z = 8;
- }
-#endif
- else
- {
- memcpy(argp, *p_argv, z);
- }
- p_argv++;
- argp += z;
- }
-
- if (argp - stack > (long)ecif->cif->bytes)
- {
- Py_FatalError("FFI BUG: not enough stack space for arguments");
- }
- return;
-}
-
-/* Perform machine dependent cif processing */
-ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
-{
- /* Set the return type flag */
- switch (cif->rtype->type)
- {
- case FFI_TYPE_VOID:
- case FFI_TYPE_SINT64:
- case FFI_TYPE_FLOAT:
- case FFI_TYPE_DOUBLE:
- case FFI_TYPE_LONGDOUBLE:
- cif->flags = (unsigned) cif->rtype->type;
- break;
-
- case FFI_TYPE_STRUCT:
- /* MSVC returns small structures in registers. Put in cif->flags
- the value FFI_TYPE_STRUCT only if the structure is big enough;
- otherwise, put the 4- or 8-bytes integer type. */
- if (cif->rtype->size == 1 ||
- cif->rtype->size == 2 ||
- cif->rtype->size == 4)
- cif->flags = FFI_TYPE_INT;
- else if (cif->rtype->size == 8)
- cif->flags = FFI_TYPE_SINT64;
- else
- cif->flags = FFI_TYPE_STRUCT;
- break;
-
- case FFI_TYPE_UINT64:
-#ifdef _WIN64
- case FFI_TYPE_POINTER:
-#endif
- cif->flags = FFI_TYPE_SINT64;
- break;
-
- default:
- cif->flags = FFI_TYPE_INT;
- break;
- }
-
- return FFI_OK;
-}
-
-#ifdef _WIN32
-extern int
-ffi_call_x86(void (*)(char *, extended_cif *),
- /*@out@*/ extended_cif *,
- unsigned, unsigned,
- /*@out@*/ unsigned *,
- void (*fn)());
-#endif
-
-#ifdef _WIN64
-extern int
-ffi_call_AMD64(void (*)(char *, extended_cif *),
- /*@out@*/ extended_cif *,
- unsigned, unsigned,
- /*@out@*/ unsigned *,
- void (*fn)());
-#endif
-
-int
-ffi_call(/*@dependent@*/ ffi_cif *cif,
- void (*fn)(),
- /*@out@*/ void *rvalue,
- /*@dependent@*/ void **avalue)
-{
- extended_cif ecif;
-
- ecif.cif = cif;
- ecif.avalue = avalue;
-
- /* If the return value is a struct and we don't have a return */
- /* value address then we need to make one */
-
- if ((rvalue == NULL) &&
- (cif->flags == FFI_TYPE_STRUCT))
- {
- /*@-sysunrecog@*/
- ecif.rvalue = alloca(cif->rtype->size);
- /*@=sysunrecog@*/
- }
- else
- ecif.rvalue = rvalue;
-
-
- switch (cif->abi)
- {
-#if !defined(_WIN64)
- case FFI_SYSV:
- case FFI_STDCALL:
- return ffi_call_x86(ffi_prep_args, &ecif, cif->bytes,
- cif->flags, ecif.rvalue, fn);
- break;
-#else
- case FFI_SYSV:
- /*@-usedef@*/
- return ffi_call_AMD64(ffi_prep_args, &ecif, cif->bytes,
- cif->flags, ecif.rvalue, fn);
- /*@=usedef@*/
- break;
-#endif
-
- default:
- FFI_ASSERT(0);
- break;
- }
- return -1; /* theller: Hrm. */
-}
-
-
-/** private members **/
-
-static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
- void** args, ffi_cif* cif);
-/* This function is jumped to by the trampoline */
-
-#ifdef _WIN64
-void *
-#else
-static void __fastcall
-#endif
-ffi_closure_SYSV (ffi_closure *closure, char *argp)
-{
- // this is our return value storage
- long double res;
-
- // our various things...
- ffi_cif *cif;
- void **arg_area;
- unsigned short rtype;
- void *resp = (void*)&res;
- void *args = argp + sizeof(void *);
-
- cif = closure->cif;
- arg_area = (void**) alloca (cif->nargs * sizeof (void*));
-
- /* this call will initialize ARG_AREA, such that each
- * element in that array points to the corresponding
- * value on the stack; and if the function returns
- * a structure, it will re-set RESP to point to the
- * structure return address. */
-
- ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif);
-
- (closure->fun) (cif, resp, arg_area, closure->user_data);
-
- rtype = cif->flags;
-
-#if defined(_WIN32) && !defined(_WIN64)
-#ifdef _MSC_VER
- /* now, do a generic return based on the value of rtype */
- if (rtype == FFI_TYPE_INT)
- {
- _asm mov eax, resp ;
- _asm mov eax, [eax] ;
- }
- else if (rtype == FFI_TYPE_FLOAT)
- {
- _asm mov eax, resp ;
- _asm fld DWORD PTR [eax] ;
-// asm ("flds (%0)" : : "r" (resp) : "st" );
- }
- else if (rtype == FFI_TYPE_DOUBLE || rtype == FFI_TYPE_LONGDOUBLE)
- {
- _asm mov eax, resp ;
- _asm fld QWORD PTR [eax] ;
-// asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
- }
- else if (rtype == FFI_TYPE_SINT64)
- {
- _asm mov edx, resp ;
- _asm mov eax, [edx] ;
- _asm mov edx, [edx + 4] ;
-// asm ("movl 0(%0),%%eax;"
-// "movl 4(%0),%%edx"
-// : : "r"(resp)
-// : "eax", "edx");
- }
- else if (rtype == FFI_TYPE_STRUCT)
- {
- _asm mov eax, resp ;
- }
-#else
- /* now, do a generic return based on the value of rtype */
- if (rtype == FFI_TYPE_INT)
- {
- asm ("movl (%0),%%eax" : : "r" (resp) : "eax");
- }
- else if (rtype == FFI_TYPE_FLOAT)
- {
- asm ("flds (%0)" : : "r" (resp) : "st" );
- }
- else if (rtype == FFI_TYPE_DOUBLE || rtype == FFI_TYPE_LONGDOUBLE)
- {
- asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
- }
- else if (rtype == FFI_TYPE_SINT64)
- {
- asm ("movl 0(%0),%%eax;"
- "movl 4(%0),%%edx"
- : : "r"(resp)
- : "eax", "edx");
- }
- else if (rtype == FFI_TYPE_STRUCT)
- {
- asm ("movl %0,%%eax" : : "r" (resp) : "eax");
- }
-#endif
-#endif
-
-#ifdef _WIN64
- /* The result is returned in rax. This does the right thing for
- result types except for floats; we have to 'mov xmm0, rax' in the
- caller to correct this.
- */
- if (rtype == FFI_TYPE_STRUCT)
- return resp;
- return *(void **)resp;
-#endif
-}
-
-/*@-exportheader@*/
-static void
-ffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
- void **avalue, ffi_cif *cif)
-/*@=exportheader@*/
-{
- unsigned int i;
- void **p_argv;
- char *argp;
- ffi_type **p_arg;
-
- argp = stack;
-
- if ( cif->flags == FFI_TYPE_STRUCT ) {
- *rvalue = *(void **) argp;
- argp += 4;
- }
-
- p_argv = avalue;
-
- for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
- {
- size_t z;
-
- /* Align if necessary */
- if ((sizeof(char *) - 1) & (size_t) argp) {
- argp = (char *) ALIGN(argp, sizeof(char*));
- }
-
- z = (*p_arg)->size;
-
- /* because we're little endian, this is what it turns into. */
-
-#ifdef _WIN64
- if (z != 1 && z != 2 && z != 4 && z != 8)
- {
- /* On Win64, if a single argument takes more than 8 bytes,
- then it is always passed by reference. */
- *p_argv = *((void**) argp);
- z = 8;
- }
- else
-#endif
- *p_argv = (void*) argp;
-
- p_argv++;
- argp += z;
- }
-
- return;
-}
-
-/* the cif must already be prep'ed */
-extern void ffi_closure_OUTER();
-
-ffi_status
-ffi_prep_closure_loc (ffi_closure* closure,
- ffi_cif* cif,
- void (*fun)(ffi_cif*,void*,void**,void*),
- void *user_data,
- void *codeloc)
-{
- short bytes;
- char *tramp;
-#ifdef _WIN64
- int mask = 0;
-#endif
- FFI_ASSERT (cif->abi == FFI_SYSV);
-
- if (cif->abi == FFI_SYSV)
- bytes = 0;
-#if !defined(_WIN64)
- else if (cif->abi == FFI_STDCALL)
- bytes = cif->bytes;
-#endif
- else
- return FFI_BAD_ABI;
-
- tramp = &closure->tramp[0];
-
-#define BYTES(text) memcpy(tramp, text, sizeof(text)), tramp += sizeof(text)-1
-#define POINTER(x) *(void**)tramp = (void*)(x), tramp += sizeof(void*)
-#define SHORT(x) *(short*)tramp = x, tramp += sizeof(short)
-#define INT(x) *(int*)tramp = x, tramp += sizeof(int)
-
-#ifdef _WIN64
- if (cif->nargs >= 1 &&
- (cif->arg_types[0]->type == FFI_TYPE_FLOAT
- || cif->arg_types[0]->type == FFI_TYPE_DOUBLE))
- mask |= 1;
- if (cif->nargs >= 2 &&
- (cif->arg_types[1]->type == FFI_TYPE_FLOAT
- || cif->arg_types[1]->type == FFI_TYPE_DOUBLE))
- mask |= 2;
- if (cif->nargs >= 3 &&
- (cif->arg_types[2]->type == FFI_TYPE_FLOAT
- || cif->arg_types[2]->type == FFI_TYPE_DOUBLE))
- mask |= 4;
- if (cif->nargs >= 4 &&
- (cif->arg_types[3]->type == FFI_TYPE_FLOAT
- || cif->arg_types[3]->type == FFI_TYPE_DOUBLE))
- mask |= 8;
-
- /* if we return a non-small struct, then the first argument is a pointer
- * to the return area, and all real arguments are shifted by one */
- if (cif->flags == FFI_TYPE_STRUCT)
- mask = (mask & ~8) << 1;
-
- /* 41 BB ---- mov r11d,mask */
- BYTES("\x41\xBB"); INT(mask);
-
- /* 48 B8 -------- mov rax, closure */
- BYTES("\x48\xB8"); POINTER(closure);
-
- /* 49 BA -------- mov r10, ffi_closure_OUTER */
- BYTES("\x49\xBA"); POINTER(ffi_closure_OUTER);
-
- /* 41 FF E2 jmp r10 */
- BYTES("\x41\xFF\xE2");
-
-#else
-
- /* mov ecx, closure */
- BYTES("\xb9"); POINTER(closure);
-
- /* mov edx, esp */
- BYTES("\x8b\xd4");
-
- /* call ffi_closure_SYSV */
- BYTES("\xe8"); POINTER((char*)&ffi_closure_SYSV - (tramp + 4));
-
- /* ret bytes */
- BYTES("\xc2");
- SHORT(bytes);
-
-#endif
-
- if (tramp - &closure->tramp[0] > FFI_TRAMPOLINE_SIZE)
- Py_FatalError("FFI_TRAMPOLINE_SIZE too small in " __FILE__);
-
- closure->cif = cif;
- closure->user_data = user_data;
- closure->fun = fun;
- return FFI_OK;
-}
diff --git a/contrib/python/cffi/c/libffi_msvc/ffi.h b/contrib/python/cffi/c/libffi_msvc/ffi.h
deleted file mode 100644
index 97cdb59aa8f..00000000000
--- a/contrib/python/cffi/c/libffi_msvc/ffi.h
+++ /dev/null
@@ -1,322 +0,0 @@
-/* -----------------------------------------------------------------*-C-*-
- libffi 2.00-beta - Copyright (c) 1996-2003 Red Hat, Inc.
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- ``Software''), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
-
- ----------------------------------------------------------------------- */
-
-/* -------------------------------------------------------------------
- The basic API is described in the README file.
-
- The raw API is designed to bypass some of the argument packing
- and unpacking on architectures for which it can be avoided.
-
- The closure API allows interpreted functions to be packaged up
- inside a C function pointer, so that they can be called as C functions,
- with no understanding on the client side that they are interpreted.
- It can also be used in other cases in which it is necessary to package
- up a user specified parameter and a function pointer as a single
- function pointer.
-
- The closure API must be implemented in order to get its functionality,
- e.g. for use by gij. Routines are provided to emulate the raw API
- if the underlying platform doesn't allow faster implementation.
-
- More details on the raw and cloure API can be found in:
-
- http://gcc.gnu.org/ml/java/1999-q3/msg00138.html
-
- and
-
- http://gcc.gnu.org/ml/java/1999-q3/msg00174.html
- -------------------------------------------------------------------- */
-
-#ifndef LIBFFI_H
-#define LIBFFI_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Specify which architecture libffi is configured for. */
-//XXX #define X86
-
-/* ---- System configuration information --------------------------------- */
-
-#include <ffitarget.h>
-
-#ifndef LIBFFI_ASM
-
-#include <stddef.h>
-#include <limits.h>
-
-/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).
- But we can find it either under the correct ANSI name, or under GNU
- C's internal name. */
-#ifdef LONG_LONG_MAX
-# define FFI_LONG_LONG_MAX LONG_LONG_MAX
-#else
-# ifdef LLONG_MAX
-# define FFI_LONG_LONG_MAX LLONG_MAX
-# else
-# ifdef __GNUC__
-# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__
-# endif
-# ifdef _MSC_VER
-# define FFI_LONG_LONG_MAX _I64_MAX
-# endif
-# endif
-#endif
-
-#if SCHAR_MAX == 127
-# define ffi_type_uchar ffi_type_uint8
-# define ffi_type_schar ffi_type_sint8
-#else
- #error "char size not supported"
-#endif
-
-#if SHRT_MAX == 32767
-# define ffi_type_ushort ffi_type_uint16
-# define ffi_type_sshort ffi_type_sint16
-#elif SHRT_MAX == 2147483647
-# define ffi_type_ushort ffi_type_uint32
-# define ffi_type_sshort ffi_type_sint32
-#else
- #error "short size not supported"
-#endif
-
-#if INT_MAX == 32767
-# define ffi_type_uint ffi_type_uint16
-# define ffi_type_sint ffi_type_sint16
-#elif INT_MAX == 2147483647
-# define ffi_type_uint ffi_type_uint32
-# define ffi_type_sint ffi_type_sint32
-#elif INT_MAX == 9223372036854775807
-# define ffi_type_uint ffi_type_uint64
-# define ffi_type_sint ffi_type_sint64
-#else
- #error "int size not supported"
-#endif
-
-#define ffi_type_ulong ffi_type_uint64
-#define ffi_type_slong ffi_type_sint64
-#if LONG_MAX == 2147483647
-# if FFI_LONG_LONG_MAX != 9223372036854775807
- #error "no 64-bit data type supported"
-# endif
-#elif LONG_MAX != 9223372036854775807
- #error "long size not supported"
-#endif
-
-/* The closure code assumes that this works on pointers, i.e. a size_t */
-/* can hold a pointer. */
-
-typedef struct _ffi_type
-{
- size_t size;
- unsigned short alignment;
- unsigned short type;
- /*@null@*/ struct _ffi_type **elements;
-} ffi_type;
-
-/* These are defined in types.c */
-extern ffi_type ffi_type_void;
-extern ffi_type ffi_type_uint8;
-extern ffi_type ffi_type_sint8;
-extern ffi_type ffi_type_uint16;
-extern ffi_type ffi_type_sint16;
-extern ffi_type ffi_type_uint32;
-extern ffi_type ffi_type_sint32;
-extern ffi_type ffi_type_uint64;
-extern ffi_type ffi_type_sint64;
-extern ffi_type ffi_type_float;
-extern ffi_type ffi_type_double;
-extern ffi_type ffi_type_longdouble;
-extern ffi_type ffi_type_pointer;
-
-
-typedef enum {
- FFI_OK = 0,
- FFI_BAD_TYPEDEF,
- FFI_BAD_ABI
-} ffi_status;
-
-typedef unsigned FFI_TYPE;
-
-typedef struct {
- ffi_abi abi;
- unsigned nargs;
- /*@dependent@*/ ffi_type **arg_types;
- /*@dependent@*/ ffi_type *rtype;
- unsigned bytes;
- unsigned flags;
-#ifdef FFI_EXTRA_CIF_FIELDS
- FFI_EXTRA_CIF_FIELDS;
-#endif
-} ffi_cif;
-
-/* ---- Definitions for the raw API -------------------------------------- */
-
-#ifdef _WIN64
-#define FFI_SIZEOF_ARG 8
-#else
-#define FFI_SIZEOF_ARG 4
-#endif
-
-typedef union {
- ffi_sarg sint;
- ffi_arg uint;
- float flt;
- char data[FFI_SIZEOF_ARG];
- void* ptr;
-} ffi_raw;
-
-void ffi_raw_call (/*@dependent@*/ ffi_cif *cif,
- void (*fn)(),
- /*@out@*/ void *rvalue,
- /*@dependent@*/ ffi_raw *avalue);
-
-void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
-void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
-size_t ffi_raw_size (ffi_cif *cif);
-
-/* This is analogous to the raw API, except it uses Java parameter */
-/* packing, even on 64-bit machines. I.e. on 64-bit machines */
-/* longs and doubles are followed by an empty 64-bit word. */
-
-void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif,
- void (*fn)(),
- /*@out@*/ void *rvalue,
- /*@dependent@*/ ffi_raw *avalue);
-
-void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);
-void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);
-size_t ffi_java_raw_size (ffi_cif *cif);
-
-/* ---- Definitions for closures ----------------------------------------- */
-
-#if FFI_CLOSURES
-
-typedef struct {
- char tramp[FFI_TRAMPOLINE_SIZE];
- ffi_cif *cif;
- void (*fun)(ffi_cif*,void*,void**,void*);
- void *user_data;
-} ffi_closure;
-
-void ffi_closure_free(void *);
-void *ffi_closure_alloc (size_t size, void **code);
-
-ffi_status
-ffi_prep_closure_loc (ffi_closure*,
- ffi_cif *,
- void (*fun)(ffi_cif*,void*,void**,void*),
- void *user_data,
- void *codeloc);
-
-/* AR: for cffi we need the following API, and not the _loc version */
-#define ffi_prep_closure(a,b,c,d) ffi_prep_closure_loc(a,b,c,d,a)
-
-typedef struct {
- char tramp[FFI_TRAMPOLINE_SIZE];
-
- ffi_cif *cif;
-
-#if !FFI_NATIVE_RAW_API
-
- /* if this is enabled, then a raw closure has the same layout
- as a regular closure. We use this to install an intermediate
- handler to do the transaltion, void** -> ffi_raw*. */
-
- void (*translate_args)(ffi_cif*,void*,void**,void*);
- void *this_closure;
-
-#endif
-
- void (*fun)(ffi_cif*,void*,ffi_raw*,void*);
- void *user_data;
-
-} ffi_raw_closure;
-
-ffi_status
-ffi_prep_raw_closure (ffi_raw_closure*,
- ffi_cif *cif,
- void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
- void *user_data);
-
-ffi_status
-ffi_prep_java_raw_closure (ffi_raw_closure*,
- ffi_cif *cif,
- void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
- void *user_data);
-
-#endif /* FFI_CLOSURES */
-
-/* ---- Public interface definition -------------------------------------- */
-
-ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
- ffi_abi abi,
- unsigned int nargs,
- /*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
- /*@dependent@*/ ffi_type **atypes);
-
-int
-ffi_call(/*@dependent@*/ ffi_cif *cif,
- void (*fn)(),
- /*@out@*/ void *rvalue,
- /*@dependent@*/ void **avalue);
-
-/* Useful for eliminating compiler warnings */
-#define FFI_FN(f) ((void (*)())f)
-
-/* ---- Definitions shared with assembly code ---------------------------- */
-
-#endif
-
-/* If these change, update src/mips/ffitarget.h. */
-#define FFI_TYPE_VOID 0
-#define FFI_TYPE_INT 1
-#define FFI_TYPE_FLOAT 2
-#define FFI_TYPE_DOUBLE 3
-#if 1
-#define FFI_TYPE_LONGDOUBLE 4
-#else
-#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
-#endif
-#define FFI_TYPE_UINT8 5
-#define FFI_TYPE_SINT8 6
-#define FFI_TYPE_UINT16 7
-#define FFI_TYPE_SINT16 8
-#define FFI_TYPE_UINT32 9
-#define FFI_TYPE_SINT32 10
-#define FFI_TYPE_UINT64 11
-#define FFI_TYPE_SINT64 12
-#define FFI_TYPE_STRUCT 13
-#define FFI_TYPE_POINTER 14
-
-/* This should always refer to the last type code (for sanity checks) */
-#define FFI_TYPE_LAST FFI_TYPE_POINTER
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
diff --git a/contrib/python/cffi/c/libffi_msvc/ffi_common.h b/contrib/python/cffi/c/libffi_msvc/ffi_common.h
deleted file mode 100644
index 43fb83b4810..00000000000
--- a/contrib/python/cffi/c/libffi_msvc/ffi_common.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* -----------------------------------------------------------------------
- ffi_common.h - Copyright (c) 1996 Red Hat, Inc.
-
- Common internal definitions and macros. Only necessary for building
- libffi.
- ----------------------------------------------------------------------- */
-
-#ifndef FFI_COMMON_H
-#define FFI_COMMON_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <fficonfig.h>
-#include <malloc.h>
-
-/* Check for the existence of memcpy. */
-#if STDC_HEADERS
-# include <string.h>
-#else
-# ifndef HAVE_MEMCPY
-# define memcpy(d, s, n) bcopy ((s), (d), (n))
-# endif
-#endif
-
-#if defined(FFI_DEBUG)
-#include <stdio.h>
-#endif
-
-#ifdef FFI_DEBUG
-/*@exits@*/ void ffi_assert(/*@temp@*/ char *expr, /*@temp@*/ char *file, int line);
-void ffi_stop_here(void);
-void ffi_type_test(/*@temp@*/ /*@out@*/ ffi_type *a, /*@temp@*/ char *file, int line);
-
-#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
-#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
-#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
-#else
-#define FFI_ASSERT(x)
-#define FFI_ASSERT_AT(x, f, l)
-#define FFI_ASSERT_VALID_TYPE(x)
-#endif
-
-#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1)
-
-/* Perform machine dependent cif processing */
-ffi_status ffi_prep_cif_machdep(ffi_cif *cif);
-
-/* Extended cif, used in callback from assembly routine */
-typedef struct
-{
- /*@dependent@*/ ffi_cif *cif;
- /*@dependent@*/ void *rvalue;
- /*@dependent@*/ void **avalue;
-} extended_cif;
-
-/* Terse sized type definitions. */
-typedef unsigned int UINT8 __attribute__((__mode__(__QI__)));
-typedef signed int SINT8 __attribute__((__mode__(__QI__)));
-typedef unsigned int UINT16 __attribute__((__mode__(__HI__)));
-typedef signed int SINT16 __attribute__((__mode__(__HI__)));
-typedef unsigned int UINT32 __attribute__((__mode__(__SI__)));
-typedef signed int SINT32 __attribute__((__mode__(__SI__)));
-typedef unsigned int UINT64 __attribute__((__mode__(__DI__)));
-typedef signed int SINT64 __attribute__((__mode__(__DI__)));
-
-typedef float FLOAT32;
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-
diff --git a/contrib/python/cffi/c/libffi_msvc/fficonfig.h b/contrib/python/cffi/c/libffi_msvc/fficonfig.h
deleted file mode 100644
index c14f653ec89..00000000000
--- a/contrib/python/cffi/c/libffi_msvc/fficonfig.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* fficonfig.h. Originally created by configure, now hand_maintained for MSVC. */
-
-/* fficonfig.h. Generated automatically by configure. */
-/* fficonfig.h.in. Generated automatically from configure.in by autoheader. */
-
-/* Define this for MSVC, but not for mingw32! */
-#ifdef _MSC_VER
-#define __attribute__(x) /* */
-#endif
-#define alloca _alloca
-
-/*----------------------------------------------------------------*/
-
-/* Define if using alloca.c. */
-/* #undef C_ALLOCA */
-
-/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
- This function is required for alloca.c support on those systems. */
-/* #undef CRAY_STACKSEG_END */
-
-/* Define if you have alloca, as a function or macro. */
-#define HAVE_ALLOCA 1
-
-/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
-/* #define HAVE_ALLOCA_H 1 */
-
-/* If using the C implementation of alloca, define if you know the
- direction of stack growth for your system; otherwise it will be
- automatically deduced at run-time.
- STACK_DIRECTION > 0 => grows toward higher addresses
- STACK_DIRECTION < 0 => grows toward lower addresses
- STACK_DIRECTION = 0 => direction of growth unknown
- */
-/* #undef STACK_DIRECTION */
-
-/* Define if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define if you have the memcpy function. */
-#define HAVE_MEMCPY 1
-
-/* Define if read-only mmap of a plain file works. */
-//#define HAVE_MMAP_FILE 1
-
-/* Define if mmap of /dev/zero works. */
-//#define HAVE_MMAP_DEV_ZERO 1
-
-/* Define if mmap with MAP_ANON(YMOUS) works. */
-//#define HAVE_MMAP_ANON 1
-
-/* The number of bytes in type double */
-#define SIZEOF_DOUBLE 8
-
-/* The number of bytes in type long double */
-#define SIZEOF_LONG_DOUBLE 12
-
-/* Define if you have the long double type and it is bigger than a double */
-#define HAVE_LONG_DOUBLE 1
-
-/* whether byteorder is bigendian */
-/* #undef WORDS_BIGENDIAN */
-
-/* Define if the host machine stores words of multi-word integers in
- big-endian order. */
-/* #undef HOST_WORDS_BIG_ENDIAN */
-
-/* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */
-#define BYTEORDER 1234
-
-/* Define if your assembler and linker support unaligned PC relative relocs. */
-/* #undef HAVE_AS_SPARC_UA_PCREL */
-
-/* Define if your assembler supports .register. */
-/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
-
-/* Define if .eh_frame sections should be read-only. */
-/* #undef HAVE_RO_EH_FRAME */
-
-/* Define to the flags needed for the .section .eh_frame directive. */
-/* #define EH_FRAME_FLAGS "aw" */
-
-/* Define to the flags needed for the .section .eh_frame directive. */
-/* #define EH_FRAME_FLAGS "aw" */
-
-/* Define this if you want extra debugging. */
-/* #undef FFI_DEBUG */
-
-/* Define this is you do not want support for aggregate types. */
-/* #undef FFI_NO_STRUCTS */
-
-/* Define this is you do not want support for the raw API. */
-/* #undef FFI_NO_RAW_API */
-
-/* Define this if you are using Purify and want to suppress spurious messages. */
-/* #undef USING_PURIFY */
-
diff --git a/contrib/python/cffi/c/libffi_msvc/ffitarget.h b/contrib/python/cffi/c/libffi_msvc/ffitarget.h
deleted file mode 100644
index 85f5ee81bbe..00000000000
--- a/contrib/python/cffi/c/libffi_msvc/ffitarget.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
- Target configuration macros for x86 and x86-64.
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- ``Software''), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
-
- ----------------------------------------------------------------------- */
-
-#ifndef LIBFFI_TARGET_H
-#define LIBFFI_TARGET_H
-
-/* ---- System specific configurations ----------------------------------- */
-
-#if defined (X86_64) && defined (__i386__)
-#undef X86_64
-#define X86
-#endif
-
-/* ---- Generic type definitions ----------------------------------------- */
-
-#ifndef LIBFFI_ASM
-#ifndef _WIN64
-typedef unsigned long ffi_arg;
-#else
-typedef unsigned __int64 ffi_arg;
-#endif
-typedef signed long ffi_sarg;
-
-typedef enum ffi_abi {
- FFI_FIRST_ABI = 0,
-
- /* ---- Intel x86 Win32 ---------- */
- FFI_SYSV,
-#ifndef _WIN64
- FFI_STDCALL,
-#endif
- /* TODO: Add fastcall support for the sake of completeness */
- FFI_DEFAULT_ABI = FFI_SYSV,
-
- /* ---- Intel x86 and AMD x86-64 - */
-/* #if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) */
-/* FFI_SYSV, */
-/* FFI_UNIX64,*/ /* Unix variants all use the same ABI for x86-64 */
-/* #ifdef __i386__ */
-/* FFI_DEFAULT_ABI = FFI_SYSV, */
-/* #else */
-/* FFI_DEFAULT_ABI = FFI_UNIX64, */
-/* #endif */
-/* #endif */
-
- FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
-} ffi_abi;
-#endif
-
-/* ---- Definitions for closures ----------------------------------------- */
-
-#define FFI_CLOSURES 1
-
-#ifdef _WIN64
-#define FFI_TRAMPOLINE_SIZE 29
-#define FFI_NATIVE_RAW_API 0
-#else
-#define FFI_TRAMPOLINE_SIZE 15
-#define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
-#endif
-
-#endif
-
diff --git a/contrib/python/cffi/c/libffi_msvc/prep_cif.c b/contrib/python/cffi/c/libffi_msvc/prep_cif.c
deleted file mode 100644
index df94a988758..00000000000
--- a/contrib/python/cffi/c/libffi_msvc/prep_cif.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/* -----------------------------------------------------------------------
- prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc.
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- ``Software''), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- ----------------------------------------------------------------------- */
-
-#include <ffi.h>
-#include <ffi_common.h>
-#include <stdlib.h>
-
-
-/* Round up to FFI_SIZEOF_ARG. */
-
-#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
-
-/* Perform machine independent initialization of aggregate type
- specifications. */
-
-static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg)
-{
- ffi_type **ptr;
-
- FFI_ASSERT(arg != NULL);
-
- /*@-usedef@*/
-
- FFI_ASSERT(arg->elements != NULL);
- FFI_ASSERT(arg->size == 0);
- FFI_ASSERT(arg->alignment == 0);
-
- ptr = &(arg->elements[0]);
-
- while ((*ptr) != NULL)
- {
- if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
- return FFI_BAD_TYPEDEF;
-
- /* Perform a sanity check on the argument type */
- FFI_ASSERT_VALID_TYPE(*ptr);
-
- arg->size = ALIGN(arg->size, (*ptr)->alignment);
- arg->size += (*ptr)->size;
-
- arg->alignment = (arg->alignment > (*ptr)->alignment) ?
- arg->alignment : (*ptr)->alignment;
-
- ptr++;
- }
-
- /* Structure size includes tail padding. This is important for
- structures that fit in one register on ABIs like the PowerPC64
- Linux ABI that right justify small structs in a register.
- It's also needed for nested structure layout, for example
- struct A { long a; char b; }; struct B { struct A x; char y; };
- should find y at an offset of 2*sizeof(long) and result in a
- total size of 3*sizeof(long). */
- arg->size = ALIGN (arg->size, arg->alignment);
-
- if (arg->size == 0)
- return FFI_BAD_TYPEDEF;
- else
- return FFI_OK;
-
- /*@=usedef@*/
-}
-
-/* Perform machine independent ffi_cif preparation, then call
- machine dependent routine. */
-
-ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif,
- ffi_abi abi, unsigned int nargs,
- /*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype,
- /*@dependent@*/ ffi_type **atypes)
-{
- unsigned bytes = 0;
- unsigned int i;
- ffi_type **ptr;
-
- FFI_ASSERT(cif != NULL);
- FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
-
- cif->abi = abi;
- cif->arg_types = atypes;
- cif->nargs = nargs;
- cif->rtype = rtype;
-
- cif->flags = 0;
-
- /* Initialize the return type if necessary */
- /*@-usedef@*/
- if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK))
- return FFI_BAD_TYPEDEF;
- /*@=usedef@*/
-
- /* Perform a sanity check on the return type */
- FFI_ASSERT_VALID_TYPE(cif->rtype);
-
- /* x86-64 and s390 stack space allocation is handled in prep_machdep. */
-#if !defined M68K && !defined __x86_64__ && !defined S390
- /* Make space for the return structure pointer */
- if (cif->rtype->type == FFI_TYPE_STRUCT
-#ifdef _WIN32
- && (cif->rtype->size != 1) /* MSVC returns small structs in registers */
- && (cif->rtype->size != 2)
- && (cif->rtype->size != 4)
- && (cif->rtype->size != 8)
-#endif
-#ifdef SPARC
- && (cif->abi != FFI_V9 || cif->rtype->size > 32)
-#endif
- )
- bytes = STACK_ARG_SIZE(sizeof(void*));
-#endif
-
- for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
- {
-
- /* Initialize any uninitialized aggregate type definitions */
- if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK))
- return FFI_BAD_TYPEDEF;
-
- /* Perform a sanity check on the argument type, do this
- check after the initialization. */
- FFI_ASSERT_VALID_TYPE(*ptr);
-
-#if !defined __x86_64__ && !defined S390
-#ifdef SPARC
- if (((*ptr)->type == FFI_TYPE_STRUCT
- && ((*ptr)->size > 16 || cif->abi != FFI_V9))
- || ((*ptr)->type == FFI_TYPE_LONGDOUBLE
- && cif->abi != FFI_V9))
- bytes += sizeof(void*);
- else
-#endif
- {
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
- /* Don't know if this is a libffi bug or not. At least on
- Windows with MSVC, function call parameters are *not*
- aligned in the same way as structure fields are, they are
- only aligned in integer boundaries.
-
- This doesn't do any harm for cdecl functions and closures,
- since the caller cleans up the stack, but it is wrong for
- stdcall functions where the callee cleans.
- */
-
- /* Add any padding if necessary */
- if (((*ptr)->alignment - 1) & bytes)
- bytes = ALIGN(bytes, (*ptr)->alignment);
-
-#endif
- bytes += STACK_ARG_SIZE((*ptr)->size);
- }
-#endif
- }
-
-#ifdef _WIN64
- /* Function call needs at least 40 bytes stack size, on win64 AMD64 */
- if (bytes < 40)
- bytes = 40;
-#endif
-
- cif->bytes = bytes;
-
- /* Perform machine dependent cif processing */
- return ffi_prep_cif_machdep(cif);
-}
diff --git a/contrib/python/cffi/c/libffi_msvc/types.c b/contrib/python/cffi/c/libffi_msvc/types.c
deleted file mode 100644
index 4433ac28c8c..00000000000
--- a/contrib/python/cffi/c/libffi_msvc/types.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/* -----------------------------------------------------------------------
- types.c - Copyright (c) 1996, 1998 Red Hat, Inc.
-
- Predefined ffi_types needed by libffi.
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- ``Software''), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- ----------------------------------------------------------------------- */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-/* Type definitions */
-
-#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) ffi_type ffi_type_##n = { s, a, t, NULL }
-#define FFI_AGGREGATE_TYPEDEF(n, e) ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e }
-
-/* Size and alignment are fake here. They must not be 0. */
-FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID);
-
-FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8);
-FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8);
-FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16);
-FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16);
-FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32);
-FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32);
-FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT);
-
-#if defined ALPHA || defined SPARC64 || defined X86_64 || defined S390X \
- || defined IA64 || defined _WIN64
-
-FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER);
-
-#else
-
-FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER);
-
-#endif
-
-#if defined X86 || defined X86_WIN32 || defined ARM || defined M68K
-
-FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
-FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
-
-#elif defined SH
-
-FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64);
-FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64);
-
-#else
-
-FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64);
-FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64);
-
-#endif
-
-
-#if defined X86 || defined X86_WIN32 || defined M68K
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE);
-
-#elif defined ARM || defined SH || defined POWERPC_AIX || defined POWERPC_DARWIN
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE);
-
-#elif defined SPARC
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
-#ifdef SPARC64
-FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
-#else
-FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE);
-#endif
-
-#elif defined X86_64
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE);
-
-#else
-
-FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE);
-FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE);
-
-#endif
-
diff --git a/contrib/python/cffi/c/libffi_msvc/win32.c b/contrib/python/cffi/c/libffi_msvc/win32.c
deleted file mode 100644
index d1149a85eb4..00000000000
--- a/contrib/python/cffi/c/libffi_msvc/win32.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/* -----------------------------------------------------------------------
- win32.S - Copyright (c) 1996, 1998, 2001, 2002 Red Hat, Inc.
- Copyright (c) 2001 John Beniton
- Copyright (c) 2002 Ranjit Mathew
-
-
- X86 Foreign Function Interface
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- ``Software''), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- ----------------------------------------------------------------------- */
-
-/* theller: almost verbatim translation from gas syntax to MSVC inline
- assembler code. */
-
-/* theller: ffi_call_x86 now returns an integer - the difference of the stack
- pointer before and after the function call. If everything is ok, zero is
- returned. If stdcall functions are passed the wrong number of arguments,
- the difference will be nonzero. */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-__declspec(naked) int
-ffi_call_x86(void (* prepfunc)(char *, extended_cif *), /* 8 */
- extended_cif *ecif, /* 12 */
- unsigned bytes, /* 16 */
- unsigned flags, /* 20 */
- unsigned *rvalue, /* 24 */
- void (*fn)()) /* 28 */
-{
- _asm {
- push ebp
- mov ebp, esp
-
- push esi // NEW: this register must be preserved across function calls
-// XXX SAVE ESP NOW!
- mov esi, esp // save stack pointer before the call
-
-// Make room for all of the new args.
- mov ecx, [ebp+16]
- sub esp, ecx // sub esp, bytes
-
- mov eax, esp
-
-// Place all of the ffi_prep_args in position
- push [ebp + 12] // ecif
- push eax
- call [ebp + 8] // prepfunc
-
-// Return stack to previous state and call the function
- add esp, 8
-// FIXME: Align the stack to a 128-bit boundary to avoid
-// potential performance hits.
- call [ebp + 28]
-
-// Load ecif->cif->abi
- mov ecx, [ebp + 12]
- mov ecx, [ecx]ecif.cif
- mov ecx, [ecx]ecif.cif.abi
-
- cmp ecx, FFI_STDCALL
- je noclean
-// STDCALL: Remove the space we pushed for the args
- mov ecx, [ebp + 16]
- add esp, ecx
-// CDECL: Caller has already cleaned the stack
-noclean:
-// Check that esp has the same value as before!
- sub esi, esp
-
-// Load %ecx with the return type code
- mov ecx, [ebp + 20]
-
-// If the return value pointer is NULL, assume no return value.
-/*
- Intel asm is weird. We have to explicitely specify 'DWORD PTR' in the nexr instruction,
- otherwise only one BYTE will be compared (instead of a DWORD)!
- */
- cmp DWORD PTR [ebp + 24], 0
- jne sc_retint
-
-// Even if there is no space for the return value, we are
-// obliged to handle floating-point values.
- cmp ecx, FFI_TYPE_FLOAT
- jne sc_noretval
-// fstp %st(0)
- fstp st(0)
-
- jmp sc_epilogue
-
-sc_retint:
- cmp ecx, FFI_TYPE_INT
- jne sc_retfloat
-// # Load %ecx with the pointer to storage for the return value
- mov ecx, [ebp + 24]
- mov [ecx + 0], eax
- jmp sc_epilogue
-
-sc_retfloat:
- cmp ecx, FFI_TYPE_FLOAT
- jne sc_retdouble
-// Load %ecx with the pointer to storage for the return value
- mov ecx, [ebp+24]
-// fstps (%ecx)
- fstp DWORD PTR [ecx]
- jmp sc_epilogue
-
-sc_retdouble:
- cmp ecx, FFI_TYPE_DOUBLE
- jne sc_retlongdouble
-// movl 24(%ebp),%ecx
- mov ecx, [ebp+24]
- fstp QWORD PTR [ecx]
- jmp sc_epilogue
-
- jmp sc_retlongdouble // avoid warning about unused label
-sc_retlongdouble:
- cmp ecx, FFI_TYPE_LONGDOUBLE
- jne sc_retint64
-// Load %ecx with the pointer to storage for the return value
- mov ecx, [ebp+24]
-// fstpt (%ecx)
- fstp QWORD PTR [ecx] /* XXX ??? */
- jmp sc_epilogue
-
-sc_retint64:
- cmp ecx, FFI_TYPE_SINT64
- jne sc_retstruct
-// Load %ecx with the pointer to storage for the return value
- mov ecx, [ebp+24]
- mov [ecx+0], eax
- mov [ecx+4], edx
-
-sc_retstruct:
-// Nothing to do!
-
-sc_noretval:
-sc_epilogue:
- mov eax, esi
- pop esi // NEW restore: must be preserved across function calls
- mov esp, ebp
- pop ebp
- ret
- }
-}
diff --git a/contrib/python/cffi/c/libffi_msvc/win64.asm b/contrib/python/cffi/c/libffi_msvc/win64.asm
deleted file mode 100644
index 301188bc9c1..00000000000
--- a/contrib/python/cffi/c/libffi_msvc/win64.asm
+++ /dev/null
@@ -1,156 +0,0 @@
-PUBLIC ffi_call_AMD64
-
-EXTRN __chkstk:NEAR
-EXTRN ffi_closure_SYSV:NEAR
-
-_TEXT SEGMENT
-
-;;; ffi_closure_OUTER will be called with these registers set:
-;;; rax points to 'closure'
-;;; r11 contains a bit mask that specifies which of the
-;;; first four parameters are float or double
-;;;
-;;; It must move the parameters passed in registers to their stack location,
-;;; call ffi_closure_SYSV for the actual work, then return the result.
-;;;
-ffi_closure_OUTER PROC FRAME
- ;; save actual arguments to their stack space.
- test r11, 1
- jne first_is_float
- mov QWORD PTR [rsp+8], rcx
- jmp second
-first_is_float:
- movlpd QWORD PTR [rsp+8], xmm0
-
-second:
- test r11, 2
- jne second_is_float
- mov QWORD PTR [rsp+16], rdx
- jmp third
-second_is_float:
- movlpd QWORD PTR [rsp+16], xmm1
-
-third:
- test r11, 4
- jne third_is_float
- mov QWORD PTR [rsp+24], r8
- jmp forth
-third_is_float:
- movlpd QWORD PTR [rsp+24], xmm2
-
-forth:
- test r11, 8
- jne forth_is_float
- mov QWORD PTR [rsp+32], r9
- jmp done
-forth_is_float:
- movlpd QWORD PTR [rsp+32], xmm3
-
-done:
-.ALLOCSTACK 40
- sub rsp, 40
-.ENDPROLOG
- mov rcx, rax ; context is first parameter
- mov rdx, rsp ; stack is second parameter
- add rdx, 40 ; correct our own area
- mov rax, ffi_closure_SYSV
- call rax ; call the real closure function
- ;; Here, code is missing that handles float return values
- add rsp, 40
- movd xmm0, rax ; In case the closure returned a float.
- ret 0
-ffi_closure_OUTER ENDP
-
-
-;;; ffi_call_AMD64
-
-stack$ = 0
-prepfunc$ = 32
-ecif$ = 40
-bytes$ = 48
-flags$ = 56
-rvalue$ = 64
-fn$ = 72
-
-ffi_call_AMD64 PROC FRAME
-
- mov QWORD PTR [rsp+32], r9
- mov QWORD PTR [rsp+24], r8
- mov QWORD PTR [rsp+16], rdx
- mov QWORD PTR [rsp+8], rcx
-.PUSHREG rbp
- push rbp
-.ALLOCSTACK 48
- sub rsp, 48 ; 00000030H
-.SETFRAME rbp, 32
- lea rbp, QWORD PTR [rsp+32]
-.ENDPROLOG
-
- mov eax, DWORD PTR bytes$[rbp]
- add rax, 15
- and rax, -16
- call __chkstk
- sub rsp, rax
- lea rax, QWORD PTR [rsp+32]
- mov QWORD PTR stack$[rbp], rax
-
- mov rdx, QWORD PTR ecif$[rbp]
- mov rcx, QWORD PTR stack$[rbp]
- call QWORD PTR prepfunc$[rbp]
-
- mov rsp, QWORD PTR stack$[rbp]
-
- movlpd xmm3, QWORD PTR [rsp+24]
- movd r9, xmm3
-
- movlpd xmm2, QWORD PTR [rsp+16]
- movd r8, xmm2
-
- movlpd xmm1, QWORD PTR [rsp+8]
- movd rdx, xmm1
-
- movlpd xmm0, QWORD PTR [rsp]
- movd rcx, xmm0
-
- call QWORD PTR fn$[rbp]
-ret_int$:
- cmp DWORD PTR flags$[rbp], 1 ; FFI_TYPE_INT
- jne ret_float$
-
- mov rcx, QWORD PTR rvalue$[rbp]
- mov DWORD PTR [rcx], eax
- jmp SHORT ret_nothing$
-
-ret_float$:
- cmp DWORD PTR flags$[rbp], 2 ; FFI_TYPE_FLOAT
- jne SHORT ret_double$
-
- mov rax, QWORD PTR rvalue$[rbp]
- movlpd QWORD PTR [rax], xmm0
- jmp SHORT ret_nothing$
-
-ret_double$:
- cmp DWORD PTR flags$[rbp], 3 ; FFI_TYPE_DOUBLE
- jne SHORT ret_int64$
-
- mov rax, QWORD PTR rvalue$[rbp]
- movlpd QWORD PTR [rax], xmm0
- jmp SHORT ret_nothing$
-
-ret_int64$:
- cmp DWORD PTR flags$[rbp], 12 ; FFI_TYPE_SINT64
- jne ret_nothing$
-
- mov rcx, QWORD PTR rvalue$[rbp]
- mov QWORD PTR [rcx], rax
- jmp SHORT ret_nothing$
-
-ret_nothing$:
- xor eax, eax
-
- lea rsp, QWORD PTR [rbp+16]
- pop rbp
- ret 0
-ffi_call_AMD64 ENDP
-_TEXT ENDS
-END
diff --git a/contrib/python/cffi/c/libffi_msvc/win64.obj b/contrib/python/cffi/c/libffi_msvc/win64.obj
deleted file mode 100644
index 38d3cd166b0..00000000000
--- a/contrib/python/cffi/c/libffi_msvc/win64.obj
+++ /dev/null
Binary files differ
diff --git a/contrib/python/cffi/c/test_c.py b/contrib/python/cffi/c/test_c.py
deleted file mode 100644
index 654584d9244..00000000000
--- a/contrib/python/cffi/c/test_c.py
+++ /dev/null
@@ -1,4575 +0,0 @@
-import py
-import pytest
-
-def _setup_path():
- import os, sys
- sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
-_setup_path()
-from _cffi_backend import *
-from _cffi_backend import _get_types, _get_common_types
-try:
- from _cffi_backend import _testfunc
-except ImportError:
- def _testfunc(num):
- pytest.skip("_testunc() not available")
-from _cffi_backend import __version__
-
-# ____________________________________________________________
-
-import sys
-assert __version__ == "1.15.0", ("This test_c.py file is for testing a version"
- " of cffi that differs from the one that we"
- " get from 'import _cffi_backend'")
-if sys.version_info < (3,):
- type_or_class = "type"
- mandatory_b_prefix = ''
- mandatory_u_prefix = 'u'
- bytechr = chr
- bitem2bchr = lambda x: x
- class U(object):
- def __add__(self, other):
- return eval('u'+repr(other).replace(r'\\u', r'\u')
- .replace(r'\\U', r'\U'))
- u = U()
- str2bytes = str
- strict_compare = False
-else:
- type_or_class = "class"
- long = int
- unicode = str
- unichr = chr
- mandatory_b_prefix = 'b'
- mandatory_u_prefix = ''
- bytechr = lambda n: bytes([n])
- bitem2bchr = bytechr
- u = ""
- str2bytes = lambda s: bytes(s, "ascii")
- strict_compare = True
-
-def size_of_int():
- BInt = new_primitive_type("int")
- return sizeof(BInt)
-
-def size_of_long():
- BLong = new_primitive_type("long")
- return sizeof(BLong)
-
-def size_of_ptr():
- BInt = new_primitive_type("int")
- BPtr = new_pointer_type(BInt)
- return sizeof(BPtr)
-
-
-def find_and_load_library(name, flags=RTLD_NOW):
- import ctypes.util
- if name is None:
- path = None
- else:
- path = ctypes.util.find_library(name)
- if path is None and name == 'c':
- assert sys.platform == 'win32'
- assert (sys.version_info >= (3,) or
- '__pypy__' in sys.builtin_module_names)
- py.test.skip("dlopen(None) cannot work on Windows "
- "with PyPy or Python 3")
- return load_library(path, flags)
-
-def test_load_library():
- x = find_and_load_library('c')
- assert repr(x).startswith("<clibrary '")
- x = find_and_load_library('c', RTLD_NOW | RTLD_GLOBAL)
- assert repr(x).startswith("<clibrary '")
- x = find_and_load_library('c', RTLD_LAZY)
- assert repr(x).startswith("<clibrary '")
-
-def test_all_rtld_symbols():
- import sys
- FFI_DEFAULT_ABI # these symbols must be defined
- FFI_CDECL
- RTLD_LAZY
- RTLD_NOW
- RTLD_GLOBAL
- RTLD_LOCAL
- if sys.platform.startswith("linux"):
- RTLD_NODELETE
- RTLD_NOLOAD
- RTLD_DEEPBIND
-
-def test_new_primitive_type():
- py.test.raises(KeyError, new_primitive_type, "foo")
- p = new_primitive_type("signed char")
- assert repr(p) == "<ctype 'signed char'>"
-
-def check_dir(p, expected):
- got = [name for name in dir(p) if not name.startswith('_')]
- assert got == sorted(expected)
-
-def test_inspect_primitive_type():
- p = new_primitive_type("signed char")
- assert p.kind == "primitive"
- assert p.cname == "signed char"
- check_dir(p, ['cname', 'kind'])
-
-def test_cast_to_signed_char():
- p = new_primitive_type("signed char")
- x = cast(p, -65 + 17*256)
- assert repr(x) == "<cdata 'signed char' -65>"
- assert repr(type(x)) == "<%s '_cffi_backend._CDataBase'>" % type_or_class
- assert int(x) == -65
- x = cast(p, -66 + (1<<199)*256)
- assert repr(x) == "<cdata 'signed char' -66>"
- assert int(x) == -66
- assert (x == cast(p, -66)) is True
- assert (x != cast(p, -66)) is False
- q = new_primitive_type("short")
- assert (x == cast(q, -66)) is True
- assert (x != cast(q, -66)) is False
-
-def test_sizeof_type():
- py.test.raises(TypeError, sizeof, 42.5)
- p = new_primitive_type("short")
- assert sizeof(p) == 2
-
-def test_integer_types():
- for name in ['signed char', 'short', 'int', 'long', 'long long']:
- p = new_primitive_type(name)
- size = sizeof(p)
- min = -(1 << (8*size-1))
- max = (1 << (8*size-1)) - 1
- assert int(cast(p, min)) == min
- assert int(cast(p, max)) == max
- assert int(cast(p, min - 1)) == max
- assert int(cast(p, max + 1)) == min
- py.test.raises(TypeError, cast, p, None)
- assert long(cast(p, min - 1)) == max
- assert int(cast(p, b'\x08')) == 8
- assert int(cast(p, u+'\x08')) == 8
- for name in ['char', 'short', 'int', 'long', 'long long']:
- p = new_primitive_type('unsigned ' + name)
- size = sizeof(p)
- max = (1 << (8*size)) - 1
- assert int(cast(p, 0)) == 0
- assert int(cast(p, max)) == max
- assert int(cast(p, -1)) == max
- assert int(cast(p, max + 1)) == 0
- assert long(cast(p, -1)) == max
- assert int(cast(p, b'\xFE')) == 254
- assert int(cast(p, u+'\xFE')) == 254
-
-def test_no_float_on_int_types():
- p = new_primitive_type('long')
- py.test.raises(TypeError, float, cast(p, 42))
- py.test.raises(TypeError, complex, cast(p, 42))
-
-def test_float_types():
- INF = 1E200 * 1E200
- for name in ["float", "double"]:
- p = new_primitive_type(name)
- assert bool(cast(p, 0)) is False # since 1.7
- assert bool(cast(p, -0.0)) is False # since 1.7
- assert bool(cast(p, 1e-42)) is True
- assert bool(cast(p, -1e-42)) is True
- assert bool(cast(p, INF))
- assert bool(cast(p, -INF))
- assert bool(cast(p, float("nan")))
- assert int(cast(p, -150)) == -150
- assert int(cast(p, 61.91)) == 61
- assert long(cast(p, 61.91)) == 61
- assert type(int(cast(p, 61.91))) is int
- assert type(int(cast(p, 1E22))) is long
- assert type(long(cast(p, 61.91))) is long
- assert type(long(cast(p, 1E22))) is long
- py.test.raises(OverflowError, int, cast(p, INF))
- py.test.raises(OverflowError, int, cast(p, -INF))
- assert float(cast(p, 1.25)) == 1.25
- assert float(cast(p, INF)) == INF
- assert float(cast(p, -INF)) == -INF
- if name == "float":
- assert float(cast(p, 1.1)) != 1.1 # rounding error
- assert float(cast(p, 1E200)) == INF # limited range
-
- assert cast(p, -1.1) == cast(p, -1.1)
- assert repr(float(cast(p, -0.0))) == '-0.0'
- assert float(cast(p, b'\x09')) == 9.0
- assert float(cast(p, u+'\x09')) == 9.0
- assert float(cast(p, True)) == 1.0
- py.test.raises(TypeError, cast, p, None)
-
-def test_complex_types():
- INF = 1E200 * 1E200
- for name in ["float", "double"]:
- p = new_primitive_type(name + " _Complex")
- assert bool(cast(p, 0)) is False
- assert bool(cast(p, INF))
- assert bool(cast(p, -INF))
- assert bool(cast(p, 0j)) is False
- assert bool(cast(p, INF*1j))
- assert bool(cast(p, -INF*1j))
- # "can't convert complex to float", like CPython's "float(0j)"
- py.test.raises(TypeError, int, cast(p, -150))
- py.test.raises(TypeError, long, cast(p, -150))
- py.test.raises(TypeError, float, cast(p, -150))
- assert complex(cast(p, 1.25)) == 1.25
- assert complex(cast(p, 1.25j)) == 1.25j
- assert complex(cast(p, complex(0,INF))) == complex(0,INF)
- assert complex(cast(p, -INF)) == -INF
- if name == "float":
- assert complex(cast(p, 1.1j)) != 1.1j # rounding error
- assert complex(cast(p, 1E200+3j)) == INF+3j # limited range
- assert complex(cast(p, complex(3,1E200))) == complex(3,INF) # limited range
-
- assert cast(p, -1.1j) == cast(p, -1.1j)
- assert repr(complex(cast(p, -0.0)).real) == '-0.0'
- #assert repr(complex(cast(p, -0j))) == '-0j' # http://bugs.python.org/issue29602
- assert complex(cast(p, b'\x09')) == 9.0 + 0j
- assert complex(cast(p, u+'\x09')) == 9.0 + 0j
- assert complex(cast(p, True)) == 1.0 + 0j
- py.test.raises(TypeError, cast, p, None)
- #
- py.test.raises(TypeError, cast, new_primitive_type(name), 1+0j)
- #
- for basetype in ["char", "int", "uint64_t", "float",
- "double", "long double"]:
- baseobj = cast(new_primitive_type(basetype), 65)
- py.test.raises(TypeError, complex, baseobj)
- #
- BArray = new_array_type(new_pointer_type(p), 10)
- x = newp(BArray, None)
- x[5] = 12.34 + 56.78j
- assert type(x[5]) is complex
- assert abs(x[5] - (12.34 + 56.78j)) < 1e-5
- assert (x[5] == 12.34 + 56.78j) == (name == "double") # rounding error
- #
- class Foo:
- def __complex__(self):
- return 2 + 3j
- assert complex(Foo()) == 2 + 3j
- assert complex(cast(p, Foo())) == 2 + 3j
- py.test.raises(TypeError, cast, new_primitive_type("int"), 1+0j)
-
-def test_character_type():
- p = new_primitive_type("char")
- assert bool(cast(p, 'A')) is True
- assert bool(cast(p, '\x00')) is False # since 1.7
- assert cast(p, '\x00') == cast(p, -17*256)
- assert int(cast(p, 'A')) == 65
- assert long(cast(p, 'A')) == 65
- assert type(int(cast(p, 'A'))) is int
- assert type(long(cast(p, 'A'))) is long
- assert str(cast(p, 'A')) == repr(cast(p, 'A'))
- assert repr(cast(p, 'A')) == "<cdata 'char' %s'A'>" % mandatory_b_prefix
- assert repr(cast(p, 255)) == r"<cdata 'char' %s'\xff'>" % mandatory_b_prefix
- assert repr(cast(p, 0)) == r"<cdata 'char' %s'\x00'>" % mandatory_b_prefix
-
-def test_pointer_type():
- p = new_primitive_type("int")
- assert repr(p) == "<ctype 'int'>"
- p = new_pointer_type(p)
- assert repr(p) == "<ctype 'int *'>"
- p = new_pointer_type(p)
- assert repr(p) == "<ctype 'int * *'>"
- p = new_pointer_type(p)
- assert repr(p) == "<ctype 'int * * *'>"
-
-def test_inspect_pointer_type():
- p1 = new_primitive_type("int")
- p2 = new_pointer_type(p1)
- assert p2.kind == "pointer"
- assert p2.cname == "int *"
- assert p2.item is p1
- check_dir(p2, ['cname', 'kind', 'item'])
- p3 = new_pointer_type(p2)
- assert p3.item is p2
-
-def test_pointer_to_int():
- BInt = new_primitive_type("int")
- py.test.raises(TypeError, newp, BInt)
- py.test.raises(TypeError, newp, BInt, None)
- BPtr = new_pointer_type(BInt)
- p = newp(BPtr)
- assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int()
- p = newp(BPtr, None)
- assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int()
- p = newp(BPtr, 5000)
- assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int()
- q = cast(BPtr, p)
- assert repr(q).startswith("<cdata 'int *' 0x")
- assert p == q
- assert hash(p) == hash(q)
- e = py.test.raises(TypeError, newp, new_array_type(BPtr, None), None)
- assert str(e.value) == (
- "expected new array length or list/tuple/str, not NoneType")
-
-def test_pointer_bool():
- BInt = new_primitive_type("int")
- BPtr = new_pointer_type(BInt)
- p = cast(BPtr, 0)
- assert bool(p) is False
- p = cast(BPtr, 42)
- assert bool(p) is True
-
-def test_pointer_to_pointer():
- BInt = new_primitive_type("int")
- BPtr = new_pointer_type(BInt)
- BPtrPtr = new_pointer_type(BPtr)
- p = newp(BPtrPtr, None)
- assert repr(p) == "<cdata 'int * *' owning %d bytes>" % size_of_ptr()
-
-def test_reading_pointer_to_int():
- BInt = new_primitive_type("int")
- BPtr = new_pointer_type(BInt)
- p = newp(BPtr, None)
- assert p[0] == 0
- p = newp(BPtr, 5000)
- assert p[0] == 5000
- with pytest.raises(IndexError):
- p[1]
- with pytest.raises(IndexError):
- p[-1]
-
-def test_reading_pointer_to_float():
- BFloat = new_primitive_type("float")
- py.test.raises(TypeError, newp, BFloat, None)
- BPtr = new_pointer_type(BFloat)
- p = newp(BPtr, None)
- assert p[0] == 0.0 and type(p[0]) is float
- p = newp(BPtr, 1.25)
- assert p[0] == 1.25 and type(p[0]) is float
- p = newp(BPtr, 1.1)
- assert p[0] != 1.1 and abs(p[0] - 1.1) < 1E-5 # rounding errors
-
-def test_cast_float_to_int():
- for type in ["int", "unsigned int", "long", "unsigned long",
- "long long", "unsigned long long"]:
- p = new_primitive_type(type)
- assert int(cast(p, 4.2)) == 4
- py.test.raises(TypeError, newp, new_pointer_type(p), 4.2)
-
-def test_newp_integer_types():
- for name in ['signed char', 'short', 'int', 'long', 'long long']:
- p = new_primitive_type(name)
- pp = new_pointer_type(p)
- size = sizeof(p)
- min = -(1 << (8*size-1))
- max = (1 << (8*size-1)) - 1
- assert newp(pp, min)[0] == min
- assert newp(pp, max)[0] == max
- py.test.raises(OverflowError, newp, pp, min - 2 ** 32)
- py.test.raises(OverflowError, newp, pp, min - 2 ** 64)
- py.test.raises(OverflowError, newp, pp, max + 2 ** 32)
- py.test.raises(OverflowError, newp, pp, max + 2 ** 64)
- py.test.raises(OverflowError, newp, pp, min - 1)
- py.test.raises(OverflowError, newp, pp, max + 1)
- py.test.raises(OverflowError, newp, pp, min - 1 - 2 ** 32)
- py.test.raises(OverflowError, newp, pp, min - 1 - 2 ** 64)
- py.test.raises(OverflowError, newp, pp, max + 1)
- py.test.raises(OverflowError, newp, pp, max + 1 + 2 ** 32)
- py.test.raises(OverflowError, newp, pp, max + 1 + 2 ** 64)
- py.test.raises(TypeError, newp, pp, 1.0)
- for name in ['char', 'short', 'int', 'long', 'long long']:
- p = new_primitive_type('unsigned ' + name)
- pp = new_pointer_type(p)
- size = sizeof(p)
- max = (1 << (8*size)) - 1
- assert newp(pp, 0)[0] == 0
- assert newp(pp, max)[0] == max
- py.test.raises(OverflowError, newp, pp, -1)
- py.test.raises(OverflowError, newp, pp, max + 1)
-
-def test_reading_pointer_to_char():
- BChar = new_primitive_type("char")
- py.test.raises(TypeError, newp, BChar, None)
- BPtr = new_pointer_type(BChar)
- p = newp(BPtr, None)
- assert p[0] == b'\x00'
- p = newp(BPtr, b'A')
- assert p[0] == b'A'
- py.test.raises(TypeError, newp, BPtr, 65)
- py.test.raises(TypeError, newp, BPtr, b"foo")
- py.test.raises(TypeError, newp, BPtr, u+"foo")
- c = cast(BChar, b'A')
- assert str(c) == repr(c)
- assert int(c) == ord(b'A')
- py.test.raises(TypeError, cast, BChar, b'foo')
- py.test.raises(TypeError, cast, BChar, u+'foo')
- e = py.test.raises(TypeError, newp, new_array_type(BPtr, None), 12.3)
- assert str(e.value) == (
- "expected new array length or list/tuple/str, not float")
-
-def test_reading_pointer_to_pointer():
- BVoidP = new_pointer_type(new_void_type())
- BCharP = new_pointer_type(new_primitive_type("char"))
- BInt = new_primitive_type("int")
- BIntPtr = new_pointer_type(BInt)
- BIntPtrPtr = new_pointer_type(BIntPtr)
- q = newp(BIntPtr, 42)
- assert q[0] == 42
- p = newp(BIntPtrPtr, None)
- assert p[0] is not None
- assert p[0] == cast(BVoidP, 0)
- assert p[0] == cast(BCharP, 0)
- assert p[0] != None
- assert repr(p[0]) == "<cdata 'int *' NULL>"
- p[0] = q
- assert p[0] != cast(BVoidP, 0)
- assert p[0] != cast(BCharP, 0)
- assert p[0][0] == 42
- q[0] += 1
- assert p[0][0] == 43
- p = newp(BIntPtrPtr, q)
- assert p[0][0] == 43
-
-def test_load_standard_library():
- if sys.platform == "win32":
- py.test.raises(OSError, find_and_load_library, None)
- return
- x = find_and_load_library(None)
- BVoidP = new_pointer_type(new_void_type())
- assert x.load_function(BVoidP, 'strcpy')
- py.test.raises(AttributeError, x.load_function,
- BVoidP, 'xxx_this_function_does_not_exist')
- # the next one is from 'libm', not 'libc', but we assume
- # that it is already loaded too, so it should work
- assert x.load_function(BVoidP, 'sqrt')
- #
- x.close_lib()
- py.test.raises(ValueError, x.load_function, BVoidP, 'sqrt')
- x.close_lib()
-
-def test_no_len_on_nonarray():
- p = new_primitive_type("int")
- py.test.raises(TypeError, len, cast(p, 42))
-
-def test_cmp_none():
- p = new_primitive_type("int")
- x = cast(p, 42)
- assert (x == None) is False
- assert (x != None) is True
- assert (x == ["hello"]) is False
- assert (x != ["hello"]) is True
- y = cast(p, 0)
- assert (y == None) is False
-
-def test_invalid_indexing():
- p = new_primitive_type("int")
- x = cast(p, 42)
- with pytest.raises(TypeError):
- x[0]
-
-def test_default_str():
- BChar = new_primitive_type("char")
- x = cast(BChar, 42)
- assert str(x) == repr(x)
- BInt = new_primitive_type("int")
- x = cast(BInt, 42)
- assert str(x) == repr(x)
- BArray = new_array_type(new_pointer_type(BInt), 10)
- x = newp(BArray, None)
- assert str(x) == repr(x)
-
-def test_default_unicode():
- BInt = new_primitive_type("int")
- x = cast(BInt, 42)
- assert unicode(x) == unicode(repr(x))
- BArray = new_array_type(new_pointer_type(BInt), 10)
- x = newp(BArray, None)
- assert unicode(x) == unicode(repr(x))
-
-def test_cast_from_cdataint():
- BInt = new_primitive_type("int")
- x = cast(BInt, 0)
- y = cast(new_pointer_type(BInt), x)
- assert bool(y) is False
- #
- x = cast(BInt, 42)
- y = cast(BInt, x)
- assert int(y) == 42
- y = cast(new_primitive_type("char"), x)
- assert int(y) == 42
- y = cast(new_primitive_type("float"), x)
- assert float(y) == 42.0
- #
- z = cast(BInt, 42.5)
- assert int(z) == 42
- z = cast(BInt, y)
- assert int(z) == 42
-
-def test_void_type():
- p = new_void_type()
- assert p.kind == "void"
- assert p.cname == "void"
- check_dir(p, ['kind', 'cname'])
-
-def test_array_type():
- p = new_primitive_type("int")
- assert repr(p) == "<ctype 'int'>"
- #
- py.test.raises(TypeError, new_array_type, new_pointer_type(p), "foo")
- py.test.raises(ValueError, new_array_type, new_pointer_type(p), -42)
- #
- p1 = new_array_type(new_pointer_type(p), None)
- assert repr(p1) == "<ctype 'int[]'>"
- py.test.raises(ValueError, new_array_type, new_pointer_type(p1), 42)
- #
- p1 = new_array_type(new_pointer_type(p), 42)
- p2 = new_array_type(new_pointer_type(p1), 25)
- assert repr(p2) == "<ctype 'int[25][42]'>"
- p2 = new_array_type(new_pointer_type(p1), None)
- assert repr(p2) == "<ctype 'int[][42]'>"
- #
- py.test.raises(OverflowError,
- new_array_type, new_pointer_type(p), sys.maxsize+1)
- py.test.raises(OverflowError,
- new_array_type, new_pointer_type(p), sys.maxsize // 3)
-
-def test_inspect_array_type():
- p = new_primitive_type("int")
- p1 = new_array_type(new_pointer_type(p), None)
- assert p1.kind == "array"
- assert p1.cname == "int[]"
- assert p1.item is p
- assert p1.length is None
- check_dir(p1, ['cname', 'kind', 'item', 'length'])
- p1 = new_array_type(new_pointer_type(p), 42)
- assert p1.kind == "array"
- assert p1.cname == "int[42]"
- assert p1.item is p
- assert p1.length == 42
- check_dir(p1, ['cname', 'kind', 'item', 'length'])
-
-def test_array_instance():
- LENGTH = 1423
- p = new_primitive_type("int")
- p1 = new_array_type(new_pointer_type(p), LENGTH)
- a = newp(p1, None)
- assert repr(a) == "<cdata 'int[%d]' owning %d bytes>" % (
- LENGTH, LENGTH * size_of_int())
- assert len(a) == LENGTH
- for i in range(LENGTH):
- assert a[i] == 0
- with pytest.raises(IndexError):
- a[LENGTH]
- with pytest.raises(IndexError):
- a[-1]
- for i in range(LENGTH):
- a[i] = i * i + 1
- for i in range(LENGTH):
- assert a[i] == i * i + 1
- with pytest.raises(IndexError) as e:
- a[LENGTH+100] = 500
- assert ('(expected %d < %d)' % (LENGTH+100, LENGTH)) in str(e.value)
- py.test.raises(TypeError, int, a)
-
-def test_array_of_unknown_length_instance():
- p = new_primitive_type("int")
- p1 = new_array_type(new_pointer_type(p), None)
- py.test.raises(TypeError, newp, p1, None)
- py.test.raises(ValueError, newp, p1, -42)
- a = newp(p1, 42)
- assert len(a) == 42
- for i in range(42):
- a[i] -= i
- for i in range(42):
- assert a[i] == -i
- with pytest.raises(IndexError):
- a[42]
- with pytest.raises(IndexError):
- a[-1]
- with pytest.raises(IndexError):
- a[42] = 123
- with pytest.raises(IndexError):
- a[-1] = 456
-
-def test_array_of_unknown_length_instance_with_initializer():
- p = new_primitive_type("int")
- p1 = new_array_type(new_pointer_type(p), None)
- a = newp(p1, list(range(42)))
- assert len(a) == 42
- a = newp(p1, tuple(range(142)))
- assert len(a) == 142
-
-def test_array_initializer():
- p = new_primitive_type("int")
- p1 = new_array_type(new_pointer_type(p), None)
- a = newp(p1, list(range(100, 142)))
- for i in range(42):
- assert a[i] == 100 + i
- #
- p2 = new_array_type(new_pointer_type(p), 43)
- a = newp(p2, tuple(range(100, 142)))
- for i in range(42):
- assert a[i] == 100 + i
- assert a[42] == 0 # extra uninitialized item
-
-def test_array_add():
- p = new_primitive_type("int")
- p1 = new_array_type(new_pointer_type(p), 5) # int[5]
- p2 = new_array_type(new_pointer_type(p1), 3) # int[3][5]
- a = newp(p2, [list(range(n, n+5)) for n in [100, 200, 300]])
- assert repr(a) == "<cdata 'int[3][5]' owning %d bytes>" % (
- 3*5*size_of_int(),)
- assert repr(a + 0).startswith("<cdata 'int(*)[5]' 0x")
- assert 0 + a == a + 0 != 1 + a == a + 1
- assert repr(a[0]).startswith("<cdata 'int[5]' 0x")
- assert repr((a + 0)[0]).startswith("<cdata 'int[5]' 0x")
- assert repr(a[0] + 0).startswith("<cdata 'int *' 0x")
- assert type(a[0][0]) is int
- assert type((a[0] + 0)[0]) is int
-
-def test_array_sub():
- BInt = new_primitive_type("int")
- BArray = new_array_type(new_pointer_type(BInt), 5) # int[5]
- a = newp(BArray, None)
- p = a + 1
- assert p - a == 1
- assert p - (a+0) == 1
- assert a == (p - 1)
- BPtr = new_pointer_type(new_primitive_type("short"))
- q = newp(BPtr, None)
- with pytest.raises(TypeError):
- p - q
- with pytest.raises(TypeError):
- q - p
- with pytest.raises(TypeError):
- a - q
- with pytest.raises(TypeError) as e:
- q - a
- assert str(e.value) == "cannot subtract cdata 'short *' and cdata 'int *'"
-
-def test_ptr_sub_unaligned():
- BInt = new_primitive_type("int")
- BIntPtr = new_pointer_type(BInt)
- a = cast(BIntPtr, 1240)
- for bi in range(1430, 1438):
- b = cast(BIntPtr, bi)
- if ((bi - 1240) % size_of_int()) == 0:
- assert b - a == (bi - 1240) // size_of_int()
- assert a - b == (1240 - bi) // size_of_int()
- else:
- with pytest.raises(ValueError):
- b - a
- with pytest.raises(ValueError):
- a - b
-
-def test_cast_primitive_from_cdata():
- p = new_primitive_type("int")
- n = cast(p, cast(p, -42))
- assert int(n) == -42
- #
- p = new_primitive_type("unsigned int")
- n = cast(p, cast(p, 42))
- assert int(n) == 42
- #
- p = new_primitive_type("long long")
- n = cast(p, cast(p, -(1<<60)))
- assert int(n) == -(1<<60)
- #
- p = new_primitive_type("unsigned long long")
- n = cast(p, cast(p, 1<<63))
- assert int(n) == 1<<63
- #
- p = new_primitive_type("float")
- n = cast(p, cast(p, 42.5))
- assert float(n) == 42.5
- #
- p = new_primitive_type("char")
- n = cast(p, cast(p, "A"))
- assert int(n) == ord("A")
-
-def test_new_primitive_from_cdata():
- p = new_primitive_type("int")
- p1 = new_pointer_type(p)
- n = newp(p1, cast(p, -42))
- assert n[0] == -42
- #
- p = new_primitive_type("unsigned int")
- p1 = new_pointer_type(p)
- n = newp(p1, cast(p, 42))
- assert n[0] == 42
- #
- p = new_primitive_type("float")
- p1 = new_pointer_type(p)
- n = newp(p1, cast(p, 42.5))
- assert n[0] == 42.5
- #
- p = new_primitive_type("char")
- p1 = new_pointer_type(p)
- n = newp(p1, cast(p, "A"))
- assert n[0] == b"A"
-
-def test_cast_between_pointers():
- BIntP = new_pointer_type(new_primitive_type("int"))
- BIntA = new_array_type(BIntP, None)
- a = newp(BIntA, [40, 41, 42, 43, 44])
- BShortP = new_pointer_type(new_primitive_type("short"))
- b = cast(BShortP, a)
- c = cast(BIntP, b)
- assert c[3] == 43
- BLongLong = new_primitive_type("long long")
- d = cast(BLongLong, c)
- e = cast(BIntP, d)
- assert e[3] == 43
- f = cast(BIntP, int(d))
- assert f[3] == 43
- #
- b = cast(BShortP, 0)
- assert not b
- c = cast(BIntP, b)
- assert not c
- assert int(cast(BLongLong, c)) == 0
-
-def test_alignof():
- BInt = new_primitive_type("int")
- assert alignof(BInt) == sizeof(BInt)
- BPtr = new_pointer_type(BInt)
- assert alignof(BPtr) == sizeof(BPtr)
- BArray = new_array_type(BPtr, None)
- assert alignof(BArray) == alignof(BInt)
-
-def test_new_struct_type():
- BStruct = new_struct_type("foo")
- assert repr(BStruct) == "<ctype 'foo'>"
- BStruct = new_struct_type("struct foo")
- assert repr(BStruct) == "<ctype 'struct foo'>"
- BPtr = new_pointer_type(BStruct)
- assert repr(BPtr) == "<ctype 'struct foo *'>"
- py.test.raises(ValueError, sizeof, BStruct)
- py.test.raises(ValueError, alignof, BStruct)
-
-def test_new_union_type():
- BUnion = new_union_type("union foo")
- assert repr(BUnion) == "<ctype 'union foo'>"
- BPtr = new_pointer_type(BUnion)
- assert repr(BPtr) == "<ctype 'union foo *'>"
-
-def test_complete_struct():
- BLong = new_primitive_type("long")
- BChar = new_primitive_type("char")
- BShort = new_primitive_type("short")
- BStruct = new_struct_type("struct foo")
- assert BStruct.kind == "struct"
- assert BStruct.cname == "struct foo"
- assert BStruct.fields is None
- check_dir(BStruct, ['cname', 'kind', 'fields'])
- #
- complete_struct_or_union(BStruct, [('a1', BLong, -1),
- ('a2', BChar, -1),
- ('a3', BShort, -1)])
- d = BStruct.fields
- assert len(d) == 3
- assert d[0][0] == 'a1'
- assert d[0][1].type is BLong
- assert d[0][1].offset == 0
- assert d[0][1].bitshift == -1
- assert d[0][1].bitsize == -1
- assert d[1][0] == 'a2'
- assert d[1][1].type is BChar
- assert d[1][1].offset == sizeof(BLong)
- assert d[1][1].bitshift == -1
- assert d[1][1].bitsize == -1
- assert d[2][0] == 'a3'
- assert d[2][1].type is BShort
- assert d[2][1].offset == sizeof(BLong) + sizeof(BShort)
- assert d[2][1].bitshift == -1
- assert d[2][1].bitsize == -1
- assert sizeof(BStruct) == 2 * sizeof(BLong)
- assert alignof(BStruct) == alignof(BLong)
-
-def test_complete_union():
- BLong = new_primitive_type("long")
- BChar = new_primitive_type("char")
- BUnion = new_union_type("union foo")
- assert BUnion.kind == "union"
- assert BUnion.cname == "union foo"
- assert BUnion.fields is None
- complete_struct_or_union(BUnion, [('a1', BLong, -1),
- ('a2', BChar, -1)])
- d = BUnion.fields
- assert len(d) == 2
- assert d[0][0] == 'a1'
- assert d[0][1].type is BLong
- assert d[0][1].offset == 0
- assert d[1][0] == 'a2'
- assert d[1][1].type is BChar
- assert d[1][1].offset == 0
- assert sizeof(BUnion) == sizeof(BLong)
- assert alignof(BUnion) == alignof(BLong)
-
-def test_struct_instance():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- p = cast(BStructPtr, 42)
- with pytest.raises(AttributeError) as e:
- p.a1 # opaque
- assert str(e.value) == ("cdata 'struct foo *' points to an opaque type: "
- "cannot read fields")
- with pytest.raises(AttributeError) as e:
- p.a1 = 10 # opaque
- assert str(e.value) == ("cdata 'struct foo *' points to an opaque type: "
- "cannot write fields")
-
- complete_struct_or_union(BStruct, [('a1', BInt, -1),
- ('a2', BInt, -1)])
- p = newp(BStructPtr, None)
- s = p[0]
- assert s.a1 == 0
- s.a2 = 123
- assert s.a1 == 0
- assert s.a2 == 123
- with pytest.raises(OverflowError):
- s.a1 = sys.maxsize+1
- assert s.a1 == 0
- with pytest.raises(AttributeError) as e:
- p.foobar
- assert str(e.value) == "cdata 'struct foo *' has no field 'foobar'"
- with pytest.raises(AttributeError) as e:
- p.foobar = 42
- assert str(e.value) == "cdata 'struct foo *' has no field 'foobar'"
- with pytest.raises(AttributeError) as e:
- s.foobar
- assert str(e.value) == "cdata 'struct foo' has no field 'foobar'"
- with pytest.raises(AttributeError) as e:
- s.foobar = 42
- assert str(e.value) == "cdata 'struct foo' has no field 'foobar'"
- j = cast(BInt, 42)
- with pytest.raises(AttributeError) as e:
- j.foobar
- assert str(e.value) == "cdata 'int' has no attribute 'foobar'"
- with pytest.raises(AttributeError) as e:
- j.foobar = 42
- assert str(e.value) == "cdata 'int' has no attribute 'foobar'"
- j = cast(new_pointer_type(BInt), 42)
- with pytest.raises(AttributeError) as e:
- j.foobar
- assert str(e.value) == "cdata 'int *' has no attribute 'foobar'"
- with pytest.raises(AttributeError) as e:
- j.foobar = 42
- assert str(e.value) == "cdata 'int *' has no attribute 'foobar'"
- pp = newp(new_pointer_type(BStructPtr), p)
- with pytest.raises(AttributeError) as e:
- pp.a1
- assert str(e.value) == "cdata 'struct foo * *' has no attribute 'a1'"
- with pytest.raises(AttributeError) as e:
- pp.a1 = 42
- assert str(e.value) == "cdata 'struct foo * *' has no attribute 'a1'"
-
-def test_union_instance():
- BInt = new_primitive_type("int")
- BUInt = new_primitive_type("unsigned int")
- BUnion = new_union_type("union bar")
- complete_struct_or_union(BUnion, [('a1', BInt, -1), ('a2', BUInt, -1)])
- p = newp(new_pointer_type(BUnion), [-42])
- bigval = -42 + (1 << (8*size_of_int()))
- assert p.a1 == -42
- assert p.a2 == bigval
- p = newp(new_pointer_type(BUnion), {'a2': bigval})
- assert p.a1 == -42
- assert p.a2 == bigval
- py.test.raises(OverflowError, newp, new_pointer_type(BUnion),
- {'a1': bigval})
- p = newp(new_pointer_type(BUnion), [])
- assert p.a1 == p.a2 == 0
-
-def test_struct_pointer():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BInt, -1),
- ('a2', BInt, -1)])
- p = newp(BStructPtr, None)
- assert p.a1 == 0 # read/write via the pointer (C equivalent: '->')
- p.a2 = 123
- assert p.a1 == 0
- assert p.a2 == 123
-
-def test_struct_init_list():
- BVoidP = new_pointer_type(new_void_type())
- BInt = new_primitive_type("int")
- BIntPtr = new_pointer_type(BInt)
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BInt, -1),
- ('a2', BInt, -1),
- ('a3', BInt, -1),
- ('p4', BIntPtr, -1)])
- s = newp(BStructPtr, [123, 456])
- assert s.a1 == 123
- assert s.a2 == 456
- assert s.a3 == 0
- assert s.p4 == cast(BVoidP, 0)
- assert s.p4 != 0
- #
- s = newp(BStructPtr, {'a2': 41122, 'a3': -123})
- assert s.a1 == 0
- assert s.a2 == 41122
- assert s.a3 == -123
- assert s.p4 == cast(BVoidP, 0)
- #
- py.test.raises(KeyError, newp, BStructPtr, {'foobar': 0})
- #
- p = newp(BIntPtr, 14141)
- s = newp(BStructPtr, [12, 34, 56, p])
- assert s.p4 == p
- assert s.p4
- #
- s = newp(BStructPtr, [12, 34, 56, cast(BVoidP, 0)])
- assert s.p4 == cast(BVoidP, 0)
- assert not s.p4
- #
- py.test.raises(TypeError, newp, BStructPtr, [12, 34, 56, None])
-
-def test_array_in_struct():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- BArrayInt5 = new_array_type(new_pointer_type(BInt), 5)
- complete_struct_or_union(BStruct, [('a1', BArrayInt5, -1)])
- s = newp(new_pointer_type(BStruct), [[20, 24, 27, 29, 30]])
- assert s.a1[2] == 27
- assert repr(s.a1).startswith("<cdata 'int[5]' 0x")
-
-def test_offsetof():
- def offsetof(BType, fieldname):
- return typeoffsetof(BType, fieldname)[1]
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- py.test.raises(TypeError, offsetof, BInt, "abc")
- py.test.raises(TypeError, offsetof, BStruct, "abc")
- complete_struct_or_union(BStruct, [('abc', BInt, -1), ('def', BInt, -1)])
- assert offsetof(BStruct, 'abc') == 0
- assert offsetof(BStruct, 'def') == size_of_int()
- py.test.raises(KeyError, offsetof, BStruct, "ghi")
- assert offsetof(new_pointer_type(BStruct), "def") == size_of_int()
-
-def test_function_type():
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BInt, BInt), BInt, False)
- assert repr(BFunc) == "<ctype 'int(*)(int, int)'>"
- BFunc2 = new_function_type((), BFunc, False)
- assert repr(BFunc2) == "<ctype 'int(*(*)())(int, int)'>"
-
-def test_inspect_function_type():
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BInt, BInt), BInt, False)
- assert BFunc.kind == "function"
- assert BFunc.cname == "int(*)(int, int)"
- assert BFunc.args == (BInt, BInt)
- assert BFunc.result is BInt
- assert BFunc.ellipsis is False
- assert BFunc.abi == FFI_DEFAULT_ABI
-
-def test_function_type_taking_struct():
- BChar = new_primitive_type("char")
- BShort = new_primitive_type("short")
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a1', BChar, -1),
- ('a2', BShort, -1)])
- BFunc = new_function_type((BStruct,), BShort, False)
- assert repr(BFunc) == "<ctype 'short(*)(struct foo)'>"
-
-def test_function_void_result():
- BVoid = new_void_type()
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BInt, BInt), BVoid, False)
- assert repr(BFunc) == "<ctype 'void(*)(int, int)'>"
-
-def test_function_void_arg():
- BVoid = new_void_type()
- BInt = new_primitive_type("int")
- py.test.raises(TypeError, new_function_type, (BVoid,), BInt, False)
-
-def test_call_function_0():
- BSignedChar = new_primitive_type("signed char")
- BFunc0 = new_function_type((BSignedChar, BSignedChar), BSignedChar, False)
- f = cast(BFunc0, _testfunc(0))
- assert f(40, 2) == 42
- assert f(-100, -100) == -200 + 256
- py.test.raises(OverflowError, f, 128, 0)
- py.test.raises(OverflowError, f, 0, 128)
-
-def test_call_function_0_pretend_bool_result():
- BSignedChar = new_primitive_type("signed char")
- BBool = new_primitive_type("_Bool")
- BFunc0 = new_function_type((BSignedChar, BSignedChar), BBool, False)
- f = cast(BFunc0, _testfunc(0))
- assert f(40, -39) is True
- assert f(40, -40) is False
- py.test.raises(ValueError, f, 40, 2)
-
-def test_call_function_1():
- BInt = new_primitive_type("int")
- BLong = new_primitive_type("long")
- BFunc1 = new_function_type((BInt, BLong), BLong, False)
- f = cast(BFunc1, _testfunc(1))
- assert f(40, 2) == 42
- assert f(-100, -100) == -200
- int_max = (1 << (8*size_of_int()-1)) - 1
- long_max = (1 << (8*size_of_long()-1)) - 1
- if int_max == long_max:
- assert f(int_max, 1) == - int_max - 1
- else:
- assert f(int_max, 1) == int_max + 1
-
-def test_call_function_2():
- BLongLong = new_primitive_type("long long")
- BFunc2 = new_function_type((BLongLong, BLongLong), BLongLong, False)
- f = cast(BFunc2, _testfunc(2))
- longlong_max = (1 << (8*sizeof(BLongLong)-1)) - 1
- assert f(longlong_max - 42, 42) == longlong_max
- assert f(43, longlong_max - 42) == - longlong_max - 1
-
-def test_call_function_3():
- BFloat = new_primitive_type("float")
- BDouble = new_primitive_type("double")
- BFunc3 = new_function_type((BFloat, BDouble), BDouble, False)
- f = cast(BFunc3, _testfunc(3))
- assert f(1.25, 5.1) == 1.25 + 5.1 # exact
- res = f(1.3, 5.1)
- assert res != 6.4 and abs(res - 6.4) < 1E-5 # inexact
-
-def test_call_function_4():
- BFloat = new_primitive_type("float")
- BDouble = new_primitive_type("double")
- BFunc4 = new_function_type((BFloat, BDouble), BFloat, False)
- f = cast(BFunc4, _testfunc(4))
- res = f(1.25, 5.1)
- assert res != 6.35 and abs(res - 6.35) < 1E-5 # inexact
-
-def test_call_function_5():
- BVoid = new_void_type()
- BFunc5 = new_function_type((), BVoid, False)
- f = cast(BFunc5, _testfunc(5))
- f() # did not crash
-
-def test_call_function_6():
- BInt = new_primitive_type("int")
- BIntPtr = new_pointer_type(BInt)
- BFunc6 = new_function_type((BIntPtr,), BIntPtr, False)
- f = cast(BFunc6, _testfunc(6))
- x = newp(BIntPtr, 42)
- res = f(x)
- assert typeof(res) is BIntPtr
- assert res[0] == 42 - 1000
- #
- BIntArray = new_array_type(BIntPtr, None)
- BFunc6bis = new_function_type((BIntArray,), BIntPtr, False)
- f = cast(BFunc6bis, _testfunc(6))
- #
- res = f([142])
- assert typeof(res) is BIntPtr
- assert res[0] == 142 - 1000
- #
- res = f((143,))
- assert typeof(res) is BIntPtr
- assert res[0] == 143 - 1000
- #
- x = newp(BIntArray, [242])
- res = f(x)
- assert typeof(res) is BIntPtr
- assert res[0] == 242 - 1000
- #
- py.test.raises(TypeError, f, 123456)
- py.test.raises(TypeError, f, "foo")
- py.test.raises(TypeError, f, u+"bar")
-
-def test_call_function_7():
- BChar = new_primitive_type("char")
- BShort = new_primitive_type("short")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BChar, -1),
- ('a2', BShort, -1)])
- BFunc7 = new_function_type((BStruct,), BShort, False)
- f = cast(BFunc7, _testfunc(7))
- res = f({'a1': b'A', 'a2': -4042})
- assert res == -4042 + ord(b'A')
- #
- x = newp(BStructPtr, {'a1': b'A', 'a2': -4042})
- res = f(x[0])
- assert res == -4042 + ord(b'A')
-
-def test_call_function_20():
- BChar = new_primitive_type("char")
- BShort = new_primitive_type("short")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BChar, -1),
- ('a2', BShort, -1)])
- BFunc20 = new_function_type((BStructPtr,), BShort, False)
- f = cast(BFunc20, _testfunc(20))
- x = newp(BStructPtr, {'a1': b'A', 'a2': -4042})
- # can't pass a 'struct foo'
- py.test.raises(TypeError, f, x[0])
-
-def test_call_function_21():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a', BInt, -1),
- ('b', BInt, -1),
- ('c', BInt, -1),
- ('d', BInt, -1),
- ('e', BInt, -1),
- ('f', BInt, -1),
- ('g', BInt, -1),
- ('h', BInt, -1),
- ('i', BInt, -1),
- ('j', BInt, -1)])
- BFunc21 = new_function_type((BStruct,), BInt, False)
- f = cast(BFunc21, _testfunc(21))
- res = f(list(range(13, 3, -1)))
- lst = [(n << i) for (i, n) in enumerate(range(13, 3, -1))]
- assert res == sum(lst)
-
-def test_call_function_22():
- BInt = new_primitive_type("int")
- BArray10 = new_array_type(new_pointer_type(BInt), 10)
- BStruct = new_struct_type("struct foo")
- BStructP = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a', BArray10, -1)])
- BFunc22 = new_function_type((BStruct, BStruct), BStruct, False)
- f = cast(BFunc22, _testfunc(22))
- p1 = newp(BStructP, {'a': list(range(100, 110))})
- p2 = newp(BStructP, {'a': list(range(1000, 1100, 10))})
- res = f(p1[0], p2[0])
- for i in range(10):
- assert res.a[i] == p1.a[i] - p2.a[i]
-
-def test_call_function_23():
- BVoid = new_void_type() # declaring the function as int(void*)
- BVoidP = new_pointer_type(BVoid)
- BInt = new_primitive_type("int")
- BFunc23 = new_function_type((BVoidP,), BInt, False)
- f = cast(BFunc23, _testfunc(23))
- res = f(b"foo")
- assert res == 1000 * ord(b'f')
- res = f(cast(BVoidP, 0)) # NULL
- assert res == -42
- py.test.raises(TypeError, f, None)
- py.test.raises(TypeError, f, 0)
- py.test.raises(TypeError, f, 0.0)
-
-def test_call_function_23_bis():
- # declaring the function as int(unsigned char*)
- BUChar = new_primitive_type("unsigned char")
- BUCharP = new_pointer_type(BUChar)
- BInt = new_primitive_type("int")
- BFunc23 = new_function_type((BUCharP,), BInt, False)
- f = cast(BFunc23, _testfunc(23))
- res = f(b"foo")
- assert res == 1000 * ord(b'f')
-
-def test_call_function_23_bool_array():
- # declaring the function as int(_Bool*)
- BBool = new_primitive_type("_Bool")
- BBoolP = new_pointer_type(BBool)
- BInt = new_primitive_type("int")
- BFunc23 = new_function_type((BBoolP,), BInt, False)
- f = cast(BFunc23, _testfunc(23))
- res = f(b"\x01\x01")
- assert res == 1000
- py.test.raises(ValueError, f, b"\x02\x02")
-
-def test_cannot_pass_struct_with_array_of_length_0():
- BInt = new_primitive_type("int")
- BArray0 = new_array_type(new_pointer_type(BInt), 0)
- BStruct = new_struct_type("struct foo")
- BStructP = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a', BArray0)])
- BFunc = new_function_type((BStruct,), BInt, False)
- py.test.raises(NotImplementedError, cast(BFunc, 123), cast(BStructP, 123))
- BFunc2 = new_function_type((BInt,), BStruct, False)
- py.test.raises(NotImplementedError, cast(BFunc2, 123), 123)
-
-def test_call_function_9():
- BInt = new_primitive_type("int")
- BFunc9 = new_function_type((BInt,), BInt, True) # vararg
- f = cast(BFunc9, _testfunc(9))
- assert f(0) == 0
- assert f(1, cast(BInt, 42)) == 42
- assert f(2, cast(BInt, 40), cast(BInt, 2)) == 42
- py.test.raises(TypeError, f, 1, 42)
- py.test.raises(TypeError, f, 2, None)
- # promotion of chars and shorts to ints
- BSChar = new_primitive_type("signed char")
- BUChar = new_primitive_type("unsigned char")
- BSShort = new_primitive_type("short")
- assert f(3, cast(BSChar, -3), cast(BUChar, 200), cast(BSShort, -5)) == 192
-
-def test_call_function_24():
- BFloat = new_primitive_type("float")
- BFloatComplex = new_primitive_type("float _Complex")
- BFunc3 = new_function_type((BFloat, BFloat), BFloatComplex, False)
- if 0: # libffi returning nonsense silently, so logic disabled for now
- f = cast(BFunc3, _testfunc(24))
- result = f(1.25, 5.1)
- assert type(result) == complex
- assert result.real == 1.25 # exact
- assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-5) # inexact
- else:
- f = cast(BFunc3, _testfunc(9))
- py.test.raises(NotImplementedError, f, 12.3, 34.5)
-
-def test_call_function_25():
- BDouble = new_primitive_type("double")
- BDoubleComplex = new_primitive_type("double _Complex")
- BFunc3 = new_function_type((BDouble, BDouble), BDoubleComplex, False)
- if 0: # libffi returning nonsense silently, so logic disabled for now
- f = cast(BFunc3, _testfunc(25))
- result = f(1.25, 5.1)
- assert type(result) == complex
- assert result.real == 1.25 # exact
- assert (result.imag != 2*5.1) and (abs(result.imag - 2*5.1) < 1e-10) # inexact
- else:
- f = cast(BFunc3, _testfunc(9))
- py.test.raises(NotImplementedError, f, 12.3, 34.5)
-
-def test_cannot_call_with_a_autocompleted_struct():
- BSChar = new_primitive_type("signed char")
- BDouble = new_primitive_type("double")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('c', BDouble, -1, 8),
- ('a', BSChar, -1, 2),
- ('b', BSChar, -1, 0)])
- BFunc = new_function_type((BStruct,), BDouble) # internally not callable
- dummy_func = cast(BFunc, 42)
- e = py.test.raises(NotImplementedError, dummy_func, "?")
- msg = ("ctype 'struct foo' not supported as argument. It is a struct "
- 'declared with "...;", but the C calling convention may depend '
- "on the missing fields; or, it contains anonymous struct/unions. "
- "Such structs are only supported as argument if the function is "
- "'API mode' and non-variadic (i.e. declared inside ffibuilder."
- "cdef()+ffibuilder.set_source() and not taking a final '...' "
- "argument)")
- assert str(e.value) == msg
-
-def test_new_charp():
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- x = newp(BCharA, 42)
- assert len(x) == 42
- x = newp(BCharA, b"foobar")
- assert len(x) == 7
-
-def test_load_and_call_function():
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BLong = new_primitive_type("long")
- BFunc = new_function_type((BCharP,), BLong, False)
- ll = find_and_load_library('c')
- strlen = ll.load_function(BFunc, "strlen")
- input = newp(new_array_type(BCharP, None), b"foobar")
- assert strlen(input) == 6
- #
- assert strlen(b"foobarbaz") == 9
- #
- BVoidP = new_pointer_type(new_void_type())
- strlenaddr = ll.load_function(BVoidP, "strlen")
- assert strlenaddr == cast(BVoidP, strlen)
-
-def test_read_variable():
- ## FIXME: this test assumes glibc specific behavior, it's not compliant with C standard
- ## https://bugs.pypy.org/issue1643
- if not sys.platform.startswith("linux"):
- py.test.skip("untested")
- BVoidP = new_pointer_type(new_void_type())
- ll = find_and_load_library('c')
- stderr = ll.read_variable(BVoidP, "stderr")
- assert stderr == cast(BVoidP, _testfunc(8))
- #
- ll.close_lib()
- py.test.raises(ValueError, ll.read_variable, BVoidP, "stderr")
-
-def test_read_variable_as_unknown_length_array():
- ## FIXME: this test assumes glibc specific behavior, it's not compliant with C standard
- ## https://bugs.pypy.org/issue1643
- if not sys.platform.startswith("linux"):
- py.test.skip("untested")
- BCharP = new_pointer_type(new_primitive_type("char"))
- BArray = new_array_type(BCharP, None)
- ll = find_and_load_library('c')
- stderr = ll.read_variable(BArray, "stderr")
- assert repr(stderr).startswith("<cdata 'char *' 0x")
- # ^^ and not 'char[]', which is basically not allowed and would crash
-
-def test_write_variable():
- ## FIXME: this test assumes glibc specific behavior, it's not compliant with C standard
- ## https://bugs.pypy.org/issue1643
- if not sys.platform.startswith("linux"):
- py.test.skip("untested")
- BVoidP = new_pointer_type(new_void_type())
- ll = find_and_load_library('c')
- stderr = ll.read_variable(BVoidP, "stderr")
- ll.write_variable(BVoidP, "stderr", cast(BVoidP, 0))
- assert ll.read_variable(BVoidP, "stderr") is not None
- assert not ll.read_variable(BVoidP, "stderr")
- ll.write_variable(BVoidP, "stderr", stderr)
- assert ll.read_variable(BVoidP, "stderr") == stderr
- #
- ll.close_lib()
- py.test.raises(ValueError, ll.write_variable, BVoidP, "stderr", stderr)
-
-def test_callback():
- BInt = new_primitive_type("int")
- def make_callback():
- def cb(n):
- return n + 1
- BFunc = new_function_type((BInt,), BInt, False)
- return callback(BFunc, cb, 42) # 'cb' and 'BFunc' go out of scope
- f = make_callback()
- assert f(-142) == -141
- assert repr(f).startswith(
- "<cdata 'int(*)(int)' calling <function ")
- assert "cb at 0x" in repr(f)
- e = py.test.raises(TypeError, f)
- assert str(e.value) == "'int(*)(int)' expects 1 arguments, got 0"
-
-def test_callback_exception():
- try:
- import cStringIO
- except ImportError:
- import io as cStringIO # Python 3
- import linecache
- def matches(istr, ipattern, ipattern38):
- if sys.version_info >= (3, 8):
- ipattern = ipattern38
- str, pattern = istr, ipattern
- while '$' in pattern:
- i = pattern.index('$')
- assert str[:i] == pattern[:i]
- j = str.find(pattern[i+1], i)
- assert i + 1 <= j <= str.find('\n', i)
- str = str[j:]
- pattern = pattern[i+1:]
- assert str == pattern
- return True
- def check_value(x):
- if x == 10000:
- raise ValueError(42)
- def Zcb1(x):
- check_value(x)
- return x * 3
- BShort = new_primitive_type("short")
- BFunc = new_function_type((BShort,), BShort, False)
- f = callback(BFunc, Zcb1, -42)
- #
- seen = []
- oops_result = None
- def oops(*args):
- seen.append(args)
- return oops_result
- ff = callback(BFunc, Zcb1, -42, oops)
- #
- orig_stderr = sys.stderr
- orig_getline = linecache.getline
- try:
- linecache.getline = lambda *args: 'LINE' # hack: speed up PyPy tests
- sys.stderr = cStringIO.StringIO()
- if hasattr(sys, '__unraisablehook__'): # work around pytest
- sys.unraisablehook = sys.__unraisablehook__ # on recent CPythons
- assert f(100) == 300
- assert sys.stderr.getvalue() == ''
- assert f(10000) == -42
- assert matches(sys.stderr.getvalue(), """\
-From cffi callback <function$Zcb1 at 0x$>:
-Traceback (most recent call last):
- File "$", line $, in Zcb1
- $
- File "$", line $, in check_value
- $
-ValueError: 42
-""", """\
-Exception ignored from cffi callback <function$Zcb1 at 0x$>:
-Traceback (most recent call last):
- File "$", line $, in Zcb1
- $
- File "$", line $, in check_value
- $
-ValueError: 42
-""")
- sys.stderr = cStringIO.StringIO()
- bigvalue = 20000
- assert f(bigvalue) == -42
- assert matches(sys.stderr.getvalue(), """\
-From cffi callback <function$Zcb1 at 0x$>:
-Trying to convert the result back to C:
-OverflowError: integer 60000 does not fit 'short'
-""", """\
-Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C:
-Traceback (most recent call last):
- File "$", line $, in test_callback_exception
- $
-OverflowError: integer 60000 does not fit 'short'
-""")
- sys.stderr = cStringIO.StringIO()
- bigvalue = 20000
- assert len(seen) == 0
- assert ff(bigvalue) == -42
- assert sys.stderr.getvalue() == ""
- assert len(seen) == 1
- exc, val, tb = seen[0]
- assert exc is OverflowError
- assert str(val) == "integer 60000 does not fit 'short'"
- #
- sys.stderr = cStringIO.StringIO()
- bigvalue = 20000
- del seen[:]
- oops_result = 81
- assert ff(bigvalue) == 81
- oops_result = None
- assert sys.stderr.getvalue() == ""
- assert len(seen) == 1
- exc, val, tb = seen[0]
- assert exc is OverflowError
- assert str(val) == "integer 60000 does not fit 'short'"
- #
- sys.stderr = cStringIO.StringIO()
- bigvalue = 20000
- del seen[:]
- oops_result = "xy" # not None and not an int!
- assert ff(bigvalue) == -42
- oops_result = None
- assert matches(sys.stderr.getvalue(), """\
-From cffi callback <function$Zcb1 at 0x$>:
-Trying to convert the result back to C:
-OverflowError: integer 60000 does not fit 'short'
-
-During the call to 'onerror', another exception occurred:
-
-TypeError: $integer$
-""", """\
-Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C:
-Traceback (most recent call last):
- File "$", line $, in test_callback_exception
- $
-OverflowError: integer 60000 does not fit 'short'
-Exception ignored during handling of the above exception by 'onerror':
-Traceback (most recent call last):
- File "$", line $, in test_callback_exception
- $
-TypeError: $integer$
-""")
- #
- sys.stderr = cStringIO.StringIO()
- seen = "not a list" # this makes the oops() function crash
- assert ff(bigvalue) == -42
- # the $ after the AttributeError message are for the suggestions that
- # will be added in Python 3.10
- assert matches(sys.stderr.getvalue(), """\
-From cffi callback <function$Zcb1 at 0x$>:
-Trying to convert the result back to C:
-OverflowError: integer 60000 does not fit 'short'
-
-During the call to 'onerror', another exception occurred:
-
-Traceback (most recent call last):
- File "$", line $, in oops
- $
-AttributeError: 'str' object has no attribute 'append$
-""", """\
-Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C:
-Traceback (most recent call last):
- File "$", line $, in test_callback_exception
- $
-OverflowError: integer 60000 does not fit 'short'
-Exception ignored during handling of the above exception by 'onerror':
-Traceback (most recent call last):
- File "$", line $, in oops
- $
-AttributeError: 'str' object has no attribute 'append$
-""")
- finally:
- sys.stderr = orig_stderr
- linecache.getline = orig_getline
-
-def test_callback_return_type():
- for rettype in ["signed char", "short", "int", "long", "long long",
- "unsigned char", "unsigned short", "unsigned int",
- "unsigned long", "unsigned long long"]:
- BRet = new_primitive_type(rettype)
- def cb(n):
- return n + 1
- BFunc = new_function_type((BRet,), BRet)
- f = callback(BFunc, cb, 42)
- assert f(41) == 42
- if rettype.startswith("unsigned "):
- min = 0
- max = (1 << (8*sizeof(BRet))) - 1
- else:
- min = -(1 << (8*sizeof(BRet)-1))
- max = (1 << (8*sizeof(BRet)-1)) - 1
- assert f(min) == min + 1
- assert f(max - 1) == max
- assert f(max) == 42
-
-def test_a_lot_of_callbacks():
- BIGNUM = 10000
- if 'PY_DOT_PY' in globals(): BIGNUM = 100 # tests on py.py
- #
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BInt,), BInt, False)
- def make_callback(m):
- def cb(n):
- return n + m
- return callback(BFunc, cb, 42) # 'cb' goes out of scope
- #
- flist = [make_callback(i) for i in range(BIGNUM)]
- for i, f in enumerate(flist):
- assert f(-142) == -142 + i
-
-def test_callback_receiving_tiny_struct():
- BSChar = new_primitive_type("signed char")
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a', BSChar, -1),
- ('b', BSChar, -1)])
- def cb(s):
- return s.a + 10 * s.b
- BFunc = new_function_type((BStruct,), BInt)
- f = callback(BFunc, cb)
- p = newp(BStructPtr, [-2, -4])
- n = f(p[0])
- assert n == -42
-
-def test_callback_returning_tiny_struct():
- BSChar = new_primitive_type("signed char")
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a', BSChar, -1),
- ('b', BSChar, -1)])
- def cb(n):
- return newp(BStructPtr, [-n, -3*n])[0]
- BFunc = new_function_type((BInt,), BStruct)
- f = callback(BFunc, cb)
- s = f(10)
- assert typeof(s) is BStruct
- assert repr(s) == "<cdata 'struct foo' owning 2 bytes>"
- assert s.a == -10
- assert s.b == -30
-
-def test_callback_receiving_struct():
- BSChar = new_primitive_type("signed char")
- BInt = new_primitive_type("int")
- BDouble = new_primitive_type("double")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a', BSChar, -1),
- ('b', BDouble, -1)])
- def cb(s):
- return s.a + int(s.b)
- BFunc = new_function_type((BStruct,), BInt)
- f = callback(BFunc, cb)
- p = newp(BStructPtr, [-2, 44.444])
- n = f(p[0])
- assert n == 42
-
-def test_callback_returning_struct():
- BSChar = new_primitive_type("signed char")
- BInt = new_primitive_type("int")
- BDouble = new_primitive_type("double")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a', BSChar, -1),
- ('b', BDouble, -1)])
- def cb(n):
- return newp(BStructPtr, [-n, 1E-42])[0]
- BFunc = new_function_type((BInt,), BStruct)
- f = callback(BFunc, cb)
- s = f(10)
- assert typeof(s) is BStruct
- assert repr(s) in ["<cdata 'struct foo' owning 12 bytes>",
- "<cdata 'struct foo' owning 16 bytes>"]
- assert s.a == -10
- assert s.b == 1E-42
-
-def test_callback_receiving_big_struct():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a', BInt, -1),
- ('b', BInt, -1),
- ('c', BInt, -1),
- ('d', BInt, -1),
- ('e', BInt, -1),
- ('f', BInt, -1),
- ('g', BInt, -1),
- ('h', BInt, -1),
- ('i', BInt, -1),
- ('j', BInt, -1)])
- def cb(s):
- for i, name in enumerate("abcdefghij"):
- assert getattr(s, name) == 13 - i
- return 42
- BFunc = new_function_type((BStruct,), BInt)
- f = callback(BFunc, cb)
- p = newp(BStructPtr, list(range(13, 3, -1)))
- n = f(p[0])
- assert n == 42
-
-def test_callback_returning_big_struct():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a', BInt, -1),
- ('b', BInt, -1),
- ('c', BInt, -1),
- ('d', BInt, -1),
- ('e', BInt, -1),
- ('f', BInt, -1),
- ('g', BInt, -1),
- ('h', BInt, -1),
- ('i', BInt, -1),
- ('j', BInt, -1)])
- def cb():
- return newp(BStructPtr, list(range(13, 3, -1)))[0]
- BFunc = new_function_type((), BStruct)
- f = callback(BFunc, cb)
- s = f()
- assert typeof(s) is BStruct
- assert repr(s) in ["<cdata 'struct foo' owning 40 bytes>",
- "<cdata 'struct foo' owning 80 bytes>"]
- for i, name in enumerate("abcdefghij"):
- assert getattr(s, name) == 13 - i
-
-def test_callback_returning_void():
- BVoid = new_void_type()
- BFunc = new_function_type((), BVoid, False)
- def cb():
- seen.append(42)
- f = callback(BFunc, cb)
- seen = []
- f()
- assert seen == [42]
- py.test.raises(TypeError, callback, BFunc, cb, -42)
-
-def test_enum_type():
- BUInt = new_primitive_type("unsigned int")
- BEnum = new_enum_type("foo", (), (), BUInt)
- assert repr(BEnum) == "<ctype 'foo'>"
- assert BEnum.kind == "enum"
- assert BEnum.cname == "foo"
- assert BEnum.elements == {}
- #
- BInt = new_primitive_type("int")
- BEnum = new_enum_type("enum foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
- assert BEnum.kind == "enum"
- assert BEnum.cname == "enum foo"
- assert BEnum.elements == {-20: 'ab', 0: 'def', 1: 'c'}
- # 'elements' is not the real dict, but merely a copy
- BEnum.elements[2] = '??'
- assert BEnum.elements == {-20: 'ab', 0: 'def', 1: 'c'}
- #
- BEnum = new_enum_type("enum bar", ('ab', 'cd'), (5, 5), BUInt)
- assert BEnum.elements == {5: 'ab'}
- assert BEnum.relements == {'ab': 5, 'cd': 5}
-
-def test_cast_to_enum():
- BInt = new_primitive_type("int")
- BEnum = new_enum_type("enum foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
- assert sizeof(BEnum) == sizeof(BInt)
- e = cast(BEnum, 0)
- assert repr(e) == "<cdata 'enum foo' 0: def>"
- assert repr(cast(BEnum, -42)) == "<cdata 'enum foo' -42>"
- assert repr(cast(BEnum, -20)) == "<cdata 'enum foo' -20: ab>"
- assert string(e) == 'def'
- assert string(cast(BEnum, -20)) == 'ab'
- assert int(cast(BEnum, 1)) == 1
- assert int(cast(BEnum, 0)) == 0
- assert int(cast(BEnum, -242 + 2**128)) == -242
- assert string(cast(BEnum, -242 + 2**128)) == '-242'
- #
- BUInt = new_primitive_type("unsigned int")
- BEnum = new_enum_type("enum bar", ('def', 'c', 'ab'), (0, 1, 20), BUInt)
- e = cast(BEnum, -1)
- assert repr(e) == "<cdata 'enum bar' 4294967295>" # unsigned int
- #
- BLong = new_primitive_type("long")
- BEnum = new_enum_type("enum baz", (), (), BLong)
- assert sizeof(BEnum) == sizeof(BLong)
- e = cast(BEnum, -1)
- assert repr(e) == "<cdata 'enum baz' -1>"
-
-def test_enum_with_non_injective_mapping():
- BInt = new_primitive_type("int")
- BEnum = new_enum_type("enum foo", ('ab', 'cd'), (7, 7), BInt)
- e = cast(BEnum, 7)
- assert repr(e) == "<cdata 'enum foo' 7: ab>"
- assert string(e) == 'ab'
-
-def test_enum_in_struct():
- BInt = new_primitive_type("int")
- BEnum = new_enum_type("enum foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
- BStruct = new_struct_type("struct bar")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BEnum, -1)])
- p = newp(BStructPtr, [-20])
- assert p.a1 == -20
- p = newp(BStructPtr, [12])
- assert p.a1 == 12
- e = py.test.raises(TypeError, newp, BStructPtr, [None])
- msg = str(e.value)
- assert ("an integer is required" in msg or # CPython
- "unsupported operand type for int(): 'NoneType'" in msg or # old PyPys
- "expected integer, got NoneType object" in msg) # newer PyPys
- with pytest.raises(TypeError):
- p.a1 = "def"
- if sys.version_info < (3,):
- BEnum2 = new_enum_type(unicode("foo"), (unicode('abc'),), (5,), BInt)
- assert string(cast(BEnum2, 5)) == 'abc'
- assert type(string(cast(BEnum2, 5))) is str
-
-def test_enum_overflow():
- max_uint = 2 ** (size_of_int()*8) - 1
- max_int = max_uint // 2
- max_ulong = 2 ** (size_of_long()*8) - 1
- max_long = max_ulong // 2
- for BPrimitive in [new_primitive_type("int"),
- new_primitive_type("unsigned int"),
- new_primitive_type("long"),
- new_primitive_type("unsigned long")]:
- for x in [max_uint, max_int, max_ulong, max_long]:
- for testcase in [x, x+1, -x-1, -x-2]:
- if int(cast(BPrimitive, testcase)) == testcase:
- # fits
- BEnum = new_enum_type("foo", ("AA",), (testcase,),
- BPrimitive)
- assert int(cast(BEnum, testcase)) == testcase
- else:
- # overflows
- py.test.raises(OverflowError, new_enum_type,
- "foo", ("AA",), (testcase,), BPrimitive)
-
-def test_callback_returning_enum():
- BInt = new_primitive_type("int")
- BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20), BInt)
- def cb(n):
- if n & 1:
- return cast(BEnum, n)
- else:
- return n
- BFunc = new_function_type((BInt,), BEnum)
- f = callback(BFunc, cb)
- assert f(0) == 0
- assert f(1) == 1
- assert f(-20) == -20
- assert f(20) == 20
- assert f(21) == 21
-
-def test_callback_returning_enum_unsigned():
- BInt = new_primitive_type("int")
- BUInt = new_primitive_type("unsigned int")
- BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, 20), BUInt)
- def cb(n):
- if n & 1:
- return cast(BEnum, n)
- else:
- return n
- BFunc = new_function_type((BInt,), BEnum)
- f = callback(BFunc, cb)
- assert f(0) == 0
- assert f(1) == 1
- assert f(-21) == 2**32 - 21
- assert f(20) == 20
- assert f(21) == 21
-
-def test_callback_returning_char():
- BInt = new_primitive_type("int")
- BChar = new_primitive_type("char")
- def cb(n):
- return bytechr(n)
- BFunc = new_function_type((BInt,), BChar)
- f = callback(BFunc, cb)
- assert f(0) == b'\x00'
- assert f(255) == b'\xFF'
-
-def _hacked_pypy_uni4():
- pyuni4 = {1: True, 2: False}[len(u+'\U00012345')]
- return 'PY_DOT_PY' in globals() and not pyuni4
-
-def test_callback_returning_wchar_t():
- BInt = new_primitive_type("int")
- BWChar = new_primitive_type("wchar_t")
- def cb(n):
- if n == -1:
- return u+'\U00012345'
- if n == -2:
- raise ValueError
- return unichr(n)
- BFunc = new_function_type((BInt,), BWChar)
- f = callback(BFunc, cb)
- assert f(0) == unichr(0)
- assert f(255) == unichr(255)
- assert f(0x1234) == u+'\u1234'
- if sizeof(BWChar) == 4 and not _hacked_pypy_uni4():
- assert f(-1) == u+'\U00012345'
- assert f(-2) == u+'\x00' # and an exception printed to stderr
-
-def test_struct_with_bitfields():
- BLong = new_primitive_type("long")
- BStruct = new_struct_type("struct foo")
- LONGBITS = 8 * sizeof(BLong)
- complete_struct_or_union(BStruct, [('a1', BLong, 1),
- ('a2', BLong, 2),
- ('a3', BLong, 3),
- ('a4', BLong, LONGBITS - 5)])
- d = BStruct.fields
- assert d[0][1].offset == d[1][1].offset == d[2][1].offset == 0
- assert d[3][1].offset == sizeof(BLong)
- def f(m, r):
- if sys.byteorder == 'little':
- return r
- else:
- return LONGBITS - m - r
- assert d[0][1].bitshift == f(1, 0)
- assert d[0][1].bitsize == 1
- assert d[1][1].bitshift == f(2, 1)
- assert d[1][1].bitsize == 2
- assert d[2][1].bitshift == f(3, 3)
- assert d[2][1].bitsize == 3
- assert d[3][1].bitshift == f(LONGBITS - 5, 0)
- assert d[3][1].bitsize == LONGBITS - 5
- assert sizeof(BStruct) == 2 * sizeof(BLong)
- assert alignof(BStruct) == alignof(BLong)
-
-def test_bitfield_instance():
- BInt = new_primitive_type("int")
- BUnsignedInt = new_primitive_type("unsigned int")
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a1', BInt, 1),
- ('a2', BUnsignedInt, 2),
- ('a3', BInt, 3)])
- p = newp(new_pointer_type(BStruct), None)
- p.a1 = -1
- assert p.a1 == -1
- p.a1 = 0
- with pytest.raises(OverflowError):
- p.a1 = 2
- assert p.a1 == 0
- #
- p.a1 = -1
- p.a2 = 3
- p.a3 = -4
- with pytest.raises(OverflowError):
- p.a3 = 4
- with pytest.raises(OverflowError) as e:
- p.a3 = -5
- assert str(e.value) == ("value -5 outside the range allowed by the "
- "bit field width: -4 <= x <= 3")
- assert p.a1 == -1 and p.a2 == 3 and p.a3 == -4
- #
- # special case for convenience: "int x:1", while normally signed,
- # allows also setting the value "1" (it still gets read back as -1)
- p.a1 = 1
- assert p.a1 == -1
- with pytest.raises(OverflowError) as e:
- p.a1 = -2
- assert str(e.value) == ("value -2 outside the range allowed by the "
- "bit field width: -1 <= x <= 1")
-
-def test_bitfield_instance_init():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a1', BInt, 1)])
- p = newp(new_pointer_type(BStruct), [-1])
- assert p.a1 == -1
- p = newp(new_pointer_type(BStruct), {'a1': -1})
- assert p.a1 == -1
- #
- BUnion = new_union_type("union bar")
- complete_struct_or_union(BUnion, [('a1', BInt, 1)])
- p = newp(new_pointer_type(BUnion), [-1])
- assert p.a1 == -1
-
-def test_weakref():
- import _weakref
- BInt = new_primitive_type("int")
- BPtr = new_pointer_type(BInt)
- rlist = [_weakref.ref(BInt),
- _weakref.ref(newp(BPtr, 42)),
- _weakref.ref(cast(BPtr, 42)),
- _weakref.ref(cast(BInt, 42)),
- _weakref.ref(buffer(newp(BPtr, 42))),
- ]
- for i in range(5):
- import gc; gc.collect()
- if [r() for r in rlist] == [None for r in rlist]:
- break
-
-def test_no_inheritance():
- BInt = new_primitive_type("int")
- try:
- class foo(type(BInt)): pass
- except TypeError:
- pass
- else:
- raise AssertionError
- x = cast(BInt, 42)
- try:
- class foo(type(x)): pass
- except TypeError:
- pass
- else:
- raise AssertionError
-
-def test_assign_string():
- BChar = new_primitive_type("char")
- BArray1 = new_array_type(new_pointer_type(BChar), 5)
- BArray2 = new_array_type(new_pointer_type(BArray1), 5)
- a = newp(BArray2, [b"abc", b"de", b"ghij"])
- assert string(a[1]) == b"de"
- assert string(a[2]) == b"ghij"
- a[2] = b"."
- assert string(a[2]) == b"."
- a[2] = b"12345"
- assert string(a[2]) == b"12345"
- with pytest.raises(IndexError) as e:
- a[2] = b"123456"
- assert 'char[5]' in str(e.value)
- assert 'got 6 characters' in str(e.value)
-
-def test_add_error():
- x = cast(new_primitive_type("int"), 42)
- with pytest.raises(TypeError):
- x + 1
- with pytest.raises(TypeError):
- x - 1
-
-def test_void_errors():
- py.test.raises(ValueError, alignof, new_void_type())
- py.test.raises(TypeError, newp, new_pointer_type(new_void_type()), None)
-
-def test_too_many_items():
- BChar = new_primitive_type("char")
- BArray = new_array_type(new_pointer_type(BChar), 5)
- py.test.raises(IndexError, newp, BArray, tuple(b'123456'))
- py.test.raises(IndexError, newp, BArray, list(b'123456'))
- py.test.raises(IndexError, newp, BArray, b'123456')
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [])
- py.test.raises(TypeError, newp, new_pointer_type(BStruct), b'')
- py.test.raises(ValueError, newp, new_pointer_type(BStruct), [b'1'])
-
-def test_more_type_errors():
- BInt = new_primitive_type("int")
- BChar = new_primitive_type("char")
- BArray = new_array_type(new_pointer_type(BChar), 5)
- py.test.raises(TypeError, newp, BArray, 12.34)
- BArray = new_array_type(new_pointer_type(BInt), 5)
- py.test.raises(TypeError, newp, BArray, 12.34)
- BFloat = new_primitive_type("float")
- py.test.raises(TypeError, cast, BFloat, newp(BArray, None))
-
-def test_more_overflow_errors():
- BUInt = new_primitive_type("unsigned int")
- py.test.raises(OverflowError, newp, new_pointer_type(BUInt), -1)
- py.test.raises(OverflowError, newp, new_pointer_type(BUInt), 2**32)
-
-def test_newp_copying():
- """Test that we can do newp(<type>, <cdata of the given type>) for most
- types, including same-type arrays.
- """
- BInt = new_primitive_type("int")
- p = newp(new_pointer_type(BInt), cast(BInt, 42))
- assert p[0] == 42
- #
- BUInt = new_primitive_type("unsigned int")
- p = newp(new_pointer_type(BUInt), cast(BUInt, 42))
- assert p[0] == 42
- #
- BChar = new_primitive_type("char")
- p = newp(new_pointer_type(BChar), cast(BChar, '!'))
- assert p[0] == b'!'
- #
- BFloat = new_primitive_type("float")
- p = newp(new_pointer_type(BFloat), cast(BFloat, 12.25))
- assert p[0] == 12.25
- #
- BStruct = new_struct_type("struct foo_s")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BInt, -1)])
- s1 = newp(BStructPtr, [42])
- p1 = newp(new_pointer_type(BStructPtr), s1)
- assert p1[0] == s1
- #
- BArray = new_array_type(new_pointer_type(BInt), None)
- a1 = newp(BArray, [1, 2, 3, 4])
- py.test.raises(TypeError, newp, BArray, a1)
- BArray6 = new_array_type(new_pointer_type(BInt), 6)
- a1 = newp(BArray6, [10, 20, 30])
- a2 = newp(BArray6, a1)
- assert list(a2) == [10, 20, 30, 0, 0, 0]
- #
- s1 = newp(BStructPtr, [42])
- s2 = newp(BStructPtr, s1[0])
- assert s2.a1 == 42
- #
- BUnion = new_union_type("union foo_u")
- BUnionPtr = new_pointer_type(BUnion)
- complete_struct_or_union(BUnion, [('a1', BInt, -1)])
- u1 = newp(BUnionPtr, [42])
- u2 = newp(BUnionPtr, u1[0])
- assert u2.a1 == 42
- #
- BFunc = new_function_type((BInt,), BUInt)
- p1 = cast(BFunc, 42)
- p2 = newp(new_pointer_type(BFunc), p1)
- assert p2[0] == p1
-
-def test_string():
- BChar = new_primitive_type("char")
- assert string(cast(BChar, 42)) == b'*'
- assert string(cast(BChar, 0)) == b'\x00'
- BCharP = new_pointer_type(BChar)
- BArray = new_array_type(BCharP, 10)
- a = newp(BArray, b"hello")
- assert len(a) == 10
- assert string(a) == b"hello"
- p = a + 2
- assert string(p) == b"llo"
- assert string(newp(new_array_type(BCharP, 4), b"abcd")) == b"abcd"
- py.test.raises(RuntimeError, string, cast(BCharP, 0))
- assert string(a, 4) == b"hell"
- assert string(a, 5) == b"hello"
- assert string(a, 6) == b"hello"
-
-def test_string_byte():
- BByte = new_primitive_type("signed char")
- assert string(cast(BByte, 42)) == b'*'
- assert string(cast(BByte, 0)) == b'\x00'
- BArray = new_array_type(new_pointer_type(BByte), None)
- a = newp(BArray, [65, 66, 67])
- assert type(string(a)) is bytes and string(a) == b'ABC'
- #
- BByte = new_primitive_type("unsigned char")
- assert string(cast(BByte, 42)) == b'*'
- assert string(cast(BByte, 0)) == b'\x00'
- BArray = new_array_type(new_pointer_type(BByte), None)
- a = newp(BArray, [65, 66, 67])
- assert type(string(a)) is bytes and string(a) == b'ABC'
- if 'PY_DOT_PY' not in globals() and sys.version_info < (3,):
- assert string(a, 8).startswith(b'ABC') # may contain additional garbage
-
-def test_string_wchar():
- for typename in ["wchar_t", "char16_t", "char32_t"]:
- _test_string_wchar_variant(typename)
-
-def _test_string_wchar_variant(typename):
- BWChar = new_primitive_type(typename)
- assert string(cast(BWChar, 42)) == u+'*'
- assert string(cast(BWChar, 0x4253)) == u+'\u4253'
- assert string(cast(BWChar, 0)) == u+'\x00'
- BArray = new_array_type(new_pointer_type(BWChar), None)
- a = newp(BArray, [u+'A', u+'B', u+'C'])
- assert type(string(a)) is unicode and string(a) == u+'ABC'
- if 'PY_DOT_PY' not in globals() and sys.version_info < (3,):
- try:
- # may contain additional garbage
- assert string(a, 8).startswith(u+'ABC')
- except ValueError: # garbage contains values > 0x10FFFF
- assert sizeof(BWChar) == 4
-
-def test_string_typeerror():
- BShort = new_primitive_type("short")
- BArray = new_array_type(new_pointer_type(BShort), None)
- a = newp(BArray, [65, 66, 67])
- py.test.raises(TypeError, string, a)
-
-def test_bug_convert_to_ptr():
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BDouble = new_primitive_type("double")
- x = cast(BDouble, 42)
- py.test.raises(TypeError, newp, new_pointer_type(BCharP), x)
-
-def test_set_struct_fields():
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharArray10 = new_array_type(BCharP, 10)
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BCharArray10, -1)])
- p = newp(BStructPtr, None)
- assert string(p.a1) == b''
- p.a1 = b'foo'
- assert string(p.a1) == b'foo'
- assert list(p.a1) == [b'f', b'o', b'o'] + [b'\x00'] * 7
- p.a1 = [b'x', b'y']
- assert string(p.a1) == b'xyo'
-
-def test_invalid_function_result_types():
- BFunc = new_function_type((), new_void_type())
- BArray = new_array_type(new_pointer_type(BFunc), 5) # works
- new_function_type((), BFunc) # works
- new_function_type((), new_primitive_type("int"))
- new_function_type((), new_pointer_type(BFunc))
- BUnion = new_union_type("union foo_u")
- complete_struct_or_union(BUnion, [])
- BFunc = new_function_type((), BUnion)
- py.test.raises(NotImplementedError, cast(BFunc, 123))
- py.test.raises(TypeError, new_function_type, (), BArray)
-
-def test_struct_return_in_func():
- BChar = new_primitive_type("char")
- BShort = new_primitive_type("short")
- BFloat = new_primitive_type("float")
- BDouble = new_primitive_type("double")
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo_s")
- complete_struct_or_union(BStruct, [('a1', BChar, -1),
- ('a2', BShort, -1)])
- BFunc10 = new_function_type((BInt,), BStruct)
- f = cast(BFunc10, _testfunc(10))
- s = f(40)
- assert repr(s) == "<cdata 'struct foo_s' owning 4 bytes>"
- assert s.a1 == bytechr(40)
- assert s.a2 == 40 * 40
- #
- BStruct11 = new_struct_type("struct test11")
- complete_struct_or_union(BStruct11, [('a1', BInt, -1),
- ('a2', BInt, -1)])
- BFunc11 = new_function_type((BInt,), BStruct11)
- f = cast(BFunc11, _testfunc(11))
- s = f(40)
- assert repr(s) == "<cdata 'struct test11' owning 8 bytes>"
- assert s.a1 == 40
- assert s.a2 == 40 * 40
- #
- BStruct12 = new_struct_type("struct test12")
- complete_struct_or_union(BStruct12, [('a1', BDouble, -1),
- ])
- BFunc12 = new_function_type((BInt,), BStruct12)
- f = cast(BFunc12, _testfunc(12))
- s = f(40)
- assert repr(s) == "<cdata 'struct test12' owning 8 bytes>"
- assert s.a1 == 40.0
- #
- BStruct13 = new_struct_type("struct test13")
- complete_struct_or_union(BStruct13, [('a1', BInt, -1),
- ('a2', BInt, -1),
- ('a3', BInt, -1)])
- BFunc13 = new_function_type((BInt,), BStruct13)
- f = cast(BFunc13, _testfunc(13))
- s = f(40)
- assert repr(s) == "<cdata 'struct test13' owning 12 bytes>"
- assert s.a1 == 40
- assert s.a2 == 40 * 40
- assert s.a3 == 40 * 40 * 40
- #
- BStruct14 = new_struct_type("struct test14")
- complete_struct_or_union(BStruct14, [('a1', BFloat, -1),
- ])
- BFunc14 = new_function_type((BInt,), BStruct14)
- f = cast(BFunc14, _testfunc(14))
- s = f(40)
- assert repr(s) == "<cdata 'struct test14' owning 4 bytes>"
- assert s.a1 == 40.0
- #
- BStruct15 = new_struct_type("struct test15")
- complete_struct_or_union(BStruct15, [('a1', BFloat, -1),
- ('a2', BInt, -1)])
- BFunc15 = new_function_type((BInt,), BStruct15)
- f = cast(BFunc15, _testfunc(15))
- s = f(40)
- assert repr(s) == "<cdata 'struct test15' owning 8 bytes>"
- assert s.a1 == 40.0
- assert s.a2 == 40 * 40
- #
- BStruct16 = new_struct_type("struct test16")
- complete_struct_or_union(BStruct16, [('a1', BFloat, -1),
- ('a2', BFloat, -1)])
- BFunc16 = new_function_type((BInt,), BStruct16)
- f = cast(BFunc16, _testfunc(16))
- s = f(40)
- assert repr(s) == "<cdata 'struct test16' owning 8 bytes>"
- assert s.a1 == 40.0
- assert s.a2 == -40.0
- #
- BStruct17 = new_struct_type("struct test17")
- complete_struct_or_union(BStruct17, [('a1', BInt, -1),
- ('a2', BFloat, -1)])
- BFunc17 = new_function_type((BInt,), BStruct17)
- f = cast(BFunc17, _testfunc(17))
- s = f(40)
- assert repr(s) == "<cdata 'struct test17' owning 8 bytes>"
- assert s.a1 == 40
- assert s.a2 == 40.0 * 40.0
- #
- BStruct17Ptr = new_pointer_type(BStruct17)
- BFunc18 = new_function_type((BStruct17Ptr,), BInt)
- f = cast(BFunc18, _testfunc(18))
- x = f([[40, 2.5]])
- assert x == 42
- x = f([{'a2': 43.1}])
- assert x == 43
-
-def test_cast_with_functionptr():
- BFunc = new_function_type((), new_void_type())
- BFunc2 = new_function_type((), new_primitive_type("short"))
- BCharP = new_pointer_type(new_primitive_type("char"))
- BIntP = new_pointer_type(new_primitive_type("int"))
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BFunc, -1)])
- newp(BStructPtr, [cast(BFunc, 0)])
- newp(BStructPtr, [cast(BCharP, 0)])
- py.test.raises(TypeError, newp, BStructPtr, [cast(BIntP, 0)])
- py.test.raises(TypeError, newp, BStructPtr, [cast(BFunc2, 0)])
-
-def test_wchar():
- _test_wchar_variant("wchar_t")
- if sys.platform.startswith("linux"):
- BWChar = new_primitive_type("wchar_t")
- assert sizeof(BWChar) == 4
- # wchar_t is often signed on Linux, but not always (e.g. on ARM)
- assert int(cast(BWChar, -1)) in (-1, 4294967295)
-
-def test_char16():
- BChar16 = new_primitive_type("char16_t")
- assert sizeof(BChar16) == 2
- _test_wchar_variant("char16_t")
- assert int(cast(BChar16, -1)) == 0xffff # always unsigned
-
-def test_char32():
- BChar32 = new_primitive_type("char32_t")
- assert sizeof(BChar32) == 4
- _test_wchar_variant("char32_t")
- assert int(cast(BChar32, -1)) == 0xffffffff # always unsigned
-
-def _test_wchar_variant(typename):
- BWChar = new_primitive_type(typename)
- BInt = new_primitive_type("int")
- pyuni4 = {1: True, 2: False}[len(u+'\U00012345')]
- wchar4 = {2: False, 4: True}[sizeof(BWChar)]
- assert str(cast(BWChar, 0x45)) == "<cdata '%s' %s'E'>" % (
- typename, mandatory_u_prefix)
- assert str(cast(BWChar, 0x1234)) == "<cdata '%s' %s'\u1234'>" % (
- typename, mandatory_u_prefix)
- if not _hacked_pypy_uni4():
- if wchar4:
- x = cast(BWChar, 0x12345)
- assert str(x) == "<cdata '%s' %s'\U00012345'>" % (
- typename, mandatory_u_prefix)
- assert int(x) == 0x12345
- else:
- x = cast(BWChar, 0x18345)
- assert str(x) == "<cdata '%s' %s'\u8345'>" % (
- typename, mandatory_u_prefix)
- assert int(x) == 0x8345
- #
- BWCharP = new_pointer_type(BWChar)
- BStruct = new_struct_type("struct foo_s")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BWChar, -1),
- ('a2', BWCharP, -1)])
- s = newp(BStructPtr)
- s.a1 = u+'\x00'
- assert s.a1 == u+'\x00'
- with pytest.raises(TypeError):
- s.a1 = b'a'
- with pytest.raises(TypeError):
- s.a1 = bytechr(0xFF)
- s.a1 = u+'\u1234'
- assert s.a1 == u+'\u1234'
- if pyuni4:
- if wchar4:
- s.a1 = u+'\U00012345'
- assert s.a1 == u+'\U00012345'
- elif wchar4:
- if not _hacked_pypy_uni4():
- s.a1 = cast(BWChar, 0x12345)
- assert s.a1 == u+'\ud808\udf45'
- s.a1 = u+'\ud807\udf44'
- assert s.a1 == u+'\U00011f44'
- else:
- with pytest.raises(TypeError):
- s.a1 = u+'\U00012345'
- #
- BWCharArray = new_array_type(BWCharP, None)
- a = newp(BWCharArray, u+'hello \u1234 world')
- assert len(a) == 14 # including the final null
- assert string(a) == u+'hello \u1234 world'
- a[13] = u+'!'
- assert string(a) == u+'hello \u1234 world!'
- assert str(a) == repr(a)
- assert a[6] == u+'\u1234'
- a[6] = u+'-'
- assert string(a) == u+'hello - world!'
- assert str(a) == repr(a)
- #
- if wchar4 and not _hacked_pypy_uni4():
- u1 = u+'\U00012345\U00012346\U00012347'
- a = newp(BWCharArray, u1)
- assert len(a) == 4
- assert string(a) == u1
- assert len(list(a)) == 4
- expected = [u+'\U00012345', u+'\U00012346', u+'\U00012347', unichr(0)]
- assert list(a) == expected
- got = [a[i] for i in range(4)]
- assert got == expected
- with pytest.raises(IndexError):
- a[4]
- #
- w = cast(BWChar, 'a')
- assert repr(w) == "<cdata '%s' %s'a'>" % (typename, mandatory_u_prefix)
- assert str(w) == repr(w)
- assert string(w) == u+'a'
- assert int(w) == ord('a')
- w = cast(BWChar, 0x1234)
- assert repr(w) == "<cdata '%s' %s'\u1234'>" % (typename, mandatory_u_prefix)
- assert str(w) == repr(w)
- assert string(w) == u+'\u1234'
- assert int(w) == 0x1234
- w = cast(BWChar, u+'\u8234')
- assert repr(w) == "<cdata '%s' %s'\u8234'>" % (typename, mandatory_u_prefix)
- assert str(w) == repr(w)
- assert string(w) == u+'\u8234'
- assert int(w) == 0x8234
- w = cast(BInt, u+'\u1234')
- assert repr(w) == "<cdata 'int' 4660>"
- if wchar4 and not _hacked_pypy_uni4():
- w = cast(BWChar, u+'\U00012345')
- assert repr(w) == "<cdata '%s' %s'\U00012345'>" % (
- typename, mandatory_u_prefix)
- assert str(w) == repr(w)
- assert string(w) == u+'\U00012345'
- assert int(w) == 0x12345
- w = cast(BInt, u+'\U00012345')
- assert repr(w) == "<cdata 'int' 74565>"
- py.test.raises(TypeError, cast, BInt, u+'')
- py.test.raises(TypeError, cast, BInt, u+'XX')
- assert int(cast(BInt, u+'a')) == ord('a')
- #
- a = newp(BWCharArray, u+'hello - world')
- p = cast(BWCharP, a)
- assert string(p) == u+'hello - world'
- p[6] = u+'\u2345'
- assert string(p) == u+'hello \u2345 world'
- #
- s = newp(BStructPtr, [u+'\u1234', p])
- assert s.a1 == u+'\u1234'
- assert s.a2 == p
- assert str(s.a2) == repr(s.a2)
- assert string(s.a2) == u+'hello \u2345 world'
- #
- q = cast(BWCharP, 0)
- assert str(q) == repr(q)
- py.test.raises(RuntimeError, string, q)
- #
- def cb(p):
- assert repr(p).startswith("<cdata '%s *' 0x" % typename)
- return len(string(p))
- BFunc = new_function_type((BWCharP,), BInt, False)
- f = callback(BFunc, cb, -42)
- assert f(u+'a\u1234b') == 3
- #
- if wchar4 and not pyuni4 and not _hacked_pypy_uni4():
- # try out-of-range wchar_t values
- x = cast(BWChar, 1114112)
- py.test.raises(ValueError, string, x)
- x = cast(BWChar, -1)
- py.test.raises(ValueError, string, x)
-
-def test_wchar_variants_mix():
- BWChar = new_primitive_type("wchar_t")
- BChar16 = new_primitive_type("char16_t")
- BChar32 = new_primitive_type("char32_t")
- assert int(cast(BChar32, cast(BChar16, -2))) == 0xfffe
- assert int(cast(BWChar, cast(BChar16, -2))) == 0xfffe
- assert int(cast(BChar16, cast(BChar32, 0x0001f345))) == 0xf345
- assert int(cast(BChar16, cast(BWChar, 0x0001f345))) == 0xf345
- #
- BChar16A = new_array_type(new_pointer_type(BChar16), None)
- BChar32A = new_array_type(new_pointer_type(BChar32), None)
- x = cast(BChar32, 'A')
- py.test.raises(TypeError, newp, BChar16A, [x])
- x = cast(BChar16, 'A')
- py.test.raises(TypeError, newp, BChar32A, [x])
- #
- a = newp(BChar16A, u+'\U00012345')
- assert len(a) == 3
- a = newp(BChar32A, u+'\U00012345')
- assert len(a) == 2 # even if the Python unicode string above is 2 chars
-
-def test_keepalive_struct():
- # exception to the no-keepalive rule: p=newp(BStructPtr) returns a
- # pointer owning the memory, and p[0] returns a pointer to the
- # struct that *also* owns the memory
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', new_primitive_type("int"), -1),
- ('a2', new_primitive_type("int"), -1),
- ('a3', new_primitive_type("int"), -1)])
- p = newp(BStructPtr)
- assert repr(p) == "<cdata 'struct foo *' owning 12 bytes>"
- q = p[0]
- assert repr(q) == "<cdata 'struct foo' owning 12 bytes>"
- q.a1 = 123456
- assert p.a1 == 123456
- r = cast(BStructPtr, p)
- assert repr(r[0]).startswith("<cdata 'struct foo &' 0x")
- del p
- import gc; gc.collect()
- assert q.a1 == 123456
- assert repr(q) == "<cdata 'struct foo' owning 12 bytes>"
- assert q.a1 == 123456
-
-def test_nokeepalive_struct():
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- BStructPtrPtr = new_pointer_type(BStructPtr)
- complete_struct_or_union(BStruct, [('a1', new_primitive_type("int"), -1)])
- p = newp(BStructPtr)
- pp = newp(BStructPtrPtr)
- pp[0] = p
- s = pp[0][0]
- assert repr(s).startswith("<cdata 'struct foo &' 0x")
-
-def test_owning_repr():
- BInt = new_primitive_type("int")
- BArray = new_array_type(new_pointer_type(BInt), None) # int[]
- p = newp(BArray, 7)
- assert repr(p) == "<cdata 'int[]' owning 28 bytes>"
- assert sizeof(p) == 28
- #
- BArray = new_array_type(new_pointer_type(BInt), 7) # int[7]
- p = newp(BArray, None)
- assert repr(p) == "<cdata 'int[7]' owning 28 bytes>"
- assert sizeof(p) == 28
-
-def test_cannot_dereference_void():
- BVoidP = new_pointer_type(new_void_type())
- p = cast(BVoidP, 123456)
- with pytest.raises(TypeError):
- p[0]
- p = cast(BVoidP, 0)
- with pytest.raises((TypeError, RuntimeError)):
- p[0]
-
-def test_iter():
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BArray = new_array_type(BIntP, None) # int[]
- p = newp(BArray, 7)
- assert list(p) == list(iter(p)) == [0] * 7
- #
- py.test.raises(TypeError, iter, cast(BInt, 5))
- py.test.raises(TypeError, iter, cast(BIntP, 123456))
-
-def test_cmp():
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BVoidP = new_pointer_type(new_void_type())
- p = newp(BIntP, 123)
- q = cast(BInt, 124)
- assert (p == q) is False
- assert (p != q) is True
- assert (q == p) is False
- assert (q != p) is True
- if strict_compare:
- with pytest.raises(TypeError): p < q
- with pytest.raises(TypeError): p <= q
- with pytest.raises(TypeError): q < p
- with pytest.raises(TypeError): q <= p
- with pytest.raises(TypeError): p > q
- with pytest.raises(TypeError): p >= q
- r = cast(BVoidP, p)
- assert (p < r) is False
- assert (p <= r) is True
- assert (p == r) is True
- assert (p != r) is False
- assert (p > r) is False
- assert (p >= r) is True
- s = newp(BIntP, 125)
- assert (p == s) is False
- assert (p != s) is True
- assert (p < s) is (p <= s) is (s > p) is (s >= p)
- assert (p > s) is (p >= s) is (s < p) is (s <= p)
- assert (p < s) ^ (p > s)
-
-def test_buffer():
- try:
- import __builtin__
- except ImportError:
- import builtins as __builtin__
- BShort = new_primitive_type("short")
- s = newp(new_pointer_type(BShort), 100)
- assert sizeof(s) == size_of_ptr()
- assert sizeof(BShort) == 2
- assert len(buffer(s)) == 2
- #
- BChar = new_primitive_type("char")
- BCharArray = new_array_type(new_pointer_type(BChar), None)
- c = newp(BCharArray, b"hi there")
- #
- buf = buffer(c)
- assert repr(buf).startswith('<_cffi_backend.buffer object at 0x')
- assert bytes(buf) == b"hi there\x00"
- assert type(buf) is buffer
- if sys.version_info < (3,):
- assert str(buf) == "hi there\x00"
- assert unicode(buf) == u+"hi there\x00"
- else:
- assert str(buf) == repr(buf)
- # --mb_length--
- assert len(buf) == len(b"hi there\x00")
- # --mb_item--
- for i in range(-12, 12):
- try:
- expected = b"hi there\x00"[i]
- except IndexError:
- with pytest.raises(IndexError):
- buf[i]
- else:
- assert buf[i] == bitem2bchr(expected)
- # --mb_slice--
- assert buf[:] == b"hi there\x00"
- for i in range(-12, 12):
- assert buf[i:] == b"hi there\x00"[i:]
- assert buf[:i] == b"hi there\x00"[:i]
- for j in range(-12, 12):
- assert buf[i:j] == b"hi there\x00"[i:j]
- # --misc--
- assert list(buf) == list(map(bitem2bchr, b"hi there\x00"))
- # --mb_as_buffer--
- if hasattr(__builtin__, 'buffer'): # Python <= 2.7
- py.test.raises(TypeError, __builtin__.buffer, c)
- bf1 = __builtin__.buffer(buf)
- assert len(bf1) == len(buf) and bf1[3] == "t"
- if hasattr(__builtin__, 'memoryview'): # Python >= 2.7
- py.test.raises(TypeError, memoryview, c)
- mv1 = memoryview(buf)
- assert len(mv1) == len(buf) and mv1[3] in (b"t", ord(b"t"))
- # --mb_ass_item--
- expected = list(map(bitem2bchr, b"hi there\x00"))
- for i in range(-12, 12):
- try:
- expected[i] = bytechr(i & 0xff)
- except IndexError:
- with pytest.raises(IndexError):
- buf[i] = bytechr(i & 0xff)
- else:
- buf[i] = bytechr(i & 0xff)
- assert list(buf) == expected
- # --mb_ass_slice--
- buf[:] = b"hi there\x00"
- assert list(buf) == list(c) == list(map(bitem2bchr, b"hi there\x00"))
- with pytest.raises(ValueError):
- buf[:] = b"shorter"
- with pytest.raises(ValueError):
- buf[:] = b"this is much too long!"
- buf[4:2] = b"" # no effect, but should work
- assert buf[:] == b"hi there\x00"
- buf[:2] = b"HI"
- assert buf[:] == b"HI there\x00"
- buf[:2] = b"hi"
- expected = list(map(bitem2bchr, b"hi there\x00"))
- x = 0
- for i in range(-12, 12):
- for j in range(-12, 12):
- start = i if i >= 0 else i + len(buf)
- stop = j if j >= 0 else j + len(buf)
- start = max(0, min(len(buf), start))
- stop = max(0, min(len(buf), stop))
- sample = bytechr(x & 0xff) * (stop - start)
- x += 1
- buf[i:j] = sample
- expected[i:j] = map(bitem2bchr, sample)
- assert list(buf) == expected
-
-def test_getcname():
- BUChar = new_primitive_type("unsigned char")
- BArray = new_array_type(new_pointer_type(BUChar), 123)
- assert getcname(BArray, "<-->") == "unsigned char<-->[123]"
-
-def test_errno():
- BVoid = new_void_type()
- BFunc5 = new_function_type((), BVoid)
- f = cast(BFunc5, _testfunc(5))
- set_errno(50)
- f()
- assert get_errno() == 65
- f(); f()
- assert get_errno() == 95
-
-def test_errno_callback():
- if globals().get('PY_DOT_PY'):
- py.test.skip("cannot run this test on py.py (e.g. fails on Windows)")
- set_errno(95)
- def cb():
- e = get_errno()
- set_errno(e - 6)
- BVoid = new_void_type()
- BFunc5 = new_function_type((), BVoid)
- f = callback(BFunc5, cb)
- f()
- assert get_errno() == 89
- f(); f()
- assert get_errno() == 77
-
-def test_cast_to_array():
- # not valid in C! extension to get a non-owning <cdata 'int[3]'>
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BArray = new_array_type(BIntP, 3)
- x = cast(BArray, 0)
- assert repr(x) == "<cdata 'int[3]' NULL>"
-
-def test_cast_invalid():
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [])
- p = cast(new_pointer_type(BStruct), 123456)
- s = p[0]
- py.test.raises(TypeError, cast, BStruct, s)
-
-def test_bug_float_convertion():
- BDouble = new_primitive_type("double")
- BDoubleP = new_pointer_type(BDouble)
- py.test.raises(TypeError, newp, BDoubleP, "foobar")
-
-def test_bug_delitem():
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- x = newp(BCharP)
- with pytest.raises(TypeError):
- del x[0]
-
-def test_bug_delattr():
- BLong = new_primitive_type("long")
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a1', BLong, -1)])
- x = newp(new_pointer_type(BStruct))
- with pytest.raises(AttributeError):
- del x.a1
-
-def test_variable_length_struct():
- py.test.skip("later")
- BLong = new_primitive_type("long")
- BArray = new_array_type(new_pointer_type(BLong), None)
- BStruct = new_struct_type("struct foo")
- BStructP = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BLong, -1),
- ('a2', BArray, -1)])
- assert sizeof(BStruct) == size_of_long()
- assert alignof(BStruct) == alignof(BLong)
- #
- py.test.raises(TypeError, newp, BStructP, None)
- x = newp(BStructP, 5)
- assert sizeof(x) == 6 * size_of_long()
- x[4] = 123
- assert x[4] == 123
- with pytest.raises(IndexError):
- x[5]
- assert len(x.a2) == 5
- #
- py.test.raises(TypeError, newp, BStructP, [123])
- x = newp(BStructP, [123, 5])
- assert x.a1 == 123
- assert len(x.a2) == 5
- assert list(x.a2) == [0] * 5
- #
- x = newp(BStructP, {'a2': 5})
- assert x.a1 == 0
- assert len(x.a2) == 5
- assert list(x.a2) == [0] * 5
- #
- x = newp(BStructP, [123, (4, 5)])
- assert x.a1 == 123
- assert len(x.a2) == 2
- assert list(x.a2) == [4, 5]
- #
- x = newp(BStructP, {'a2': (4, 5)})
- assert x.a1 == 0
- assert len(x.a2) == 2
- assert list(x.a2) == [4, 5]
-
-def test_autocast_int():
- BInt = new_primitive_type("int")
- BIntPtr = new_pointer_type(BInt)
- BLongLong = new_primitive_type("long long")
- BULongLong = new_primitive_type("unsigned long long")
- BULongLongPtr = new_pointer_type(BULongLong)
- x = newp(BIntPtr, cast(BInt, 42))
- assert x[0] == 42
- x = newp(BIntPtr, cast(BLongLong, 42))
- assert x[0] == 42
- x = newp(BIntPtr, cast(BULongLong, 42))
- assert x[0] == 42
- x = newp(BULongLongPtr, cast(BInt, 42))
- assert x[0] == 42
- py.test.raises(OverflowError, newp, BULongLongPtr, cast(BInt, -42))
- x = cast(BInt, cast(BInt, 42))
- assert int(x) == 42
- x = cast(BInt, cast(BLongLong, 42))
- assert int(x) == 42
- x = cast(BInt, cast(BULongLong, 42))
- assert int(x) == 42
- x = cast(BULongLong, cast(BInt, 42))
- assert int(x) == 42
- x = cast(BULongLong, cast(BInt, -42))
- assert int(x) == 2 ** 64 - 42
- x = cast(BIntPtr, cast(BInt, 42))
- assert int(cast(BInt, x)) == 42
-
-def test_autocast_float():
- BFloat = new_primitive_type("float")
- BDouble = new_primitive_type("float")
- BFloatPtr = new_pointer_type(BFloat)
- x = newp(BFloatPtr, cast(BDouble, 12.5))
- assert x[0] == 12.5
- x = cast(BFloat, cast(BDouble, 12.5))
- assert float(x) == 12.5
-
-def test_longdouble():
- py_py = 'PY_DOT_PY' in globals()
- BInt = new_primitive_type("int")
- BLongDouble = new_primitive_type("long double")
- BLongDoublePtr = new_pointer_type(BLongDouble)
- BLongDoubleArray = new_array_type(BLongDoublePtr, None)
- a = newp(BLongDoubleArray, 1)
- x = a[0]
- if not py_py:
- assert repr(x).startswith("<cdata 'long double' 0.0")
- assert float(x) == 0.0
- assert int(x) == 0
- #
- b = newp(BLongDoubleArray, [1.23])
- x = b[0]
- if not py_py:
- assert repr(x).startswith("<cdata 'long double' 1.23")
- assert float(x) == 1.23
- assert int(x) == 1
- #
- BFunc19 = new_function_type((BLongDouble, BInt), BLongDouble)
- f = cast(BFunc19, _testfunc(19))
- start = lstart = 1.5
- for i in range(107):
- start = 4 * start - start * start
- lstart = f(lstart, 1)
- lother = f(1.5, 107)
- if not py_py:
- assert float(lstart) == float(lother)
- assert repr(lstart) == repr(lother)
- if sizeof(BLongDouble) > sizeof(new_primitive_type("double")):
- assert float(lstart) != start
- assert repr(lstart).startswith("<cdata 'long double' ")
- #
- c = newp(BLongDoubleArray, [lstart])
- x = c[0]
- assert float(f(lstart, 107)) == float(f(x, 107))
-
-def test_get_array_of_length_zero():
- for length in [0, 5, 10]:
- BLong = new_primitive_type("long")
- BLongP = new_pointer_type(BLong)
- BArray0 = new_array_type(BLongP, length)
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BArray0, -1)])
- p = newp(BStructPtr, None)
- if length == 0:
- assert repr(p.a1).startswith("<cdata 'long *' 0x")
- else:
- assert repr(p.a1).startswith("<cdata 'long[%d]' 0x" % length)
-
-def test_nested_anonymous_struct():
- BInt = new_primitive_type("int")
- BChar = new_primitive_type("char")
- BStruct = new_struct_type("struct foo")
- BInnerStruct = new_struct_type("struct foo")
- complete_struct_or_union(BInnerStruct, [('a1', BInt, -1),
- ('a2', BChar, -1)])
- complete_struct_or_union(BStruct, [('', BInnerStruct, -1),
- ('a3', BChar, -1)])
- assert sizeof(BInnerStruct) == sizeof(BInt) * 2 # with alignment
- assert sizeof(BStruct) == sizeof(BInt) * 3 # 'a3' is placed after
- d = BStruct.fields
- assert len(d) == 3
- assert d[0][0] == 'a1'
- assert d[0][1].type is BInt
- assert d[0][1].offset == 0
- assert d[0][1].bitshift == -1
- assert d[0][1].bitsize == -1
- assert d[1][0] == 'a2'
- assert d[1][1].type is BChar
- assert d[1][1].offset == sizeof(BInt)
- assert d[1][1].bitshift == -1
- assert d[1][1].bitsize == -1
- assert d[2][0] == 'a3'
- assert d[2][1].type is BChar
- assert d[2][1].offset == sizeof(BInt) * 2
- assert d[2][1].bitshift == -1
- assert d[2][1].bitsize == -1
-
-def test_nested_anonymous_struct_2():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- BInnerUnion = new_union_type("union bar")
- complete_struct_or_union(BInnerUnion, [('a1', BInt, -1),
- ('a2', BInt, -1)])
- complete_struct_or_union(BStruct, [('b1', BInt, -1),
- ('', BInnerUnion, -1),
- ('b2', BInt, -1)])
- assert sizeof(BInnerUnion) == sizeof(BInt)
- assert sizeof(BStruct) == sizeof(BInt) * 3
- fields = [(name, fld.offset, fld.flags) for (name, fld) in BStruct.fields]
- assert fields == [
- ('b1', 0 * sizeof(BInt), 0),
- ('a1', 1 * sizeof(BInt), 0),
- ('a2', 1 * sizeof(BInt), 1),
- ('b2', 2 * sizeof(BInt), 0),
- ]
-
-def test_sizeof_union():
- # a union has the largest alignment of its members, and a total size
- # that is the largest of its items *possibly further aligned* if
- # another smaller item has a larger alignment...
- BChar = new_primitive_type("char")
- BShort = new_primitive_type("short")
- assert sizeof(BShort) == alignof(BShort) == 2
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a1', BChar),
- ('a2', BChar),
- ('a3', BChar)])
- assert sizeof(BStruct) == 3 and alignof(BStruct) == 1
- BUnion = new_union_type("union u")
- complete_struct_or_union(BUnion, [('s', BStruct),
- ('i', BShort)])
- assert sizeof(BUnion) == 4
- assert alignof(BUnion) == 2
-
-def test_unaligned_struct():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('b', BInt, -1, 1)],
- None, 5, 1)
-
-def test_CData_CType():
- CData, CType = _get_types()
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- nullchr = cast(BChar, 0)
- chrref = newp(BCharP, None)
- assert isinstance(nullchr, CData)
- assert isinstance(chrref, CData)
- assert not isinstance(BChar, CData)
- assert not isinstance(nullchr, CType)
- assert not isinstance(chrref, CType)
- assert isinstance(BChar, CType)
-
-def test_no_cdata_float():
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BUInt = new_primitive_type("unsigned int")
- BUIntP = new_pointer_type(BUInt)
- BFloat = new_primitive_type("float")
- py.test.raises(TypeError, newp, BIntP, cast(BFloat, 0.0))
- py.test.raises(TypeError, newp, BUIntP, cast(BFloat, 0.0))
-
-def test_bool():
- BBool = new_primitive_type("_Bool")
- BBoolP = new_pointer_type(BBool)
- assert int(cast(BBool, False)) == 0
- assert int(cast(BBool, True)) == 1
- assert bool(cast(BBool, False)) is False # since 1.7
- assert bool(cast(BBool, True)) is True
- assert int(cast(BBool, 3)) == 1
- assert int(cast(BBool, long(3))) == 1
- assert int(cast(BBool, long(10)**4000)) == 1
- assert int(cast(BBool, -0.1)) == 1
- assert int(cast(BBool, -0.0)) == 0
- assert int(cast(BBool, '\x00')) == 0
- assert int(cast(BBool, '\xff')) == 1
- assert newp(BBoolP, False)[0] == 0
- assert newp(BBoolP, True)[0] == 1
- assert newp(BBoolP, 0)[0] == 0
- assert newp(BBoolP, 1)[0] == 1
- py.test.raises(TypeError, newp, BBoolP, 1.0)
- py.test.raises(TypeError, newp, BBoolP, '\x00')
- py.test.raises(OverflowError, newp, BBoolP, 2)
- py.test.raises(OverflowError, newp, BBoolP, -1)
- BCharP = new_pointer_type(new_primitive_type("char"))
- p = newp(BCharP, b'\x01')
- q = cast(BBoolP, p)
- assert q[0] is True
- p = newp(BCharP, b'\x00')
- q = cast(BBoolP, p)
- assert q[0] is False
- py.test.raises(TypeError, string, cast(BBool, False))
- BDouble = new_primitive_type("double")
- assert int(cast(BBool, cast(BDouble, 0.1))) == 1
- assert int(cast(BBool, cast(BDouble, 0.0))) == 0
- BBoolA = new_array_type(BBoolP, None)
- p = newp(BBoolA, b'\x01\x00')
- assert p[0] is True
- assert p[1] is False
-
-def test_bool_forbidden_cases():
- BBool = new_primitive_type("_Bool")
- BBoolP = new_pointer_type(BBool)
- BBoolA = new_array_type(BBoolP, None)
- BCharP = new_pointer_type(new_primitive_type("char"))
- p = newp(BCharP, b'X')
- q = cast(BBoolP, p)
- with pytest.raises(ValueError):
- q[0]
- py.test.raises(TypeError, newp, BBoolP, b'\x00')
- assert newp(BBoolP, 0)[0] is False
- assert newp(BBoolP, 1)[0] is True
- py.test.raises(OverflowError, newp, BBoolP, 2)
- py.test.raises(OverflowError, newp, BBoolP, -1)
- py.test.raises(ValueError, newp, BBoolA, b'\x00\x01\x02')
- py.test.raises(OverflowError, newp, BBoolA, [0, 1, 2])
- py.test.raises(TypeError, string, newp(BBoolP, 1))
- py.test.raises(TypeError, string, newp(BBoolA, [1]))
-
-def test_typeoffsetof():
- BChar = new_primitive_type("char")
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BChar, -1),
- ('a2', BChar, -1),
- ('a3', BChar, -1)])
- py.test.raises(TypeError, typeoffsetof, BStructPtr, None)
- py.test.raises(TypeError, typeoffsetof, BStruct, None)
- assert typeoffsetof(BStructPtr, 'a1') == (BChar, 0)
- assert typeoffsetof(BStruct, 'a1') == (BChar, 0)
- assert typeoffsetof(BStructPtr, 'a2') == (BChar, 1)
- assert typeoffsetof(BStruct, 'a3') == (BChar, 2)
- assert typeoffsetof(BStructPtr, 'a2', 0) == (BChar, 1)
- assert typeoffsetof(BStruct, u+'a3') == (BChar, 2)
- py.test.raises(TypeError, typeoffsetof, BStructPtr, 'a2', 1)
- py.test.raises(KeyError, typeoffsetof, BStructPtr, 'a4')
- py.test.raises(KeyError, typeoffsetof, BStruct, 'a5')
- py.test.raises(TypeError, typeoffsetof, BStruct, 42)
- py.test.raises(TypeError, typeoffsetof, BChar, 'a1')
-
-def test_typeoffsetof_array():
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BArray = new_array_type(BIntP, None)
- py.test.raises(TypeError, typeoffsetof, BArray, None)
- py.test.raises(TypeError, typeoffsetof, BArray, 'a1')
- assert typeoffsetof(BArray, 51) == (BInt, 51 * size_of_int())
- assert typeoffsetof(BIntP, 51) == (BInt, 51 * size_of_int())
- assert typeoffsetof(BArray, -51) == (BInt, -51 * size_of_int())
- MAX = sys.maxsize // size_of_int()
- assert typeoffsetof(BArray, MAX) == (BInt, MAX * size_of_int())
- assert typeoffsetof(BIntP, MAX) == (BInt, MAX * size_of_int())
- py.test.raises(OverflowError, typeoffsetof, BArray, MAX + 1)
-
-def test_typeoffsetof_no_bitfield():
- BInt = new_primitive_type("int")
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a1', BInt, 4)])
- py.test.raises(TypeError, typeoffsetof, BStruct, 'a1')
-
-def test_rawaddressof():
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BStruct = new_struct_type("struct foo")
- BStructPtr = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('a1', BChar, -1),
- ('a2', BChar, -1),
- ('a3', BChar, -1)])
- p = newp(BStructPtr)
- assert repr(p) == "<cdata 'struct foo *' owning 3 bytes>"
- s = p[0]
- assert repr(s) == "<cdata 'struct foo' owning 3 bytes>"
- a = rawaddressof(BStructPtr, s, 0)
- assert repr(a).startswith("<cdata 'struct foo *' 0x")
- py.test.raises(TypeError, rawaddressof, BStruct, s, 0)
- b = rawaddressof(BCharP, s, 0)
- assert b == cast(BCharP, p)
- c = rawaddressof(BStructPtr, a, 0)
- assert c == a
- py.test.raises(TypeError, rawaddressof, BStructPtr, cast(BChar, '?'), 0)
- #
- d = rawaddressof(BCharP, s, 1)
- assert d == cast(BCharP, p) + 1
- #
- e = cast(BCharP, 109238)
- f = rawaddressof(BCharP, e, 42)
- assert f == e + 42
- #
- BCharA = new_array_type(BCharP, None)
- e = newp(BCharA, 50)
- f = rawaddressof(BCharP, e, 42)
- assert f == e + 42
-
-def test_newp_signed_unsigned_char():
- BCharArray = new_array_type(
- new_pointer_type(new_primitive_type("char")), None)
- p = newp(BCharArray, b"foo")
- assert len(p) == 4
- assert list(p) == [b"f", b"o", b"o", b"\x00"]
- #
- BUCharArray = new_array_type(
- new_pointer_type(new_primitive_type("unsigned char")), None)
- p = newp(BUCharArray, b"fo\xff")
- assert len(p) == 4
- assert list(p) == [ord("f"), ord("o"), 0xff, 0]
- #
- BSCharArray = new_array_type(
- new_pointer_type(new_primitive_type("signed char")), None)
- p = newp(BSCharArray, b"fo\xff")
- assert len(p) == 4
- assert list(p) == [ord("f"), ord("o"), -1, 0]
-
-def test_newp_from_bytearray_doesnt_work():
- BCharArray = new_array_type(
- new_pointer_type(new_primitive_type("char")), None)
- py.test.raises(TypeError, newp, BCharArray, bytearray(b"foo"))
- p = newp(BCharArray, 5)
- buffer(p)[:] = bytearray(b"foo.\x00")
- assert len(p) == 5
- assert list(p) == [b"f", b"o", b"o", b".", b"\x00"]
- p[1:3] = bytearray(b"XY")
- assert list(p) == [b"f", b"X", b"Y", b".", b"\x00"]
-
-def test_string_assignment_to_byte_array():
- BByteArray = new_array_type(
- new_pointer_type(new_primitive_type("unsigned char")), None)
- p = newp(BByteArray, 5)
- p[0:3] = bytearray(b"XYZ")
- assert list(p) == [ord("X"), ord("Y"), ord("Z"), 0, 0]
-
-# XXX hack
-if sys.version_info >= (3,):
- try:
- import posix, io
- posix.fdopen = io.open
- except ImportError:
- pass # win32
-
-def test_FILE():
- if sys.platform == "win32":
- py.test.skip("testing FILE not implemented")
- #
- BFILE = new_struct_type("struct _IO_FILE")
- BFILEP = new_pointer_type(BFILE)
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BCharP, BFILEP), BInt, False)
- BFunc2 = new_function_type((BFILEP, BCharP), BInt, True)
- ll = find_and_load_library('c')
- fputs = ll.load_function(BFunc, "fputs")
- fscanf = ll.load_function(BFunc2, "fscanf")
- #
- import posix
- fdr, fdw = posix.pipe()
- fr1 = posix.fdopen(fdr, 'rb', 256)
- fw1 = posix.fdopen(fdw, 'wb', 256)
- #
- fw1.write(b"X")
- res = fputs(b"hello world\n", fw1)
- assert res >= 0
- fw1.flush() # should not be needed
- #
- p = newp(new_array_type(BCharP, 100), None)
- res = fscanf(fr1, b"%s\n", p)
- assert res == 1
- assert string(p) == b"Xhello"
- fr1.close()
- fw1.close()
-
-def test_FILE_only_for_FILE_arg():
- if sys.platform == "win32":
- py.test.skip("testing FILE not implemented")
- #
- B_NOT_FILE = new_struct_type("struct NOT_FILE")
- B_NOT_FILEP = new_pointer_type(B_NOT_FILE)
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BCharP, B_NOT_FILEP), BInt, False)
- ll = find_and_load_library('c')
- fputs = ll.load_function(BFunc, "fputs")
- #
- import posix
- fdr, fdw = posix.pipe()
- fr1 = posix.fdopen(fdr, 'r')
- fw1 = posix.fdopen(fdw, 'w')
- #
- e = py.test.raises(TypeError, fputs, b"hello world\n", fw1)
- assert str(e.value).startswith(
- "initializer for ctype 'struct NOT_FILE *' must "
- "be a cdata pointer, not ")
-
-def test_FILE_object():
- if sys.platform == "win32":
- py.test.skip("testing FILE not implemented")
- #
- BFILE = new_struct_type("FILE")
- BFILEP = new_pointer_type(BFILE)
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BCharP, BFILEP), BInt, False)
- BFunc2 = new_function_type((BFILEP,), BInt, False)
- ll = find_and_load_library('c')
- fputs = ll.load_function(BFunc, "fputs")
- fileno = ll.load_function(BFunc2, "fileno")
- #
- import posix
- fdr, fdw = posix.pipe()
- fw1 = posix.fdopen(fdw, 'wb', 256)
- #
- fw1p = cast(BFILEP, fw1)
- fw1.write(b"X")
- fw1.flush()
- res = fputs(b"hello\n", fw1p)
- assert res >= 0
- res = fileno(fw1p)
- assert (res == fdw) == (sys.version_info < (3,))
- fw1.close()
- #
- data = posix.read(fdr, 256)
- assert data == b"Xhello\n"
- posix.close(fdr)
-
-def test_errno_saved():
- set_errno(42)
- # a random function that will reset errno to 0 (at least on non-windows)
- import os; os.stat('.')
- #
- res = get_errno()
- assert res == 42
-
-def test_GetLastError():
- if sys.platform != "win32":
- py.test.skip("GetLastError(): only for Windows")
- #
- lib = find_and_load_library('KERNEL32.DLL')
- BInt = new_primitive_type("int")
- BVoid = new_void_type()
- BFunc1 = new_function_type((BInt,), BVoid, False)
- BFunc2 = new_function_type((), BInt, False)
- SetLastError = lib.load_function(BFunc1, "SetLastError")
- GetLastError = lib.load_function(BFunc2, "GetLastError")
- #
- SetLastError(42)
- # a random function that will reset the real GetLastError() to 0
- import nt; nt.stat('.')
- #
- res = GetLastError()
- assert res == 42
- #
- SetLastError(2)
- code, message = getwinerror()
- assert code == 2
- assert message == "The system cannot find the file specified"
- #
- code, message = getwinerror(1155)
- assert code == 1155
- assert message == ("No application is associated with the "
- "specified file for this operation")
-
-def test_nonstandard_integer_types():
- for typename in ['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']:
- new_primitive_type(typename) # works
-
-def test_cannot_convert_unicode_to_charp():
- BCharP = new_pointer_type(new_primitive_type("char"))
- BCharArray = new_array_type(BCharP, None)
- py.test.raises(TypeError, newp, BCharArray, u+'foobar')
-
-def test_buffer_keepalive():
- BCharP = new_pointer_type(new_primitive_type("char"))
- BCharArray = new_array_type(BCharP, None)
- buflist = []
- for i in range(20):
- c = newp(BCharArray, str2bytes("hi there %d" % i))
- buflist.append(buffer(c))
- import gc; gc.collect()
- for i in range(20):
- buf = buflist[i]
- assert buf[:] == str2bytes("hi there %d\x00" % i)
-
-def test_slice():
- BIntP = new_pointer_type(new_primitive_type("int"))
- BIntArray = new_array_type(BIntP, None)
- c = newp(BIntArray, 5)
- assert len(c) == 5
- assert repr(c) == "<cdata 'int[]' owning 20 bytes>"
- d = c[1:4]
- assert len(d) == 3
- assert repr(d) == "<cdata 'int[]' sliced length 3>"
- d[0] = 123
- d[2] = 456
- assert c[1] == 123
- assert c[3] == 456
- assert d[2] == 456
- with pytest.raises(IndexError):
- d[3]
- with pytest.raises(IndexError):
- d[-1]
-
-def test_slice_ptr():
- BIntP = new_pointer_type(new_primitive_type("int"))
- BIntArray = new_array_type(BIntP, None)
- c = newp(BIntArray, 5)
- d = (c+1)[0:2]
- assert len(d) == 2
- assert repr(d) == "<cdata 'int[]' sliced length 2>"
- d[1] += 50
- assert c[2] == 50
-
-def test_slice_array_checkbounds():
- BIntP = new_pointer_type(new_primitive_type("int"))
- BIntArray = new_array_type(BIntP, None)
- c = newp(BIntArray, 5)
- c[0:5]
- assert len(c[5:5]) == 0
- with pytest.raises(IndexError):
- c[-1:1]
- cp = c + 0
- cp[-1:1]
-
-def test_nonstandard_slice():
- BIntP = new_pointer_type(new_primitive_type("int"))
- BIntArray = new_array_type(BIntP, None)
- c = newp(BIntArray, 5)
- with pytest.raises(IndexError) as e:
- c[:5]
- assert str(e.value) == "slice start must be specified"
- with pytest.raises(IndexError) as e:
- c[4:]
- assert str(e.value) == "slice stop must be specified"
- with pytest.raises(IndexError) as e:
- c[1:2:3]
- assert str(e.value) == "slice with step not supported"
- with pytest.raises(IndexError) as e:
- c[1:2:1]
- assert str(e.value) == "slice with step not supported"
- with pytest.raises(IndexError) as e:
- c[4:2]
- assert str(e.value) == "slice start > stop"
- with pytest.raises(IndexError) as e:
- c[6:6]
- assert str(e.value) == "index too large (expected 6 <= 5)"
-
-def test_setslice():
- BIntP = new_pointer_type(new_primitive_type("int"))
- BIntArray = new_array_type(BIntP, None)
- c = newp(BIntArray, 5)
- c[1:3] = [100, 200]
- assert list(c) == [0, 100, 200, 0, 0]
- cp = c + 3
- cp[-1:1] = [300, 400]
- assert list(c) == [0, 100, 300, 400, 0]
- cp[-1:1] = iter([500, 600])
- assert list(c) == [0, 100, 500, 600, 0]
- with pytest.raises(ValueError):
- cp[-1:1] = [1000]
- assert list(c) == [0, 100, 1000, 600, 0]
- with pytest.raises(ValueError):
- cp[-1:1] = (700, 800, 900)
- assert list(c) == [0, 100, 700, 800, 0]
-
-def test_setslice_array():
- BIntP = new_pointer_type(new_primitive_type("int"))
- BIntArray = new_array_type(BIntP, None)
- c = newp(BIntArray, 5)
- d = newp(BIntArray, [10, 20, 30])
- c[1:4] = d
- assert list(c) == [0, 10, 20, 30, 0]
- #
- BShortP = new_pointer_type(new_primitive_type("short"))
- BShortArray = new_array_type(BShortP, None)
- d = newp(BShortArray, [40, 50])
- c[1:3] = d
- assert list(c) == [0, 40, 50, 30, 0]
-
-def test_cdata_name_module_doc():
- p = new_primitive_type("signed char")
- x = cast(p, 17)
- assert x.__module__ == '_cffi_backend'
- assert x.__name__ == '<cdata>'
- assert hasattr(x, '__doc__')
-
-def test_different_types_of_ptr_equality():
- BVoidP = new_pointer_type(new_void_type())
- BIntP = new_pointer_type(new_primitive_type("int"))
- x = cast(BVoidP, 12345)
- assert x == cast(BIntP, 12345)
- assert x != cast(BIntP, 12344)
- assert hash(x) == hash(cast(BIntP, 12345))
-
-def test_new_handle():
- import _weakref
- BVoidP = new_pointer_type(new_void_type())
- BCharP = new_pointer_type(new_primitive_type("char"))
- class mylist(list):
- pass
- o = mylist([2, 3, 4])
- x = newp_handle(BVoidP, o)
- assert repr(x) == "<cdata 'void *' handle to [2, 3, 4]>"
- assert x
- assert from_handle(x) is o
- assert from_handle(cast(BCharP, x)) is o
- wr = _weakref.ref(o)
- del o
- import gc; gc.collect()
- assert wr() is not None
- assert from_handle(x) == list((2, 3, 4))
- assert from_handle(cast(BCharP, x)) == list((2, 3, 4))
- del x
- for i in range(3):
- if wr() is not None:
- import gc; gc.collect()
- assert wr() is None
- py.test.raises(RuntimeError, from_handle, cast(BCharP, 0))
-
-def test_new_handle_cycle():
- import _weakref
- BVoidP = new_pointer_type(new_void_type())
- class A(object):
- pass
- o = A()
- o.cycle = newp_handle(BVoidP, o)
- wr = _weakref.ref(o)
- del o
- for i in range(3):
- if wr() is not None:
- import gc; gc.collect()
- assert wr() is None
-
-def _test_bitfield_details(flag):
- BChar = new_primitive_type("char")
- BShort = new_primitive_type("short")
- BInt = new_primitive_type("int")
- BUInt = new_primitive_type("unsigned int")
- BStruct = new_struct_type("struct foo1")
- complete_struct_or_union(BStruct, [('a', BChar, -1),
- ('b1', BInt, 9),
- ('b2', BUInt, 7),
- ('c', BChar, -1)], -1, -1, -1, flag)
- if not (flag & SF_MSVC_BITFIELDS): # gcc, any variant
- assert typeoffsetof(BStruct, 'c') == (BChar, 3)
- assert sizeof(BStruct) == 4
- else: # msvc
- assert typeoffsetof(BStruct, 'c') == (BChar, 8)
- assert sizeof(BStruct) == 12
- assert alignof(BStruct) == 4
- #
- p = newp(new_pointer_type(BStruct), None)
- p.a = b'A'
- p.b1 = -201
- p.b2 = 99
- p.c = b'\x9D'
- raw = buffer(p)[:]
- if sys.byteorder == 'little':
- if flag & SF_MSVC_BITFIELDS:
- assert raw == b'A\x00\x00\x007\xC7\x00\x00\x9D\x00\x00\x00'
- elif flag & SF_GCC_LITTLE_ENDIAN:
- assert raw == b'A7\xC7\x9D'
- elif flag & SF_GCC_BIG_ENDIAN:
- assert raw == b'A\xE3\x9B\x9D'
- else:
- raise AssertionError("bad flag")
- else:
- if flag & SF_MSVC_BITFIELDS:
- assert raw == b'A\x00\x00\x00\x00\x00\xC77\x9D\x00\x00\x00'
- elif flag & SF_GCC_LITTLE_ENDIAN:
- assert raw == b'A\xC77\x9D'
- elif flag & SF_GCC_BIG_ENDIAN:
- assert raw == b'A\x9B\xE3\x9D'
- else:
- raise AssertionError("bad flag")
- #
- BStruct = new_struct_type("struct foo2")
- complete_struct_or_union(BStruct, [('a', BChar, -1),
- ('', BShort, 9),
- ('c', BChar, -1)], -1, -1, -1, flag)
- assert typeoffsetof(BStruct, 'c') == (BChar, 4)
- if flag & SF_MSVC_BITFIELDS:
- assert sizeof(BStruct) == 6
- assert alignof(BStruct) == 2
- elif flag & SF_GCC_X86_BITFIELDS:
- assert sizeof(BStruct) == 5
- assert alignof(BStruct) == 1
- elif flag & SF_GCC_ARM_BITFIELDS:
- assert sizeof(BStruct) == 6
- assert alignof(BStruct) == 2
- else:
- raise AssertionError("bad flag")
- #
- BStruct = new_struct_type("struct foo2")
- complete_struct_or_union(BStruct, [('a', BChar, -1),
- ('', BInt, 0),
- ('', BInt, 0),
- ('c', BChar, -1)], -1, -1, -1, flag)
- if flag & SF_MSVC_BITFIELDS:
- assert typeoffsetof(BStruct, 'c') == (BChar, 1)
- assert sizeof(BStruct) == 2
- assert alignof(BStruct) == 1
- elif flag & SF_GCC_X86_BITFIELDS:
- assert typeoffsetof(BStruct, 'c') == (BChar, 4)
- assert sizeof(BStruct) == 5
- assert alignof(BStruct) == 1
- elif flag & SF_GCC_ARM_BITFIELDS:
- assert typeoffsetof(BStruct, 'c') == (BChar, 4)
- assert sizeof(BStruct) == 8
- assert alignof(BStruct) == 4
- else:
- raise AssertionError("bad flag")
-
-
-SF_MSVC_BITFIELDS = 0x01
-SF_GCC_ARM_BITFIELDS = 0x02
-SF_GCC_X86_BITFIELDS = 0x10
-
-SF_GCC_BIG_ENDIAN = 0x04
-SF_GCC_LITTLE_ENDIAN = 0x40
-
-SF_PACKED = 0x08
-
-def test_bitfield_as_x86_gcc():
- _test_bitfield_details(flag=SF_GCC_X86_BITFIELDS|SF_GCC_LITTLE_ENDIAN)
-
-def test_bitfield_as_msvc():
- _test_bitfield_details(flag=SF_MSVC_BITFIELDS|SF_GCC_LITTLE_ENDIAN)
-
-def test_bitfield_as_arm_gcc():
- _test_bitfield_details(flag=SF_GCC_ARM_BITFIELDS|SF_GCC_LITTLE_ENDIAN)
-
-def test_bitfield_as_ppc_gcc():
- # PowerPC uses the same format as X86, but is big-endian
- _test_bitfield_details(flag=SF_GCC_X86_BITFIELDS|SF_GCC_BIG_ENDIAN)
-
-
-def test_struct_array_no_length():
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BArray = new_array_type(BIntP, None)
- BStruct = new_struct_type("foo")
- py.test.raises(TypeError, complete_struct_or_union,
- BStruct, [('x', BArray),
- ('y', BInt)])
- #
- BStruct = new_struct_type("foo")
- complete_struct_or_union(BStruct, [('x', BInt),
- ('y', BArray)])
- assert sizeof(BStruct) == size_of_int()
- d = BStruct.fields
- assert len(d) == 2
- assert d[0][0] == 'x'
- assert d[0][1].type is BInt
- assert d[0][1].offset == 0
- assert d[0][1].bitshift == -1
- assert d[0][1].bitsize == -1
- assert d[1][0] == 'y'
- assert d[1][1].type is BArray
- assert d[1][1].offset == size_of_int()
- assert d[1][1].bitshift == -2
- assert d[1][1].bitsize == -1
- #
- p = newp(new_pointer_type(BStruct))
- p.x = 42
- assert p.x == 42
- assert typeof(p.y) is BArray
- assert len(p.y) == 0
- assert p.y == cast(BIntP, p) + 1
- #
- p = newp(new_pointer_type(BStruct), [100])
- assert p.x == 100
- assert len(p.y) == 0
- #
- # Tests for
- # ffi.new("struct_with_var_array *", [field.., [the_array_items..]])
- # ffi.new("struct_with_var_array *", [field.., array_size])
- plist = []
- for i in range(20):
- if i % 2 == 0:
- p = newp(new_pointer_type(BStruct), [100, [200, i, 400]])
- else:
- p = newp(new_pointer_type(BStruct), [100, 3])
- p.y[1] = i
- p.y[0] = 200
- assert p.y[2] == 0
- p.y[2] = 400
- assert len(p.y) == 3
- assert len(p[0].y) == 3
- assert len(buffer(p)) == sizeof(BInt) * 4
- assert sizeof(p[0]) == sizeof(BInt) * 4
- plist.append(p)
- for i in range(20):
- p = plist[i]
- assert p.x == 100
- assert p.y[0] == 200
- assert p.y[1] == i
- assert p.y[2] == 400
- assert list(p.y) == [200, i, 400]
- #
- # the following assignment works, as it normally would, for any array field
- p.y = [501, 601]
- assert list(p.y) == [501, 601, 400]
- p[0].y = [500, 600]
- assert list(p[0].y) == [500, 600, 400]
- assert repr(p) == "<cdata 'foo *' owning %d bytes>" % (
- sizeof(BStruct) + 3 * sizeof(BInt),)
- assert repr(p[0]) == "<cdata 'foo' owning %d bytes>" % (
- sizeof(BStruct) + 3 * sizeof(BInt),)
- assert sizeof(p[0]) == sizeof(BStruct) + 3 * sizeof(BInt)
- #
- # from a non-owning pointer, we can't get the length
- q = cast(new_pointer_type(BStruct), p)
- assert q.y[0] == 500
- assert q[0].y[0] == 500
- py.test.raises(TypeError, len, q.y)
- py.test.raises(TypeError, len, q[0].y)
- assert typeof(q.y) is BIntP
- assert typeof(q[0].y) is BIntP
- assert sizeof(q[0]) == sizeof(BStruct)
- #
- # error cases
- with pytest.raises(IndexError):
- p.y[4]
- with pytest.raises(TypeError):
- p.y = cast(BIntP, 0)
- with pytest.raises(TypeError):
- p.y = 15
- with pytest.raises(TypeError):
- p.y = None
- #
- # accepting this may be specified by the C99 standard,
- # or a GCC strangeness...
- BStruct2 = new_struct_type("bar")
- complete_struct_or_union(BStruct2, [('f', BStruct),
- ('n', BInt)])
- p = newp(new_pointer_type(BStruct2), {'n': 42})
- assert p.n == 42
- #
- # more error cases
- py.test.raises(TypeError, newp, new_pointer_type(BStruct), [100, None])
- BArray4 = new_array_type(BIntP, 4)
- BStruct4 = new_struct_type("test4")
- complete_struct_or_union(BStruct4, [('a', BArray4)]) # not varsized
- py.test.raises(TypeError, newp, new_pointer_type(BStruct4), [None])
- py.test.raises(TypeError, newp, new_pointer_type(BStruct4), [4])
- p = newp(new_pointer_type(BStruct4), [[10, 20, 30]])
- assert p.a[0] == 10
- assert p.a[1] == 20
- assert p.a[2] == 30
- assert p.a[3] == 0
- #
- # struct of struct of varsized array
- BStruct2 = new_struct_type("bar")
- complete_struct_or_union(BStruct2, [('head', BInt),
- ('tail', BStruct)])
- for i in range(2): # try to detect heap overwrites
- p = newp(new_pointer_type(BStruct2), [100, [200, list(range(50))]])
- assert p.tail.y[49] == 49
-
-
-def test_struct_array_no_length_explicit_position():
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BArray = new_array_type(BIntP, None)
- BStruct = new_struct_type("foo")
- complete_struct_or_union(BStruct, [('x', BArray, -1, 0), # actually 3 items
- ('y', BInt, -1, 12)])
- p = newp(new_pointer_type(BStruct), [[10, 20], 30])
- assert p.x[0] == 10
- assert p.x[1] == 20
- assert p.x[2] == 0
- assert p.y == 30
- p = newp(new_pointer_type(BStruct), {'x': [40], 'y': 50})
- assert p.x[0] == 40
- assert p.x[1] == 0
- assert p.x[2] == 0
- assert p.y == 50
- p = newp(new_pointer_type(BStruct), {'y': 60})
- assert p.x[0] == 0
- assert p.x[1] == 0
- assert p.x[2] == 0
- assert p.y == 60
- #
- # This "should" work too, allocating a larger structure
- # (a bit strange in this case, but useful in general)
- plist = []
- for i in range(20):
- p = newp(new_pointer_type(BStruct), [[10, 20, 30, 40, 50, 60, 70]])
- plist.append(p)
- for i in range(20):
- p = plist[i]
- assert p.x[0] == 10
- assert p.x[1] == 20
- assert p.x[2] == 30
- assert p.x[3] == 40 == p.y
- assert p.x[4] == 50
- assert p.x[5] == 60
- assert p.x[6] == 70
-
-def test_struct_array_not_aligned():
- # struct a { int x; char y; char z[]; };
- # ends up of size 8, but 'z' is at offset 5
- BChar = new_primitive_type("char")
- BInt = new_primitive_type("int")
- BCharP = new_pointer_type(BChar)
- BArray = new_array_type(BCharP, None)
- BStruct = new_struct_type("foo")
- complete_struct_or_union(BStruct, [('x', BInt),
- ('y', BChar),
- ('z', BArray)])
- assert sizeof(BStruct) == 2 * size_of_int()
- def offsetof(BType, fieldname):
- return typeoffsetof(BType, fieldname)[1]
- base = offsetof(BStruct, 'z')
- assert base == size_of_int() + 1
- #
- p = newp(new_pointer_type(BStruct), {'z': 3})
- assert sizeof(p[0]) == base + 3
- q = newp(new_pointer_type(BStruct), {'z': size_of_int()})
- assert sizeof(q) == size_of_ptr()
- assert sizeof(q[0]) == base + size_of_int()
- assert len(p.z) == 3
- assert len(p[0].z) == 3
- assert len(q.z) == size_of_int()
- assert len(q[0].z) == size_of_int()
-
-def test_ass_slice():
- BChar = new_primitive_type("char")
- BArray = new_array_type(new_pointer_type(BChar), None)
- p = newp(BArray, b"foobar")
- p[2:5] = [b"*", b"Z", b"T"]
- p[1:3] = b"XY"
- assert list(p) == [b"f", b"X", b"Y", b"Z", b"T", b"r", b"\x00"]
- with pytest.raises(TypeError):
- p[1:5] = u+'XYZT'
- with pytest.raises(TypeError):
- p[1:5] = [1, 2, 3, 4]
- #
- for typename in ["wchar_t", "char16_t", "char32_t"]:
- BUniChar = new_primitive_type(typename)
- BArray = new_array_type(new_pointer_type(BUniChar), None)
- p = newp(BArray, u+"foobar")
- p[2:5] = [u+"*", u+"Z", u+"T"]
- p[1:3] = u+"XY"
- assert list(p) == [u+"f", u+"X", u+"Y", u+"Z", u+"T", u+"r", u+"\x00"]
- with pytest.raises(TypeError):
- p[1:5] = b'XYZT'
- with pytest.raises(TypeError):
- p[1:5] = [1, 2, 3, 4]
-
-def test_void_p_arithmetic():
- BVoid = new_void_type()
- BInt = new_primitive_type("intptr_t")
- p = cast(new_pointer_type(BVoid), 100000)
- assert int(cast(BInt, p)) == 100000
- assert int(cast(BInt, p + 42)) == 100042
- assert int(cast(BInt, p - (-42))) == 100042
- assert (p + 42) - p == 42
- q = cast(new_pointer_type(new_primitive_type("char")), 100000)
- with pytest.raises(TypeError):
- p - q
- with pytest.raises(TypeError):
- q - p
- with pytest.raises(TypeError):
- p + cast(new_primitive_type('int'), 42)
- with pytest.raises(TypeError):
- p - cast(new_primitive_type('int'), 42)
-
-def test_sizeof_sliced_array():
- BInt = new_primitive_type("int")
- BArray = new_array_type(new_pointer_type(BInt), 10)
- p = newp(BArray, None)
- assert sizeof(p[2:9]) == 7 * sizeof(BInt)
-
-def test_packed():
- BLong = new_primitive_type("long")
- BChar = new_primitive_type("char")
- BShort = new_primitive_type("short")
- for extra_args in [(SF_PACKED,), (0, 1)]:
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a1', BLong, -1),
- ('a2', BChar, -1),
- ('a3', BShort, -1)],
- None, -1, -1, *extra_args)
- d = BStruct.fields
- assert len(d) == 3
- assert d[0][0] == 'a1'
- assert d[0][1].type is BLong
- assert d[0][1].offset == 0
- assert d[0][1].bitshift == -1
- assert d[0][1].bitsize == -1
- assert d[1][0] == 'a2'
- assert d[1][1].type is BChar
- assert d[1][1].offset == sizeof(BLong)
- assert d[1][1].bitshift == -1
- assert d[1][1].bitsize == -1
- assert d[2][0] == 'a3'
- assert d[2][1].type is BShort
- assert d[2][1].offset == sizeof(BLong) + sizeof(BChar)
- assert d[2][1].bitshift == -1
- assert d[2][1].bitsize == -1
- assert sizeof(BStruct) == sizeof(BLong) + sizeof(BChar) + sizeof(BShort)
- assert alignof(BStruct) == 1
- #
- BStruct2 = new_struct_type("struct foo")
- complete_struct_or_union(BStruct2, [('b1', BChar, -1),
- ('b2', BLong, -1)],
- None, -1, -1, 0, 2)
- d = BStruct2.fields
- assert len(d) == 2
- assert d[0][0] == 'b1'
- assert d[0][1].type is BChar
- assert d[0][1].offset == 0
- assert d[0][1].bitshift == -1
- assert d[0][1].bitsize == -1
- assert d[1][0] == 'b2'
- assert d[1][1].type is BLong
- assert d[1][1].offset == 2
- assert d[1][1].bitshift == -1
- assert d[1][1].bitsize == -1
- assert sizeof(BStruct2) == 2 + sizeof(BLong)
- assert alignof(BStruct2) == 2
-
-def test_packed_with_bitfields():
- if sys.platform == "win32":
- py.test.skip("testing gcc behavior")
- BLong = new_primitive_type("long")
- BChar = new_primitive_type("char")
- BStruct = new_struct_type("struct foo")
- py.test.raises(NotImplementedError,
- complete_struct_or_union,
- BStruct, [('a1', BLong, 30),
- ('a2', BChar, 5)],
- None, -1, -1, SF_PACKED)
-
-def test_from_buffer():
- import array
- a = array.array('H', [10000, 20000, 30000])
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- c = from_buffer(BCharA, a)
- assert typeof(c) is BCharA
- assert len(c) == 6
- assert repr(c) == "<cdata 'char[]' buffer len 6 from 'array.array' object>"
- p = new_pointer_type(new_primitive_type("unsigned short"))
- cast(p, c)[1] += 500
- assert list(a) == [10000, 20500, 30000]
-
-def test_from_buffer_not_str_unicode():
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- p1 = from_buffer(BCharA, b"foo")
- assert p1 == from_buffer(BCharA, b"foo")
- import gc; gc.collect()
- assert p1 == from_buffer(BCharA, b"foo")
- py.test.raises(TypeError, from_buffer, BCharA, u+"foo")
- try:
- from __builtin__ import buffer
- except ImportError:
- pass
- else:
- # Python 2 only
- contents = from_buffer(BCharA, buffer(b"foo"))
- assert len(contents) == len(p1)
- for i in range(len(contents)):
- assert contents[i] == p1[i]
- p4 = buffer(u+"foo")
- contents = from_buffer(BCharA, buffer(u+"foo"))
- assert len(contents) == len(p4)
- for i in range(len(contents)):
- assert contents[i] == p4[i]
- try:
- from __builtin__ import memoryview
- except ImportError:
- pass
- else:
- contents = from_buffer(BCharA, memoryview(b"foo"))
- assert len(contents) == len(p1)
- for i in range(len(contents)):
- assert contents[i] == p1[i]
-
-
-def test_from_buffer_bytearray():
- a = bytearray(b"xyz")
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- p = from_buffer(BCharA, a)
- assert typeof(p) is BCharA
- assert len(p) == 3
- assert repr(p) == "<cdata 'char[]' buffer len 3 from 'bytearray' object>"
- assert p[2] == b"z"
- p[2] = b"."
- assert a[2] == ord(".")
- a[2] = ord("?")
- assert p[2] == b"?"
-
-def test_from_buffer_more_cases():
- try:
- from _cffi_backend import _testbuff
- except ImportError:
- py.test.skip("not for pypy")
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- #
- def check1(bufobj, expected):
- c = from_buffer(BCharA, bufobj)
- assert typeof(c) is BCharA
- if sys.version_info >= (3,):
- expected = [bytes(c, "ascii") for c in expected]
- assert list(c) == list(expected)
- #
- def check(methods, expected, expected_for_memoryview=None):
- if sys.version_info >= (3,):
- if methods <= 7:
- return
- if expected_for_memoryview is not None:
- expected = expected_for_memoryview
- class X(object):
- pass
- _testbuff(X, methods)
- bufobj = X()
- check1(bufobj, expected)
- try:
- from __builtin__ import buffer
- bufobjb = buffer(bufobj)
- except (TypeError, ImportError):
- pass
- else:
- check1(bufobjb, expected)
- try:
- bufobjm = memoryview(bufobj)
- except (TypeError, NameError):
- pass
- else:
- check1(bufobjm, expected_for_memoryview or expected)
- #
- check(1, "RDB")
- check(2, "WRB")
- check(4, "CHB")
- check(8, "GTB")
- check(16, "ROB")
- #
- check(1 | 2, "RDB")
- check(1 | 4, "RDB")
- check(2 | 4, "CHB")
- check(1 | 8, "RDB", "GTB")
- check(1 | 16, "RDB", "ROB")
- check(2 | 8, "WRB", "GTB")
- check(2 | 16, "WRB", "ROB")
- check(4 | 8, "CHB", "GTB")
- check(4 | 16, "CHB", "ROB")
-
-def test_from_buffer_require_writable():
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- p1 = from_buffer(BCharA, b"foo", False)
- assert p1 == from_buffer(BCharA, b"foo", False)
- py.test.raises((TypeError, BufferError), from_buffer, BCharA, b"foo", True)
- ba = bytearray(b"foo")
- p1 = from_buffer(BCharA, ba, True)
- p1[0] = b"g"
- assert ba == b"goo"
-
-def test_from_buffer_types():
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BIntA = new_array_type(BIntP, None)
- lst = [-12345678, 87654321, 489148]
- bytestring = bytearray(buffer(newp(BIntA, lst))[:] + b'XYZ')
- lst2 = lst + [42, -999999999]
- bytestring2 = bytearray(buffer(newp(BIntA, lst2))[:] + b'XYZ')
- #
- p1 = from_buffer(BIntA, bytestring) # int[]
- assert typeof(p1) is BIntA
- assert len(p1) == 3
- assert p1[0] == lst[0]
- assert p1[1] == lst[1]
- assert p1[2] == lst[2]
- with pytest.raises(IndexError):
- p1[3]
- with pytest.raises(IndexError):
- p1[-1]
- #
- py.test.raises(TypeError, from_buffer, BInt, bytestring)
- #
- p2 = from_buffer(BIntP, bytestring) # int *
- assert p2 == p1 or 'PY_DOT_PY' in globals()
- # note: on py.py ^^^, bytearray buffers are not emulated well enough
- assert typeof(p2) is BIntP
- assert p2[0] == lst[0]
- assert p2[1] == lst[1]
- assert p2[2] == lst[2]
- # hopefully does not crash, but doesn't raise an exception:
- p2[3]
- p2[-1]
- # not enough data even for one, but this is not enforced:
- from_buffer(BIntP, b"")
- #
- BIntA2 = new_array_type(BIntP, 2)
- p2 = from_buffer(BIntA2, bytestring) # int[2]
- assert typeof(p2) is BIntA2
- assert len(p2) == 2
- assert p2[0] == lst[0]
- assert p2[1] == lst[1]
- with pytest.raises(IndexError):
- p2[2]
- with pytest.raises(IndexError):
- p2[-1]
- assert p2 == p1 or 'PY_DOT_PY' in globals()
- #
- BIntA4 = new_array_type(BIntP, 4) # int[4]: too big
- py.test.raises(ValueError, from_buffer, BIntA4, bytestring)
- #
- BStruct = new_struct_type("foo")
- complete_struct_or_union(BStruct, [('a1', BInt, -1),
- ('a2', BInt, -1)])
- BStructP = new_pointer_type(BStruct)
- BStructA = new_array_type(BStructP, None)
- p1 = from_buffer(BStructA, bytestring2) # struct[]
- assert len(p1) == 2
- assert typeof(p1) is BStructA
- assert p1[0].a1 == lst2[0]
- assert p1[0].a2 == lst2[1]
- assert p1[1].a1 == lst2[2]
- assert p1[1].a2 == lst2[3]
- with pytest.raises(IndexError):
- p1[2]
- with pytest.raises(IndexError):
- p1[-1]
- assert repr(p1) == "<cdata 'foo[]' buffer len 2 from 'bytearray' object>"
- #
- p2 = from_buffer(BStructP, bytestring2) # 'struct *'
- assert p2 == p1 or 'PY_DOT_PY' in globals()
- assert typeof(p2) is BStructP
- assert p2.a1 == lst2[0]
- assert p2.a2 == lst2[1]
- assert p2[0].a1 == lst2[0]
- assert p2[0].a2 == lst2[1]
- assert p2[1].a1 == lst2[2]
- assert p2[1].a2 == lst2[3]
- # does not crash:
- p2[2]
- p2[-1]
- # not enough data even for one, but this is not enforced:
- from_buffer(BStructP, b"")
- from_buffer(BStructP, b"1234567")
- #
- release(p1)
- assert repr(p1) == "<cdata 'foo[]' buffer RELEASED>"
- #
- BEmptyStruct = new_struct_type("empty")
- complete_struct_or_union(BEmptyStruct, [], Ellipsis, 0)
- assert sizeof(BEmptyStruct) == 0
- BEmptyStructP = new_pointer_type(BEmptyStruct)
- BEmptyStructA = new_array_type(BEmptyStructP, None)
- py.test.raises(ZeroDivisionError, from_buffer, # empty[]
- BEmptyStructA, bytestring)
- #
- BEmptyStructA5 = new_array_type(BEmptyStructP, 5)
- p1 = from_buffer(BEmptyStructA5, bytestring) # struct empty[5]
- assert typeof(p1) is BEmptyStructA5
- assert len(p1) == 5
- assert (cast(BIntP, p1) == from_buffer(BIntA, bytestring)
- or 'PY_DOT_PY' in globals())
- #
- BVarStruct = new_struct_type("varfoo")
- BVarStructP = new_pointer_type(BVarStruct)
- complete_struct_or_union(BVarStruct, [('a1', BInt, -1),
- ('va', BIntA, -1)])
- with pytest.raises(TypeError):
- from_buffer(BVarStruct, bytestring)
- pv = from_buffer(BVarStructP, bytestring) # varfoo *
- assert pv.a1 == lst[0]
- assert pv.va[0] == lst[1]
- assert pv.va[1] == lst[2]
- assert sizeof(pv[0]) == 1 * size_of_int()
- with pytest.raises(TypeError):
- len(pv.va)
- # hopefully does not crash, but doesn't raise an exception:
- pv.va[2]
- pv.va[-1]
- # not enough data even for one, but this is not enforced:
- from_buffer(BVarStructP, b"")
- assert repr(pv) == "<cdata 'varfoo *' buffer from 'bytearray' object>"
- assert repr(pv[0]).startswith("<cdata 'varfoo &' ")
- #
- release(pv)
- assert repr(pv) == "<cdata 'varfoo *' buffer RELEASED>"
- assert repr(pv[0]).startswith("<cdata 'varfoo &' ")
- #
- pv = from_buffer(BVarStructP, bytestring) # make a fresh one
- with pytest.raises(ValueError):
- release(pv[0])
-
-def test_issue483():
- BInt = new_primitive_type("int")
- BIntP = new_pointer_type(BInt)
- BIntA = new_array_type(BIntP, None)
- lst = list(range(25))
- bytestring = bytearray(buffer(newp(BIntA, lst))[:] + b'XYZ')
- p1 = from_buffer(BIntA, bytestring) # int[]
- assert len(buffer(p1)) == 25 * size_of_int()
- assert sizeof(p1) == 25 * size_of_int()
- #
- p2 = from_buffer(BIntP, bytestring)
- assert sizeof(p2) == size_of_ptr()
- assert len(buffer(p2)) == size_of_int() # first element only, by default
-
-def test_memmove():
- Short = new_primitive_type("short")
- ShortA = new_array_type(new_pointer_type(Short), None)
- Char = new_primitive_type("char")
- CharA = new_array_type(new_pointer_type(Char), None)
- p = newp(ShortA, [-1234, -2345, -3456, -4567, -5678])
- memmove(p, p + 1, 4)
- assert list(p) == [-2345, -3456, -3456, -4567, -5678]
- p[2] = 999
- memmove(p + 2, p, 6)
- assert list(p) == [-2345, -3456, -2345, -3456, 999]
- memmove(p + 4, newp(CharA, b"\x71\x72"), 2)
- if sys.byteorder == 'little':
- assert list(p) == [-2345, -3456, -2345, -3456, 0x7271]
- else:
- assert list(p) == [-2345, -3456, -2345, -3456, 0x7172]
-
-def test_memmove_buffer():
- import array
- Short = new_primitive_type("short")
- ShortA = new_array_type(new_pointer_type(Short), None)
- a = array.array('H', [10000, 20000, 30000])
- p = newp(ShortA, 5)
- memmove(p, a, 6)
- assert list(p) == [10000, 20000, 30000, 0, 0]
- memmove(p + 1, a, 6)
- assert list(p) == [10000, 10000, 20000, 30000, 0]
- b = array.array('h', [-1000, -2000, -3000])
- memmove(b, a, 4)
- assert b.tolist() == [10000, 20000, -3000]
- assert a.tolist() == [10000, 20000, 30000]
- p[0] = 999
- p[1] = 998
- p[2] = 997
- p[3] = 996
- p[4] = 995
- memmove(b, p, 2)
- assert b.tolist() == [999, 20000, -3000]
- memmove(b, p + 2, 4)
- assert b.tolist() == [997, 996, -3000]
- p[2] = -p[2]
- p[3] = -p[3]
- memmove(b, p + 2, 6)
- assert b.tolist() == [-997, -996, 995]
-
-def test_memmove_readonly_readwrite():
- SignedChar = new_primitive_type("signed char")
- SignedCharA = new_array_type(new_pointer_type(SignedChar), None)
- p = newp(SignedCharA, 5)
- memmove(p, b"abcde", 3)
- assert list(p) == [ord("a"), ord("b"), ord("c"), 0, 0]
- memmove(p, bytearray(b"ABCDE"), 2)
- assert list(p) == [ord("A"), ord("B"), ord("c"), 0, 0]
- py.test.raises((TypeError, BufferError), memmove, b"abcde", p, 3)
- ba = bytearray(b"xxxxx")
- memmove(dest=ba, src=p, n=3)
- assert ba == bytearray(b"ABcxx")
- memmove(ba, b"EFGH", 4)
- assert ba == bytearray(b"EFGHx")
-
-def test_memmove_sign_check():
- SignedChar = new_primitive_type("signed char")
- SignedCharA = new_array_type(new_pointer_type(SignedChar), None)
- p = newp(SignedCharA, 5)
- py.test.raises(ValueError, memmove, p, p + 1, -1) # not segfault
-
-def test_memmove_bad_cdata():
- BInt = new_primitive_type("int")
- p = cast(BInt, 42)
- py.test.raises(TypeError, memmove, p, bytearray(b'a'), 1)
- py.test.raises(TypeError, memmove, bytearray(b'a'), p, 1)
-
-def test_dereference_null_ptr():
- BInt = new_primitive_type("int")
- BIntPtr = new_pointer_type(BInt)
- p = cast(BIntPtr, 0)
- with pytest.raises(RuntimeError):
- p[0]
- with pytest.raises(RuntimeError):
- p[0] = 42
- with pytest.raises(RuntimeError):
- p[42]
- with pytest.raises(RuntimeError):
- p[42] = -1
-
-def test_mixup():
- BStruct1 = new_struct_type("foo")
- BStruct2 = new_struct_type("foo") # <= same name as BStruct1
- BStruct3 = new_struct_type("bar")
- BStruct1Ptr = new_pointer_type(BStruct1)
- BStruct2Ptr = new_pointer_type(BStruct2)
- BStruct3Ptr = new_pointer_type(BStruct3)
- BStruct1PtrPtr = new_pointer_type(BStruct1Ptr)
- BStruct2PtrPtr = new_pointer_type(BStruct2Ptr)
- BStruct3PtrPtr = new_pointer_type(BStruct3Ptr)
- pp1 = newp(BStruct1PtrPtr)
- pp2 = newp(BStruct2PtrPtr)
- pp3 = newp(BStruct3PtrPtr)
- pp1[0] = pp1[0]
- with pytest.raises(TypeError) as e:
- pp3[0] = pp1[0]
- assert str(e.value).startswith("initializer for ctype 'bar *' must be a ")
- assert str(e.value).endswith(", not cdata 'foo *'")
- with pytest.raises(TypeError) as e:
- pp2[0] = pp1[0]
- assert str(e.value) == ("initializer for ctype 'foo *' appears indeed to "
- "be 'foo *', but the types are different (check "
- "that you are not e.g. mixing up different ffi "
- "instances)")
-
-def test_stdcall_function_type():
- assert FFI_CDECL == FFI_DEFAULT_ABI
- try:
- stdcall = FFI_STDCALL
- except NameError:
- stdcall = FFI_DEFAULT_ABI
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BInt, BInt), BInt, False, stdcall)
- if stdcall != FFI_DEFAULT_ABI:
- assert repr(BFunc) == "<ctype 'int(__stdcall *)(int, int)'>"
- else:
- assert repr(BFunc) == "<ctype 'int(*)(int, int)'>"
-
-def test_get_common_types():
- d = {}
- _get_common_types(d)
- assert d['bool'] == '_Bool'
-
-def test_unpack():
- BChar = new_primitive_type("char")
- BArray = new_array_type(new_pointer_type(BChar), 10) # char[10]
- p = newp(BArray, b"abc\x00def")
- p0 = p
- assert unpack(p, 10) == b"abc\x00def\x00\x00\x00"
- assert unpack(p+1, 5) == b"bc\x00de"
-
- for typename in ["wchar_t", "char16_t", "char32_t"]:
- BWChar = new_primitive_type(typename)
- BArray = new_array_type(new_pointer_type(BWChar), 10) # wchar_t[10]
- p = newp(BArray, u"abc\x00def")
- assert unpack(p, 10) == u"abc\x00def\x00\x00\x00"
-
- for typename, samples in [
- ("uint8_t", [0, 2**8-1]),
- ("uint16_t", [0, 2**16-1]),
- ("uint32_t", [0, 2**32-1]),
- ("uint64_t", [0, 2**64-1]),
- ("int8_t", [-2**7, 2**7-1]),
- ("int16_t", [-2**15, 2**15-1]),
- ("int32_t", [-2**31, 2**31-1]),
- ("int64_t", [-2**63, 2**63-1]),
- ("_Bool", [False, True]),
- ("float", [0.0, 10.5]),
- ("double", [12.34, 56.78]),
- ]:
- BItem = new_primitive_type(typename)
- BArray = new_array_type(new_pointer_type(BItem), 10)
- p = newp(BArray, samples)
- result = unpack(p, len(samples))
- assert result == samples
- for i in range(len(samples)):
- assert result[i] == p[i] and type(result[i]) is type(p[i])
- assert (type(result[i]) is bool) == (type(samples[i]) is bool)
- #
- BInt = new_primitive_type("int")
- py.test.raises(TypeError, unpack, p)
- py.test.raises(TypeError, unpack, b"foobar", 6)
- py.test.raises(TypeError, unpack, cast(BInt, 42), 1)
- #
- BPtr = new_pointer_type(BInt)
- random_ptr = cast(BPtr, -424344)
- other_ptr = cast(BPtr, 54321)
- BArray = new_array_type(new_pointer_type(BPtr), None)
- lst = unpack(newp(BArray, [random_ptr, other_ptr]), 2)
- assert lst == [random_ptr, other_ptr]
- #
- BFunc = new_function_type((BInt, BInt), BInt, False)
- BFuncPtr = new_pointer_type(BFunc)
- lst = unpack(newp(new_array_type(BFuncPtr, None), 2), 2)
- assert len(lst) == 2
- assert not lst[0] and not lst[1]
- assert typeof(lst[0]) is BFunc
- #
- BStruct = new_struct_type("foo")
- BStructPtr = new_pointer_type(BStruct)
- e = py.test.raises(ValueError, unpack, cast(BStructPtr, 42), 5)
- assert str(e.value) == "'foo *' points to items of unknown size"
- complete_struct_or_union(BStruct, [('a1', BInt, -1),
- ('a2', BInt, -1)])
- array_of_structs = newp(new_array_type(BStructPtr, None), [[4,5], [6,7]])
- lst = unpack(array_of_structs, 2)
- assert typeof(lst[0]) is BStruct
- assert lst[0].a1 == 4 and lst[1].a2 == 7
- #
- py.test.raises(RuntimeError, unpack, cast(new_pointer_type(BChar), 0), 0)
- py.test.raises(RuntimeError, unpack, cast(new_pointer_type(BChar), 0), 10)
- #
- py.test.raises(ValueError, unpack, p0, -1)
- py.test.raises(ValueError, unpack, p, -1)
-
-def test_cdata_dir():
- BInt = new_primitive_type("int")
- p = cast(BInt, 42)
- check_dir(p, [])
- p = newp(new_array_type(new_pointer_type(BInt), None), 5)
- check_dir(p, [])
- BStruct = new_struct_type("foo")
- p = cast(new_pointer_type(BStruct), 0)
- check_dir(p, []) # opaque
- complete_struct_or_union(BStruct, [('a2', BInt, -1),
- ('a1', BInt, -1)])
- check_dir(p, ['a1', 'a2']) # always sorted
- p = newp(new_pointer_type(BStruct), None)
- check_dir(p, ['a1', 'a2'])
- check_dir(p[0], ['a1', 'a2'])
- pp = newp(new_pointer_type(new_pointer_type(BStruct)), p)
- check_dir(pp, [])
- check_dir(pp[0], ['a1', 'a2'])
- check_dir(pp[0][0], ['a1', 'a2'])
-
-def test_char_pointer_conversion():
- import warnings
- assert __version__.startswith("1."), (
- "the warning will be an error if we ever release cffi 2.x")
- BCharP = new_pointer_type(new_primitive_type("char"))
- BIntP = new_pointer_type(new_primitive_type("int"))
- BVoidP = new_pointer_type(new_void_type())
- BUCharP = new_pointer_type(new_primitive_type("unsigned char"))
- z1 = cast(BCharP, 0)
- z2 = cast(BIntP, 0)
- z3 = cast(BVoidP, 0)
- z4 = cast(BUCharP, 0)
- with warnings.catch_warnings(record=True) as w:
- warnings.simplefilter("always")
- newp(new_pointer_type(BIntP), z1) # warn
- assert len(w) == 1
- newp(new_pointer_type(BVoidP), z1) # fine
- assert len(w) == 1
- newp(new_pointer_type(BCharP), z2) # warn
- assert len(w) == 2
- newp(new_pointer_type(BVoidP), z2) # fine
- assert len(w) == 2
- newp(new_pointer_type(BCharP), z3) # fine
- assert len(w) == 2
- newp(new_pointer_type(BIntP), z3) # fine
- assert len(w) == 2
- newp(new_pointer_type(BCharP), z4) # fine (ignore signedness here)
- assert len(w) == 2
- newp(new_pointer_type(BUCharP), z1) # fine (ignore signedness here)
- assert len(w) == 2
- newp(new_pointer_type(BUCharP), z3) # fine
- assert len(w) == 2
- # check that the warnings are associated with lines in this file
- assert w[1].lineno == w[0].lineno + 4
-
-def test_primitive_comparison():
- def assert_eq(a, b):
- assert (a == b) is True
- assert (b == a) is True
- assert (a != b) is False
- assert (b != a) is False
- assert (a < b) is False
- assert (a <= b) is True
- assert (a > b) is False
- assert (a >= b) is True
- assert (b < a) is False
- assert (b <= a) is True
- assert (b > a) is False
- assert (b >= a) is True
- assert hash(a) == hash(b)
- def assert_lt(a, b, check_hash=True):
- assert (a == b) is False
- assert (b == a) is False
- assert (a != b) is True
- assert (b != a) is True
- assert (a < b) is True
- assert (a <= b) is True
- assert (a > b) is False
- assert (a >= b) is False
- assert (b < a) is False
- assert (b <= a) is False
- assert (b > a) is True
- assert (b >= a) is True
- if check_hash:
- assert hash(a) != hash(b) # (or at least, it is unlikely)
- def assert_gt(a, b, check_hash=True):
- assert_lt(b, a, check_hash)
- def assert_ne(a, b):
- assert (a == b) is False
- assert (b == a) is False
- assert (a != b) is True
- assert (b != a) is True
- if strict_compare:
- with pytest.raises(TypeError): a < b
- with pytest.raises(TypeError): a <= b
- with pytest.raises(TypeError): a > b
- with pytest.raises(TypeError): a >= b
- with pytest.raises(TypeError): b < a
- with pytest.raises(TypeError): b <= a
- with pytest.raises(TypeError): b > a
- with pytest.raises(TypeError): b >= a
- elif a < b:
- assert_lt(a, b)
- else:
- assert_lt(b, a)
- assert_eq(5, 5)
- assert_lt(3, 5)
- assert_ne('5', 5)
- #
- t1 = new_primitive_type("char")
- t2 = new_primitive_type("int")
- t3 = new_primitive_type("unsigned char")
- t4 = new_primitive_type("unsigned int")
- t5 = new_primitive_type("float")
- t6 = new_primitive_type("double")
- assert_eq(cast(t1, 65), b'A')
- assert_lt(cast(t1, 64), b'\x99')
- assert_gt(cast(t1, 200), b'A')
- assert_ne(cast(t1, 65), 65)
- assert_eq(cast(t2, -25), -25)
- assert_lt(cast(t2, -25), -24)
- assert_gt(cast(t2, -25), -26)
- assert_eq(cast(t3, 65), 65)
- assert_ne(cast(t3, 65), b'A')
- assert_ne(cast(t3, 65), cast(t1, 65))
- assert_gt(cast(t4, -1), -1, check_hash=False)
- assert_gt(cast(t4, -1), cast(t2, -1), check_hash=False)
- assert_gt(cast(t4, -1), 99999)
- assert_eq(cast(t4, -1), 256 ** size_of_int() - 1)
- assert_eq(cast(t5, 3.0), 3)
- assert_eq(cast(t5, 3.5), 3.5)
- assert_lt(cast(t5, 3.3), 3.3) # imperfect rounding
- assert_eq(cast(t6, 3.3), 3.3)
- assert_eq(cast(t5, 3.5), cast(t6, 3.5))
- assert_lt(cast(t5, 3.1), cast(t6, 3.1)) # imperfect rounding
- assert_eq(cast(t5, 7.0), cast(t3, 7))
- assert_lt(cast(t5, 3.1), 3.101)
- assert_gt(cast(t5, 3.1), 3)
-
-def test_explicit_release_new():
- # release() on a ffi.new() object has no effect on CPython, but
- # really releases memory on PyPy. We can't test that effect
- # though, because a released cdata is not marked.
- BIntP = new_pointer_type(new_primitive_type("int"))
- p = newp(BIntP)
- p[0] = 42
- with pytest.raises(IndexError):
- p[1]
- release(p)
- # here, reading p[0] might give garbage or segfault...
- release(p) # no effect
- #
- BStruct = new_struct_type("struct foo")
- BStructP = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('p', BIntP, -1)])
- pstruct = newp(BStructP)
- assert pstruct.p == cast(BIntP, 0)
- release(pstruct)
- # here, reading pstruct.p might give garbage or segfault...
- release(pstruct) # no effect
-
-def test_explicit_release_new_contextmgr():
- BIntP = new_pointer_type(new_primitive_type("int"))
- with newp(BIntP) as p:
- p[0] = 42
- assert p[0] == 42
- # here, reading p[0] might give garbage or segfault...
- release(p) # no effect
-
-def test_explicit_release_badtype():
- BIntP = new_pointer_type(new_primitive_type("int"))
- p = cast(BIntP, 12345)
- py.test.raises(ValueError, release, p)
- py.test.raises(ValueError, release, p)
- BStruct = new_struct_type("struct foo")
- BStructP = new_pointer_type(BStruct)
- complete_struct_or_union(BStruct, [('p', BIntP, -1)])
- pstruct = newp(BStructP)
- py.test.raises(ValueError, release, pstruct[0])
-
-def test_explicit_release_badtype_contextmgr():
- BIntP = new_pointer_type(new_primitive_type("int"))
- p = cast(BIntP, 12345)
- with pytest.raises(ValueError):
- with p:
- pass
- with pytest.raises(ValueError):
- with p:
- pass
-
-def test_explicit_release_gc():
- BIntP = new_pointer_type(new_primitive_type("int"))
- seen = []
- intp1 = newp(BIntP, 12345)
- p1 = cast(BIntP, intp1)
- p = gcp(p1, seen.append)
- assert seen == []
- release(p)
- assert seen == [p1]
- assert p1[0] == 12345
- assert p[0] == 12345 # true so far, but might change to raise RuntimeError
- release(p) # no effect
-
-def test_explicit_release_gc_contextmgr():
- BIntP = new_pointer_type(new_primitive_type("int"))
- seen = []
- intp1 = newp(BIntP, 12345)
- p1 = cast(BIntP, intp1)
- p = gcp(p1, seen.append)
- with p:
- assert p[0] == 12345
- assert seen == []
- assert seen == [p1]
- assert p1[0] == 12345
- assert p[0] == 12345 # true so far, but might change to raise RuntimeError
- release(p) # no effect
-
-def test_explicit_release_from_buffer():
- a = bytearray(b"xyz")
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- p = from_buffer(BCharA, a)
- assert p[2] == b"z"
- assert repr(p) == "<cdata 'char[]' buffer len 3 from 'bytearray' object>"
- release(p)
- assert p[2] == b"z" # true so far, but might change to raise RuntimeError
- assert repr(p) == "<cdata 'char[]' buffer RELEASED>"
- release(p) # no effect
-
-def test_explicit_release_from_buffer_contextmgr():
- a = bytearray(b"xyz")
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- p = from_buffer(BCharA, a)
- with p:
- assert p[2] == b"z"
- assert p[2] == b"z" # true so far, but might change to raise RuntimeError
- assert repr(p) == "<cdata 'char[]' buffer RELEASED>"
- release(p) # no effect
-
-def test_explicit_release_bytearray_on_cpython():
- if '__pypy__' in sys.builtin_module_names:
- py.test.skip("pypy's bytearray are never locked")
- a = bytearray(b"xyz")
- BChar = new_primitive_type("char")
- BCharP = new_pointer_type(BChar)
- BCharA = new_array_type(BCharP, None)
- a += b't' * 10
- p = from_buffer(BCharA, a)
- with pytest.raises(BufferError):
- a += b'u' * 100
- release(p)
- a += b'v' * 100
- release(p) # no effect
- a += b'w' * 1000
- assert a == bytearray(b"xyz" + b't' * 10 + b'v' * 100 + b'w' * 1000)
-
-def test_int_doesnt_give_bool():
- BBool = new_primitive_type("_Bool")
- x = int(cast(BBool, 42))
- assert type(x) is int and x == 1
- x = long(cast(BBool, 42))
- assert type(x) is long and x == 1
- with pytest.raises(TypeError):
- float(cast(BBool, 42))
- with pytest.raises(TypeError):
- complex(cast(BBool, 42))
-
-def test_cannot_call_null_function_pointer():
- BInt = new_primitive_type("int")
- BFunc = new_function_type((BInt, BInt), BInt, False)
- f = cast(BFunc, 0)
- with pytest.raises(RuntimeError):
- f(40, 2)
-
-def test_huge_structure():
- BChar = new_primitive_type("char")
- BArray = new_array_type(new_pointer_type(BChar), sys.maxsize)
- assert sizeof(BArray) == sys.maxsize
- BStruct = new_struct_type("struct foo")
- complete_struct_or_union(BStruct, [('a1', BArray, -1)])
- assert sizeof(BStruct) == sys.maxsize
-
-def test_get_types():
- import _cffi_backend
- CData, CType = _get_types()
- assert CData is _cffi_backend._CDataBase
- assert CType is _cffi_backend.CType
-
-def test_type_available_with_correct_names():
- import _cffi_backend
- check_names = [
- 'CType',
- 'CField',
- 'CLibrary',
- '_CDataBase',
- 'FFI',
- 'Lib',
- 'buffer',
- ]
- if '__pypy__' in sys.builtin_module_names:
- check_names += [
- '__CData_iterator',
- '__FFIGlobSupport',
- '__FFIAllocator',
- '__FFIFunctionWrapper',
- ]
- else:
- check_names += [
- '__CDataOwn',
- '__CDataOwnGC',
- '__CDataFromBuf',
- '__CDataGCP',
- '__CData_iterator',
- '__FFIGlobSupport',
- ]
- for name in check_names:
- tp = getattr(_cffi_backend, name)
- assert isinstance(tp, type)
- assert (tp.__module__, tp.__name__) == ('_cffi_backend', name)
-
-def test_unaligned_types():
- BByteArray = new_array_type(
- new_pointer_type(new_primitive_type("unsigned char")), None)
- pbuf = newp(BByteArray, 40)
- buf = buffer(pbuf)
- #
- for name in ['short', 'int', 'long', 'long long', 'float', 'double',
- 'float _Complex', 'double _Complex']:
- p = new_primitive_type(name)
- if name.endswith(' _Complex'):
- num = cast(p, 1.23 - 4.56j)
- else:
- num = cast(p, 0x0123456789abcdef)
- size = sizeof(p)
- buf[0:40] = b"\x00" * 40
- pbuf1 = cast(new_pointer_type(p), pbuf + 1)
- pbuf1[0] = num
- assert pbuf1[0] == num
- assert buf[0] == b'\x00'
- assert buf[1 + size] == b'\x00'
diff --git a/contrib/python/cffi/cffi/__init__.py b/contrib/python/cffi/cffi/__init__.py
index 82a961832c6..90e2e6559da 100644
--- a/contrib/python/cffi/cffi/__init__.py
+++ b/contrib/python/cffi/cffi/__init__.py
@@ -5,8 +5,8 @@ from .api import FFI
from .error import CDefError, FFIError, VerificationError, VerificationMissing
from .error import PkgConfigError
-__version__ = "1.15.0"
-__version_info__ = (1, 15, 0)
+__version__ = "1.15.1"
+__version_info__ = (1, 15, 1)
# The verifier module file names are based on the CRC32 of a string that
# contains the following version number. It may be older than __version__
diff --git a/contrib/python/cffi/cffi/_embedding.h b/contrib/python/cffi/cffi/_embedding.h
index e863d8541a4..8e8df882d47 100644
--- a/contrib/python/cffi/cffi/_embedding.h
+++ b/contrib/python/cffi/cffi/_embedding.h
@@ -22,7 +22,8 @@ extern "C" {
* _cffi_call_python_org, which on CPython is actually part of the
_cffi_exports[] array, is the function pointer copied from
- _cffi_backend.
+ _cffi_backend. If _cffi_start_python() fails, then this is set
+ to NULL; otherwise, it should never be NULL.
After initialization is complete, both are equal. However, the
first one remains equal to &_cffi_start_and_call_python until the
@@ -224,7 +225,7 @@ static int _cffi_initialize_python(void)
if (f != NULL && f != Py_None) {
PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
- "\ncompiled with cffi version: 1.15.0"
+ "\ncompiled with cffi version: 1.15.1"
"\n_cffi_backend module: ", f);
modules = PyImport_GetModuleDict();
mod = PyDict_GetItemString(modules, "_cffi_backend");
diff --git a/contrib/python/cffi/cffi/recompiler.py b/contrib/python/cffi/cffi/recompiler.py
index 87203dcff8c..f5a366b57a7 100644
--- a/contrib/python/cffi/cffi/recompiler.py
+++ b/contrib/python/cffi/cffi/recompiler.py
@@ -405,7 +405,7 @@ class Recompiler:
prnt(' NULL, /* no includes */')
prnt(' %d, /* num_types */' % (len(self.cffi_types),))
flags = 0
- if self._num_externpy:
+ if self._num_externpy > 0 or self.ffi._embedding is not None:
flags |= 1 # set to mean that we use extern "Python"
prnt(' %d, /* flags */' % flags)
prnt('};')
@@ -420,7 +420,7 @@ class Recompiler:
prnt('PyMODINIT_FUNC')
prnt('_cffi_pypyinit_%s(const void *p[])' % (base_module_name,))
prnt('{')
- if self._num_externpy:
+ if flags & 1:
prnt(' if (((intptr_t)p[0]) >= 0x0A03) {')
prnt(' _cffi_call_python_org = '
'(void(*)(struct _cffi_externpy_s *, char *))p[1];')
diff --git a/contrib/python/cffi/patches/01-arcadia.patch b/contrib/python/cffi/patches/01-arcadia.patch
new file mode 100644
index 00000000000..8e02c807c6a
--- /dev/null
+++ b/contrib/python/cffi/patches/01-arcadia.patch
@@ -0,0 +1,118 @@
+--- contrib/python/cffi/c/_cffi_backend.c (index)
++++ contrib/python/cffi/c/_cffi_backend.c (working tree)
+@@ -294,7 +294,6 @@ typedef union {
+ unsigned long long m_longlong;
+ float m_float;
+ double m_double;
+- long double m_longdouble;
+ } union_alignment;
+
+ typedef struct {
+--- contrib/python/cffi/c/call_python.c (index)
++++ contrib/python/cffi/c/call_python.c (working tree)
+@@ -202,7 +202,7 @@ static int _update_cache_to_call_python(struct _cffi_externpy_s *externpy)
+ # elif defined(_AIX)
+ # define read_barrier() __lwsync()
+ # elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+-# include <mbarrier.h>
++# error include <mbarrier.h>
+ # define read_barrier() __compiler_barrier()
+ # elif defined(__hpux)
+ # define read_barrier() _Asm_mf()
+--- contrib/python/cffi/c/lib_obj.c (index)
++++ contrib/python/cffi/c/lib_obj.c (working tree)
+@@ -15,6 +15,18 @@
+ __getattr__.
+ */
+
++#if defined(_asan_enabled_)
++void __lsan_ignore_object(const void* p);
++#endif
++
++inline static void MarkAsIntentionallyLeaked(const void* ptr) {
++#if defined(_asan_enabled_)
++ __lsan_ignore_object(ptr);
++#else
++ (void)ptr;
++#endif
++}
++
+ struct CPyExtFunc_s {
+ PyMethodDef md;
+ void *direct_fn;
+@@ -340,6 +352,7 @@ static PyObject *lib_build_and_cache_attr(LibObject *lib, PyObject *name,
+ PyErr_NoMemory();
+ return NULL;
+ }
++ MarkAsIntentionallyLeaked(data);
+ ((void(*)(char*))g->address)(data);
+ }
+ x = convert_to_object(data, ct);
+--- contrib/python/cffi/c/misc_win32.h (index)
++++ contrib/python/cffi/c/misc_win32.h (working tree)
+@@ -8,30 +8,6 @@
+
+ static DWORD cffi_tls_index = TLS_OUT_OF_INDEXES;
+
+-BOOL WINAPI DllMain(HINSTANCE hinstDLL,
+- DWORD reason_for_call,
+- LPVOID reserved)
+-{
+- LPVOID p;
+-
+- switch (reason_for_call) {
+-
+- case DLL_THREAD_DETACH:
+- if (cffi_tls_index != TLS_OUT_OF_INDEXES) {
+- p = TlsGetValue(cffi_tls_index);
+- if (p != NULL) {
+- TlsSetValue(cffi_tls_index, NULL);
+- cffi_thread_shutdown(p);
+- }
+- }
+- break;
+-
+- default:
+- break;
+- }
+- return TRUE;
+-}
+-
+ static void init_cffi_tls(void)
+ {
+ if (cffi_tls_index == TLS_OUT_OF_INDEXES) {
+--- contrib/python/cffi/c/wchar_helper.h (index)
++++ contrib/python/cffi/c/wchar_helper.h (working tree)
+@@ -20,7 +20,7 @@ static PyObject *
+ _my_PyUnicode_FromChar32(const cffi_char32_t *w, Py_ssize_t size)
+ {
+ PyObject *unicode;
+- register Py_ssize_t i;
++ Py_ssize_t i;
+ Py_ssize_t alloc;
+ const cffi_char32_t *orig_w;
+
+@@ -38,7 +38,7 @@ _my_PyUnicode_FromChar32(const cffi_char32_t *w, Py_ssize_t size)
+
+ /* Copy the wchar_t data into the new object */
+ {
+- register Py_UNICODE *u;
++ Py_UNICODE *u;
+ u = PyUnicode_AS_UNICODE(unicode);
+ for (i = size; i > 0; i--) {
+ if (*w > 0xFFFF) {
+--- contrib/python/cffi/cffi/recompiler.py (index)
++++ contrib/python/cffi/cffi/recompiler.py (working tree)
+@@ -287,10 +287,8 @@ class Recompiler:
+ self.write_c_source_to_f(f, preamble)
+
+ def _rel_readlines(self, filename):
+- g = open(os.path.join(os.path.dirname(__file__), filename), 'r')
+- lines = g.readlines()
+- g.close()
+- return lines
++ import pkgutil
++ return pkgutil.get_data('cffi', filename).decode('utf-8').splitlines(True)
+
+ def write_c_source_to_f(self, f, preamble):
+ self._f = f
diff --git a/contrib/python/cffi/patches/02-fix-ya.make.patch b/contrib/python/cffi/patches/02-fix-ya.make.patch
new file mode 100644
index 00000000000..f2d7b9cec82
--- /dev/null
+++ b/contrib/python/cffi/patches/02-fix-ya.make.patch
@@ -0,0 +1,22 @@
+--- contrib/python/cffi/ya.make (index)
++++ contrib/python/cffi/ya.make (working tree)
+@@ -21,6 +21,8 @@ NO_COMPILER_WARNINGS()
+
+ NO_LINT()
+
++SUPPRESSIONS(lsan.supp)
++
+ SRCS(
+ c/_cffi_backend.c
+ )
+@@ -54,6 +56,10 @@ RESOURCE_FILES(
+ .dist-info/METADATA
+ .dist-info/entry_points.txt
+ .dist-info/top_level.txt
++ cffi/_cffi_errors.h
++ cffi/_cffi_include.h
++ cffi/_embedding.h
++ cffi/parse_c_type.h
+ )
+
+ END()