Codebase list python-cffi-py2 / 0dd18177-ef34-4976-84ae-a17e8dedcf5b/upstream
Import upstream version 1.14.6 Kali Janitor 2 years ago
46 changed file(s) with 1315 addition(s) and 288 deletion(s). Raw diff Collapse all Expand all
0 Metadata-Version: 1.1
0 Metadata-Version: 2.1
11 Name: cffi
2 Version: 1.14.0
2 Version: 1.14.6
33 Summary: Foreign Function Interface for Python calling C code.
44 Home-page: http://cffi.readthedocs.org
55 Author: Armin Rigo, Maciej Fijalkowski
66 Author-email: [email protected]
77 License: MIT
8 Description:
9 CFFI
10 ====
11
12 Foreign Function Interface for Python calling C code.
13 Please see the `Documentation <http://cffi.readthedocs.org/>`_.
14
15 Contact
16 -------
17
18 `Mailing list <https://groups.google.com/forum/#!forum/python-cffi>`_
19
208 Platform: UNKNOWN
219 Classifier: Programming Language :: Python
2210 Classifier: Programming Language :: Python :: 2
3119 Classifier: Programming Language :: Python :: Implementation :: CPython
3220 Classifier: Programming Language :: Python :: Implementation :: PyPy
3321 Classifier: License :: OSI Approved :: MIT License
22 License-File: LICENSE
23
24
25 CFFI
26 ====
27
28 Foreign Function Interface for Python calling C code.
29 Please see the `Documentation <http://cffi.readthedocs.org/>`_.
30
31 Contact
32 -------
33
34 `Mailing list <https://groups.google.com/forum/#!forum/python-cffi>`_
35
36
11 #include <Python.h>
22 #include "structmember.h"
33
4 #define CFFI_VERSION "1.14.0"
4 #define CFFI_VERSION "1.14.6"
55
66 #ifdef MS_WIN32
77 #include <windows.h>
7979 * That sounds like a horribly bad idea to me, and is the reason for why
8080 * I prefer CFFI crashing cleanly.
8181 *
82 * Currently, we use libffi's ffi_closure_alloc() only on NetBSD. It is
82 * Currently, we use libffi's ffi_closure_alloc() on NetBSD. It is
8383 * known that on the NetBSD kernel, a different strategy is used which
8484 * should not be open to the fork() bug.
85 *
86 * This is also used on macOS, provided we are executing on macOS 10.15 or
87 * above. It's a mess because it needs runtime checks in that case.
8588 */
8689 #ifdef __NetBSD__
87 # define CFFI_TRUST_LIBFFI
90
91 # define CFFI_CHECK_FFI_CLOSURE_ALLOC 1
92 # define CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE 1
93 # define CFFI_CHECK_FFI_PREP_CLOSURE_LOC 1
94 # define CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE 1
95 # define CFFI_CHECK_FFI_PREP_CIF_VAR 0
96 # define CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE 0
97
98 #elif defined(__APPLE__) && defined(FFI_AVAILABLE_APPLE)
99
100 # define CFFI_CHECK_FFI_CLOSURE_ALLOC __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
101 # define CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE 1
102 # define CFFI_CHECK_FFI_PREP_CLOSURE_LOC __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
103 # define CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE 1
104 # define CFFI_CHECK_FFI_PREP_CIF_VAR __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)
105 # define CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE 1
106
107 #else
108
109 # define CFFI_CHECK_FFI_CLOSURE_ALLOC 0
110 # define CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE 0
111 # define CFFI_CHECK_FFI_PREP_CLOSURE_LOC 0
112 # define CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE 0
113 # define CFFI_CHECK_FFI_PREP_CIF_VAR 0
114 # define CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE 0
115
88116 #endif
89117
90 #ifndef CFFI_TRUST_LIBFFI
91 # include "malloc_closure.h"
92 #endif
118 /* always includes this, even if it turns out not to be used on NetBSD
119 because calls are behind "if (0)" */
120 #include "malloc_closure.h"
93121
94122
95123 #if PY_MAJOR_VERSION >= 3
147175 (PyCObject_FromVoidPtr(pointer, destructor))
148176 #endif
149177
178 #if PY_VERSION_HEX < 0x030900a4
179 # define Py_SET_REFCNT(obj, val) (Py_REFCNT(obj) = (val))
180 #endif
181
182 #if PY_VERSION_HEX >= 0x03080000
183 # define USE_WRITEUNRAISABLEMSG
184 #endif
185
150186 /************************************************************/
151187
152188 /* base type flag: exactly one of the following: */
403439
404440 if (ct->ct_unique_key != NULL) {
405441 /* revive dead object temporarily for DelItem */
406 Py_REFCNT(ct) = 43;
442 Py_SET_REFCNT(ct, 43);
407443 PyDict_DelItem(unique_cache, ct->ct_unique_key);
408444 assert(Py_REFCNT(ct) == 42);
409 Py_REFCNT(ct) = 0;
445 Py_SET_REFCNT(ct, 0);
410446 Py_DECREF(ct->ct_unique_key);
411447 }
412448 Py_XDECREF(ct->ct_itemdescr);
652688
653689 static PyTypeObject CTypeDescr_Type = {
654690 PyVarObject_HEAD_INIT(NULL, 0)
655 "_cffi_backend.CTypeDescr",
691 "_cffi_backend.CType",
656692 offsetof(CTypeDescrObject, ct_name),
657693 sizeof(char),
658694 (destructor)ctypedescr_dealloc, /* tp_dealloc */
18851921 ffi_closure *closure = ((CDataObject_closure *)cd)->closure;
18861922 PyObject *args = (PyObject *)(closure->user_data);
18871923 Py_XDECREF(args);
1888 #ifdef CFFI_TRUST_LIBFFI
1889 ffi_closure_free(closure);
1890 #else
1891 cffi_closure_free(closure);
1924 #if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE
1925 if (CFFI_CHECK_FFI_CLOSURE_ALLOC) {
1926 ffi_closure_free(closure);
1927 } else
18921928 #endif
1929 cffi_closure_free(closure);
18931930 }
18941931 else {
18951932 Py_FatalError("cdata CDataOwningGC_Type with unexpected type flags");
28872924 convert_struct_to_owning_object(char *data, CTypeDescrObject *ct); /*forward*/
28882925
28892926 static cif_description_t *
2890 fb_prepare_cif(PyObject *fargs, CTypeDescrObject *, ffi_abi); /*forward*/
2927 fb_prepare_cif(PyObject *fargs, CTypeDescrObject *, Py_ssize_t, ffi_abi);
2928 /*forward*/
28912929
28922930 static PyObject *new_primitive_type(const char *name); /*forward*/
28932931
30803118 #else
30813119 fabi = PyLong_AS_LONG(PyTuple_GET_ITEM(signature, 0));
30823120 #endif
3083 cif_descr = fb_prepare_cif(fvarargs, fresult, fabi);
3121 cif_descr = fb_prepare_cif(fvarargs, fresult, nargs_declared, fabi);
30843122 if (cif_descr == NULL)
30853123 goto error;
30863124 }
33533391
33543392 static PyTypeObject CData_Type = {
33553393 PyVarObject_HEAD_INIT(NULL, 0)
3356 "_cffi_backend.CData",
3394 "_cffi_backend._CDataBase",
33573395 sizeof(CDataObject),
33583396 0,
33593397 (destructor)cdata_dealloc, /* tp_dealloc */
33723410 (setattrofunc)cdata_setattro, /* tp_setattro */
33733411 0, /* tp_as_buffer */
33743412 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
3375 0, /* tp_doc */
3413 "The internal base type for CData objects. Use FFI.CData to access "
3414 "it. Always check with isinstance(): subtypes are sometimes returned "
3415 "on CPython, for performance reasons.", /* tp_doc */
33763416 0, /* tp_traverse */
33773417 0, /* tp_clear */
33783418 cdata_richcompare, /* tp_richcompare */
33953435
33963436 static PyTypeObject CDataOwning_Type = {
33973437 PyVarObject_HEAD_INIT(NULL, 0)
3398 "_cffi_backend.CDataOwn",
3438 "_cffi_backend.__CDataOwn",
33993439 sizeof(CDataObject),
34003440 0,
34013441 (destructor)cdataowning_dealloc, /* tp_dealloc */
34143454 0, /* inherited */ /* tp_setattro */
34153455 0, /* tp_as_buffer */
34163456 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
3417 0, /* tp_doc */
3457 "This is an internal subtype of _CDataBase for performance only on "
3458 "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */
34183459 0, /* tp_traverse */
34193460 0, /* tp_clear */
34203461 0, /* inherited */ /* tp_richcompare */
34373478
34383479 static PyTypeObject CDataOwningGC_Type = {
34393480 PyVarObject_HEAD_INIT(NULL, 0)
3440 "_cffi_backend.CDataOwnGC",
3481 "_cffi_backend.__CDataOwnGC",
34413482 sizeof(CDataObject_own_structptr),
34423483 0,
34433484 (destructor)cdataowninggc_dealloc, /* tp_dealloc */
34573498 0, /* tp_as_buffer */
34583499 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */
34593500 | Py_TPFLAGS_HAVE_GC,
3460 0, /* tp_doc */
3501 "This is an internal subtype of _CDataBase for performance only on "
3502 "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */
34613503 (traverseproc)cdataowninggc_traverse, /* tp_traverse */
34623504 (inquiry)cdataowninggc_clear, /* tp_clear */
34633505 0, /* inherited */ /* tp_richcompare */
34803522
34813523 static PyTypeObject CDataFromBuf_Type = {
34823524 PyVarObject_HEAD_INIT(NULL, 0)
3483 "_cffi_backend.CDataFromBuf",
3525 "_cffi_backend.__CDataFromBuf",
34843526 sizeof(CDataObject_frombuf),
34853527 0,
34863528 (destructor)cdatafrombuf_dealloc, /* tp_dealloc */
35003542 0, /* tp_as_buffer */
35013543 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */
35023544 | Py_TPFLAGS_HAVE_GC,
3503 0, /* tp_doc */
3545 "This is an internal subtype of _CDataBase for performance only on "
3546 "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */
35043547 (traverseproc)cdatafrombuf_traverse, /* tp_traverse */
35053548 (inquiry)cdatafrombuf_clear, /* tp_clear */
35063549 0, /* inherited */ /* tp_richcompare */
35233566
35243567 static PyTypeObject CDataGCP_Type = {
35253568 PyVarObject_HEAD_INIT(NULL, 0)
3526 "_cffi_backend.CDataGCP",
3569 "_cffi_backend.__CDataGCP",
35273570 sizeof(CDataObject_gcp),
35283571 0,
35293572 (destructor)cdatagcp_dealloc, /* tp_dealloc */
35463589 | Py_TPFLAGS_HAVE_FINALIZE
35473590 #endif
35483591 | Py_TPFLAGS_HAVE_GC,
3549 0, /* tp_doc */
3592 "This is an internal subtype of _CDataBase for performance only on "
3593 "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */
35503594 (traverseproc)cdatagcp_traverse, /* tp_traverse */
35513595 0, /* tp_clear */
35523596 0, /* inherited */ /* tp_richcompare */
36073651
36083652 static PyTypeObject CDataIter_Type = {
36093653 PyVarObject_HEAD_INIT(NULL, 0)
3610 "_cffi_backend.CDataIter", /* tp_name */
3654 "_cffi_backend.__CData_iterator", /* tp_name */
36113655 sizeof(CDataIterObject), /* tp_basicsize */
36123656 0, /* tp_itemsize */
36133657 /* methods */
43624406
43634407 static PyTypeObject dl_type = {
43644408 PyVarObject_HEAD_INIT(NULL, 0)
4365 "_cffi_backend.Library", /* tp_name */
4409 "_cffi_backend.CLibrary", /* tp_name */
43664410 sizeof(DynLibObject), /* tp_basicsize */
43674411 0, /* tp_itemsize */
43684412 /* methods */
44404484 {
44414485 PyObject *s = PyTuple_GET_ITEM(args, 0);
44424486 #ifdef MS_WIN32
4443 Py_UNICODE *filenameW;
4444 if (PyArg_ParseTuple(args, "u|i:load_library", &filenameW, &flags))
4487 PyObject *filename_unicode;
4488 if (PyArg_ParseTuple(args, "U|i:load_library", &filename_unicode, &flags))
44454489 {
4490 Py_ssize_t sz1;
4491 wchar_t *w1;
44464492 #if PY_MAJOR_VERSION < 3
44474493 s = PyUnicode_AsUTF8String(s);
44484494 if (s == NULL)
44534499 if (*p_printable_filename == NULL)
44544500 return NULL;
44554501
4456 handle = dlopenW(filenameW);
4502 sz1 = PyUnicode_GetSize(filename_unicode) + 1;
4503 sz1 *= 2; /* should not be needed, but you never know */
4504 w1 = alloca(sizeof(wchar_t) * sz1);
4505 sz1 = PyUnicode_AsWideChar((PyUnicodeObject *)filename_unicode,
4506 w1, sz1 - 1);
4507 if (sz1 < 0)
4508 return NULL;
4509 w1[sz1] = 0;
4510 handle = dlopenW(w1);
44574511 goto got_handle;
44584512 }
44594513 PyErr_Clear();
44654519 if (PyUnicode_Check(s))
44664520 {
44674521 s = PyUnicode_AsUTF8String(s);
4468 if (s == NULL)
4522 if (s == NULL) {
4523 PyMem_Free(filename_or_null);
44694524 return NULL;
4525 }
44704526 *p_temp = s;
44714527 }
44724528 #endif
44734529 *p_printable_filename = PyText_AsUTF8(s);
4474 if (*p_printable_filename == NULL)
4530 if (*p_printable_filename == NULL) {
4531 PyMem_Free(filename_or_null);
44754532 return NULL;
4533 }
44764534 }
44774535 if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0)
44784536 flags |= RTLD_NOW;
44794537
4538 #ifdef MS_WIN32
4539 if (filename_or_null == NULL) {
4540 PyErr_SetString(PyExc_OSError, "dlopen(None) not supported on Windows");
4541 return NULL;
4542 }
4543 #endif
4544
44804545 handle = dlopen(filename_or_null, flags);
4546 PyMem_Free(filename_or_null);
44814547
44824548 #ifdef MS_WIN32
44834549 got_handle:
49945060 #ifdef MS_WIN32
49955061 sflags |= SF_MSVC_BITFIELDS;
49965062 #else
4997 # if defined(__arm__) || defined(__aarch64__)
5063 # if defined(__APPLE__) && defined(__arm64__)
5064 sflags |= SF_GCC_X86_BITFIELDS;
5065 # elif defined(__arm__) || defined(__aarch64__)
49985066 sflags |= SF_GCC_ARM_BITFIELDS;
49995067 # else
50005068 sflags |= SF_GCC_X86_BITFIELDS;
57825850
57835851 static cif_description_t *fb_prepare_cif(PyObject *fargs,
57845852 CTypeDescrObject *fresult,
5853 Py_ssize_t variadic_nargs_declared,
57855854 ffi_abi fabi)
5855
57865856 {
57875857 char *buffer;
57885858 cif_description_t *cif_descr;
57895859 struct funcbuilder_s funcbuffer;
5860 ffi_status status = (ffi_status)-1;
57905861
57915862 funcbuffer.nb_bytes = 0;
57925863 funcbuffer.bufferp = NULL;
58095880 assert(funcbuffer.bufferp == buffer + funcbuffer.nb_bytes);
58105881
58115882 cif_descr = (cif_description_t *)buffer;
5812 if (ffi_prep_cif(&cif_descr->cif, fabi, funcbuffer.nargs,
5813 funcbuffer.rtype, funcbuffer.atypes) != FFI_OK) {
5883
5884 /* use `ffi_prep_cif_var` if necessary and available */
5885 #if CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE
5886 if (variadic_nargs_declared >= 0) {
5887 if (CFFI_CHECK_FFI_PREP_CIF_VAR) {
5888 status = ffi_prep_cif_var(&cif_descr->cif, fabi,
5889 variadic_nargs_declared, funcbuffer.nargs,
5890 funcbuffer.rtype, funcbuffer.atypes);
5891 }
5892 }
5893 #endif
5894
5895 if (status == (ffi_status)-1) {
5896 status = ffi_prep_cif(&cif_descr->cif, fabi, funcbuffer.nargs,
5897 funcbuffer.rtype, funcbuffer.atypes);
5898 }
5899
5900 if (status != FFI_OK) {
58145901 PyErr_SetString(PyExc_SystemError,
58155902 "libffi failed to build this function type");
58165903 goto error;
58545941 is computed here. */
58555942 cif_description_t *cif_descr;
58565943
5857 cif_descr = fb_prepare_cif(fargs, fresult, fabi);
5944 cif_descr = fb_prepare_cif(fargs, fresult, -1, fabi);
58585945 if (cif_descr == NULL) {
58595946 if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
58605947 PyErr_Clear(); /* will get the exception if we see an
59826069 char *extra_error_line)
59836070 {
59846071 /* like PyErr_WriteUnraisable(), but write a full traceback */
6072 #ifdef USE_WRITEUNRAISABLEMSG
6073
6074 /* PyErr_WriteUnraisable actually writes the full traceback anyway
6075 from Python 3.4, but we can't really get the formatting of the
6076 custom text to be what we want. We can do better from Python
6077 3.8 by calling the new _PyErr_WriteUnraisableMsg().
6078 Luckily it's also Python 3.8 that adds new functionality that
6079 people might want: the new sys.unraisablehook().
6080 */
6081 PyObject *s;
6082 int first_char;
6083 assert(objdescr != NULL && objdescr[0] != 0); /* non-empty */
6084 first_char = objdescr[0];
6085 if (first_char >= 'A' && first_char <= 'Z')
6086 first_char += 'a' - 'A'; /* lower() the very first character */
6087 if (extra_error_line == NULL)
6088 extra_error_line = "";
6089
6090 if (obj != NULL)
6091 s = PyUnicode_FromFormat("%c%s%R%s",
6092 first_char, objdescr + 1, obj, extra_error_line);
6093 else
6094 s = PyUnicode_FromFormat("%c%s%s",
6095 first_char, objdescr + 1, extra_error_line);
6096
6097 PyErr_Restore(t, v, tb);
6098 if (s != NULL) {
6099 _PyErr_WriteUnraisableMsg(PyText_AS_UTF8(s), NULL);
6100 Py_DECREF(s);
6101 }
6102 else
6103 PyErr_WriteUnraisable(obj); /* best effort */
6104 PyErr_Clear();
6105
6106 #else
6107
6108 /* version for Python 2.7 and < 3.8 */
59856109 PyObject *f;
59866110 #if PY_MAJOR_VERSION >= 3
59876111 /* jump through hoops to ensure the tb is attached to v, on Python 3 */
60066130 Py_XDECREF(t);
60076131 Py_XDECREF(v);
60086132 Py_XDECREF(tb);
6133
6134 #endif
60096135 }
60106136
60116137 static void general_invoke_callback(int decode_args_from_libffi,
60556181 goto error;
60566182 if (convert_from_object_fficallback(result, SIGNATURE(1), py_res,
60576183 decode_args_from_libffi) < 0) {
6184 #ifdef USE_WRITEUNRAISABLEMSG
6185 extra_error_line = ", trying to convert the result back to C";
6186 #else
60586187 extra_error_line = "Trying to convert the result back to C:\n";
6188 #endif
60596189 goto error;
60606190 }
60616191 done:
61076237 _my_PyErr_WriteUnraisable(exc1, val1, tb1,
61086238 "From cffi callback ", py_ob,
61096239 extra_error_line);
6240 #ifdef USE_WRITEUNRAISABLEMSG
6241 _my_PyErr_WriteUnraisable(exc2, val2, tb2,
6242 "during handling of the above exception by 'onerror'",
6243 NULL, NULL);
6244 #else
61106245 extra_error_line = ("\nDuring the call to 'onerror', "
61116246 "another exception occurred:\n\n");
61126247 _my_PyErr_WriteUnraisable(exc2, val2, tb2,
61136248 NULL, NULL, extra_error_line);
6249 #endif
61146250 _cffi_stop_error_capture(ecap);
61156251 }
61166252 }
61786314 infotuple = Py_BuildValue("OOOO", ct, ob, py_rawerr, onerror_ob);
61796315 Py_DECREF(py_rawerr);
61806316
6181 #ifdef WITH_THREAD
6317 #if defined(WITH_THREAD) && PY_VERSION_HEX < 0x03070000
61826318 /* 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. */
6319 some other non-Pythonic thread. This is the same as ctypes.
6320 But PyEval_InitThreads() is always a no-op from CPython 3.7
6321 (the call from ctypes was removed some time later I think). */
61846322 PyEval_InitThreads();
61856323 #endif
61866324
61876325 return infotuple;
61886326 }
61896327
6328 /* messily try to silence a gcc/clang deprecation warning for
6329 ffi_prep_closure. Don't miss the "pragma pop" after the function.
6330 This is done around the whole function because very old GCCs don't
6331 support it inside a function. */
6332 #if defined(__clang__)
6333 # pragma clang diagnostic push
6334 # pragma clang diagnostic ignored "-Wdeprecated-declarations"
6335 #elif defined(__GNUC__)
6336 # pragma GCC diagnostic push
6337 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
6338 #endif
61906339 static PyObject *b_callback(PyObject *self, PyObject *args)
61916340 {
61926341 CTypeDescrObject *ct;
61956344 PyObject *infotuple;
61966345 cif_description_t *cif_descr;
61976346 ffi_closure *closure;
6347 ffi_status status;
61986348 void *closure_exec;
61996349
62006350 if (!PyArg_ParseTuple(args, "O!O|OO:callback", &CTypeDescr_Type, &ct, &ob,
62056355 if (infotuple == NULL)
62066356 return NULL;
62076357
6208 #ifdef CFFI_TRUST_LIBFFI
6209 closure = ffi_closure_alloc(sizeof(ffi_closure), &closure_exec);
6210 #else
6211 closure = cffi_closure_alloc();
6212 closure_exec = closure;
6358 #if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE
6359 if (CFFI_CHECK_FFI_CLOSURE_ALLOC) {
6360 closure = ffi_closure_alloc(sizeof(ffi_closure), &closure_exec);
6361 } else
62136362 #endif
6363 {
6364 closure = cffi_closure_alloc();
6365 closure_exec = closure;
6366 }
6367
62146368 if (closure == NULL) {
62156369 Py_DECREF(infotuple);
62166370 PyErr_SetString(PyExc_MemoryError,
62276381 cd->head.c_type = ct;
62286382 cd->head.c_data = (char *)closure_exec;
62296383 cd->head.c_weakreflist = NULL;
6384 closure->user_data = NULL;
62306385 cd->closure = closure;
6231 PyObject_GC_Track(cd);
62326386
62336387 cif_descr = (cif_description_t *)ct->ct_extra;
62346388 if (cif_descr == NULL) {
62376391 "return type or with '...'", ct->ct_name);
62386392 goto error;
62396393 }
6240 #ifdef CFFI_TRUST_LIBFFI
6241 if (ffi_prep_closure_loc(closure, &cif_descr->cif,
6242 invoke_callback, infotuple, closure_exec) != FFI_OK) {
6394
6395 #if CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE
6396 if (CFFI_CHECK_FFI_PREP_CLOSURE_LOC) {
6397 status = ffi_prep_closure_loc(closure, &cif_descr->cif,
6398 invoke_callback, infotuple, closure_exec);
6399 }
6400 else
6401 #endif
6402 {
6403 #if defined(__APPLE__) && defined(FFI_AVAILABLE_APPLE) && !FFI_LEGACY_CLOSURE_API
6404 PyErr_Format(PyExc_SystemError, "ffi_prep_closure_loc() is missing");
6405 goto error;
62436406 #else
6244 if (ffi_prep_closure(closure, &cif_descr->cif,
6245 invoke_callback, infotuple) != FFI_OK) {
6407 status = ffi_prep_closure(closure, &cif_descr->cif,
6408 invoke_callback, infotuple);
62466409 #endif
6410 }
6411
6412 if (status != FFI_OK) {
62476413 PyErr_SetString(PyExc_SystemError,
62486414 "libffi failed to build this callback");
62496415 goto error;
62506416 }
6417
62516418 if (closure->user_data != infotuple) {
62526419 /* Issue #266. Should not occur, but could, if we are using
62536420 at runtime a version of libffi compiled with a different
62626429 "different from the 'ffi.h' file seen at compile-time)");
62636430 goto error;
62646431 }
6432 PyObject_GC_Track(cd);
62656433 return (PyObject *)cd;
62666434
62676435 error:
62686436 closure->user_data = NULL;
62696437 if (cd == NULL) {
6270 #ifdef CFFI_TRUST_LIBFFI
6271 ffi_closure_free(closure);
6272 #else
6273 cffi_closure_free(closure);
6438 #if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE
6439 if (CFFI_CHECK_FFI_CLOSURE_ALLOC) {
6440 ffi_closure_free(closure);
6441 }
6442 else
62746443 #endif
6444 cffi_closure_free(closure);
62756445 }
62766446 else
62776447 Py_DECREF(cd);
62786448 Py_XDECREF(infotuple);
62796449 return NULL;
62806450 }
6451 #if defined(__clang__)
6452 # pragma clang diagnostic pop
6453 #elif defined(__GNUC__)
6454 # pragma GCC diagnostic pop
6455 #endif
62816456
62826457 static PyObject *b_new_enum_type(PyObject *self, PyObject *args)
62836458 {
77877962 PyObject *m, *v;
77887963 int i;
77897964 static char init_done = 0;
7965 static PyTypeObject *all_types[] = {
7966 &dl_type,
7967 &CTypeDescr_Type,
7968 &CField_Type,
7969 &CData_Type,
7970 &CDataOwning_Type,
7971 &CDataOwningGC_Type,
7972 &CDataFromBuf_Type,
7973 &CDataGCP_Type,
7974 &CDataIter_Type,
7975 &MiniBuffer_Type,
7976 &FFI_Type,
7977 &Lib_Type,
7978 &GlobSupport_Type,
7979 NULL
7980 };
77907981
77917982 v = PySys_GetObject("version");
77927983 if (v == NULL || !PyText_Check(v) ||
78128003 INITERROR;
78138004 }
78148005
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;
8006 /* readify all types and add them to the module */
8007 for (i = 0; all_types[i] != NULL; i++) {
8008 PyTypeObject *tp = all_types[i];
8009 PyObject *tpo = (PyObject *)tp;
8010 if (strncmp(tp->tp_name, "_cffi_backend.", 14) != 0) {
8011 PyErr_Format(PyExc_ImportError,
8012 "'%s' is an ill-formed type name", tp->tp_name);
8013 INITERROR;
8014 }
8015 if (PyType_Ready(tp) < 0)
8016 INITERROR;
8017
8018 Py_INCREF(tpo);
8019 if (PyModule_AddObject(m, tp->tp_name + 14, tpo) < 0)
8020 INITERROR;
8021 }
78358022
78368023 if (!init_done) {
78378024 v = PyText_FromString("_cffi_backend");
78778064 INITERROR;
78788065 }
78798066
7880 Py_INCREF(&MiniBuffer_Type);
7881 if (PyModule_AddObject(m, "buffer", (PyObject *)&MiniBuffer_Type) < 0)
7882 INITERROR;
7883
78848067 init_cffi_tls();
78858068 if (PyErr_Occurred())
78868069 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 */
10691069 if (res != NULL) {
10701070 tup = PyTuple_Pack(2, Py_True, res);
10711071 if (tup == NULL || PyDict_SetItem(cache, tag, tup) < 0) {
1072 Py_XDECREF(tup);
10731072 Py_DECREF(res);
10741073 res = NULL;
10751074 }
1075 Py_XDECREF(tup);
10761076 }
10771077 }
10781078
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.6", ("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>"
13251330 except ImportError:
13261331 import io as cStringIO # Python 3
13271332 import linecache
1328 def matches(istr, ipattern):
1333 def matches(istr, ipattern, ipattern38):
1334 if sys.version_info >= (3, 8):
1335 ipattern = ipattern38
13291336 str, pattern = istr, ipattern
13301337 while '$' in pattern:
13311338 i = pattern.index('$')
13581365 try:
13591366 linecache.getline = lambda *args: 'LINE' # hack: speed up PyPy tests
13601367 sys.stderr = cStringIO.StringIO()
1368 if hasattr(sys, '__unraisablehook__'): # work around pytest
1369 sys.unraisablehook = sys.__unraisablehook__ # on recent CPythons
13611370 assert f(100) == 300
13621371 assert sys.stderr.getvalue() == ''
13631372 assert f(10000) == -42
13641373 assert matches(sys.stderr.getvalue(), """\
13651374 From cffi callback <function$Zcb1 at 0x$>:
1375 Traceback (most recent call last):
1376 File "$", line $, in Zcb1
1377 $
1378 File "$", line $, in check_value
1379 $
1380 ValueError: 42
1381 """, """\
1382 Exception ignored from cffi callback <function$Zcb1 at 0x$>:
13661383 Traceback (most recent call last):
13671384 File "$", line $, in Zcb1
13681385 $
13761393 assert matches(sys.stderr.getvalue(), """\
13771394 From cffi callback <function$Zcb1 at 0x$>:
13781395 Trying to convert the result back to C:
1396 OverflowError: integer 60000 does not fit 'short'
1397 """, """\
1398 Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C:
1399 Traceback (most recent call last):
1400 File "$", line $, in test_callback_exception
1401 $
13791402 OverflowError: integer 60000 does not fit 'short'
13801403 """)
13811404 sys.stderr = cStringIO.StringIO()
14141437 During the call to 'onerror', another exception occurred:
14151438
14161439 TypeError: $integer$
1440 """, """\
1441 Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C:
1442 Traceback (most recent call last):
1443 File "$", line $, in test_callback_exception
1444 $
1445 OverflowError: integer 60000 does not fit 'short'
1446 Exception ignored during handling of the above exception by 'onerror':
1447 Traceback (most recent call last):
1448 File "$", line $, in test_callback_exception
1449 $
1450 TypeError: $integer$
14171451 """)
14181452 #
14191453 sys.stderr = cStringIO.StringIO()
14201454 seen = "not a list" # this makes the oops() function crash
14211455 assert ff(bigvalue) == -42
1456 # the $ after the AttributeError message are for the suggestions that
1457 # will be added in Python 3.10
14221458 assert matches(sys.stderr.getvalue(), """\
14231459 From cffi callback <function$Zcb1 at 0x$>:
14241460 Trying to convert the result back to C:
14291465 Traceback (most recent call last):
14301466 File "$", line $, in oops
14311467 $
1432 AttributeError: 'str' object has no attribute 'append'
1468 AttributeError: 'str' object has no attribute 'append$
1469 """, """\
1470 Exception ignored from cffi callback <function$Zcb1 at 0x$>, trying to convert the result back to C:
1471 Traceback (most recent call last):
1472 File "$", line $, in test_callback_exception
1473 $
1474 OverflowError: integer 60000 does not fit 'short'
1475 Exception ignored during handling of the above exception by 'onerror':
1476 Traceback (most recent call last):
1477 File "$", line $, in oops
1478 $
1479 AttributeError: 'str' object has no attribute 'append$
14331480 """)
14341481 finally:
14351482 sys.stderr = orig_stderr
14641511 def make_callback(m):
14651512 def cb(n):
14661513 return n + m
1467 return callback(BFunc, cb, 42) # 'cb' and 'BFunc' go out of scope
1514 return callback(BFunc, cb, 42) # 'cb' goes out of scope
14681515 #
14691516 flist = [make_callback(i) for i in range(BIGNUM)]
14701517 for i, f in enumerate(flist):
25472594 assert get_errno() == 95
25482595
25492596 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")
2597 if globals().get('PY_DOT_PY'):
2598 py.test.skip("cannot run this test on py.py (e.g. fails on Windows)")
25522599 set_errno(95)
25532600 def cb():
25542601 e = get_errno()
39674014 pv = from_buffer(BVarStructP, bytestring) # make a fresh one
39684015 with pytest.raises(ValueError):
39694016 release(pv[0])
4017
4018 def test_issue483():
4019 BInt = new_primitive_type("int")
4020 BIntP = new_pointer_type(BInt)
4021 BIntA = new_array_type(BIntP, None)
4022 lst = list(range(25))
4023 bytestring = bytearray(buffer(newp(BIntA, lst))[:] + b'XYZ')
4024 p1 = from_buffer(BIntA, bytestring) # int[]
4025 assert len(buffer(p1)) == 25 * size_of_int()
4026 assert sizeof(p1) == 25 * size_of_int()
4027 #
4028 p2 = from_buffer(BIntP, bytestring)
4029 assert sizeof(p2) == size_of_ptr()
4030 assert len(buffer(p2)) == size_of_int() # first element only, by default
39704031
39714032 def test_memmove():
39724033 Short = new_primitive_type("short")
44524513 BStruct = new_struct_type("struct foo")
44534514 complete_struct_or_union(BStruct, [('a1', BArray, -1)])
44544515 assert sizeof(BStruct) == sys.maxsize
4516
4517 def test_get_types():
4518 import _cffi_backend
4519 CData, CType = _get_types()
4520 assert CData is _cffi_backend._CDataBase
4521 assert CType is _cffi_backend.CType
4522
4523 def test_type_available_with_correct_names():
4524 import _cffi_backend
4525 check_names = [
4526 'CType',
4527 'CField',
4528 'CLibrary',
4529 '_CDataBase',
4530 'FFI',
4531 'Lib',
4532 'buffer',
4533 ]
4534 if '__pypy__' in sys.builtin_module_names:
4535 check_names += [
4536 '__CData_iterator',
4537 '__FFIGlobSupport',
4538 '__FFIAllocator',
4539 '__FFIFunctionWrapper',
4540 ]
4541 else:
4542 check_names += [
4543 '__CDataOwn',
4544 '__CDataOwnGC',
4545 '__CDataFromBuf',
4546 '__CDataGCP',
4547 '__CData_iterator',
4548 '__FFIGlobSupport',
4549 ]
4550 for name in check_names:
4551 tp = getattr(_cffi_backend, name)
4552 assert isinstance(tp, type)
4553 assert (tp.__module__, tp.__name__) == ('_cffi_backend', name)
4554
4555 def test_unaligned_types():
4556 BByteArray = new_array_type(
4557 new_pointer_type(new_primitive_type("unsigned char")), None)
4558 pbuf = newp(BByteArray, 40)
4559 buf = buffer(pbuf)
4560 #
4561 for name in ['short', 'int', 'long', 'long long', 'float', 'double',
4562 'float _Complex', 'double _Complex']:
4563 p = new_primitive_type(name)
4564 if name.endswith(' _Complex'):
4565 num = cast(p, 1.23 - 4.56j)
4566 else:
4567 num = cast(p, 0x0123456789abcdef)
4568 size = sizeof(p)
4569 buf[0:40] = b"\x00" * 40
4570 pbuf1 = cast(new_pointer_type(p), pbuf + 1)
4571 pbuf1[0] = num
4572 assert pbuf1[0] == num
4573 assert buf[0] == b'\x00'
4574 assert buf[1 + size] == b'\x00'
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.6"
8 __version_info__ = (1, 14, 6)
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__
5353 " of.write(x)\n"
5454 " except: pass\n"
5555 " self.buf += x\n"
56 " def flush(self):\n"
57 " pass\n"
5658 "fl = FileLike()\n"
5759 "fl.buf = ''\n"
5860 "of = sys.stderr\n"
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.6"
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:
189192 assert isinstance(op, CffiOp)
190193 self.cffi_types = tuple(self.cffi_types) # don't change any more
191194
195 def _enum_fields(self, tp):
196 # When producing C, expand all anonymous struct/union fields.
197 # That's necessary to have C code checking the offsets of the
198 # individual fields contained in them. When producing Python,
199 # don't do it and instead write it like it is, with the
200 # corresponding fields having an empty name. Empty names are
201 # recognized at runtime when we import the generated Python
202 # file.
203 expand_anonymous_struct_union = not self.target_is_python
204 return tp.enumfields(expand_anonymous_struct_union)
205
192206 def _do_collect_type(self, tp):
193207 if not isinstance(tp, model.BaseTypeByIdentity):
194208 if isinstance(tp, tuple):
202216 elif isinstance(tp, model.StructOrUnion):
203217 if tp.fldtypes is not None and (
204218 tp not in self.ffi._parser._included_declarations):
205 for name1, tp1, _, _ in tp.enumfields():
219 for name1, tp1, _, _ in self._enum_fields(tp):
206220 self._do_collect_type(self._field_type(tp, name1, tp1))
207221 else:
208222 for _, x in tp._get_items():
282296 prnt = self._prnt
283297 if self.ffi._embedding is not None:
284298 prnt('#define _CFFI_USE_EMBEDDING')
299 if not USE_LIMITED_API:
300 prnt('#define _CFFI_NO_LIMITED_API')
285301 #
286302 # first the '#include' (actually done by inlining the file's content)
287303 lines = self._rel_readlines('_cffi_include.h')
858874 prnt('{')
859875 prnt(' /* only to generate compile-time warnings or errors */')
860876 prnt(' (void)p;')
861 for fname, ftype, fbitsize, fqual in tp.enumfields():
877 for fname, ftype, fbitsize, fqual in self._enum_fields(tp):
862878 try:
863879 if ftype.is_integer_type() or fbitsize >= 0:
864880 # accept all integers, but complain on float or double
914930 flags = '|'.join(flags) or '0'
915931 c_fields = []
916932 if reason_for_not_expanding is None:
917 expand_anonymous_struct_union = not self.target_is_python
918 enumfields = list(tp.enumfields(expand_anonymous_struct_union))
933 enumfields = list(self._enum_fields(tp))
919934 for fldname, fldtype, fbitsize, fqual in enumfields:
920935 fldtype = self._field_type(tp, fldname, fldtype)
921936 self._check_not_opaque(fldtype,
12951310 def _print_string_literal_in_array(self, s):
12961311 prnt = self._prnt
12971312 prnt('// # NB. this is not a string because of a size limit in MSVC')
1313 if not isinstance(s, bytes): # unicode
1314 s = s.encode('utf-8') # -> bytes
1315 else:
1316 s.decode('utf-8') # got bytes, check for valid utf-8
1317 try:
1318 s.decode('ascii')
1319 except UnicodeDecodeError:
1320 s = b'# -*- encoding: utf8 -*-\n' + s
12981321 for line in s.splitlines(True):
1299 prnt(('// ' + line).rstrip())
1322 comment = line
1323 if type('//') is bytes: # python2
1324 line = map(ord, line) # make a list of integers
1325 else: # python3
1326 # type(line) is bytes, which enumerates like a list of integers
1327 comment = ascii(comment)[1:-1]
1328 prnt(('// ' + comment).rstrip())
13001329 printed_line = ''
13011330 for c in line:
13021331 if len(printed_line) >= 76:
13031332 prnt(printed_line)
13041333 printed_line = ''
1305 printed_line += '%d,' % (ord(c),)
1334 printed_line += '%d,' % (c,)
13061335 prnt(printed_line)
13071336
13081337 # ----------
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)
4949 if tag:
5050 raise TypeError("can't specify both 'modulename' and 'tag'")
5151 else:
52 key = '\x00'.join([sys.version[:3], __version_verifier_modules__,
52 key = '\x00'.join(['%d.%d' % sys.version_info[:2],
53 __version_verifier_modules__,
5354 preamble, flattened_kwds] +
5455 ffi._cdefsources)
5556 if sys.version_info >= (3,):
0 Metadata-Version: 1.1
0 Metadata-Version: 2.1
11 Name: cffi
2 Version: 1.14.0
2 Version: 1.14.6
33 Summary: Foreign Function Interface for Python calling C code.
44 Home-page: http://cffi.readthedocs.org
55 Author: Armin Rigo, Maciej Fijalkowski
66 Author-email: [email protected]
77 License: MIT
8 Description:
9 CFFI
10 ====
11
12 Foreign Function Interface for Python calling C code.
13 Please see the `Documentation <http://cffi.readthedocs.org/>`_.
14
15 Contact
16 -------
17
18 `Mailing list <https://groups.google.com/forum/#!forum/python-cffi>`_
19
208 Platform: UNKNOWN
219 Classifier: Programming Language :: Python
2210 Classifier: Programming Language :: Python :: 2
3119 Classifier: Programming Language :: Python :: Implementation :: CPython
3220 Classifier: Programming Language :: Python :: Implementation :: PyPy
3321 Classifier: License :: OSI Approved :: MIT License
22 License-File: LICENSE
23
24
25 CFFI
26 ====
27
28 Foreign Function Interface for Python calling C code.
29 Please see the `Documentation <http://cffi.readthedocs.org/>`_.
30
31 Contact
32 -------
33
34 `Mailing list <https://groups.google.com/forum/#!forum/python-cffi>`_
35
36
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.6'
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
5454 Comments and bugs
5555 -----------------
5656
57 The best way to contact us is on the IRC ``#pypy`` channel of
58 ``irc.freenode.net``. Feel free to discuss matters either there or in
57 The best way to contact us is on the IRC ``#cffi`` or ``#pypy`` channels of
58 ``irc.libera.chat``. Feel free to discuss matters either there or in
5959 the `mailing list`_. Please report to the `issue tracker`_ any bugs.
6060
6161 As a general rule, when there is a design issue to resolve, we pick the
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.6:
5555
5656 - MD5: ...
5757
58 - SHA: ...
58 - SHA1: ...
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 v1.14.6
5 =======
6
7 * Test fixes for CPython 3.10.0b3
8
9 * Support for `sys.unraisablehook()` on Python >= 3.8
10
11 * Fix two minor memory leaks (thanks Sebastian!)
12
13 * Like many projects that had an IRC channel on freenode, we moved it to
14 ``irc.libera.chat``.
15
16 v1.14.5
17 =======
18
19 * Source fix for old gcc versions
20
21 * This and future releases should include wheels on more platforms,
22 thanks to our new release managers Matt and Matt!
23
24 v1.14.4
25 =======
26
27 Release done for pip reasons.
28
29 v1.14.3
30 =======
31
32 Release done for pip reasons.
33
34 v1.14.2
35 =======
36
37 * CPython 3 on Windows: we again try to compile with ``Py_LIMITED_API``
38 by default. This flag is not added if you run the compilation with
39 CPython 3.4, as it only works with CPython >= 3.5, but by now this
40 version of Python is quite old (and we no longer distribute cffi
41 wheels for it).
42
43 This may require that you upgrade ``virtualenv`` (requires version 16
44 or newer) or at least copy manually ``python3.dll`` into your existing
45 virtualenvs. For distributing wheels with your cffi modules, you may
46 also need to upgrade ``wheel`` to the just-released version 0.35.
47
48 You can manually disable ``Py_LIMITED_API`` by calling
49 ``ffi.set_source(..., py_limited_api=False)``.
50
51
52 v1.14.1
53 =======
54
55 * CFFI source code is now `hosted on Heptapod`_.
56
57 * Improved support for ``typedef int my_array_t[...];`` with an explicit
58 dot-dot-dot in API mode (`issue #453`_)
59
60 * Windows (32 and 64 bits): multiple fixes for ABI-mode call to functions
61 that return a structure.
62
63 * Experimental support for MacOS 11 on aarch64.
64
65 * and a few other minor changes and bug fixes.
66
67 .. _`hosted on Heptapod`: https://foss.heptapod.net/pypy/cffi/
68 .. _`issue #453`: https://foss.heptapod.net/pypy/cffi/issues/453
369
470
571 v1.14
35101 * re-release because the Linux wheels came with an attached version of libffi
36102 that was very old and buggy (`issue #432`_).
37103
38 .. _`issue #432`: https://bitbucket.org/cffi/cffi/issues/432/
104 .. _`issue #432`: https://foss.heptapod.net/pypy/cffi/-/issues/432
39105
40106
41107
54120 * fixed `issue #427`_ where a multithreading mistake in the embedding logic
55121 initialization code would cause deadlocks on CPython 3.7.
56122
57 .. _`issue #429`: https://bitbucket.org/cffi/cffi/issues/429/
58 .. _`issue #427`: https://bitbucket.org/cffi/cffi/issues/427/
123 .. _`issue #429`: https://foss.heptapod.net/pypy/cffi/-/issues/429
124 .. _`issue #427`: https://foss.heptapod.net/pypy/cffi/-/issues/427
59125
60126
61127 v1.13
81147 recursion, with ``ffi.cdef("""struct X { void(*fnptr)(struct X); };""")``
82148
83149
150 Older Versions
151 ==============
152
84153 v1.12.3
85 =======
154 -------
86155
87156 * Fix for nested struct types that end in a var-sized array (#405).
88157
93162
94163
95164 v1.12.2
96 =======
165 -------
97166
98167 * Added temporary workaround to compile on CPython 3.8.0a2.
99168
100169
101170 v1.12.1
102 =======
171 -------
103172
104173 * CPython 3 on Windows: we again no longer compile with ``Py_LIMITED_API``
105174 by default because such modules *still* cannot be used with virtualenv.
115184
116185
117186 v1.12
118 =====
187 -----
119188
120189 * `Direct support for pkg-config`__.
121190
150219 to 1 byte instead of 4).
151220
152221 .. __: cdef.html#pkgconfig
153 .. _`issue #362`: https://bitbucket.org/cffi/cffi/issues/362/
154
155
156 Older Versions
157 ==============
222 .. _`issue #362`: https://foss.heptapod.net/pypy/cffi/-/issues/362
223
158224
159225 v1.11.5
160226 -------
185251 concerned about virtualenv: pass ``define_macros=[("Py_LIMITED_API",
186252 None)]`` as a keyword to the ``ffibuilder.set_source()`` call.
187253
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/
254 .. _`Issue #345`: https://foss.heptapod.net/pypy/cffi/-/issues/345
255 .. _`Issue #350`: https://foss.heptapod.net/pypy/cffi/-/issues/350
256 .. _`Issue #358`: https://foss.heptapod.net/pypy/cffi/-/issues/358
257 .. _`Issue #357`: https://foss.heptapod.net/pypy/cffi/-/issues/357
192258
193259
194260 v1.11.4
201267 ``foo.cp36-win32.pyd``, to make it clear that they are regular
202268 CPython modules depending on ``python36.dll``.
203269
204 .. _`Issue #355`: https://bitbucket.org/cffi/cffi/issues/355/
270 .. _`Issue #355`: https://foss.heptapod.net/pypy/cffi/-/issues/355
205271
206272
207273 v1.11.3
290356 that are *slower* to call than the API mode does. For some reason it
291357 is often thought to be faster. It is not!
292358
293 .. __: https://bitbucket.org/cffi/cffi/issues/321/cffi-191-segmentation-fault-during-self
359 .. __: https://foss.heptapod.net/pypy/cffi/-/issues/321
294360 .. __: ref.html#ffi-gc
295 .. __: https://bitbucket.org/cffi/cffi/issues/320/improve-memory_pressure-management
361 .. __: https://foss.heptapod.net/pypy/cffi/-/issues/320
296362 .. __: http://bugs.python.org/issue31105
297363
298364
5555 tries to compile C code. (Hints: on OS/X 10.8, for errors about
5656 -mno-fused-madd see http://stackoverflow.com/questions/22313407/
5757 Otherwise, see https://wiki.python.org/moin/CompLangPython or
58 the IRC channel #python on irc.freenode.net.)
58 the IRC channel #python on irc.libera.chat.)
5959
6060 Trying to continue anyway. If you are trying to install CFFI from
6161 a build done in a different context, you can ignore this warning.
148148 ask_supports_thread()
149149 ask_supports_sync_synchronize()
150150
151 if 'darwin' in sys.platform:
152 # priority is given to `pkg_config`, but always fall back on SDK's libffi.
153 extra_compile_args += ['-iwithsysroot/usr/include/ffi']
154
151155 if 'freebsd' in sys.platform:
152156 include_dirs.append('/usr/local/include')
153157 library_dirs.append('/usr/local/lib')
154
155 if 'darwin' in sys.platform:
156 try:
157 p = subprocess.Popen(['xcrun', '--show-sdk-path'],
158 stdout=subprocess.PIPE)
159 except OSError as e:
160 if e.errno not in [errno.ENOENT, errno.EACCES]:
161 raise
162 else:
163 t = p.stdout.read().decode().strip()
164 p.stdout.close()
165 if p.wait() == 0:
166 include_dirs.append(t + '/usr/include/ffi')
167
168
169158
170159 if __name__ == '__main__':
171160 from setuptools import setup, Distribution, Extension
197186
198187 `Mailing list <https://groups.google.com/forum/#!forum/python-cffi>`_
199188 """,
200 version='1.14.0',
189 version='1.14.6',
201190 packages=['cffi'] if cpython else [],
202191 package_data={'cffi': ['_cffi_include.h', 'parse_c_type.h',
203192 '_embedding.h', '_cffi_errors.h']}
77 if __name__ == '__main__':
88 from distutils.core import setup
99 from distutils.extension import Extension
10
1011 standard = '__pypy__' not in sys.builtin_module_names
1112 setup(packages=['cffi'],
1213 requires=['pycparser'],
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:
178178 setters = ['case %d: s.%s = value; break;' % iname
179179 for iname in enumerate(fnames)]
180180 lib = ffi1.verify("""
181 #include <string.h>
181182 struct s1 { %s };
182183 struct sa { char a; struct s1 b; };
183184 #define Gofs_y offsetof(struct s1, y)
245246 self.check("int a:2; short b:15; char c:2; char y;", 5, 4, 8)
246247 self.check("int a:2; char b:1; char c:1; char y;", 1, 4, 4)
247248
248 @pytest.mark.skipif("platform.machine().startswith(('arm', 'aarch64'))")
249 @pytest.mark.skipif(
250 "not (sys.platform == 'darwin' and platform.machine() == 'arm64')"
251 " and "
252 "platform.machine().startswith(('arm', 'aarch64'))")
249253 def test_bitfield_anonymous_no_align(self):
250254 L = FFI().alignof("long long")
251255 self.check("char y; int :1;", 0, 1, 2)
259263 self.check("char x; long long :57; char y;", L + 8, 1, L + 9)
260264
261265 @pytest.mark.skipif(
266 "(sys.platform == 'darwin' and platform.machine() == 'arm64')"
267 " or "
262268 "not platform.machine().startswith(('arm', 'aarch64'))")
263269 def test_bitfield_anonymous_align_arm(self):
264270 L = FFI().alignof("long long")
272278 self.check("char x; long long z:57; char y;", L + 8, L, L + 8 + L)
273279 self.check("char x; long long :57; char y;", L + 8, L, L + 8 + L)
274280
275 @pytest.mark.skipif("platform.machine().startswith(('arm', 'aarch64'))")
281 @pytest.mark.skipif(
282 "not (sys.platform == 'darwin' and platform.machine() == 'arm64')"
283 " and "
284 "platform.machine().startswith(('arm', 'aarch64'))")
276285 def test_bitfield_zero(self):
277286 L = FFI().alignof("long long")
278287 self.check("char y; int :0;", 0, 1, 4)
284293 self.check("int a:1; int :0; int b:1; char y;", 5, 4, 8)
285294
286295 @pytest.mark.skipif(
296 "(sys.platform == 'darwin' and platform.machine() == 'arm64')"
297 " or "
287298 "not platform.machine().startswith(('arm', 'aarch64'))")
288299 def test_bitfield_zero_arm(self):
289300 L = FFI().alignof("long long")
44 import ctypes.util
55 from cffi.backend_ctypes import CTypesBackend
66 from testing.udir import udir
7 from testing.support import FdWriteCapture
7 from testing.support import FdWriteCapture, StdErrCapture
88 from .backend_tests import needs_dlopen_none
99
1010 try:
226226 def cb():
227227 return returnvalue
228228 fptr = ffi.callback("void(*)(void)", cb)
229 old_stderr = sys.stderr
230 try:
231 sys.stderr = StringIO()
229 with StdErrCapture() as f:
232230 returned = fptr()
233 printed = sys.stderr.getvalue()
234 finally:
235 sys.stderr = old_stderr
231 printed = f.getvalue()
236232 assert returned is None
237233 if returnvalue is None:
238234 assert printed == ''
239235 else:
240236 assert "None" in printed
237
238 def test_callback_returning_struct_three_bytes(self):
239 if self.Backend is CTypesBackend:
240 py.test.skip("not supported with the ctypes backend")
241 ffi = FFI(backend=self.Backend())
242 ffi.cdef("""
243 typedef struct {
244 unsigned char a, b, c;
245 } THREEBYTES;
246 """)
247 def cb():
248 return (12, 34, 56)
249 fptr = ffi.callback("THREEBYTES(*)(void)", cb)
250 tb = fptr()
251 assert tb.a == 12
252 assert tb.b == 34
253 assert tb.c == 56
241254
242255 def test_passing_array(self):
243256 ffi = FFI(backend=self.Backend())
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())
3535 v = cffi.__version__.replace('+', '')
3636 p = os.path.join(parent, 'doc', 'source', 'installation.rst')
3737 content = open(p).read()
38 assert (" package version %s:" % v) in content
38 if " package version %s:" % v not in content:
39 for i in range(5):
40 if " package version %s-%d:" % (v, i) in content:
41 break
42 else:
43 assert 0, "doc/source/installation.rst needs updating"
3944
4045 def test_setup_version():
4146 parent = os.path.dirname(os.path.dirname(cffi.__file__))
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)
7373 int strlen(const char *);
7474 struct with_union { union { int a; char b; }; };
7575 union with_struct { struct { int a; char b; }; };
76 struct with_struct_with_union { struct { union { int x; }; } cp; };
7677 struct NVGcolor { union { float rgba[4]; struct { float r,g,b,a; }; }; };
7778 typedef struct selfref { struct selfref *next; } *selfref_ptr_t;
7879 """)
246247 assert ffi.offsetof("union with_struct", "a") == 0
247248 assert ffi.offsetof("union with_struct", "b") == INT
248249 assert ffi.sizeof("union with_struct") >= INT + 1
250 #
251 assert ffi.sizeof("struct with_struct_with_union") == INT
252 p = ffi.new("struct with_struct_with_union *")
253 assert p.cp.x == 0
249254 #
250255 FLOAT = ffi.sizeof("float")
251256 assert ffi.sizeof("struct NVGcolor") == FLOAT * 4
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)"
16651668 with StdErrCapture() as f:
16661669 res = lib.bar(321)
16671670 assert res is None
1668 assert f.getvalue() == (
1669 "From cffi callback %r:\n" % (bar,) +
1670 "Trying to convert the result back to C:\n"
1671 msg = f.getvalue()
1672 assert "rom cffi callback %r" % (bar,) in msg
1673 assert "rying to convert the result back to C:\n" in msg
1674 assert msg.endswith(
16711675 "TypeError: callback with the return type 'void' must return None\n")
16721676
16731677 def test_extern_python_redefine():
21172121 py.test.raises(ffi.error, ffi.sizeof, "vmat_t")
21182122 p = ffi.new("vmat_t", 4)
21192123 assert ffi.sizeof(p[3]) == 8 * ffi.sizeof("int")
2124
2125 def test_typedef_array_dotdotdot_usage():
2126 ffi = FFI()
2127 ffi.cdef("""
2128 typedef int foo_t[...];
2129 typedef int mat_t[...][...];
2130 struct s { foo_t a; foo_t *b; foo_t **c; };
2131 int myfunc(foo_t a, foo_t *b, foo_t **c);
2132 struct sm { mat_t a; mat_t *b; mat_t **c; };
2133 int myfuncm(mat_t a, mat_t *b, mat_t **c);
2134 """)
2135 lib = verify(ffi, "test_typedef_array_dotdotdot_usage", """
2136 typedef int foo_t[50];
2137 typedef int mat_t[6][7];
2138 struct s { foo_t a; foo_t *b; foo_t **c; };
2139 static int myfunc(foo_t a, foo_t *b, foo_t **c) { return (**c)[49]; }
2140 struct sm { mat_t a; mat_t *b; mat_t **c; };
2141 static int myfuncm(mat_t a, mat_t *b, mat_t **c) { return (**c)[5][6]; }
2142 """)
2143 assert ffi.sizeof("foo_t") == 50 * ffi.sizeof("int")
2144 p = ffi.new("struct s *")
2145 assert ffi.sizeof(p[0]) == 50 * ffi.sizeof("int") + 2 * ffi.sizeof("void *")
2146 p.a[49] = 321
2147 p.b = ffi.addressof(p, 'a')
2148 p.c = ffi.addressof(p, 'b')
2149 assert lib.myfunc(ffi.NULL, ffi.NULL, p.c) == 321
2150 #
2151 assert ffi.sizeof("mat_t") == 42 * ffi.sizeof("int")
2152 p = ffi.new("struct sm *")
2153 assert ffi.sizeof(p[0]) == 42 * ffi.sizeof("int") + 2 * ffi.sizeof("void *")
2154 p.a[5][6] = -321
2155 p.b = ffi.addressof(p, 'a')
2156 p.c = ffi.addressof(p, 'b')
2157 assert lib.myfuncm(ffi.NULL, ffi.NULL, p.c) == -321
21202158
21212159 def test_call_with_custom_field_pos():
21222160 ffi = FFI()
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,))
3232 from io import StringIO
3333 self.old_stderr = sys.stderr
3434 sys.stderr = f = StringIO()
35 if hasattr(sys, '__unraisablehook__'): # work around pytest
36 self.old_unraisablebook = sys.unraisablehook # on recent CPythons
37 sys.unraisablehook = sys.__unraisablehook__
3538 return f
3639 def __exit__(self, *args):
3740 sys.stderr = self.old_stderr
41 if hasattr(self, 'old_unraisablebook'):
42 sys.unraisablehook = self.old_unraisablebook
3843
3944
4045 class FdWriteCapture(object):
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