Codebase list python-cffi-py2 / 512a81d
Import upstream version 1.14.3 Kali Janitor 3 years ago
40 changed file(s) with 995 addition(s) and 198 deletion(s). Raw diff Collapse all Expand all
00 Metadata-Version: 1.1
11 Name: cffi
2 Version: 1.14.0
2 Version: 1.14.3
33 Summary: Foreign Function Interface for Python calling C code.
44 Home-page: http://cffi.readthedocs.org
55 Author: Armin Rigo, Maciej Fijalkowski
11 #include <Python.h>
22 #include "structmember.h"
33
4 #define CFFI_VERSION "1.14.0"
4 #define CFFI_VERSION "1.14.3"
55
66 #ifdef MS_WIN32
77 #include <windows.h>
147147 (PyCObject_FromVoidPtr(pointer, destructor))
148148 #endif
149149
150 #if PY_VERSION_HEX < 0x030900a4
151 # define Py_SET_REFCNT(obj, val) (Py_REFCNT(obj) = (val))
152 #endif
153
150154 /************************************************************/
151155
152156 /* base type flag: exactly one of the following: */
403407
404408 if (ct->ct_unique_key != NULL) {
405409 /* revive dead object temporarily for DelItem */
406 Py_REFCNT(ct) = 43;
410 Py_SET_REFCNT(ct, 43);
407411 PyDict_DelItem(unique_cache, ct->ct_unique_key);
408412 assert(Py_REFCNT(ct) == 42);
409 Py_REFCNT(ct) = 0;
413 Py_SET_REFCNT(ct, 0);
410414 Py_DECREF(ct->ct_unique_key);
411415 }
412416 Py_XDECREF(ct->ct_itemdescr);
652656
653657 static PyTypeObject CTypeDescr_Type = {
654658 PyVarObject_HEAD_INIT(NULL, 0)
655 "_cffi_backend.CTypeDescr",
659 "_cffi_backend.CType",
656660 offsetof(CTypeDescrObject, ct_name),
657661 sizeof(char),
658662 (destructor)ctypedescr_dealloc, /* tp_dealloc */
28872891 convert_struct_to_owning_object(char *data, CTypeDescrObject *ct); /*forward*/
28882892
28892893 static cif_description_t *
2890 fb_prepare_cif(PyObject *fargs, CTypeDescrObject *, ffi_abi); /*forward*/
2894 fb_prepare_cif(PyObject *fargs, CTypeDescrObject *, Py_ssize_t, ffi_abi);
2895 /*forward*/
28912896
28922897 static PyObject *new_primitive_type(const char *name); /*forward*/
28932898
30803085 #else
30813086 fabi = PyLong_AS_LONG(PyTuple_GET_ITEM(signature, 0));
30823087 #endif
3083 cif_descr = fb_prepare_cif(fvarargs, fresult, fabi);
3088 cif_descr = fb_prepare_cif(fvarargs, fresult, nargs_declared, fabi);
30843089 if (cif_descr == NULL)
30853090 goto error;
30863091 }
33533358
33543359 static PyTypeObject CData_Type = {
33553360 PyVarObject_HEAD_INIT(NULL, 0)
3356 "_cffi_backend.CData",
3361 "_cffi_backend._CDataBase",
33573362 sizeof(CDataObject),
33583363 0,
33593364 (destructor)cdata_dealloc, /* tp_dealloc */
33723377 (setattrofunc)cdata_setattro, /* tp_setattro */
33733378 0, /* tp_as_buffer */
33743379 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
3375 0, /* tp_doc */
3380 "The internal base type for CData objects. Use FFI.CData to access "
3381 "it. Always check with isinstance(): subtypes are sometimes returned "
3382 "on CPython, for performance reasons.", /* tp_doc */
33763383 0, /* tp_traverse */
33773384 0, /* tp_clear */
33783385 cdata_richcompare, /* tp_richcompare */
33953402
33963403 static PyTypeObject CDataOwning_Type = {
33973404 PyVarObject_HEAD_INIT(NULL, 0)
3398 "_cffi_backend.CDataOwn",
3405 "_cffi_backend.__CDataOwn",
33993406 sizeof(CDataObject),
34003407 0,
34013408 (destructor)cdataowning_dealloc, /* tp_dealloc */
34143421 0, /* inherited */ /* tp_setattro */
34153422 0, /* tp_as_buffer */
34163423 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
3417 0, /* tp_doc */
3424 "This is an internal subtype of _CDataBase for performance only on "
3425 "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */
34183426 0, /* tp_traverse */
34193427 0, /* tp_clear */
34203428 0, /* inherited */ /* tp_richcompare */
34373445
34383446 static PyTypeObject CDataOwningGC_Type = {
34393447 PyVarObject_HEAD_INIT(NULL, 0)
3440 "_cffi_backend.CDataOwnGC",
3448 "_cffi_backend.__CDataOwnGC",
34413449 sizeof(CDataObject_own_structptr),
34423450 0,
34433451 (destructor)cdataowninggc_dealloc, /* tp_dealloc */
34573465 0, /* tp_as_buffer */
34583466 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */
34593467 | Py_TPFLAGS_HAVE_GC,
3460 0, /* tp_doc */
3468 "This is an internal subtype of _CDataBase for performance only on "
3469 "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */
34613470 (traverseproc)cdataowninggc_traverse, /* tp_traverse */
34623471 (inquiry)cdataowninggc_clear, /* tp_clear */
34633472 0, /* inherited */ /* tp_richcompare */
34803489
34813490 static PyTypeObject CDataFromBuf_Type = {
34823491 PyVarObject_HEAD_INIT(NULL, 0)
3483 "_cffi_backend.CDataFromBuf",
3492 "_cffi_backend.__CDataFromBuf",
34843493 sizeof(CDataObject_frombuf),
34853494 0,
34863495 (destructor)cdatafrombuf_dealloc, /* tp_dealloc */
35003509 0, /* tp_as_buffer */
35013510 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */
35023511 | Py_TPFLAGS_HAVE_GC,
3503 0, /* tp_doc */
3512 "This is an internal subtype of _CDataBase for performance only on "
3513 "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */
35043514 (traverseproc)cdatafrombuf_traverse, /* tp_traverse */
35053515 (inquiry)cdatafrombuf_clear, /* tp_clear */
35063516 0, /* inherited */ /* tp_richcompare */
35233533
35243534 static PyTypeObject CDataGCP_Type = {
35253535 PyVarObject_HEAD_INIT(NULL, 0)
3526 "_cffi_backend.CDataGCP",
3536 "_cffi_backend.__CDataGCP",
35273537 sizeof(CDataObject_gcp),
35283538 0,
35293539 (destructor)cdatagcp_dealloc, /* tp_dealloc */
35463556 | Py_TPFLAGS_HAVE_FINALIZE
35473557 #endif
35483558 | Py_TPFLAGS_HAVE_GC,
3549 0, /* tp_doc */
3559 "This is an internal subtype of _CDataBase for performance only on "
3560 "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */
35503561 (traverseproc)cdatagcp_traverse, /* tp_traverse */
35513562 0, /* tp_clear */
35523563 0, /* inherited */ /* tp_richcompare */
36073618
36083619 static PyTypeObject CDataIter_Type = {
36093620 PyVarObject_HEAD_INIT(NULL, 0)
3610 "_cffi_backend.CDataIter", /* tp_name */
3621 "_cffi_backend.__CData_iterator", /* tp_name */
36113622 sizeof(CDataIterObject), /* tp_basicsize */
36123623 0, /* tp_itemsize */
36133624 /* methods */
43624373
43634374 static PyTypeObject dl_type = {
43644375 PyVarObject_HEAD_INIT(NULL, 0)
4365 "_cffi_backend.Library", /* tp_name */
4376 "_cffi_backend.CLibrary", /* tp_name */
43664377 sizeof(DynLibObject), /* tp_basicsize */
43674378 0, /* tp_itemsize */
43684379 /* methods */
44404451 {
44414452 PyObject *s = PyTuple_GET_ITEM(args, 0);
44424453 #ifdef MS_WIN32
4443 Py_UNICODE *filenameW;
4444 if (PyArg_ParseTuple(args, "u|i:load_library", &filenameW, &flags))
4454 PyObject *filename_unicode;
4455 if (PyArg_ParseTuple(args, "U|i:load_library", &filename_unicode, &flags))
44454456 {
4457 Py_ssize_t sz1;
4458 wchar_t *w1;
44464459 #if PY_MAJOR_VERSION < 3
44474460 s = PyUnicode_AsUTF8String(s);
44484461 if (s == NULL)
44534466 if (*p_printable_filename == NULL)
44544467 return NULL;
44554468
4456 handle = dlopenW(filenameW);
4469 sz1 = PyUnicode_GetSize(filename_unicode) + 1;
4470 sz1 *= 2; /* should not be needed, but you never know */
4471 w1 = alloca(sizeof(wchar_t) * sz1);
4472 sz1 = PyUnicode_AsWideChar((PyUnicodeObject *)filename_unicode,
4473 w1, sz1 - 1);
4474 if (sz1 < 0)
4475 return NULL;
4476 w1[sz1] = 0;
4477 handle = dlopenW(w1);
44574478 goto got_handle;
44584479 }
44594480 PyErr_Clear();
44764497 }
44774498 if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0)
44784499 flags |= RTLD_NOW;
4500
4501 #ifdef MS_WIN32
4502 if (filename_or_null == NULL) {
4503 PyErr_SetString(PyExc_OSError, "dlopen(None) not supported on Windows");
4504 return NULL;
4505 }
4506 #endif
44794507
44804508 handle = dlopen(filename_or_null, flags);
44814509
49945022 #ifdef MS_WIN32
49955023 sflags |= SF_MSVC_BITFIELDS;
49965024 #else
4997 # if defined(__arm__) || defined(__aarch64__)
5025 # if defined(__APPLE__) && defined(__arm64__)
5026 sflags |= SF_GCC_X86_BITFIELDS;
5027 # elif defined(__arm__) || defined(__aarch64__)
49985028 sflags |= SF_GCC_ARM_BITFIELDS;
49995029 # else
50005030 sflags |= SF_GCC_X86_BITFIELDS;
57825812
57835813 static cif_description_t *fb_prepare_cif(PyObject *fargs,
57845814 CTypeDescrObject *fresult,
5815 Py_ssize_t variadic_nargs_declared,
57855816 ffi_abi fabi)
5817
57865818 {
57875819 char *buffer;
57885820 cif_description_t *cif_descr;
57895821 struct funcbuilder_s funcbuffer;
5822 ffi_status status;
57905823
57915824 funcbuffer.nb_bytes = 0;
57925825 funcbuffer.bufferp = NULL;
58095842 assert(funcbuffer.bufferp == buffer + funcbuffer.nb_bytes);
58105843
58115844 cif_descr = (cif_description_t *)buffer;
5812 if (ffi_prep_cif(&cif_descr->cif, fabi, funcbuffer.nargs,
5813 funcbuffer.rtype, funcbuffer.atypes) != FFI_OK) {
5845 #if HAVE_FFI_PREP_CIF_VAR
5846 if (variadic_nargs_declared >= 0) {
5847 status = ffi_prep_cif_var(&cif_descr->cif, fabi,
5848 variadic_nargs_declared, funcbuffer.nargs,
5849 funcbuffer.rtype, funcbuffer.atypes);
5850 } else
5851 #endif
5852 #if !HAVE_FFI_PREP_CIF_VAR && defined(__arm64__) && defined(__APPLE__)
5853 #error Apple Arm64 ABI requires ffi_prep_cif_var
5854 #endif
5855 {
5856 status = ffi_prep_cif(&cif_descr->cif, fabi, funcbuffer.nargs,
5857 funcbuffer.rtype, funcbuffer.atypes);
5858 }
5859 if (status != FFI_OK) {
58145860 PyErr_SetString(PyExc_SystemError,
58155861 "libffi failed to build this function type");
58165862 goto error;
58545900 is computed here. */
58555901 cif_description_t *cif_descr;
58565902
5857 cif_descr = fb_prepare_cif(fargs, fresult, fabi);
5903 cif_descr = fb_prepare_cif(fargs, fresult, -1, fabi);
58585904 if (cif_descr == NULL) {
58595905 if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
58605906 PyErr_Clear(); /* will get the exception if we see an
61786224 infotuple = Py_BuildValue("OOOO", ct, ob, py_rawerr, onerror_ob);
61796225 Py_DECREF(py_rawerr);
61806226
6181 #ifdef WITH_THREAD
6227 #if defined(WITH_THREAD) && PY_VERSION_HEX < 0x03070000
61826228 /* We must setup the GIL here, in case the callback is invoked in
6183 some other non-Pythonic thread. This is the same as ctypes. */
6229 some other non-Pythonic thread. This is the same as ctypes.
6230 But PyEval_InitThreads() is always a no-op from CPython 3.7
6231 (the call from ctypes was removed some time later I think). */
61846232 PyEval_InitThreads();
61856233 #endif
61866234
62376285 "return type or with '...'", ct->ct_name);
62386286 goto error;
62396287 }
6288 /* NOTE: ffi_prep_closure() is marked as deprecated. We could just
6289 * call ffi_prep_closure_loc() instead, which is what ffi_prep_closure()
6290 * does. However, cffi also runs on older systems with a libffi that
6291 * doesn't have ffi_prep_closure_loc() at all---notably, the OS X
6292 * machines on Azure are like that (June 2020). I didn't find a way to
6293 * version-check the included ffi.h. So you will have to live with the
6294 * deprecation warning for now. (We could try to check for an unrelated
6295 * macro like FFI_API which happens to be defined in libffi 3.3 and not
6296 * before, but that sounds very obscure. And I prefer a compile-time
6297 * warning rather than a cross-version binary compatibility problem.)
6298 */
62406299 #ifdef CFFI_TRUST_LIBFFI
62416300 if (ffi_prep_closure_loc(closure, &cif_descr->cif,
62426301 invoke_callback, infotuple, closure_exec) != FFI_OK) {
77877846 PyObject *m, *v;
77887847 int i;
77897848 static char init_done = 0;
7849 static PyTypeObject *all_types[] = {
7850 &dl_type,
7851 &CTypeDescr_Type,
7852 &CField_Type,
7853 &CData_Type,
7854 &CDataOwning_Type,
7855 &CDataOwningGC_Type,
7856 &CDataFromBuf_Type,
7857 &CDataGCP_Type,
7858 &CDataIter_Type,
7859 &MiniBuffer_Type,
7860 &FFI_Type,
7861 &Lib_Type,
7862 &GlobSupport_Type,
7863 NULL
7864 };
77907865
77917866 v = PySys_GetObject("version");
77927867 if (v == NULL || !PyText_Check(v) ||
78127887 INITERROR;
78137888 }
78147889
7815 if (PyType_Ready(&dl_type) < 0)
7816 INITERROR;
7817 if (PyType_Ready(&CTypeDescr_Type) < 0)
7818 INITERROR;
7819 if (PyType_Ready(&CField_Type) < 0)
7820 INITERROR;
7821 if (PyType_Ready(&CData_Type) < 0)
7822 INITERROR;
7823 if (PyType_Ready(&CDataOwning_Type) < 0)
7824 INITERROR;
7825 if (PyType_Ready(&CDataOwningGC_Type) < 0)
7826 INITERROR;
7827 if (PyType_Ready(&CDataFromBuf_Type) < 0)
7828 INITERROR;
7829 if (PyType_Ready(&CDataGCP_Type) < 0)
7830 INITERROR;
7831 if (PyType_Ready(&CDataIter_Type) < 0)
7832 INITERROR;
7833 if (PyType_Ready(&MiniBuffer_Type) < 0)
7834 INITERROR;
7890 /* readify all types and add them to the module */
7891 for (i = 0; all_types[i] != NULL; i++) {
7892 PyTypeObject *tp = all_types[i];
7893 PyObject *tpo = (PyObject *)tp;
7894 if (strncmp(tp->tp_name, "_cffi_backend.", 14) != 0) {
7895 PyErr_Format(PyExc_ImportError,
7896 "'%s' is an ill-formed type name", tp->tp_name);
7897 INITERROR;
7898 }
7899 if (PyType_Ready(tp) < 0)
7900 INITERROR;
7901
7902 Py_INCREF(tpo);
7903 if (PyModule_AddObject(m, tp->tp_name + 14, tpo) < 0)
7904 INITERROR;
7905 }
78357906
78367907 if (!init_done) {
78377908 v = PyText_FromString("_cffi_backend");
78777948 INITERROR;
78787949 }
78797950
7880 Py_INCREF(&MiniBuffer_Type);
7881 if (PyModule_AddObject(m, "buffer", (PyObject *)&MiniBuffer_Type) < 0)
7882 INITERROR;
7883
78847951 init_cffi_tls();
78857952 if (PyErr_Occurred())
78867953 INITERROR;
2424 PyObject *x;
2525 int i, res;
2626 static char init_done = 0;
27
28 if (PyType_Ready(&FFI_Type) < 0)
29 return -1;
30 if (PyType_Ready(&Lib_Type) < 0)
31 return -1;
3227
3328 if (!init_done) {
3429 if (init_global_types_dict(FFI_Type.tp_dict) < 0)
6156 }
6257 init_done = 1;
6358 }
64
65 x = (PyObject *)&FFI_Type;
66 Py_INCREF(x);
67 if (PyModule_AddObject(m, "FFI", x) < 0)
68 return -1;
69 x = (PyObject *)&Lib_Type;
70 Py_INCREF(x);
71 if (PyModule_AddObject(m, "Lib", x) < 0)
72 return -1;
73
7459 return 0;
7560 }
7661
1919
2020 static PyTypeObject GlobSupport_Type = {
2121 PyVarObject_HEAD_INIT(NULL, 0)
22 "FFIGlobSupport",
22 "_cffi_backend.__FFIGlobSupport",
2323 sizeof(GlobSupportObject),
2424 0,
2525 (destructor)glob_support_dealloc, /* tp_dealloc */
11361136
11371137 static PyTypeObject FFI_Type = {
11381138 PyVarObject_HEAD_INIT(NULL, 0)
1139 "CompiledFFI",
1139 "_cffi_backend.FFI",
11401140 sizeof(FFIObject),
11411141 0,
11421142 (destructor)ffi_dealloc, /* tp_dealloc */
588588
589589 static PyTypeObject Lib_Type = {
590590 PyVarObject_HEAD_INIT(NULL, 0)
591 "CompiledLib",
591 "_cffi_backend.Lib",
592592 sizeof(LibObject),
593593 0,
594594 (destructor)lib_dealloc, /* tp_dealloc */
102102 }
103103 }
104104 #ifdef _WIN64
105 else if (z > 8)
105 else if (z != 1 && z != 2 && z != 4 && z != 8)
106106 {
107107 /* On Win64, if a single argument takes more than 8 bytes,
108108 then it is always passed by reference. */
143143 /* MSVC returns small structures in registers. Put in cif->flags
144144 the value FFI_TYPE_STRUCT only if the structure is big enough;
145145 otherwise, put the 4- or 8-bytes integer type. */
146 if (cif->rtype->size <= 4)
146 if (cif->rtype->size == 1 ||
147 cif->rtype->size == 2 ||
148 cif->rtype->size == 4)
147149 cif->flags = FFI_TYPE_INT;
148 else if (cif->rtype->size <= 8)
150 else if (cif->rtype->size == 8)
149151 cif->flags = FFI_TYPE_SINT64;
150152 else
151153 cif->flags = FFI_TYPE_STRUCT;
286288 _asm fld DWORD PTR [eax] ;
287289 // asm ("flds (%0)" : : "r" (resp) : "st" );
288290 }
289 else if (rtype == FFI_TYPE_DOUBLE)
291 else if (rtype == FFI_TYPE_DOUBLE || rtype == FFI_TYPE_LONGDOUBLE)
290292 {
291293 _asm mov eax, resp ;
292294 _asm fld QWORD PTR [eax] ;
293295 // asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
294 }
295 else if (rtype == FFI_TYPE_LONGDOUBLE)
296 {
297 // asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
298296 }
299297 else if (rtype == FFI_TYPE_SINT64)
300298 {
306304 // : : "r"(resp)
307305 // : "eax", "edx");
308306 }
307 else if (rtype == FFI_TYPE_STRUCT)
308 {
309 _asm mov eax, resp ;
310 }
309311 #else
310312 /* now, do a generic return based on the value of rtype */
311313 if (rtype == FFI_TYPE_INT)
316318 {
317319 asm ("flds (%0)" : : "r" (resp) : "st" );
318320 }
319 else if (rtype == FFI_TYPE_DOUBLE)
321 else if (rtype == FFI_TYPE_DOUBLE || rtype == FFI_TYPE_LONGDOUBLE)
320322 {
321323 asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
322 }
323 else if (rtype == FFI_TYPE_LONGDOUBLE)
324 {
325 asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
326324 }
327325 else if (rtype == FFI_TYPE_SINT64)
328326 {
331329 : : "r"(resp)
332330 : "eax", "edx");
333331 }
332 else if (rtype == FFI_TYPE_STRUCT)
333 {
334 asm ("movl %0,%%eax" : : "r" (resp) : "eax");
335 }
334336 #endif
335337 #endif
336338
339341 result types except for floats; we have to 'mov xmm0, rax' in the
340342 caller to correct this.
341343 */
344 if (rtype == FFI_TYPE_STRUCT)
345 return resp;
342346 return *(void **)resp;
343347 #endif
344348 }
377381 /* because we're little endian, this is what it turns into. */
378382
379383 #ifdef _WIN64
380 if (z > 8)
384 if (z != 1 && z != 2 && z != 4 && z != 8)
381385 {
382386 /* On Win64, if a single argument takes more than 8 bytes,
383387 then it is always passed by reference. */
446450 || cif->arg_types[3]->type == FFI_TYPE_DOUBLE))
447451 mask |= 8;
448452
453 /* if we return a non-small struct, then the first argument is a pointer
454 * to the return area, and all real arguments are shifted by one */
455 if (cif->flags == FFI_TYPE_STRUCT)
456 mask = (mask & ~8) << 1;
457
449458 /* 41 BB ---- mov r11d,mask */
450459 BYTES("\x41\xBB"); INT(mask);
451460
116116 /* Make space for the return structure pointer */
117117 if (cif->rtype->type == FFI_TYPE_STRUCT
118118 #ifdef _WIN32
119 && (cif->rtype->size > 8) /* MSVC returns small structs in registers */
119 && (cif->rtype->size != 1) /* MSVC returns small structs in registers */
120 && (cif->rtype->size != 2)
121 && (cif->rtype->size != 4)
122 && (cif->rtype->size != 8)
120123 #endif
121124 #ifdef SPARC
122125 && (cif->abi != FFI_V9 || cif->rtype->size > 32)
22
33 def _setup_path():
44 import os, sys
5 if '__pypy__' in sys.builtin_module_names:
6 py.test.skip("_cffi_backend.c: not tested on top of pypy, "
7 "use pypy/module/_cffi_backend/test/ instead.")
85 sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
96 _setup_path()
107 from _cffi_backend import *
11 from _cffi_backend import _testfunc, _get_types, _get_common_types, __version__
8 from _cffi_backend import _get_types, _get_common_types
9 try:
10 from _cffi_backend import _testfunc
11 except ImportError:
12 def _testfunc(num):
13 pytest.skip("_testunc() not available")
14 from _cffi_backend import __version__
1215
1316 # ____________________________________________________________
1417
1518 import sys
16 assert __version__ == "1.14.0", ("This test_c.py file is for testing a version"
19 assert __version__ == "1.14.3", ("This test_c.py file is for testing a version"
1720 " of cffi that differs from the one that we"
1821 " get from 'import _cffi_backend'")
1922 if sys.version_info < (3,):
6467 path = ctypes.util.find_library(name)
6568 if path is None and name == 'c':
6669 assert sys.platform == 'win32'
67 assert sys.version_info >= (3,)
68 py.test.skip("dlopen(None) cannot work on Windows with Python 3")
70 assert (sys.version_info >= (3,) or
71 '__pypy__' in sys.builtin_module_names)
72 py.test.skip("dlopen(None) cannot work on Windows "
73 "with PyPy or Python 3")
6974 return load_library(path, flags)
7075
7176 def test_load_library():
108113 p = new_primitive_type("signed char")
109114 x = cast(p, -65 + 17*256)
110115 assert repr(x) == "<cdata 'signed char' -65>"
111 assert repr(type(x)) == "<%s '_cffi_backend.CData'>" % type_or_class
116 assert repr(type(x)) == "<%s '_cffi_backend._CDataBase'>" % type_or_class
112117 assert int(x) == -65
113118 x = cast(p, -66 + (1<<199)*256)
114119 assert repr(x) == "<cdata 'signed char' -66>"
25472552 assert get_errno() == 95
25482553
25492554 def test_errno_callback():
2550 if globals().get('PY_DOT_PY') == '2.5':
2551 py.test.skip("cannot run this test on py.py with Python 2.5")
2555 if globals().get('PY_DOT_PY'):
2556 py.test.skip("cannot run this test on py.py (e.g. fails on Windows)")
25522557 set_errno(95)
25532558 def cb():
25542559 e = get_errno()
44524457 BStruct = new_struct_type("struct foo")
44534458 complete_struct_or_union(BStruct, [('a1', BArray, -1)])
44544459 assert sizeof(BStruct) == sys.maxsize
4460
4461 def test_get_types():
4462 import _cffi_backend
4463 CData, CType = _get_types()
4464 assert CData is _cffi_backend._CDataBase
4465 assert CType is _cffi_backend.CType
4466
4467 def test_type_available_with_correct_names():
4468 import _cffi_backend
4469 check_names = [
4470 'CType',
4471 'CField',
4472 'CLibrary',
4473 '_CDataBase',
4474 'FFI',
4475 'Lib',
4476 'buffer',
4477 ]
4478 if '__pypy__' in sys.builtin_module_names:
4479 check_names += [
4480 '__CData_iterator',
4481 '__FFIGlobSupport',
4482 '__FFIAllocator',
4483 '__FFIFunctionWrapper',
4484 ]
4485 else:
4486 check_names += [
4487 '__CDataOwn',
4488 '__CDataOwnGC',
4489 '__CDataFromBuf',
4490 '__CDataGCP',
4491 '__CData_iterator',
4492 '__FFIGlobSupport',
4493 ]
4494 for name in check_names:
4495 tp = getattr(_cffi_backend, name)
4496 assert isinstance(tp, type)
4497 assert (tp.__module__, tp.__name__) == ('_cffi_backend', name)
44 from .error import CDefError, FFIError, VerificationError, VerificationMissing
55 from .error import PkgConfigError
66
7 __version__ = "1.14.0"
8 __version_info__ = (1, 14, 0)
7 __version__ = "1.14.3"
8 __version_info__ = (1, 14, 3)
99
1010 # The verifier module file names are based on the CRC32 of a string that
1111 # contains the following version number. It may be older than __version__
77 the same works for the other two macros. Py_DEBUG implies them,
88 but not the other way around.
99
10 Issue #350 is still open: on Windows, the code here causes it to link
11 with PYTHON36.DLL (for example) instead of PYTHON3.DLL. A fix was
12 attempted in 164e526a5515 and 14ce6985e1c3, but reverted: virtualenv
13 does not make PYTHON3.DLL available, and so the "correctly" compiled
14 version would not run inside a virtualenv. We will re-apply the fix
15 after virtualenv has been fixed for some time. For explanation, see
16 issue #355. For a workaround if you want PYTHON3.DLL and don't worry
17 about virtualenv, see issue #350. See also 'py_limited_api' in
18 setuptools_ext.py.
10 The implementation is messy (issue #350): on Windows, with _MSC_VER,
11 we have to define Py_LIMITED_API even before including pyconfig.h.
12 In that case, we guess what pyconfig.h will do to the macros above,
13 and check our guess after the #include.
14
15 Note that on Windows, with CPython 3.x, you need >= 3.5 and virtualenv
16 version >= 16.0.0. With older versions of either, you don't get a
17 copy of PYTHON3.DLL in the virtualenv. We can't check the version of
18 CPython *before* we even include pyconfig.h. ffi.set_source() puts
19 a ``#define _CFFI_NO_LIMITED_API'' at the start of this file if it is
20 running on Windows < 3.5, as an attempt at fixing it, but that's
21 arguably wrong because it may not be the target version of Python.
22 Still better than nothing I guess. As another workaround, you can
23 remove the definition of Py_LIMITED_API here.
24
25 See also 'py_limited_api' in cffi/setuptools_ext.py.
1926 */
2027 #if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API)
21 # include <pyconfig.h>
22 # if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG)
23 # define Py_LIMITED_API
28 # ifdef _MSC_VER
29 # if !defined(_DEBUG) && !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) && !defined(_CFFI_NO_LIMITED_API)
30 # define Py_LIMITED_API
31 # endif
32 # include <pyconfig.h>
33 /* sanity-check: Py_LIMITED_API will cause crashes if any of these
34 are also defined. Normally, the Python file PC/pyconfig.h does not
35 cause any of these to be defined, with the exception that _DEBUG
36 causes Py_DEBUG. Double-check that. */
37 # ifdef Py_LIMITED_API
38 # if defined(Py_DEBUG)
39 # error "pyconfig.h unexpectedly defines Py_DEBUG, but Py_LIMITED_API is set"
40 # endif
41 # if defined(Py_TRACE_REFS)
42 # error "pyconfig.h unexpectedly defines Py_TRACE_REFS, but Py_LIMITED_API is set"
43 # endif
44 # if defined(Py_REF_DEBUG)
45 # error "pyconfig.h unexpectedly defines Py_REF_DEBUG, but Py_LIMITED_API is set"
46 # endif
47 # endif
48 # else
49 # include <pyconfig.h>
50 # if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) && !defined(_CFFI_NO_LIMITED_API)
51 # define Py_LIMITED_API
52 # endif
2453 # endif
2554 #endif
2655
223223
224224 if (f != NULL && f != Py_None) {
225225 PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
226 "\ncompiled with cffi version: 1.14.0"
226 "\ncompiled with cffi version: 1.14.3"
227227 "\n_cffi_backend module: ", f);
228228 modules = PyImport_GetModuleDict();
229229 mod = PyDict_GetItemString(modules, "_cffi_backend");
245245 goto done;
246246 }
247247
248 #if PY_VERSION_HEX < 0x03080000
248249 PyAPI_DATA(char *) _PyParser_TokenNames[]; /* from CPython */
250 #endif
249251
250252 static int _cffi_carefully_make_gil(void)
251253 {
328330 /* call Py_InitializeEx() */
329331 if (!Py_IsInitialized()) {
330332 _cffi_py_initialize();
333 #if PY_VERSION_HEX < 0x03070000
331334 PyEval_InitThreads();
335 #endif
332336 PyEval_SaveThread(); /* release the GIL */
333337 /* the returned tstate must be the one that has been stored into the
334338 autoTLSkey by _PyGILState_Init() called from Py_Initialize(). */
335339 }
336340 else {
341 #if PY_VERSION_HEX < 0x03070000
342 /* PyEval_InitThreads() is always a no-op from CPython 3.7 */
337343 PyGILState_STATE state = PyGILState_Ensure();
338344 PyEval_InitThreads();
339345 PyGILState_Release(state);
346 #endif
340347 }
341348
342349 #ifdef WITH_THREAD
360367
361368 static struct _cffi_pypy_init_s {
362369 const char *name;
363 void (*func)(const void *[]);
370 void *func; /* function pointer */
364371 const char *code;
365372 } _cffi_pypy_init = {
366373 _CFFI_MODULE_NAME,
367 (void(*)(const void *[]))_CFFI_PYTHON_STARTUP_FUNC,
374 _CFFI_PYTHON_STARTUP_FUNC,
368375 _CFFI_PYTHON_STARTUP_CODE,
369376 };
370377
2828 _r_define = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)"
2929 r"\b((?:[^\n\\]|\\.)*?)$",
3030 re.DOTALL | re.MULTILINE)
31 _r_line_directive = re.compile(r"^[ \t]*#[ \t]*(?:line|\d+)\b.*$", re.MULTILINE)
3132 _r_partial_enum = re.compile(r"=\s*\.\.\.\s*[,}]|\.\.\.\s*\}")
3233 _r_enum_dotdotdot = re.compile(r"__dotdotdot\d+__$")
3334 _r_partial_array = re.compile(r"\[\s*\.\.\.\s*\]")
162163 "with C it should have a storage class specifier "
163164 "(usually 'extern')" % (decl.name,))
164165
166 def _remove_line_directives(csource):
167 # _r_line_directive matches whole lines, without the final \n, if they
168 # start with '#line' with some spacing allowed, or '#NUMBER'. This
169 # function stores them away and replaces them with exactly the string
170 # '#line@N', where N is the index in the list 'line_directives'.
171 line_directives = []
172 def replace(m):
173 i = len(line_directives)
174 line_directives.append(m.group())
175 return '#line@%d' % i
176 csource = _r_line_directive.sub(replace, csource)
177 return csource, line_directives
178
179 def _put_back_line_directives(csource, line_directives):
180 def replace(m):
181 s = m.group()
182 if not s.startswith('#line@'):
183 raise AssertionError("unexpected #line directive "
184 "(should have been processed and removed")
185 return line_directives[int(s[6:])]
186 return _r_line_directive.sub(replace, csource)
187
165188 def _preprocess(csource):
189 # First, remove the lines of the form '#line N "filename"' because
190 # the "filename" part could confuse the rest
191 csource, line_directives = _remove_line_directives(csource)
166192 # Remove comments. NOTE: this only work because the cdef() section
167 # should not contain any string literal!
168 csource = _r_comment.sub(' ', csource)
193 # should not contain any string literals (except in line directives)!
194 def replace_keeping_newlines(m):
195 return ' ' + m.group().count('\n') * '\n'
196 csource = _r_comment.sub(replace_keeping_newlines, csource)
169197 # Remove the "#define FOO x" lines
170198 macros = {}
171199 for match in _r_define.finditer(csource):
218246 csource = _r_float_dotdotdot.sub(' __dotdotdotfloat__ ', csource)
219247 # Replace all remaining "..." with the same name, "__dotdotdot__",
220248 # which is declared with a typedef for the purpose of C parsing.
221 return csource.replace('...', ' __dotdotdot__ '), macros
249 csource = csource.replace('...', ' __dotdotdot__ ')
250 # Finally, put back the line directives
251 csource = _put_back_line_directives(csource, line_directives)
252 return csource, macros
222253
223254 def _common_type_names(csource):
224255 # Look in the source for what looks like usages of types from the
394425 realtype = self._get_unknown_ptr_type(decl)
395426 else:
396427 realtype, quals = self._get_type_and_quals(
397 decl.type, name=decl.name, partial_length_ok=True)
428 decl.type, name=decl.name, partial_length_ok=True,
429 typedef_example="*(%s *)0" % (decl.name,))
398430 self._declare('typedef ' + decl.name, realtype, quals=quals)
399431 elif decl.__class__.__name__ == 'Pragma':
400432 pass # skip pragma, only in pycparser 2.15
561593 return model.NamedPointerType(type, declname, quals)
562594 return model.PointerType(type, quals)
563595
564 def _get_type_and_quals(self, typenode, name=None, partial_length_ok=False):
596 def _get_type_and_quals(self, typenode, name=None, partial_length_ok=False,
597 typedef_example=None):
565598 # first, dereference typedefs, if we have it already parsed, we're good
566599 if (isinstance(typenode, pycparser.c_ast.TypeDecl) and
567600 isinstance(typenode.type, pycparser.c_ast.IdentifierType) and
578611 else:
579612 length = self._parse_constant(
580613 typenode.dim, partial_length_ok=partial_length_ok)
614 # a hack: in 'typedef int foo_t[...][...];', don't use '...' as
615 # the length but use directly the C expression that would be
616 # generated by recompiler.py. This lets the typedef be used in
617 # many more places within recompiler.py
618 if typedef_example is not None:
619 if length == '...':
620 length = '_cffi_array_len(%s)' % (typedef_example,)
621 typedef_example = "*" + typedef_example
622 #
581623 tp, quals = self._get_type_and_quals(typenode.type,
582 partial_length_ok=partial_length_ok)
624 partial_length_ok=partial_length_ok,
625 typedef_example=typedef_example)
583626 return model.ArrayType(tp, length), quals
584627 #
585628 if isinstance(typenode, pycparser.c_ast.PtrDecl):
306306 self.c_name_with_marker = (
307307 self.item.c_name_with_marker.replace('&', brackets))
308308
309 def length_is_unknown(self):
310 return isinstance(self.length, str)
311
309312 def resolve_length(self, newlength):
310313 return ArrayType(self.item, newlength)
311314
312315 def build_backend_type(self, ffi, finishlist):
313 if self.length == '...':
316 if self.length_is_unknown():
314317 raise CDefError("cannot render the type %r: unknown length" %
315318 (self,))
316319 self.item.get_cached_btype(ffi, finishlist) # force the item BType
429432 fsize = fieldsize[i]
430433 ftype = self.fldtypes[i]
431434 #
432 if isinstance(ftype, ArrayType) and ftype.length == '...':
435 if isinstance(ftype, ArrayType) and ftype.length_is_unknown():
433436 # fix the length to match the total size
434437 BItemType = ftype.item.get_cached_btype(ffi, finishlist)
435438 nlen, nrest = divmod(fsize, ffi.sizeof(BItemType))
55 VERSION_BASE = 0x2601
66 VERSION_EMBEDDED = 0x2701
77 VERSION_CHAR16CHAR32 = 0x2801
8
9 USE_LIMITED_API = (sys.platform != 'win32' or sys.version_info < (3, 0) or
10 sys.version_info >= (3, 5))
811
912
1013 class GlobalExpr:
282285 prnt = self._prnt
283286 if self.ffi._embedding is not None:
284287 prnt('#define _CFFI_USE_EMBEDDING')
288 if not USE_LIMITED_API:
289 prnt('#define _CFFI_NO_LIMITED_API')
285290 #
286291 # first the '#include' (actually done by inlining the file's content)
287292 lines = self._rel_readlines('_cffi_include.h')
12951300 def _print_string_literal_in_array(self, s):
12961301 prnt = self._prnt
12971302 prnt('// # NB. this is not a string because of a size limit in MSVC')
1303 if not isinstance(s, bytes): # unicode
1304 s = s.encode('utf-8') # -> bytes
1305 else:
1306 s.decode('utf-8') # got bytes, check for valid utf-8
1307 try:
1308 s.decode('ascii')
1309 except UnicodeDecodeError:
1310 s = b'# -*- encoding: utf8 -*-\n' + s
12981311 for line in s.splitlines(True):
1299 prnt(('// ' + line).rstrip())
1312 comment = line
1313 if type('//') is bytes: # python2
1314 line = map(ord, line) # make a list of integers
1315 else: # python3
1316 # type(line) is bytes, which enumerates like a list of integers
1317 comment = ascii(comment)[1:-1]
1318 prnt(('// ' + comment).rstrip())
13001319 printed_line = ''
13011320 for c in line:
13021321 if len(printed_line) >= 76:
13031322 prnt(printed_line)
13041323 printed_line = ''
1305 printed_line += '%d,' % (ord(c),)
1324 printed_line += '%d,' % (c,)
13061325 prnt(printed_line)
13071326
13081327 # ----------
8383
8484 On Windows, with CPython <= 3.4, it's better not to use py_limited_api
8585 because virtualenv *still* doesn't copy PYTHON3.DLL on these versions.
86 For now we'll skip py_limited_api on all Windows versions to avoid an
87 inconsistent mess.
86 Recently (2020) we started shipping only >= 3.5 wheels, though. So
87 we'll give it another try and set py_limited_api on Windows >= 3.5.
8888 """
89 from cffi import recompiler
90
8991 if ('py_limited_api' not in kwds and not hasattr(sys, 'gettotalrefcount')
90 and sys.platform != 'win32'):
92 and recompiler.USE_LIMITED_API):
9193 import setuptools
9294 try:
9395 setuptools_major_version = int(setuptools.__version__.partition('.')[0])
761761 if isinstance(tp, model.ArrayType):
762762 tp_ptr = model.PointerType(tp.item)
763763 self._generate_cpy_const(False, name, tp, vartp=tp_ptr,
764 size_too = (tp.length == '...'))
764 size_too = tp.length_is_unknown())
765765 else:
766766 tp_ptr = model.PointerType(tp)
767767 self._generate_cpy_const(False, name, tp_ptr, category='var')
773773 value = getattr(library, name)
774774 if isinstance(tp, model.ArrayType): # int a[5] is "constant" in the
775775 # sense that "a=..." is forbidden
776 if tp.length == '...':
776 if tp.length_is_unknown():
777777 assert isinstance(value, tuple)
778778 (value, size) = value
779779 BItemType = self.ffi._get_cached_btype(tp.item)
564564
565565 def _generate_gen_variable_decl(self, tp, name):
566566 if isinstance(tp, model.ArrayType):
567 if tp.length == '...':
567 if tp.length_is_unknown():
568568 prnt = self._prnt
569569 funcname = '_cffi_sizeof_%s' % (name,)
570570 self.export_symbols.append(funcname)
583583 def _loaded_gen_variable(self, tp, name, module, library):
584584 if isinstance(tp, model.ArrayType): # int a[5] is "constant" in the
585585 # sense that "a=..." is forbidden
586 if tp.length == '...':
586 if tp.length_is_unknown():
587587 funcname = '_cffi_sizeof_%s' % (name,)
588588 BFunc = self.ffi._typeof_locked('size_t(*)(void)')[0]
589589 function = module.load_function(BFunc, funcname)
00 Metadata-Version: 1.1
11 Name: cffi
2 Version: 1.14.0
2 Version: 1.14.3
33 Summary: Foreign Function Interface for Python calling C code.
44 Home-page: http://cffi.readthedocs.org
55 Author: Armin Rigo, Maciej Fijalkowski
153153 testing/cffi1/test_dlopen.py
154154 testing/cffi1/test_dlopen_unicode_literals.py
155155 testing/cffi1/test_ffi_obj.py
156 testing/cffi1/test_function_args.py
156157 testing/cffi1/test_new_ffi_1.py
157158 testing/cffi1/test_parse_c_type.py
158159 testing/cffi1/test_pkgconfig.py
184185 testing/embedding/thread2-test.c
185186 testing/embedding/thread3-test.c
186187 testing/embedding/tlocal-test.c
187 testing/embedding/tlocal.py
188 testing/embedding/tlocal.py
189 testing/embedding/withunicode.py
589589 different declarations). The reason for that is detailed in `a comment
590590 about an issue.`__
591591
592 .. __: https://bitbucket.org/cffi/cffi/issues/265/cffi-doesnt-allow-creating-pointers-to#comment-28406958
592 .. __: https://foss.heptapod.net/pypy/cffi/-/issues/265#note_50393
593593
594594
595595 ffibuilder.compile() etc.: compiling out-of-line modules
4646 # The short X.Y version.
4747 version = '1.14'
4848 # The full version, including alpha/beta/rc tags.
49 release = '1.14.0'
49 release = '1.14.3'
5050
5151 # The language for content autogenerated by Sphinx. Refer to documentation
5252 # for a list of supported languages.
379379 ``dlopen("libpythonX.Y.so", RTLD_LAZY|RTLD_GLOBAL)``, which will
380380 force ``libpythonX.Y.so`` to be loaded first.
381381
382 .. __: https://bitbucket.org/cffi/cffi/issues/264/
382 .. __: https://foss.heptapod.net/pypy/cffi/-/issues/264
383383
384384
385385 Using multiple CFFI-made DLLs
6464
6565 --- the authors, Armin Rigo and Maciej Fijalkowski
6666
67 .. _`issue tracker`: https://bitbucket.org/cffi/cffi/issues
67 .. _`issue tracker`: https://foss.heptapod.net/pypy/cffi/issues
6868 .. _`mailing list`: https://groups.google.com/forum/#!forum/python-cffi
5151
5252 * https://pypi.python.org/pypi/cffi
5353
54 * Checksums of the "source" package version 1.14.0:
54 * Checksums of the "source" package version 1.14.3:
5555
5656 - MD5: ...
5757
5959
6060 - SHA256: ...
6161
62 * Or grab the most current version from the `Bitbucket page`_:
63 ``hg clone https://bitbucket.org/cffi/cffi``
62 * Or grab the most current version from the `Heptapod page`_:
63 ``hg clone https://foss.heptapod.net/pypy/cffi``
6464
6565 * ``python setup.py install`` or ``python setup_base.py install``
6666 (should work out of the box on Linux or Windows; see below for
67 `MacOS X`_ or `Windows 64`_.)
67 `MacOS X`_.)
6868
6969 * running the tests: ``py.test c/ testing/`` (if you didn't
7070 install cffi yet, you need first ``python setup_base.py build_ext -f
7171 -i``)
7272
73 .. _`Bitbucket page`: https://bitbucket.org/cffi/cffi
73 .. _`Heptapod page`: https://foss.heptapod.net/pypy/cffi
7474
7575 Demos:
7676
8181 ultimate reference is given by the tests, notably
8282 `testing/cffi1/test_verify1.py`_ and `testing/cffi0/backend_tests.py`_.
8383
84 .. _`demo`: https://bitbucket.org/cffi/cffi/src/default/demo
85 .. _`testing/cffi1/test_verify1.py`: https://bitbucket.org/cffi/cffi/src/default/testing/cffi1/test_verify1.py
86 .. _`testing/cffi0/backend_tests.py`: https://bitbucket.org/cffi/cffi/src/default/testing/cffi0/backend_tests.py
84 .. _`demo`: https://foss.heptapod.net/pypy/cffi/-/tree/branch/default/demo
85 .. _`testing/cffi1/test_verify1.py`: https://foss.heptapod.net/pypy/cffi/-/blob/branch/default/testing/cffi1/test_verify1.py
86 .. _`testing/cffi0/backend_tests.py`: https://foss.heptapod.net/pypy/cffi/-/blob/branch/default/testing/cffi0/backend_tests.py
8787
8888
8989 Platform-specific instructions
132132 .. _here: http://superuser.com/questions/259278/python-2-6-1-pycrypto-2-3-pypi-package-broken-pipe-during-build
133133
134134
135 Windows (regular 32-bit)
136 ++++++++++++++++++++++++
135 Windows (32/64-bit)
136 +++++++++++++++++++
137137
138 Win32 works and is tested at least each official release.
138 Win32 and Win64 work and are tested at least each official release.
139139
140140 The recommended C compiler compatible with Python 2.7 is this one:
141141 http://www.microsoft.com/en-us/download/details.aspx?id=44266
147147
148148 For Python 3.4 and beyond:
149149 https://www.visualstudio.com/en-us/downloads/visual-studio-2015-ctp-vs
150
151
152 Windows 64
153 ++++++++++
154
155 Win64 received very basic testing and we applied a few essential
156 fixes in cffi 0.7. The comment above applies for Python 2.7 on
157 Windows 64 as well. Please report any other issue.
158
159 Note as usual that this is only about running the 64-bit version of
160 Python on the 64-bit OS. If you're running the 32-bit version (the
161 common case apparently), then you're running Win32 as far as we're
162 concerned.
163
164 .. _`issue 9`: https://bitbucket.org/cffi/cffi/issue/9
165 .. _`Python issue 7546`: http://bugs.python.org/issue7546
166150
167151
168152 Linux and OS/X: UCS2 versus UCS4
357357 from _pi.lib import pi_approx
358358
359359 approx = pi_approx(10)
360 assert str(pi_approximation).startswith("3.")
360 assert str(approx).startswith("3.")
361361
362362 approx = pi_approx(10000)
363363 assert str(approx).startswith("3.1")
458458 order, see the discussion in `issue 340`__.
459459
460460 .. __: http://bugs.python.org/issue31105
461 .. __: https://bitbucket.org/cffi/cffi/issues/340/resources-release-issues
461 .. __: https://foss.heptapod.net/pypy/cffi/-/issues/340
462462
463463
464464 .. _ffi-new-handle:
730730 raise IndexError("index too large!")
731731 ...
732732
733 .. __: https://bitbucket.org/cffi/cffi/issues/233/
733 .. __: https://foss.heptapod.net/pypy/cffi/-/issues/233
734734
735735
736736 .. _ffi-getctype:
786786 may be implemented in the future. (`This demo`__ shows how to do it
787787 anyway, but it is a bit lengthy.)
788788
789 .. __: https://bitbucket.org/cffi/cffi/src/default/demo/extern_python_varargs.py
789 .. __: https://foss.heptapod.net/pypy/cffi/-/blob/branch/default/demo/extern_python_varargs.py
790790
791791 Each corresponding Python callback function is defined with the
792792 ``@ffi.def_extern()`` decorator. Be careful when writing this
895895 to refactor the involved code so that it no longer uses ``ffi.callback()``.
896896
897897 .. __: https://github.com/pyca/pyopenssl/issues/596
898 .. __: https://bitbucket.org/cffi/cffi/issues/391/
898 .. __: https://foss.heptapod.net/pypy/cffi/-/issues/391
899899 .. __: https://bugzilla.redhat.com/show_bug.cgi?id=1249685
900900
901901 Warning: like ffi.new(), ffi.callback() returns a cdata that has
00 ======================
11 What's New
22 ======================
3
4
5 v1.14.2
6 =======
7
8 * CPython 3 on Windows: we again try to compile with ``Py_LIMITED_API``
9 by default. This flag is not added if you run the compilation with
10 CPython 3.4, as it only works with CPython >= 3.5, but by now this
11 version of Python is quite old (and we no longer distribute cffi
12 wheels for it).
13
14 This may require that you upgrade ``virtualenv`` (requires version 16
15 or newer) or at least copy manually ``python3.dll`` into your existing
16 virtualenvs. For distributing wheels with your cffi modules, you may
17 also need to upgrade ``wheel`` to the just-released version 0.35.
18
19 You can manually disable ``Py_LIMITED_API`` by calling
20 ``ffi.set_source(..., py_limited_api=False)``.
21
22
23 v1.14.1
24 =======
25
26 * CFFI source code is now `hosted on Heptapod`_.
27
28 * Improved support for ``typedef int my_array_t[...];`` with an explicit
29 dot-dot-dot in API mode (`issue #453`_)
30
31 * Windows (32 and 64 bits): multiple fixes for ABI-mode call to functions
32 that return a structure.
33
34 * Experimental support for MacOS 11 on aarch64.
35
36 * and a few other minor changes and bug fixes.
37
38 .. _`hosted on Heptapod`: https://foss.heptapod.net/pypy/cffi/
39 .. _`issue #453`: https://foss.heptapod.net/pypy/cffi/issues/453
340
441
542 v1.14
3572 * re-release because the Linux wheels came with an attached version of libffi
3673 that was very old and buggy (`issue #432`_).
3774
38 .. _`issue #432`: https://bitbucket.org/cffi/cffi/issues/432/
75 .. _`issue #432`: https://foss.heptapod.net/pypy/cffi/-/issues/432
3976
4077
4178
5491 * fixed `issue #427`_ where a multithreading mistake in the embedding logic
5592 initialization code would cause deadlocks on CPython 3.7.
5693
57 .. _`issue #429`: https://bitbucket.org/cffi/cffi/issues/429/
58 .. _`issue #427`: https://bitbucket.org/cffi/cffi/issues/427/
94 .. _`issue #429`: https://foss.heptapod.net/pypy/cffi/-/issues/429
95 .. _`issue #427`: https://foss.heptapod.net/pypy/cffi/-/issues/427
5996
6097
6198 v1.13
81118 recursion, with ``ffi.cdef("""struct X { void(*fnptr)(struct X); };""")``
82119
83120
121 Older Versions
122 ==============
123
84124 v1.12.3
85 =======
125 -------
86126
87127 * Fix for nested struct types that end in a var-sized array (#405).
88128
93133
94134
95135 v1.12.2
96 =======
136 -------
97137
98138 * Added temporary workaround to compile on CPython 3.8.0a2.
99139
100140
101141 v1.12.1
102 =======
142 -------
103143
104144 * CPython 3 on Windows: we again no longer compile with ``Py_LIMITED_API``
105145 by default because such modules *still* cannot be used with virtualenv.
115155
116156
117157 v1.12
118 =====
158 -----
119159
120160 * `Direct support for pkg-config`__.
121161
150190 to 1 byte instead of 4).
151191
152192 .. __: cdef.html#pkgconfig
153 .. _`issue #362`: https://bitbucket.org/cffi/cffi/issues/362/
154
155
156 Older Versions
157 ==============
193 .. _`issue #362`: https://foss.heptapod.net/pypy/cffi/-/issues/362
194
158195
159196 v1.11.5
160197 -------
185222 concerned about virtualenv: pass ``define_macros=[("Py_LIMITED_API",
186223 None)]`` as a keyword to the ``ffibuilder.set_source()`` call.
187224
188 .. _`Issue #345`: https://bitbucket.org/cffi/cffi/issues/345/
189 .. _`Issue #350`: https://bitbucket.org/cffi/cffi/issues/350/
190 .. _`Issue #358`: https://bitbucket.org/cffi/cffi/issues/358/
191 .. _`Issue #357`: https://bitbucket.org/cffi/cffi/issues/357/
225 .. _`Issue #345`: https://foss.heptapod.net/pypy/cffi/-/issues/345
226 .. _`Issue #350`: https://foss.heptapod.net/pypy/cffi/-/issues/350
227 .. _`Issue #358`: https://foss.heptapod.net/pypy/cffi/-/issues/358
228 .. _`Issue #357`: https://foss.heptapod.net/pypy/cffi/-/issues/357
192229
193230
194231 v1.11.4
201238 ``foo.cp36-win32.pyd``, to make it clear that they are regular
202239 CPython modules depending on ``python36.dll``.
203240
204 .. _`Issue #355`: https://bitbucket.org/cffi/cffi/issues/355/
241 .. _`Issue #355`: https://foss.heptapod.net/pypy/cffi/-/issues/355
205242
206243
207244 v1.11.3
290327 that are *slower* to call than the API mode does. For some reason it
291328 is often thought to be faster. It is not!
292329
293 .. __: https://bitbucket.org/cffi/cffi/issues/321/cffi-191-segmentation-fault-during-self
330 .. __: https://foss.heptapod.net/pypy/cffi/-/issues/321
294331 .. __: ref.html#ffi-gc
295 .. __: https://bitbucket.org/cffi/cffi/issues/320/improve-memory_pressure-management
332 .. __: https://foss.heptapod.net/pypy/cffi/-/issues/320
296333 .. __: http://bugs.python.org/issue31105
297334
298335
7070 config = Distribution().get_command_obj('config')
7171 return config
7272
73 def macosx_deployment_target():
74 from distutils.sysconfig import get_config_var
75 return tuple(map(int, get_config_var("MACOSX_DEPLOYMENT_TARGET").split('.')))
76
7377 def ask_supports_thread():
7478 config = get_config()
7579 ok = (sys.platform != 'win32' and
144148 sources.extend(os.path.join(COMPILE_LIBFFI, filename)
145149 for filename in _filenames)
146150 else:
147 use_pkg_config()
151 if 'darwin' in sys.platform and macosx_deployment_target() >= (10, 15):
152 # use libffi from Mac OS SDK if we're targetting 10.15 (including
153 # on arm64). This libffi is safe against the crash-after-fork
154 # issue described in _cffi_backend.c. Also, arm64 uses a different
155 # ABI for calls to vararg functions as opposed to regular functions.
156 extra_compile_args += ['-iwithsysroot/usr/include/ffi']
157 define_macros += [('CFFI_TRUST_LIBFFI', '1'),
158 ('HAVE_FFI_PREP_CIF_VAR', '1')]
159 libraries += ['ffi']
160 else:
161 use_pkg_config()
148162 ask_supports_thread()
149163 ask_supports_sync_synchronize()
150164
197211
198212 `Mailing list <https://groups.google.com/forum/#!forum/python-cffi>`_
199213 """,
200 version='1.14.0',
214 version='1.14.3',
201215 packages=['cffi'] if cpython else [],
202216 package_data={'cffi': ['_cffi_include.h', 'parse_c_type.h',
203217 '_embedding.h', '_cffi_errors.h']}
00 import py
11 import pytest
22 import platform
3 import sys, ctypes
3 import sys, ctypes, ctypes.util
44 from cffi import FFI, CDefError, FFIError, VerificationMissing
55 from testing.support import *
66
1111 SIZE_OF_WCHAR = ctypes.sizeof(ctypes.c_wchar)
1212
1313 def needs_dlopen_none():
14 if sys.platform == 'win32' and sys.version_info >= (3,):
15 py.test.skip("dlopen(None) cannot work on Windows for Python 3")
14 if sys.platform == 'win32' and not ctypes.util.find_library('c'):
15 py.test.skip("dlopen(None) cannot work on Windows with this runtime")
1616
1717
1818 class BackendTests:
245245 self.check("int a:2; short b:15; char c:2; char y;", 5, 4, 8)
246246 self.check("int a:2; char b:1; char c:1; char y;", 1, 4, 4)
247247
248 @pytest.mark.skipif("platform.machine().startswith(('arm', 'aarch64'))")
248 @pytest.mark.skipif(
249 "not (sys.platform == 'darwin' and platform.machine() == 'arm64')"
250 " and "
251 "platform.machine().startswith(('arm', 'aarch64'))")
249252 def test_bitfield_anonymous_no_align(self):
250253 L = FFI().alignof("long long")
251254 self.check("char y; int :1;", 0, 1, 2)
259262 self.check("char x; long long :57; char y;", L + 8, 1, L + 9)
260263
261264 @pytest.mark.skipif(
265 "(sys.platform == 'darwin' and platform.machine() == 'arm64')"
266 " or "
262267 "not platform.machine().startswith(('arm', 'aarch64'))")
263268 def test_bitfield_anonymous_align_arm(self):
264269 L = FFI().alignof("long long")
272277 self.check("char x; long long z:57; char y;", L + 8, L, L + 8 + L)
273278 self.check("char x; long long :57; char y;", L + 8, L, L + 8 + L)
274279
275 @pytest.mark.skipif("platform.machine().startswith(('arm', 'aarch64'))")
280 @pytest.mark.skipif(
281 "not (sys.platform == 'darwin' and platform.machine() == 'arm64')"
282 " and "
283 "platform.machine().startswith(('arm', 'aarch64'))")
276284 def test_bitfield_zero(self):
277285 L = FFI().alignof("long long")
278286 self.check("char y; int :0;", 0, 1, 4)
284292 self.check("int a:1; int :0; int b:1; char y;", 5, 4, 8)
285293
286294 @pytest.mark.skipif(
295 "(sys.platform == 'darwin' and platform.machine() == 'arm64')"
296 " or "
287297 "not platform.machine().startswith(('arm', 'aarch64'))")
288298 def test_bitfield_zero_arm(self):
289299 L = FFI().alignof("long long")
239239 else:
240240 assert "None" in printed
241241
242 def test_callback_returning_struct_three_bytes(self):
243 if self.Backend is CTypesBackend:
244 py.test.skip("not supported with the ctypes backend")
245 ffi = FFI(backend=self.Backend())
246 ffi.cdef("""
247 typedef struct {
248 unsigned char a, b, c;
249 } THREEBYTES;
250 """)
251 def cb():
252 return (12, 34, 56)
253 fptr = ffi.callback("THREEBYTES(*)(void)", cb)
254 tb = fptr()
255 assert tb.a == 12
256 assert tb.b == 34
257 assert tb.c == 56
258
242259 def test_passing_array(self):
243260 ffi = FFI(backend=self.Backend())
244261 ffi.cdef("""
3333 long right;
3434 long bottom;
3535 } RECT;
36
37 typedef struct {
38 unsigned char a, b, c;
39 } THREEBYTES;
3640
3741
3842 EXPORT int PointInRect(RECT *prc, POINT pt)
105109 EXPORT void modify_struct_value(RECT r)
106110 {
107111 r.left = r.right = r.top = r.bottom = 500;
112 }
113
114 EXPORT THREEBYTES return_three_bytes(void)
115 {
116 THREEBYTES result;
117 result.a = 12;
118 result.b = 34;
119 result.c = 56;
120 return result;
108121 }
109122 """
110123
396409
397410 err = lib1.dlclose(handle)
398411 assert err == 0
412
413 def test_return_three_bytes(self):
414 if self.module is None:
415 py.test.skip("fix the auto-generation of the tiny test lib")
416 if self.__class__.Backend is CTypesBackend:
417 py.test.skip("not working on win32 on the ctypes backend")
418 ffi = FFI(backend=self.Backend())
419 ffi.cdef("""
420 typedef struct {
421 unsigned char a, b, c;
422 } THREEBYTES;
423
424 THREEBYTES return_three_bytes(void);
425 """)
426 lib = ffi.dlopen(self.module)
427 tb = lib.return_three_bytes()
428 assert tb.a == 12
429 assert tb.b == 34
430 assert tb.c == 56
173173 double // blah \\
174174 more comments
175175 x(void);
176 double // blah\\\\
176 double // blah // blah\\\\
177177 y(void);
178178 double // blah\\ \
179179 etc
183183 m.x
184184 m.y
185185 m.z
186
187 def test_dont_remove_comment_in_line_directives():
188 ffi = FFI(backend=FakeBackend())
189 e = py.test.raises(CDefError, ffi.cdef, """
190 \t # \t line \t 8 \t "baz.c" \t
191
192 some syntax error here
193 """)
194 assert str(e.value) == "parse error\nbaz.c:9:14: before: syntax"
195 #
196 e = py.test.raises(CDefError, ffi.cdef, """
197 #line 7 "foo//bar.c"
198
199 some syntax error here
200 """)
201 #
202 assert str(e.value) == "parse error\nfoo//bar.c:8:14: before: syntax"
203 ffi = FFI(backend=FakeBackend())
204 e = py.test.raises(CDefError, ffi.cdef, """
205 \t # \t 8 \t "baz.c" \t
206
207 some syntax error here
208 """)
209 assert str(e.value) == "parse error\nbaz.c:9:14: before: syntax"
210 #
211 e = py.test.raises(CDefError, ffi.cdef, """
212 # 7 "foo//bar.c"
213
214 some syntax error here
215 """)
216 assert str(e.value) == "parse error\nfoo//bar.c:8:14: before: syntax"
217
218 def test_multiple_line_directives():
219 ffi = FFI(backend=FakeBackend())
220 e = py.test.raises(CDefError, ffi.cdef,
221 """ #line 5 "foo.c"
222 extern int xx;
223 #line 6 "bar.c"
224 extern int yy;
225 #line 7 "baz.c"
226 some syntax error here
227 #line 8 "yadda.c"
228 extern int zz;
229 """)
230 assert str(e.value) == "parse error\nbaz.c:7:14: before: syntax"
231 #
232 e = py.test.raises(CDefError, ffi.cdef,
233 """ # 5 "foo.c"
234 extern int xx;
235 # 6 "bar.c"
236 extern int yy;
237 # 7 "baz.c"
238 some syntax error here
239 # 8 "yadda.c"
240 extern int zz;
241 """)
242 assert str(e.value) == "parse error\nbaz.c:7:14: before: syntax"
243
244 def test_commented_line_directive():
245 ffi = FFI(backend=FakeBackend())
246 e = py.test.raises(CDefError, ffi.cdef, """
247 /*
248 #line 5 "foo.c"
249 */
250 void xx(void);
251
252 #line 6 "bar.c"
253 /*
254 #line 35 "foo.c"
255 */
256 some syntax error
257 """)
258 #
259 assert str(e.value) == "parse error\nbar.c:9:14: before: syntax"
260 e = py.test.raises(CDefError, ffi.cdef, """
261 /*
262 # 5 "foo.c"
263 */
264 void xx(void);
265
266 # 6 "bar.c"
267 /*
268 # 35 "foo.c"
269 */
270 some syntax error
271 """)
272 assert str(e.value) == "parse error\nbar.c:9:14: before: syntax"
186273
187274 def test_line_continuation_in_defines():
188275 ffi = FFI(backend=FakeBackend())
0 import pytest, sys
1 try:
2 # comment out the following line to run this test.
3 # the latest on x86-64 linux: https://github.com/libffi/libffi/issues/574
4 if sys.platform != 'win32':
5 raise ImportError("this test is skipped because it keeps finding "
6 "failures in libffi, instead of cffi")
7
8 from hypothesis import given, settings, example
9 from hypothesis import strategies as st
10 except ImportError as e:
11 e1 = e
12 def test_types():
13 pytest.skip(str(e1))
14 else:
15
16 from cffi import FFI
17 import sys, random
18 from .test_recompiler import verify
19
20 ALL_PRIMITIVES = [
21 'unsigned char',
22 'short',
23 'int',
24 'long',
25 'long long',
26 'float',
27 'double',
28 #'long double', --- on x86 it can give libffi crashes
29 ]
30 def _make_struct(s):
31 return st.lists(s, min_size=1)
32 types = st.one_of(st.sampled_from(ALL_PRIMITIVES),
33 st.lists(st.sampled_from(ALL_PRIMITIVES), min_size=1))
34 # NB. 'types' could be st.recursive instead, but it doesn't
35 # really seem useful
36
37 def draw_primitive(ffi, typename):
38 value = random.random() * 2**40
39 if typename != 'long double':
40 return ffi.cast(typename, value)
41 else:
42 return value
43
44 TEST_RUN_COUNTER = 0
45
46
47 @given(st.lists(types), types)
48 @settings(max_examples=100, deadline=5000) # 5000ms
49 def test_types(tp_args, tp_result):
50 global TEST_RUN_COUNTER
51 print(tp_args, tp_result)
52 cdefs = []
53 structs = {}
54
55 def build_type(tp):
56 if type(tp) is list:
57 field_types = [build_type(tp1) for tp1 in tp]
58 fields = ['%s f%d;' % (ftp, j)
59 for (j, ftp) in enumerate(field_types)]
60 fields = '\n '.join(fields)
61 name = 's%d' % len(cdefs)
62 cdefs.append("typedef struct {\n %s\n} %s;" % (fields, name))
63 structs[name] = field_types
64 return name
65 else:
66 return tp
67
68 args = [build_type(tp) for tp in tp_args]
69 result = build_type(tp_result)
70
71 TEST_RUN_COUNTER += 1
72 signature = "%s testfargs(%s)" % (result,
73 ', '.join(['%s a%d' % (arg, i) for (i, arg) in enumerate(args)])
74 or 'void')
75
76 source = list(cdefs)
77
78 cdefs.append("%s;" % signature)
79 cdefs.append("extern %s testfargs_result;" % result)
80 for i, arg in enumerate(args):
81 cdefs.append("extern %s testfargs_arg%d;" % (arg, i))
82 source.append("%s testfargs_result;" % result)
83 for i, arg in enumerate(args):
84 source.append("%s testfargs_arg%d;" % (arg, i))
85 source.append(signature)
86 source.append("{")
87 for i, arg in enumerate(args):
88 source.append(" testfargs_arg%d = a%d;" % (i, i))
89 source.append(" return testfargs_result;")
90 source.append("}")
91
92 typedef_line = "typedef %s;" % (signature.replace('testfargs',
93 '(*mycallback_t)'),)
94 assert signature.endswith(')')
95 sig_callback = "%s testfcallback(mycallback_t callback)" % result
96 cdefs.append(typedef_line)
97 cdefs.append("%s;" % sig_callback)
98 source.append(typedef_line)
99 source.append(sig_callback)
100 source.append("{")
101 source.append(" return callback(%s);" %
102 ', '.join(["testfargs_arg%d" % i for i in range(len(args))]))
103 source.append("}")
104
105 ffi = FFI()
106 ffi.cdef("\n".join(cdefs))
107 lib = verify(ffi, 'test_function_args_%d' % TEST_RUN_COUNTER,
108 "\n".join(source), no_cpp=True)
109
110 # when getting segfaults, enable this:
111 if False:
112 from testing.udir import udir
113 import subprocess
114 f = open(str(udir.join('run1.py')), 'w')
115 f.write('import sys; sys.path = %r\n' % (sys.path,))
116 f.write('from _CFFI_test_function_args_%d import ffi, lib\n' %
117 TEST_RUN_COUNTER)
118 for i in range(len(args)):
119 f.write('a%d = ffi.new("%s *")\n' % (i, args[i]))
120 aliststr = ', '.join(['a%d[0]' % i for i in range(len(args))])
121 f.write('lib.testfargs(%s)\n' % aliststr)
122 f.write('ffi.addressof(lib, "testfargs")(%s)\n' % aliststr)
123 f.close()
124 print("checking for segfault for direct call...")
125 rc = subprocess.call([sys.executable, 'run1.py'], cwd=str(udir))
126 assert rc == 0, rc
127
128 def make_arg(tp):
129 if tp in structs:
130 return [make_arg(tp1) for tp1 in structs[tp]]
131 else:
132 return draw_primitive(ffi, tp)
133
134 passed_args = [make_arg(arg) for arg in args]
135 returned_value = make_arg(result)
136
137 def write(p, v):
138 if type(v) is list:
139 for i, v1 in enumerate(v):
140 write(ffi.addressof(p, 'f%d' % i), v1)
141 else:
142 p[0] = v
143
144 write(ffi.addressof(lib, 'testfargs_result'), returned_value)
145
146 ## CALL forcing libffi
147 print("CALL forcing libffi")
148 received_return = ffi.addressof(lib, 'testfargs')(*passed_args)
149 ##
150
151 _tp_long_double = ffi.typeof("long double")
152 def check(p, v):
153 if type(v) is list:
154 for i, v1 in enumerate(v):
155 check(ffi.addressof(p, 'f%d' % i), v1)
156 else:
157 if ffi.typeof(p).item is _tp_long_double:
158 assert ffi.cast("double", p[0]) == v
159 else:
160 assert p[0] == v
161
162 for i, arg in enumerate(passed_args):
163 check(ffi.addressof(lib, 'testfargs_arg%d' % i), arg)
164 ret = ffi.new(result + "*", received_return)
165 check(ret, returned_value)
166
167 ## CALLBACK
168 def expand(value):
169 if isinstance(value, ffi.CData):
170 t = ffi.typeof(value)
171 if t is _tp_long_double:
172 return float(ffi.cast("double", value))
173 return [expand(getattr(value, 'f%d' % i))
174 for i in range(len(t.fields))]
175 else:
176 return value
177
178 # when getting segfaults, enable this:
179 if False:
180 from testing.udir import udir
181 import subprocess
182 f = open(str(udir.join('run1.py')), 'w')
183 f.write('import sys; sys.path = %r\n' % (sys.path,))
184 f.write('from _CFFI_test_function_args_%d import ffi, lib\n' %
185 TEST_RUN_COUNTER)
186 f.write('def callback(*args): return ffi.new("%s *")[0]\n' % result)
187 f.write('fptr = ffi.callback("%s(%s)", callback)\n' % (result,
188 ','.join(args)))
189 f.write('print(lib.testfcallback(fptr))\n')
190 f.close()
191 print("checking for segfault for callback...")
192 rc = subprocess.call([sys.executable, 'run1.py'], cwd=str(udir))
193 assert rc == 0, rc
194
195 seen_args = []
196 def callback(*args):
197 seen_args.append([expand(arg) for arg in args])
198 return returned_value
199
200 fptr = ffi.callback("%s(%s)" % (result, ','.join(args)), callback)
201 print("CALL with callback")
202 received_return = lib.testfcallback(fptr)
203
204 assert len(seen_args) == 1
205 assert passed_args == seen_args[0]
206 ret = ffi.new(result + "*", received_return)
207 check(ret, returned_value)
3737 from testing.support import extra_compile_args
3838 kwds['extra_compile_args'] = (kwds.get('extra_compile_args', []) +
3939 extra_compile_args)
40 if sys.platform == 'darwin':
41 kwds['extra_link_args'] = (kwds.get('extra_link_args', []) +
42 ['-stdlib=libc++'])
4043 return _verify(ffi, module_name, source, *args, **kwds)
4144
4245 def test_set_source_no_slashes():
885888 e7 = py.test.raises(TypeError, lib.foo2, 45, 46, 47)
886889 def st1(s):
887890 s = str(s)
888 if s.startswith("_CFFI_test_unpack_args.CompiledLib."):
889 s = s[len("_CFFI_test_unpack_args.CompiledLib."):]
891 if s.startswith("_CFFI_test_unpack_args.Lib."):
892 s = s[len("_CFFI_test_unpack_args.Lib."):]
890893 return s
891894 assert st1(e1.value) == "foo0() takes no arguments (1 given)"
892895 assert st1(e2.value) == "foo0() takes no arguments (2 given)"
21182121 p = ffi.new("vmat_t", 4)
21192122 assert ffi.sizeof(p[3]) == 8 * ffi.sizeof("int")
21202123
2124 def test_typedef_array_dotdotdot_usage():
2125 ffi = FFI()
2126 ffi.cdef("""
2127 typedef int foo_t[...];
2128 typedef int mat_t[...][...];
2129 struct s { foo_t a; foo_t *b; foo_t **c; };
2130 int myfunc(foo_t a, foo_t *b, foo_t **c);
2131 struct sm { mat_t a; mat_t *b; mat_t **c; };
2132 int myfuncm(mat_t a, mat_t *b, mat_t **c);
2133 """)
2134 lib = verify(ffi, "test_typedef_array_dotdotdot_usage", """
2135 typedef int foo_t[50];
2136 typedef int mat_t[6][7];
2137 struct s { foo_t a; foo_t *b; foo_t **c; };
2138 static int myfunc(foo_t a, foo_t *b, foo_t **c) { return (**c)[49]; }
2139 struct sm { mat_t a; mat_t *b; mat_t **c; };
2140 static int myfuncm(mat_t a, mat_t *b, mat_t **c) { return (**c)[5][6]; }
2141 """)
2142 assert ffi.sizeof("foo_t") == 50 * ffi.sizeof("int")
2143 p = ffi.new("struct s *")
2144 assert ffi.sizeof(p[0]) == 50 * ffi.sizeof("int") + 2 * ffi.sizeof("void *")
2145 p.a[49] = 321
2146 p.b = ffi.addressof(p, 'a')
2147 p.c = ffi.addressof(p, 'b')
2148 assert lib.myfunc(ffi.NULL, ffi.NULL, p.c) == 321
2149 #
2150 assert ffi.sizeof("mat_t") == 42 * ffi.sizeof("int")
2151 p = ffi.new("struct sm *")
2152 assert ffi.sizeof(p[0]) == 42 * ffi.sizeof("int") + 2 * ffi.sizeof("void *")
2153 p.a[5][6] = -321
2154 p.b = ffi.addressof(p, 'a')
2155 p.c = ffi.addressof(p, 'b')
2156 assert lib.myfuncm(ffi.NULL, ffi.NULL, p.c) == -321
2157
21212158 def test_call_with_custom_field_pos():
21222159 ffi = FFI()
21232160 ffi.cdef("""
205205 self.compile('add1-test', [initerror_cffi])
206206 output = self.execute('add1-test')
207207 assert output == "got: 0 0\n" # plus lots of info to stderr
208
209 def test_embedding_with_unicode(self):
210 withunicode_cffi = self.prepare_module('withunicode')
211 self.compile('add1-test', [withunicode_cffi])
212 output = self.execute('add1-test')
213 assert output == "255\n4660\n65244\ngot: 0 0\n"
0 import sys, cffi
1 if sys.version_info < (3,):
2 u_prefix = "u"
3 else:
4 u_prefix = ""
5 unichr = chr
6
7
8 ffi = cffi.FFI()
9
10 ffi.embedding_api(u"""
11 int add1(int, int);
12 """)
13
14 ffi.embedding_init_code(("""
15 import sys, time
16 for c in %s'""" + unichr(0x00ff) + unichr(0x1234) + unichr(0xfedc) + """':
17 sys.stdout.write(str(ord(c)) + '\\n')
18 sys.stdout.flush()
19 """) % u_prefix)
20
21 ffi.set_source("_withunicode_cffi", """
22 """)
23
24 fn = ffi.compile(verbose=True)
25 print('FILENAME: %s' % (fn,))
00 import py
1 import sys
1 import sys, os, atexit
22
3 udir = py.path.local.make_numbered_dir(prefix = 'ffi-')
3
4 # This is copied from PyPy's vendored py lib. The latest py lib release
5 # (1.8.1) contains a bug and crashes if it sees another temporary directory
6 # in which we don't have write permission (e.g. because it's owned by someone
7 # else).
8 def make_numbered_dir(prefix='session-', rootdir=None, keep=3,
9 lock_timeout = 172800, # two days
10 min_timeout = 300): # five minutes
11 """ return unique directory with a number greater than the current
12 maximum one. The number is assumed to start directly after prefix.
13 if keep is true directories with a number less than (maxnum-keep)
14 will be removed.
15 """
16 if rootdir is None:
17 rootdir = py.path.local.get_temproot()
18
19 def parse_num(path):
20 """ parse the number out of a path (if it matches the prefix) """
21 bn = path.basename
22 if bn.startswith(prefix):
23 try:
24 return int(bn[len(prefix):])
25 except ValueError:
26 pass
27
28 # compute the maximum number currently in use with the
29 # prefix
30 lastmax = None
31 while True:
32 maxnum = -1
33 for path in rootdir.listdir():
34 num = parse_num(path)
35 if num is not None:
36 maxnum = max(maxnum, num)
37
38 # make the new directory
39 try:
40 udir = rootdir.mkdir(prefix + str(maxnum+1))
41 except py.error.EEXIST:
42 # race condition: another thread/process created the dir
43 # in the meantime. Try counting again
44 if lastmax == maxnum:
45 raise
46 lastmax = maxnum
47 continue
48 break
49
50 # put a .lock file in the new directory that will be removed at
51 # process exit
52 if lock_timeout:
53 lockfile = udir.join('.lock')
54 mypid = os.getpid()
55 if hasattr(lockfile, 'mksymlinkto'):
56 lockfile.mksymlinkto(str(mypid))
57 else:
58 lockfile.write(str(mypid))
59 def try_remove_lockfile():
60 # in a fork() situation, only the last process should
61 # remove the .lock, otherwise the other processes run the
62 # risk of seeing their temporary dir disappear. For now
63 # we remove the .lock in the parent only (i.e. we assume
64 # that the children finish before the parent).
65 if os.getpid() != mypid:
66 return
67 try:
68 lockfile.remove()
69 except py.error.Error:
70 pass
71 atexit.register(try_remove_lockfile)
72
73 # prune old directories
74 if keep:
75 for path in rootdir.listdir():
76 num = parse_num(path)
77 if num is not None and num <= (maxnum - keep):
78 if min_timeout:
79 # NB: doing this is needed to prevent (or reduce
80 # a lot the chance of) the following situation:
81 # 'keep+1' processes call make_numbered_dir() at
82 # the same time, they create dirs, but then the
83 # last process notices the first dir doesn't have
84 # (yet) a .lock in it and kills it.
85 try:
86 t1 = path.lstat().mtime
87 t2 = lockfile.lstat().mtime
88 if abs(t2-t1) < min_timeout:
89 continue # skip directories too recent
90 except py.error.Error:
91 continue # failure to get a time, better skip
92 lf = path.join('.lock')
93 try:
94 t1 = lf.lstat().mtime
95 t2 = lockfile.lstat().mtime
96 if not lock_timeout or abs(t2-t1) < lock_timeout:
97 continue # skip directories still locked
98 except py.error.Error:
99 pass # assume that it means that there is no 'lf'
100 try:
101 path.remove(rec=1)
102 except KeyboardInterrupt:
103 raise
104 except: # this might be py.error.Error, WindowsError ...
105 pass
106
107 # make link...
108 try:
109 username = os.environ['USER'] #linux, et al
110 except KeyError:
111 try:
112 username = os.environ['USERNAME'] #windows
113 except KeyError:
114 username = 'current'
115
116 src = str(udir)
117 dest = src[:src.rfind('-')] + '-' + username
118 try:
119 os.unlink(dest)
120 except OSError:
121 pass
122 try:
123 os.symlink(src, dest)
124 except (OSError, AttributeError, NotImplementedError):
125 pass
126
127 return udir
128
129
130 udir = make_numbered_dir(prefix = 'ffi-')
4131
5132
6133 # Windows-only workaround for some configurations: see