diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/python/cffi/c/cffi1_module.c | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/python/cffi/c/cffi1_module.c')
-rw-r--r-- | contrib/python/cffi/c/cffi1_module.c | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/contrib/python/cffi/c/cffi1_module.c b/contrib/python/cffi/c/cffi1_module.c new file mode 100644 index 0000000000..06a84fea37 --- /dev/null +++ b/contrib/python/cffi/c/cffi1_module.c @@ -0,0 +1,216 @@ + +#include "parse_c_type.c" +#include "realize_c_type.c" + +#define CFFI_VERSION_MIN 0x2601 +#define CFFI_VERSION_CHAR16CHAR32 0x2801 +#define CFFI_VERSION_MAX 0x28FF + +typedef struct FFIObject_s FFIObject; +typedef struct LibObject_s LibObject; + +static PyTypeObject FFI_Type; /* forward */ +static PyTypeObject Lib_Type; /* forward */ + +#include "ffi_obj.c" +#include "cglob.c" +#include "lib_obj.c" +#include "cdlopen.c" +#include "commontypes.c" +#include "call_python.c" + + +static int init_ffi_lib(PyObject *m) +{ + PyObject *x; + int i, res; + static char init_done = 0; + + if (!init_done) { + if (init_global_types_dict(FFI_Type.tp_dict) < 0) + return -1; + + FFIError = PyErr_NewException("ffi.error", NULL, NULL); + if (FFIError == NULL) + return -1; + if (PyDict_SetItemString(FFI_Type.tp_dict, "error", FFIError) < 0) + return -1; + if (PyDict_SetItemString(FFI_Type.tp_dict, "CType", + (PyObject *)&CTypeDescr_Type) < 0) + return -1; + if (PyDict_SetItemString(FFI_Type.tp_dict, "CData", + (PyObject *)&CData_Type) < 0) + return -1; + if (PyDict_SetItemString(FFI_Type.tp_dict, "buffer", + (PyObject *)&MiniBuffer_Type) < 0) + return -1; + + for (i = 0; all_dlopen_flags[i].name != NULL; i++) { + x = PyInt_FromLong(all_dlopen_flags[i].value); + if (x == NULL) + return -1; + res = PyDict_SetItemString(FFI_Type.tp_dict, + all_dlopen_flags[i].name, x); + Py_DECREF(x); + if (res < 0) + return -1; + } + init_done = 1; + } + return 0; +} + +static int make_included_tuples(char *module_name, + const char *const *ctx_includes, + PyObject **included_ffis, + PyObject **included_libs) +{ + Py_ssize_t num = 0; + const char *const *p_include; + + if (ctx_includes == NULL) + return 0; + + for (p_include = ctx_includes; *p_include; p_include++) { + num++; + } + *included_ffis = PyTuple_New(num); + *included_libs = PyTuple_New(num); + if (*included_ffis == NULL || *included_libs == NULL) + goto error; + + num = 0; + for (p_include = ctx_includes; *p_include; p_include++) { + PyObject *included_ffi, *included_lib; + PyObject *m = PyImport_ImportModule(*p_include); + if (m == NULL) + goto import_error; + + included_ffi = PyObject_GetAttrString(m, "ffi"); + PyTuple_SET_ITEM(*included_ffis, num, included_ffi); + + included_lib = (included_ffi == NULL) ? NULL : + PyObject_GetAttrString(m, "lib"); + PyTuple_SET_ITEM(*included_libs, num, included_lib); + + Py_DECREF(m); + if (included_lib == NULL) + goto import_error; + + if (!FFIObject_Check(included_ffi) || + !LibObject_Check(included_lib)) + goto import_error; + num++; + } + return 0; + + import_error: + PyErr_Format(PyExc_ImportError, + "while loading %.200s: failed to import ffi, lib from %.200s", + module_name, *p_include); + error: + Py_XDECREF(*included_ffis); *included_ffis = NULL; + Py_XDECREF(*included_libs); *included_libs = NULL; + return -1; +} + +static PyObject *_my_Py_InitModule(char *module_name) +{ +#if PY_MAJOR_VERSION >= 3 + struct PyModuleDef *module_def, local_module_def = { + PyModuleDef_HEAD_INIT, + module_name, + NULL, + -1, + NULL, NULL, NULL, NULL, NULL + }; + /* note: the 'module_def' is allocated dynamically and leaks, + but anyway the C extension module can never be unloaded */ + module_def = PyMem_Malloc(sizeof(struct PyModuleDef)); + if (module_def == NULL) + return PyErr_NoMemory(); + *module_def = local_module_def; + return PyModule_Create(module_def); +#else + return Py_InitModule(module_name, NULL); +#endif +} + +static PyObject *b_init_cffi_1_0_external_module(PyObject *self, PyObject *arg) +{ + PyObject *m, *modules_dict; + FFIObject *ffi; + LibObject *lib; + Py_ssize_t version, num_exports; + char *module_name, *exports, *module_name_with_lib; + void **raw; + const struct _cffi_type_context_s *ctx; + + raw = (void **)PyLong_AsVoidPtr(arg); + if (raw == NULL) + return NULL; + + module_name = (char *)raw[0]; + version = (Py_ssize_t)raw[1]; + exports = (char *)raw[2]; + ctx = (const struct _cffi_type_context_s *)raw[3]; + + if (version < CFFI_VERSION_MIN || version > CFFI_VERSION_MAX) { + if (!PyErr_Occurred()) + PyErr_Format(PyExc_ImportError, + "cffi extension module '%s' uses an unknown version tag %p. " + "This module might need a more recent version of cffi " + "than the one currently installed, which is %s", + module_name, (void *)version, CFFI_VERSION); + return NULL; + } + + /* initialize the exports array */ + num_exports = 25; + if (ctx->flags & 1) /* set to mean that 'extern "Python"' is used */ + num_exports = 26; + if (version >= CFFI_VERSION_CHAR16CHAR32) + num_exports = 28; + memcpy(exports, (char *)cffi_exports, num_exports * sizeof(void *)); + + /* make the module object */ + m = _my_Py_InitModule(module_name); + if (m == NULL) + return NULL; + + /* build the FFI and Lib object inside this new module */ + ffi = ffi_internal_new(&FFI_Type, ctx); + Py_XINCREF(ffi); /* make the ffi object really immortal */ + if (ffi == NULL || PyModule_AddObject(m, "ffi", (PyObject *)ffi) < 0) + return NULL; + + lib = lib_internal_new(ffi, module_name, NULL, 0); + if (lib == NULL || PyModule_AddObject(m, "lib", (PyObject *)lib) < 0) + return NULL; + + if (make_included_tuples(module_name, ctx->includes, + &ffi->types_builder.included_ffis, + &lib->l_types_builder->included_libs) < 0) + return NULL; + + /* add manually 'module_name.lib' in sys.modules: + see test_import_from_lib */ + modules_dict = PySys_GetObject("modules"); + if (!modules_dict) + return NULL; + module_name_with_lib = alloca(strlen(module_name) + 5); + strcpy(module_name_with_lib, module_name); + strcat(module_name_with_lib, ".lib"); + if (PyDict_SetItemString(modules_dict, module_name_with_lib, + (PyObject *)lib) < 0) + return NULL; + +#if PY_MAJOR_VERSION >= 3 + /* add manually 'module_name' in sys.modules: it seems that + Py_InitModule() is not enough to do that */ + if (PyDict_SetItemString(modules_dict, module_name, m) < 0) + return NULL; +#endif + + return m; +} |