1
2 #include "parse_c_type.c"
3 #include "realize_c_type.c"
4
5 #define CFFI_VERSION_MIN 0x2601
6 #define CFFI_VERSION_CHAR16CHAR32 0x2801
7 #define CFFI_VERSION_MAX 0x28FF
8
9 typedef struct FFIObject_s FFIObject;
10 typedef struct LibObject_s LibObject;
11
12 static PyTypeObject FFI_Type; /* forward */
13 static PyTypeObject Lib_Type; /* forward */
14
15 #include "ffi_obj.c"
16 #include "cglob.c"
17 #include "lib_obj.c"
18 #include "cdlopen.c"
19 #include "commontypes.c"
20 #include "call_python.c"
21
22
init_ffi_lib(PyObject * m)23 static int init_ffi_lib(PyObject *m)
24 {
25 PyObject *x;
26 int i, res;
27 static char init_done = 0;
28
29 if (!init_done) {
30 if (init_global_types_dict(FFI_Type.tp_dict) < 0)
31 return -1;
32
33 FFIError = PyErr_NewException("ffi.error", NULL, NULL);
34 if (FFIError == NULL)
35 return -1;
36 if (PyDict_SetItemString(FFI_Type.tp_dict, "error", FFIError) < 0)
37 return -1;
38 if (PyDict_SetItemString(FFI_Type.tp_dict, "CType",
39 (PyObject *)&CTypeDescr_Type) < 0)
40 return -1;
41 if (PyDict_SetItemString(FFI_Type.tp_dict, "CData",
42 (PyObject *)&CData_Type) < 0)
43 return -1;
44 if (PyDict_SetItemString(FFI_Type.tp_dict, "buffer",
45 (PyObject *)&MiniBuffer_Type) < 0)
46 return -1;
47
48 for (i = 0; all_dlopen_flags[i].name != NULL; i++) {
49 x = PyInt_FromLong(all_dlopen_flags[i].value);
50 if (x == NULL)
51 return -1;
52 res = PyDict_SetItemString(FFI_Type.tp_dict,
53 all_dlopen_flags[i].name, x);
54 Py_DECREF(x);
55 if (res < 0)
56 return -1;
57 }
58 init_done = 1;
59 }
60 return 0;
61 }
62
make_included_tuples(char * module_name,const char * const * ctx_includes,PyObject ** included_ffis,PyObject ** included_libs)63 static int make_included_tuples(char *module_name,
64 const char *const *ctx_includes,
65 PyObject **included_ffis,
66 PyObject **included_libs)
67 {
68 Py_ssize_t num = 0;
69 const char *const *p_include;
70
71 if (ctx_includes == NULL)
72 return 0;
73
74 for (p_include = ctx_includes; *p_include; p_include++) {
75 num++;
76 }
77 *included_ffis = PyTuple_New(num);
78 *included_libs = PyTuple_New(num);
79 if (*included_ffis == NULL || *included_libs == NULL)
80 goto error;
81
82 num = 0;
83 for (p_include = ctx_includes; *p_include; p_include++) {
84 PyObject *included_ffi, *included_lib;
85 PyObject *m = PyImport_ImportModule(*p_include);
86 if (m == NULL)
87 goto import_error;
88
89 included_ffi = PyObject_GetAttrString(m, "ffi");
90 PyTuple_SET_ITEM(*included_ffis, num, included_ffi);
91
92 included_lib = (included_ffi == NULL) ? NULL :
93 PyObject_GetAttrString(m, "lib");
94 PyTuple_SET_ITEM(*included_libs, num, included_lib);
95
96 Py_DECREF(m);
97 if (included_lib == NULL)
98 goto import_error;
99
100 if (!FFIObject_Check(included_ffi) ||
101 !LibObject_Check(included_lib))
102 goto import_error;
103 num++;
104 }
105 return 0;
106
107 import_error:
108 PyErr_Format(PyExc_ImportError,
109 "while loading %.200s: failed to import ffi, lib from %.200s",
110 module_name, *p_include);
111 error:
112 Py_XDECREF(*included_ffis); *included_ffis = NULL;
113 Py_XDECREF(*included_libs); *included_libs = NULL;
114 return -1;
115 }
116
_my_Py_InitModule(char * module_name)117 static PyObject *_my_Py_InitModule(char *module_name)
118 {
119 #if PY_MAJOR_VERSION >= 3
120 struct PyModuleDef *module_def, local_module_def = {
121 PyModuleDef_HEAD_INIT,
122 module_name,
123 NULL,
124 -1,
125 NULL, NULL, NULL, NULL, NULL
126 };
127 /* note: the 'module_def' is allocated dynamically and leaks,
128 but anyway the C extension module can never be unloaded */
129 module_def = PyMem_Malloc(sizeof(struct PyModuleDef));
130 if (module_def == NULL)
131 return PyErr_NoMemory();
132 *module_def = local_module_def;
133 return PyModule_Create(module_def);
134 #else
135 return Py_InitModule(module_name, NULL);
136 #endif
137 }
138
b_init_cffi_1_0_external_module(PyObject * self,PyObject * arg)139 static PyObject *b_init_cffi_1_0_external_module(PyObject *self, PyObject *arg)
140 {
141 PyObject *m, *modules_dict;
142 FFIObject *ffi;
143 LibObject *lib;
144 Py_ssize_t version, num_exports;
145 char *module_name, *exports, *module_name_with_lib;
146 void **raw;
147 const struct _cffi_type_context_s *ctx;
148
149 raw = (void **)PyLong_AsVoidPtr(arg);
150 if (raw == NULL)
151 return NULL;
152
153 module_name = (char *)raw[0];
154 version = (Py_ssize_t)raw[1];
155 exports = (char *)raw[2];
156 ctx = (const struct _cffi_type_context_s *)raw[3];
157
158 if (version < CFFI_VERSION_MIN || version > CFFI_VERSION_MAX) {
159 if (!PyErr_Occurred())
160 PyErr_Format(PyExc_ImportError,
161 "cffi extension module '%s' uses an unknown version tag %p. "
162 "This module might need a more recent version of cffi "
163 "than the one currently installed, which is %s",
164 module_name, (void *)version, CFFI_VERSION);
165 return NULL;
166 }
167
168 /* initialize the exports array */
169 num_exports = 25;
170 if (ctx->flags & 1) /* set to mean that 'extern "Python"' is used */
171 num_exports = 26;
172 if (version >= CFFI_VERSION_CHAR16CHAR32)
173 num_exports = 28;
174 memcpy(exports, (char *)cffi_exports, num_exports * sizeof(void *));
175
176 /* make the module object */
177 m = _my_Py_InitModule(module_name);
178 if (m == NULL)
179 return NULL;
180
181 /* build the FFI and Lib object inside this new module */
182 ffi = ffi_internal_new(&FFI_Type, ctx);
183 Py_XINCREF(ffi); /* make the ffi object really immortal */
184 if (ffi == NULL || PyModule_AddObject(m, "ffi", (PyObject *)ffi) < 0)
185 return NULL;
186
187 lib = lib_internal_new(ffi, module_name, NULL, 0);
188 if (lib == NULL || PyModule_AddObject(m, "lib", (PyObject *)lib) < 0)
189 return NULL;
190
191 if (make_included_tuples(module_name, ctx->includes,
192 &ffi->types_builder.included_ffis,
193 &lib->l_types_builder->included_libs) < 0)
194 return NULL;
195
196 /* add manually 'module_name.lib' in sys.modules:
197 see test_import_from_lib */
198 modules_dict = PySys_GetObject("modules");
199 if (!modules_dict)
200 return NULL;
201 module_name_with_lib = alloca(strlen(module_name) + 5);
202 strcpy(module_name_with_lib, module_name);
203 strcat(module_name_with_lib, ".lib");
204 if (PyDict_SetItemString(modules_dict, module_name_with_lib,
205 (PyObject *)lib) < 0)
206 return NULL;
207
208 #if PY_MAJOR_VERSION >= 3
209 /* add manually 'module_name' in sys.modules: it seems that
210 Py_InitModule() is not enough to do that */
211 if (PyDict_SetItemString(modules_dict, module_name, m) < 0)
212 return NULL;
213 #endif
214
215 return m;
216 }
217