| #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 (PyType_Ready(&FFI_Type) < 0) | |
| return -1; | |
| if (PyType_Ready(&Lib_Type) < 0) | |
| return -1; | |
| 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; | |
| } | |
| x = (PyObject *)&FFI_Type; | |
| Py_INCREF(x); | |
| if (PyModule_AddObject(m, "FFI", x) < 0) | |
| return -1; | |
| x = (PyObject *)&Lib_Type; | |
| Py_INCREF(x); | |
| if (PyModule_AddObject(m, "Lib", x) < 0) | |
| return -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); | |
| 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; | |
| } |