Codebase list python-cffi-py2 / ae4d29b1-6ad1-440e-ba48-4d0c3ed1c88a/upstream
Import upstream version 1.14.4 Kali Janitor 3 years ago
41 changed file(s) with 1109 addition(s) and 241 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.4
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.4"
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
150182 /************************************************************/
151183
152184 /* base type flag: exactly one of the following: */
403435
404436 if (ct->ct_unique_key != NULL) {
405437 /* revive dead object temporarily for DelItem */
406 Py_REFCNT(ct) = 43;
438 Py_SET_REFCNT(ct, 43);
407439 PyDict_DelItem(unique_cache, ct->ct_unique_key);
408440 assert(Py_REFCNT(ct) == 42);
409 Py_REFCNT(ct) = 0;
441 Py_SET_REFCNT(ct, 0);
410442 Py_DECREF(ct->ct_unique_key);
411443 }
412444 Py_XDECREF(ct->ct_itemdescr);
652684
653685 static PyTypeObject CTypeDescr_Type = {
654686 PyVarObject_HEAD_INIT(NULL, 0)
655 "_cffi_backend.CTypeDescr",
687 "_cffi_backend.CType",
656688 offsetof(CTypeDescrObject, ct_name),
657689 sizeof(char),
658690 (destructor)ctypedescr_dealloc, /* tp_dealloc */
18851917 ffi_closure *closure = ((CDataObject_closure *)cd)->closure;
18861918 PyObject *args = (PyObject *)(closure->user_data);
18871919 Py_XDECREF(args);
1888 #ifdef CFFI_TRUST_LIBFFI
1889 ffi_closure_free(closure);
1890 #else
1891 cffi_closure_free(closure);
1920 #if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE
1921 if (CFFI_CHECK_FFI_CLOSURE_ALLOC) {
1922 ffi_closure_free(closure);
1923 } else
18921924 #endif
1925 cffi_closure_free(closure);
18931926 }
18941927 else {
18951928 Py_FatalError("cdata CDataOwningGC_Type with unexpected type flags");
28872920 convert_struct_to_owning_object(char *data, CTypeDescrObject *ct); /*forward*/
28882921
28892922 static cif_description_t *
2890 fb_prepare_cif(PyObject *fargs, CTypeDescrObject *, ffi_abi); /*forward*/
2923 fb_prepare_cif(PyObject *fargs, CTypeDescrObject *, Py_ssize_t, ffi_abi);
2924 /*forward*/
28912925
28922926 static PyObject *new_primitive_type(const char *name); /*forward*/
28932927
30803114 #else
30813115 fabi = PyLong_AS_LONG(PyTuple_GET_ITEM(signature, 0));
30823116 #endif
3083 cif_descr = fb_prepare_cif(fvarargs, fresult, fabi);
3117 cif_descr = fb_prepare_cif(fvarargs, fresult, nargs_declared, fabi);
30843118 if (cif_descr == NULL)
30853119 goto error;
30863120 }
33533387
33543388 static PyTypeObject CData_Type = {
33553389 PyVarObject_HEAD_INIT(NULL, 0)
3356 "_cffi_backend.CData",
3390 "_cffi_backend._CDataBase",
33573391 sizeof(CDataObject),
33583392 0,
33593393 (destructor)cdata_dealloc, /* tp_dealloc */
33723406 (setattrofunc)cdata_setattro, /* tp_setattro */
33733407 0, /* tp_as_buffer */
33743408 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
3375 0, /* tp_doc */
3409 "The internal base type for CData objects. Use FFI.CData to access "
3410 "it. Always check with isinstance(): subtypes are sometimes returned "
3411 "on CPython, for performance reasons.", /* tp_doc */
33763412 0, /* tp_traverse */
33773413 0, /* tp_clear */
33783414 cdata_richcompare, /* tp_richcompare */
33953431
33963432 static PyTypeObject CDataOwning_Type = {
33973433 PyVarObject_HEAD_INIT(NULL, 0)
3398 "_cffi_backend.CDataOwn",
3434 "_cffi_backend.__CDataOwn",
33993435 sizeof(CDataObject),
34003436 0,
34013437 (destructor)cdataowning_dealloc, /* tp_dealloc */
34143450 0, /* inherited */ /* tp_setattro */
34153451 0, /* tp_as_buffer */
34163452 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
3417 0, /* tp_doc */
3453 "This is an internal subtype of _CDataBase for performance only on "
3454 "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */
34183455 0, /* tp_traverse */
34193456 0, /* tp_clear */
34203457 0, /* inherited */ /* tp_richcompare */
34373474
34383475 static PyTypeObject CDataOwningGC_Type = {
34393476 PyVarObject_HEAD_INIT(NULL, 0)
3440 "_cffi_backend.CDataOwnGC",
3477 "_cffi_backend.__CDataOwnGC",
34413478 sizeof(CDataObject_own_structptr),
34423479 0,
34433480 (destructor)cdataowninggc_dealloc, /* tp_dealloc */
34573494 0, /* tp_as_buffer */
34583495 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */
34593496 | Py_TPFLAGS_HAVE_GC,
3460 0, /* tp_doc */
3497 "This is an internal subtype of _CDataBase for performance only on "
3498 "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */
34613499 (traverseproc)cdataowninggc_traverse, /* tp_traverse */
34623500 (inquiry)cdataowninggc_clear, /* tp_clear */
34633501 0, /* inherited */ /* tp_richcompare */
34803518
34813519 static PyTypeObject CDataFromBuf_Type = {
34823520 PyVarObject_HEAD_INIT(NULL, 0)
3483 "_cffi_backend.CDataFromBuf",
3521 "_cffi_backend.__CDataFromBuf",
34843522 sizeof(CDataObject_frombuf),
34853523 0,
34863524 (destructor)cdatafrombuf_dealloc, /* tp_dealloc */
35003538 0, /* tp_as_buffer */
35013539 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES /* tp_flags */
35023540 | Py_TPFLAGS_HAVE_GC,
3503 0, /* tp_doc */
3541 "This is an internal subtype of _CDataBase for performance only on "
3542 "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */
35043543 (traverseproc)cdatafrombuf_traverse, /* tp_traverse */
35053544 (inquiry)cdatafrombuf_clear, /* tp_clear */
35063545 0, /* inherited */ /* tp_richcompare */
35233562
35243563 static PyTypeObject CDataGCP_Type = {
35253564 PyVarObject_HEAD_INIT(NULL, 0)
3526 "_cffi_backend.CDataGCP",
3565 "_cffi_backend.__CDataGCP",
35273566 sizeof(CDataObject_gcp),
35283567 0,
35293568 (destructor)cdatagcp_dealloc, /* tp_dealloc */
35463585 | Py_TPFLAGS_HAVE_FINALIZE
35473586 #endif
35483587 | Py_TPFLAGS_HAVE_GC,
3549 0, /* tp_doc */
3588 "This is an internal subtype of _CDataBase for performance only on "
3589 "CPython. Check with isinstance(x, ffi.CData).", /* tp_doc */
35503590 (traverseproc)cdatagcp_traverse, /* tp_traverse */
35513591 0, /* tp_clear */
35523592 0, /* inherited */ /* tp_richcompare */
36073647
36083648 static PyTypeObject CDataIter_Type = {
36093649 PyVarObject_HEAD_INIT(NULL, 0)
3610 "_cffi_backend.CDataIter", /* tp_name */
3650 "_cffi_backend.__CData_iterator", /* tp_name */
36113651 sizeof(CDataIterObject), /* tp_basicsize */
36123652 0, /* tp_itemsize */
36133653 /* methods */
43624402
43634403 static PyTypeObject dl_type = {
43644404 PyVarObject_HEAD_INIT(NULL, 0)
4365 "_cffi_backend.Library", /* tp_name */
4405 "_cffi_backend.CLibrary", /* tp_name */
43664406 sizeof(DynLibObject), /* tp_basicsize */
43674407 0, /* tp_itemsize */
43684408 /* methods */
44404480 {
44414481 PyObject *s = PyTuple_GET_ITEM(args, 0);
44424482 #ifdef MS_WIN32
4443 Py_UNICODE *filenameW;
4444 if (PyArg_ParseTuple(args, "u|i:load_library", &filenameW, &flags))
4483 PyObject *filename_unicode;
4484 if (PyArg_ParseTuple(args, "U|i:load_library", &filename_unicode, &flags))
44454485 {
4486 Py_ssize_t sz1;
4487 wchar_t *w1;
44464488 #if PY_MAJOR_VERSION < 3
44474489 s = PyUnicode_AsUTF8String(s);
44484490 if (s == NULL)
44534495 if (*p_printable_filename == NULL)
44544496 return NULL;
44554497
4456 handle = dlopenW(filenameW);
4498 sz1 = PyUnicode_GetSize(filename_unicode) + 1;
4499 sz1 *= 2; /* should not be needed, but you never know */
4500 w1 = alloca(sizeof(wchar_t) * sz1);
4501 sz1 = PyUnicode_AsWideChar((PyUnicodeObject *)filename_unicode,
4502 w1, sz1 - 1);
4503 if (sz1 < 0)
4504 return NULL;
4505 w1[sz1] = 0;
4506 handle = dlopenW(w1);
44574507 goto got_handle;
44584508 }
44594509 PyErr_Clear();
44764526 }
44774527 if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0)
44784528 flags |= RTLD_NOW;
4529
4530 #ifdef MS_WIN32
4531 if (filename_or_null == NULL) {
4532 PyErr_SetString(PyExc_OSError, "dlopen(None) not supported on Windows");
4533 return NULL;
4534 }
4535 #endif
44794536
44804537 handle = dlopen(filename_or_null, flags);
44814538
49945051 #ifdef MS_WIN32
49955052 sflags |= SF_MSVC_BITFIELDS;
49965053 #else
4997 # if defined(__arm__) || defined(__aarch64__)
5054 # if defined(__APPLE__) && defined(__arm64__)
5055 sflags |= SF_GCC_X86_BITFIELDS;
5056 # elif defined(__arm__) || defined(__aarch64__)
49985057 sflags |= SF_GCC_ARM_BITFIELDS;
49995058 # else
50005059 sflags |= SF_GCC_X86_BITFIELDS;
57825841
57835842 static cif_description_t *fb_prepare_cif(PyObject *fargs,
57845843 CTypeDescrObject *fresult,
5844 Py_ssize_t variadic_nargs_declared,
57855845 ffi_abi fabi)
5846
57865847 {
57875848 char *buffer;
57885849 cif_description_t *cif_descr;
57895850 struct funcbuilder_s funcbuffer;
5851 ffi_status status = -1;
57905852
57915853 funcbuffer.nb_bytes = 0;
57925854 funcbuffer.bufferp = NULL;
58095871 assert(funcbuffer.bufferp == buffer + funcbuffer.nb_bytes);
58105872
58115873 cif_descr = (cif_description_t *)buffer;
5812 if (ffi_prep_cif(&cif_descr->cif, fabi, funcbuffer.nargs,
5813 funcbuffer.rtype, funcbuffer.atypes) != FFI_OK) {
5874
5875 /* use `ffi_prep_cif_var` if necessary and available */
5876 #if CFFI_CHECK_FFI_PREP_CIF_VAR_MAYBE
5877 if (variadic_nargs_declared >= 0) {
5878 if (CFFI_CHECK_FFI_PREP_CIF_VAR) {
5879 status = ffi_prep_cif_var(&cif_descr->cif, fabi,
5880 variadic_nargs_declared, funcbuffer.nargs,
5881 funcbuffer.rtype, funcbuffer.atypes);
5882 }
5883 }
5884 #endif
5885
5886 if (status == -1) {
5887 status = ffi_prep_cif(&cif_descr->cif, fabi, funcbuffer.nargs,
5888 funcbuffer.rtype, funcbuffer.atypes);
5889 }
5890
5891 if (status != FFI_OK) {
58145892 PyErr_SetString(PyExc_SystemError,
58155893 "libffi failed to build this function type");
58165894 goto error;
58545932 is computed here. */
58555933 cif_description_t *cif_descr;
58565934
5857 cif_descr = fb_prepare_cif(fargs, fresult, fabi);
5935 cif_descr = fb_prepare_cif(fargs, fresult, -1, fabi);
58585936 if (cif_descr == NULL) {
58595937 if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
58605938 PyErr_Clear(); /* will get the exception if we see an
61786256 infotuple = Py_BuildValue("OOOO", ct, ob, py_rawerr, onerror_ob);
61796257 Py_DECREF(py_rawerr);
61806258
6181 #ifdef WITH_THREAD
6259 #if defined(WITH_THREAD) && PY_VERSION_HEX < 0x03070000
61826260 /* 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. */
6261 some other non-Pythonic thread. This is the same as ctypes.
6262 But PyEval_InitThreads() is always a no-op from CPython 3.7
6263 (the call from ctypes was removed some time later I think). */
61846264 PyEval_InitThreads();
61856265 #endif
61866266
61956275 PyObject *infotuple;
61966276 cif_description_t *cif_descr;
61976277 ffi_closure *closure;
6278 ffi_status status;
61986279 void *closure_exec;
61996280
62006281 if (!PyArg_ParseTuple(args, "O!O|OO:callback", &CTypeDescr_Type, &ct, &ob,
62056286 if (infotuple == NULL)
62066287 return NULL;
62076288
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;
6289 #if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE
6290 if (CFFI_CHECK_FFI_CLOSURE_ALLOC) {
6291 closure = ffi_closure_alloc(sizeof(ffi_closure), &closure_exec);
6292 } else
62136293 #endif
6294 {
6295 closure = cffi_closure_alloc();
6296 closure_exec = closure;
6297 }
6298
62146299 if (closure == NULL) {
62156300 Py_DECREF(infotuple);
62166301 PyErr_SetString(PyExc_MemoryError,
62276312 cd->head.c_type = ct;
62286313 cd->head.c_data = (char *)closure_exec;
62296314 cd->head.c_weakreflist = NULL;
6315 closure->user_data = NULL;
62306316 cd->closure = closure;
6231 PyObject_GC_Track(cd);
62326317
62336318 cif_descr = (cif_description_t *)ct->ct_extra;
62346319 if (cif_descr == NULL) {
62376322 "return type or with '...'", ct->ct_name);
62386323 goto error;
62396324 }
6240 #ifdef CFFI_TRUST_LIBFFI
6241 if (ffi_prep_closure_loc(closure, &cif_descr->cif,
6242 invoke_callback, infotuple, closure_exec) != FFI_OK) {
6325
6326 #if CFFI_CHECK_FFI_PREP_CLOSURE_LOC_MAYBE
6327 if (CFFI_CHECK_FFI_PREP_CLOSURE_LOC) {
6328 status = ffi_prep_closure_loc(closure, &cif_descr->cif,
6329 invoke_callback, infotuple, closure_exec);
6330 }
6331 else
6332 #endif
6333 {
6334 #if defined(__APPLE__) && defined(FFI_AVAILABLE_APPLE) && !FFI_LEGACY_CLOSURE_API
6335 PyErr_Format(PyExc_SystemError, "ffi_prep_closure_loc() is missing");
6336 goto error;
62436337 #else
6244 if (ffi_prep_closure(closure, &cif_descr->cif,
6245 invoke_callback, infotuple) != FFI_OK) {
6338 /* messily try to silence a gcc/clang deprecation warning here */
6339 # if defined(__clang__)
6340 # pragma clang diagnostic push
6341 # pragma clang diagnostic ignored "-Wdeprecated-declarations"
6342 # elif defined(__GNUC__)
6343 # pragma GCC diagnostic push
6344 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
6345 # endif
6346 status = ffi_prep_closure(closure, &cif_descr->cif,
6347 invoke_callback, infotuple);
6348 # if defined(__clang__)
6349 # pragma clang diagnostic pop
6350 # elif defined(__GNUC__)
6351 # pragma GCC diagnostic pop
6352 # endif
62466353 #endif
6354 }
6355
6356 if (status != FFI_OK) {
62476357 PyErr_SetString(PyExc_SystemError,
62486358 "libffi failed to build this callback");
62496359 goto error;
62506360 }
6361
62516362 if (closure->user_data != infotuple) {
62526363 /* Issue #266. Should not occur, but could, if we are using
62536364 at runtime a version of libffi compiled with a different
62626373 "different from the 'ffi.h' file seen at compile-time)");
62636374 goto error;
62646375 }
6376 PyObject_GC_Track(cd);
62656377 return (PyObject *)cd;
62666378
62676379 error:
62686380 closure->user_data = NULL;
62696381 if (cd == NULL) {
6270 #ifdef CFFI_TRUST_LIBFFI
6271 ffi_closure_free(closure);
6272 #else
6273 cffi_closure_free(closure);
6382 #if CFFI_CHECK_FFI_CLOSURE_ALLOC_MAYBE
6383 if (CFFI_CHECK_FFI_CLOSURE_ALLOC) {
6384 ffi_closure_free(closure);
6385 }
6386 else
62746387 #endif
6388 cffi_closure_free(closure);
62756389 }
62766390 else
62776391 Py_DECREF(cd);
77877901 PyObject *m, *v;
77887902 int i;
77897903 static char init_done = 0;
7904 static PyTypeObject *all_types[] = {
7905 &dl_type,
7906 &CTypeDescr_Type,
7907 &CField_Type,
7908 &CData_Type,
7909 &CDataOwning_Type,
7910 &CDataOwningGC_Type,
7911 &CDataFromBuf_Type,
7912 &CDataGCP_Type,
7913 &CDataIter_Type,
7914 &MiniBuffer_Type,
7915 &FFI_Type,
7916 &Lib_Type,
7917 &GlobSupport_Type,
7918 NULL
7919 };
77907920
77917921 v = PySys_GetObject("version");
77927922 if (v == NULL || !PyText_Check(v) ||
78127942 INITERROR;
78137943 }
78147944
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;
7945 /* readify all types and add them to the module */
7946 for (i = 0; all_types[i] != NULL; i++) {
7947 PyTypeObject *tp = all_types[i];
7948 PyObject *tpo = (PyObject *)tp;
7949 if (strncmp(tp->tp_name, "_cffi_backend.", 14) != 0) {
7950 PyErr_Format(PyExc_ImportError,
7951 "'%s' is an ill-formed type name", tp->tp_name);
7952 INITERROR;
7953 }
7954 if (PyType_Ready(tp) < 0)
7955 INITERROR;
7956
7957 Py_INCREF(tpo);
7958 if (PyModule_AddObject(m, tp->tp_name + 14, tpo) < 0)
7959 INITERROR;
7960 }
78357961
78367962 if (!init_done) {
78377963 v = PyText_FromString("_cffi_backend");
78778003 INITERROR;
78788004 }
78798005
7880 Py_INCREF(&MiniBuffer_Type);
7881 if (PyModule_AddObject(m, "buffer", (PyObject *)&MiniBuffer_Type) < 0)
7882 INITERROR;
7883
78848006 init_cffi_tls();
78858007 if (PyErr_Occurred())
78868008 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.4", ("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>"
14641469 def make_callback(m):
14651470 def cb(n):
14661471 return n + m
1467 return callback(BFunc, cb, 42) # 'cb' and 'BFunc' go out of scope
1472 return callback(BFunc, cb, 42) # 'cb' goes out of scope
14681473 #
14691474 flist = [make_callback(i) for i in range(BIGNUM)]
14701475 for i, f in enumerate(flist):
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)
4498
4499 def test_unaligned_types():
4500 BByteArray = new_array_type(
4501 new_pointer_type(new_primitive_type("unsigned char")), None)
4502 pbuf = newp(BByteArray, 40)
4503 buf = buffer(pbuf)
4504 #
4505 for name in ['short', 'int', 'long', 'long long', 'float', 'double',
4506 'float _Complex', 'double _Complex']:
4507 p = new_primitive_type(name)
4508 if name.endswith(' _Complex'):
4509 num = cast(p, 1.23 - 4.56j)
4510 else:
4511 num = cast(p, 0x0123456789abcdef)
4512 size = sizeof(p)
4513 buf[0:40] = b"\x00" * 40
4514 pbuf1 = cast(new_pointer_type(p), pbuf + 1)
4515 pbuf1[0] = num
4516 assert pbuf1[0] == num
4517 assert buf[0] == b'\x00'
4518 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.4"
8 __version_info__ = (1, 14, 4)
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.4"
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)
00 Metadata-Version: 1.1
11 Name: cffi
2 Version: 1.14.0
2 Version: 1.14.4
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.4'
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.4:
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
148152 ask_supports_thread()
149153 ask_supports_sync_synchronize()
150154
155 if 'darwin' in sys.platform:
156 # priority is given to `pkg_config`, but always fall back on SDK's libffi.
157 extra_compile_args += ['-iwithsysroot/usr/include/ffi']
158
151159 if 'freebsd' in sys.platform:
152160 include_dirs.append('/usr/local/include')
153161 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
169162
170163 if __name__ == '__main__':
171164 from setuptools import setup, Distribution, Extension
197190
198191 `Mailing list <https://groups.google.com/forum/#!forum/python-cffi>`_
199192 """,
200 version='1.14.0',
193 version='1.14.4',
201194 packages=['cffi'] if cpython else [],
202195 package_data={'cffi': ['_cffi_include.h', 'parse_c_type.h',
203196 '_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:
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")
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)
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)"
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