| |
|
| | |
| |
|
| | #ifdef __cplusplus |
| | extern "C" { |
| | #endif |
| |
|
| |
|
| | #if defined(_WIN32) |
| | # define CFFI_DLLEXPORT __declspec(dllexport) |
| | #elif defined(__GNUC__) |
| | # define CFFI_DLLEXPORT __attribute__((visibility("default"))) |
| | #else |
| | # define CFFI_DLLEXPORT |
| | #endif |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | #undef _cffi_call_python |
| | typedef void (*_cffi_call_python_fnptr)(struct _cffi_externpy_s *, char *); |
| | static void _cffi_start_and_call_python(struct _cffi_externpy_s *, char *); |
| | static _cffi_call_python_fnptr _cffi_call_python = &_cffi_start_and_call_python; |
| |
|
| |
|
| | #ifndef _MSC_VER |
| | |
| | # define cffi_compare_and_swap(l,o,n) __sync_bool_compare_and_swap(l,o,n) |
| | # define cffi_write_barrier() __sync_synchronize() |
| | # if !defined(__amd64__) && !defined(__x86_64__) && \ |
| | !defined(__i386__) && !defined(__i386) |
| | # define cffi_read_barrier() __sync_synchronize() |
| | # else |
| | # define cffi_read_barrier() (void)0 |
| | # endif |
| | #else |
| | |
| | # include <Windows.h> |
| | # define cffi_compare_and_swap(l,o,n) \ |
| | (InterlockedCompareExchangePointer(l,n,o) == (o)) |
| | # define cffi_write_barrier() InterlockedCompareExchange(&_cffi_dummy,0,0) |
| | # define cffi_read_barrier() (void)0 |
| | static volatile LONG _cffi_dummy; |
| | #endif |
| |
|
| | #ifdef WITH_THREAD |
| | # ifndef _MSC_VER |
| | # include <pthread.h> |
| | static pthread_mutex_t _cffi_embed_startup_lock; |
| | # else |
| | static CRITICAL_SECTION _cffi_embed_startup_lock; |
| | # endif |
| | static char _cffi_embed_startup_lock_ready = 0; |
| | #endif |
| |
|
| | static void _cffi_acquire_reentrant_mutex(void) |
| | { |
| | static void *volatile lock = NULL; |
| |
|
| | while (!cffi_compare_and_swap(&lock, NULL, (void *)1)) { |
| | |
| | |
| | |
| | |
| | } |
| |
|
| | #ifdef WITH_THREAD |
| | if (!_cffi_embed_startup_lock_ready) { |
| | # ifndef _MSC_VER |
| | pthread_mutexattr_t attr; |
| | pthread_mutexattr_init(&attr); |
| | pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); |
| | pthread_mutex_init(&_cffi_embed_startup_lock, &attr); |
| | # else |
| | InitializeCriticalSection(&_cffi_embed_startup_lock); |
| | # endif |
| | _cffi_embed_startup_lock_ready = 1; |
| | } |
| | #endif |
| |
|
| | while (!cffi_compare_and_swap(&lock, (void *)1, NULL)) |
| | ; |
| |
|
| | #ifndef _MSC_VER |
| | pthread_mutex_lock(&_cffi_embed_startup_lock); |
| | #else |
| | EnterCriticalSection(&_cffi_embed_startup_lock); |
| | #endif |
| | } |
| |
|
| | static void _cffi_release_reentrant_mutex(void) |
| | { |
| | #ifndef _MSC_VER |
| | pthread_mutex_unlock(&_cffi_embed_startup_lock); |
| | #else |
| | LeaveCriticalSection(&_cffi_embed_startup_lock); |
| | #endif |
| | } |
| |
|
| |
|
| | |
| | #ifndef PYPY_VERSION |
| |
|
| | #include "_cffi_errors.h" |
| |
|
| |
|
| | #define _cffi_call_python_org _cffi_exports[_CFFI_CPIDX] |
| |
|
| | PyMODINIT_FUNC _CFFI_PYTHON_STARTUP_FUNC(void); |
| |
|
| | static void _cffi_py_initialize(void) |
| | { |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | Py_InitializeEx(0); |
| | } |
| |
|
| | static int _cffi_initialize_python(void) |
| | { |
| | |
| | |
| | |
| | int result; |
| | PyGILState_STATE state; |
| | PyObject *pycode=NULL, *global_dict=NULL, *x; |
| | PyObject *builtins; |
| |
|
| | state = PyGILState_Ensure(); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | (void)_CFFI_PYTHON_STARTUP_FUNC(); |
| | if (PyErr_Occurred()) |
| | goto error; |
| |
|
| | |
| | |
| | pycode = Py_CompileString(_CFFI_PYTHON_STARTUP_CODE, |
| | "<init code for '" _CFFI_MODULE_NAME "'>", |
| | Py_file_input); |
| | if (pycode == NULL) |
| | goto error; |
| | global_dict = PyDict_New(); |
| | if (global_dict == NULL) |
| | goto error; |
| | builtins = PyEval_GetBuiltins(); |
| | if (builtins == NULL) |
| | goto error; |
| | if (PyDict_SetItemString(global_dict, "__builtins__", builtins) < 0) |
| | goto error; |
| | x = PyEval_EvalCode( |
| | #if PY_MAJOR_VERSION < 3 |
| | (PyCodeObject *) |
| | #endif |
| | pycode, global_dict, global_dict); |
| | if (x == NULL) |
| | goto error; |
| | Py_DECREF(x); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | result = 0; |
| | done: |
| | Py_XDECREF(pycode); |
| | Py_XDECREF(global_dict); |
| | PyGILState_Release(state); |
| | return result; |
| |
|
| | error:; |
| | { |
| | |
| | |
| | |
| | PyObject *ecap; |
| | PyObject *exception, *v, *tb, *f, *modules, *mod; |
| | PyErr_Fetch(&exception, &v, &tb); |
| | ecap = _cffi_start_error_capture(); |
| | f = PySys_GetObject((char *)"stderr"); |
| | if (f != NULL && f != Py_None) { |
| | PyFile_WriteString( |
| | "Failed to initialize the Python-CFFI embedding logic:\n\n", f); |
| | } |
| |
|
| | if (exception != NULL) { |
| | PyErr_NormalizeException(&exception, &v, &tb); |
| | PyErr_Display(exception, v, tb); |
| | } |
| | Py_XDECREF(exception); |
| | Py_XDECREF(v); |
| | Py_XDECREF(tb); |
| |
|
| | if (f != NULL && f != Py_None) { |
| | PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME |
| | "\ncompiled with cffi version: 2.0.0" |
| | "\n_cffi_backend module: ", f); |
| | modules = PyImport_GetModuleDict(); |
| | mod = PyDict_GetItemString(modules, "_cffi_backend"); |
| | if (mod == NULL) { |
| | PyFile_WriteString("not loaded", f); |
| | } |
| | else { |
| | v = PyObject_GetAttrString(mod, "__file__"); |
| | PyFile_WriteObject(v, f, 0); |
| | Py_XDECREF(v); |
| | } |
| | PyFile_WriteString("\nsys.path: ", f); |
| | PyFile_WriteObject(PySys_GetObject((char *)"path"), f, 0); |
| | PyFile_WriteString("\n\n", f); |
| | } |
| | _cffi_stop_error_capture(ecap); |
| | } |
| | result = -1; |
| | goto done; |
| | } |
| |
|
| | #if PY_VERSION_HEX < 0x03080000 |
| | PyAPI_DATA(char *) _PyParser_TokenNames[]; |
| | #endif |
| |
|
| | static int _cffi_carefully_make_gil(void) |
| | { |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #ifdef WITH_THREAD |
| | # if PY_VERSION_HEX < 0x03080000 |
| | char *volatile *lock = (char *volatile *)_PyParser_TokenNames; |
| | char *old_value, *locked_value; |
| |
|
| | while (1) { |
| | old_value = *lock; |
| | locked_value = old_value + 1; |
| | if (old_value[0] == 'E') { |
| | assert(old_value[1] == 'N'); |
| | if (cffi_compare_and_swap(lock, old_value, locked_value)) |
| | break; |
| | } |
| | else { |
| | assert(old_value[0] == 'N'); |
| | |
| | |
| | |
| | |
| | } |
| | } |
| | # else |
| | # if PY_VERSION_HEX < 0x030C0000 |
| | int volatile *lock = (int volatile *)&PyCapsule_Type.tp_version_tag; |
| | int old_value, locked_value = -42; |
| | assert(!(PyCapsule_Type.tp_flags & Py_TPFLAGS_HAVE_VERSION_TAG)); |
| | # else |
| | static struct ebp_s { PyBufferProcs buf; int mark; } empty_buffer_procs; |
| | empty_buffer_procs.mark = -42; |
| | PyBufferProcs *volatile *lock = (PyBufferProcs *volatile *) |
| | &PyCapsule_Type.tp_as_buffer; |
| | PyBufferProcs *old_value, *locked_value = &empty_buffer_procs.buf; |
| | # endif |
| |
|
| | while (1) { |
| | old_value = *lock; |
| | if (old_value == 0) { |
| | if (cffi_compare_and_swap(lock, old_value, locked_value)) |
| | break; |
| | } |
| | else { |
| | # if PY_VERSION_HEX < 0x030C0000 |
| | assert(old_value == locked_value); |
| | # else |
| | |
| | |
| | assert(((struct ebp_s *)old_value)->mark == -42); |
| | # endif |
| | |
| | |
| | |
| | |
| | } |
| | } |
| | # endif |
| | #endif |
| |
|
| | |
| | if (!Py_IsInitialized()) { |
| | _cffi_py_initialize(); |
| | #if PY_VERSION_HEX < 0x03070000 |
| | PyEval_InitThreads(); |
| | #endif |
| | PyEval_SaveThread(); |
| | |
| | |
| | } |
| | else { |
| | #if PY_VERSION_HEX < 0x03070000 |
| | |
| | PyGILState_STATE state = PyGILState_Ensure(); |
| | PyEval_InitThreads(); |
| | PyGILState_Release(state); |
| | #endif |
| | } |
| |
|
| | #ifdef WITH_THREAD |
| | |
| | while (!cffi_compare_and_swap(lock, locked_value, old_value)) |
| | ; |
| | #endif |
| |
|
| | return 0; |
| | } |
| |
|
| | |
| |
|
| |
|
| | #else |
| |
|
| |
|
| | |
| |
|
| | PyMODINIT_FUNC _CFFI_PYTHON_STARTUP_FUNC(const void *[]); |
| |
|
| | static struct _cffi_pypy_init_s { |
| | const char *name; |
| | void *func; |
| | const char *code; |
| | } _cffi_pypy_init = { |
| | _CFFI_MODULE_NAME, |
| | _CFFI_PYTHON_STARTUP_FUNC, |
| | _CFFI_PYTHON_STARTUP_CODE, |
| | }; |
| |
|
| | extern int pypy_carefully_make_gil(const char *); |
| | extern int pypy_init_embedded_cffi_module(int, struct _cffi_pypy_init_s *); |
| |
|
| | static int _cffi_carefully_make_gil(void) |
| | { |
| | return pypy_carefully_make_gil(_CFFI_MODULE_NAME); |
| | } |
| |
|
| | static int _cffi_initialize_python(void) |
| | { |
| | return pypy_init_embedded_cffi_module(0xB011, &_cffi_pypy_init); |
| | } |
| |
|
| | |
| |
|
| |
|
| | #endif |
| |
|
| |
|
| | #ifdef __GNUC__ |
| | __attribute__((noinline)) |
| | #endif |
| | static _cffi_call_python_fnptr _cffi_start_python(void) |
| | { |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | static char called = 0; |
| |
|
| | if (_cffi_carefully_make_gil() != 0) |
| | return NULL; |
| |
|
| | _cffi_acquire_reentrant_mutex(); |
| |
|
| | |
| | |
| |
|
| | |
| | |
| | if (!called) { |
| | called = 1; |
| | |
| | |
| | |
| | if (_cffi_initialize_python() == 0) { |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | cffi_write_barrier(); |
| | |
| | |
| | |
| | |
| | |
| |
|
| | assert(_cffi_call_python_org != NULL); |
| | _cffi_call_python = (_cffi_call_python_fnptr)_cffi_call_python_org; |
| | } |
| | else { |
| | |
| | |
| | |
| | |
| | _cffi_call_python_org = NULL; |
| | } |
| | } |
| |
|
| | _cffi_release_reentrant_mutex(); |
| |
|
| | return (_cffi_call_python_fnptr)_cffi_call_python_org; |
| | } |
| |
|
| | static |
| | void _cffi_start_and_call_python(struct _cffi_externpy_s *externpy, char *args) |
| | { |
| | _cffi_call_python_fnptr fnptr; |
| | int current_err = errno; |
| | #ifdef _MSC_VER |
| | int current_lasterr = GetLastError(); |
| | #endif |
| | fnptr = _cffi_start_python(); |
| | if (fnptr == NULL) { |
| | fprintf(stderr, "function %s() called, but initialization code " |
| | "failed. Returning 0.\n", externpy->name); |
| | memset(args, 0, externpy->size_of_result); |
| | } |
| | #ifdef _MSC_VER |
| | SetLastError(current_lasterr); |
| | #endif |
| | errno = current_err; |
| |
|
| | if (fnptr != NULL) |
| | fnptr(externpy, args); |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | _CFFI_UNUSED_FN |
| | static int cffi_start_python(void) |
| | { |
| | if (_cffi_call_python == &_cffi_start_and_call_python) { |
| | if (_cffi_start_python() == NULL) |
| | return -1; |
| | } |
| | cffi_read_barrier(); |
| | return 0; |
| | } |
| |
|
| | #undef cffi_compare_and_swap |
| | #undef cffi_write_barrier |
| | #undef cffi_read_barrier |
| |
|
| | #ifdef __cplusplus |
| | } |
| | #endif |
| |
|