123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- #if PY_VERSION_HEX >= 0x03080000
- # define HAVE_PYINTERPSTATE_GETDICT
- #endif
- static PyObject *_current_interp_key(void)
- {
- PyInterpreterState *interp = PyThreadState_GET()->interp;
- #ifdef HAVE_PYINTERPSTATE_GETDICT
- return PyInterpreterState_GetDict(interp);
- #else
- return interp->modules;
- #endif
- }
- static PyObject *_get_interpstate_dict(void)
- {
-
- static PyObject *attr_name = NULL;
- PyThreadState *tstate;
- PyObject *d, *interpdict;
- int err;
- PyInterpreterState *interp;
- tstate = PyThreadState_GET();
- if (tstate == NULL) {
-
- return NULL;
- }
- interp = tstate->interp;
- #ifdef HAVE_PYINTERPSTATE_GETDICT
- interpdict = PyInterpreterState_GetDict(interp);
- #else
- interpdict = interp->builtins;
- #endif
- if (interpdict == NULL) {
-
- return NULL;
- }
-
- if (attr_name == NULL) {
- attr_name = PyText_InternFromString("__cffi_backend_extern_py");
- if (attr_name == NULL)
- goto error;
- }
- d = PyDict_GetItem(interpdict, attr_name);
- if (d == NULL) {
- d = PyDict_New();
- if (d == NULL)
- goto error;
- err = PyDict_SetItem(interpdict, attr_name, d);
- Py_DECREF(d);
- if (err < 0)
- goto error;
- }
- return d;
- error:
- PyErr_Clear();
- return NULL;
- }
- static PyObject *_ffi_def_extern_decorator(PyObject *outer_args, PyObject *fn)
- {
- const char *s;
- PyObject *error, *onerror, *infotuple, *old1;
- int index, err;
- const struct _cffi_global_s *g;
- struct _cffi_externpy_s *externpy;
- CTypeDescrObject *ct;
- FFIObject *ffi;
- builder_c_t *types_builder;
- PyObject *name = NULL;
- PyObject *interpstate_dict;
- PyObject *interpstate_key;
- if (!PyArg_ParseTuple(outer_args, "OzOO", &ffi, &s, &error, &onerror))
- return NULL;
- if (s == NULL) {
- name = PyObject_GetAttrString(fn, "__name__");
- if (name == NULL)
- return NULL;
- s = PyText_AsUTF8(name);
- if (s == NULL) {
- Py_DECREF(name);
- return NULL;
- }
- }
- types_builder = &ffi->types_builder;
- index = search_in_globals(&types_builder->ctx, s, strlen(s));
- if (index < 0)
- goto not_found;
- g = &types_builder->ctx.globals[index];
- if (_CFFI_GETOP(g->type_op) != _CFFI_OP_EXTERN_PYTHON)
- goto not_found;
- Py_XDECREF(name);
- ct = realize_c_type(types_builder, types_builder->ctx.types,
- _CFFI_GETARG(g->type_op));
- if (ct == NULL)
- return NULL;
- infotuple = prepare_callback_info_tuple(ct, fn, error, onerror, 0);
- Py_DECREF(ct);
- if (infotuple == NULL)
- return NULL;
-
- interpstate_dict = _get_interpstate_dict();
- if (interpstate_dict == NULL) {
- Py_DECREF(infotuple);
- return PyErr_NoMemory();
- }
- externpy = (struct _cffi_externpy_s *)g->address;
- interpstate_key = PyLong_FromVoidPtr((void *)externpy);
- if (interpstate_key == NULL) {
- Py_DECREF(infotuple);
- return NULL;
- }
- err = PyDict_SetItem(interpstate_dict, interpstate_key, infotuple);
- Py_DECREF(interpstate_key);
- Py_DECREF(infotuple);
- if (err < 0)
- return NULL;
-
- old1 = externpy->reserved1;
- externpy->reserved1 = Py_None;
- Py_INCREF(Py_None);
- Py_XDECREF(old1);
-
- Py_INCREF(fn);
- return fn;
- not_found:
- PyErr_Format(FFIError, "ffi.def_extern('%s'): no 'extern \"Python\"' "
- "function with this name", s);
- Py_XDECREF(name);
- return NULL;
- }
- static int _update_cache_to_call_python(struct _cffi_externpy_s *externpy)
- {
- PyObject *interpstate_dict, *interpstate_key, *infotuple, *old1, *new1;
- PyObject *old2;
- interpstate_dict = _get_interpstate_dict();
- if (interpstate_dict == NULL)
- return 4;
- interpstate_key = PyLong_FromVoidPtr((void *)externpy);
- if (interpstate_key == NULL)
- goto error;
- infotuple = PyDict_GetItem(interpstate_dict, interpstate_key);
- Py_DECREF(interpstate_key);
- if (infotuple == NULL)
- return 3;
- new1 = _current_interp_key();
- Py_INCREF(new1);
- Py_INCREF(infotuple);
- old1 = (PyObject *)externpy->reserved1;
- old2 = (PyObject *)externpy->reserved2;
- externpy->reserved1 = new1;
- externpy->reserved2 = infotuple;
- Py_XDECREF(old1);
- Py_XDECREF(old2);
- return 0;
- error:
- PyErr_Clear();
- return 2;
- }
- #if (defined(WITH_THREAD) && !defined(_MSC_VER) && \
- !defined(__amd64__) && !defined(__x86_64__) && \
- !defined(__i386__) && !defined(__i386))
- # if defined(HAVE_SYNC_SYNCHRONIZE)
- # define read_barrier() __sync_synchronize()
- # elif defined(_AIX)
- # define read_barrier() __lwsync()
- # elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
- # error #include <mbarrier.h>
- # define read_barrier() __compiler_barrier()
- # elif defined(__hpux)
- # define read_barrier() _Asm_mf()
- # else
- # define read_barrier()
- # warning "no definition for read_barrier(), missing synchronization for\
- multi-thread initialization in embedded mode"
- # endif
- #else
- # define read_barrier() (void)0
- #endif
- static void cffi_call_python(struct _cffi_externpy_s *externpy, char *args)
- {
-
- int err = 0;
-
- read_barrier();
- save_errno();
-
- if (externpy->reserved1 == NULL) {
-
- err = 1;
- }
- else {
- PyGILState_STATE state = gil_ensure();
- if (externpy->reserved1 != _current_interp_key()) {
-
- err = _update_cache_to_call_python(externpy);
- }
- if (!err) {
- general_invoke_callback(0, args, args, externpy->reserved2);
- }
- gil_release(state);
- }
- if (err) {
- static const char *msg[] = {
- "no code was attached to it yet with @ffi.def_extern()",
- "got internal exception (out of memory?)",
- "@ffi.def_extern() was not called in the current subinterpreter",
- "got internal exception (shutdown issue?)",
- };
- fprintf(stderr, "extern \"Python\": function %s() called, "
- "but %s. Returning 0.\n", externpy->name, msg[err-1]);
- memset(args, 0, externpy->size_of_result);
- }
- restore_errno();
- }
|