1 | |
2 | /* Support for dynamic loading of extension modules */ |
3 | |
4 | #include "Python.h" |
5 | |
6 | /* ./configure sets HAVE_DYNAMIC_LOADING if dynamic loading of modules is |
7 | supported on this platform. configure will then compile and link in one |
8 | of the dynload_*.c files, as appropriate. We will call a function in |
9 | those modules to get a function pointer to the module's init function. |
10 | */ |
11 | #ifdef HAVE_DYNAMIC_LOADING |
12 | |
13 | #include "importdl.h" |
14 | |
15 | #ifdef MS_WINDOWS |
16 | extern dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix, |
17 | const char *shortname, |
18 | PyObject *pathname, |
19 | FILE *fp); |
20 | #else |
21 | extern dl_funcptr _PyImport_FindSharedFuncptr(const char *prefix, |
22 | const char *shortname, |
23 | const char *pathname, FILE *fp); |
24 | #endif |
25 | |
26 | static const char * const ascii_only_prefix = "PyInit" ; |
27 | static const char * const nonascii_prefix = "PyInitU" ; |
28 | |
29 | /* Get the variable part of a module's export symbol name. |
30 | * Returns a bytes instance. For non-ASCII-named modules, the name is |
31 | * encoded as per PEP 489. |
32 | * The hook_prefix pointer is set to either ascii_only_prefix or |
33 | * nonascii_prefix, as appropriate. |
34 | */ |
35 | static PyObject * |
36 | get_encoded_name(PyObject *name, const char **hook_prefix) { |
37 | PyObject *tmp; |
38 | PyObject *encoded = NULL; |
39 | PyObject *modname = NULL; |
40 | Py_ssize_t name_len, lastdot; |
41 | _Py_IDENTIFIER(replace); |
42 | |
43 | /* Get the short name (substring after last dot) */ |
44 | name_len = PyUnicode_GetLength(name); |
45 | if (name_len < 0) { |
46 | return NULL; |
47 | } |
48 | lastdot = PyUnicode_FindChar(name, '.', 0, name_len, -1); |
49 | if (lastdot < -1) { |
50 | return NULL; |
51 | } else if (lastdot >= 0) { |
52 | tmp = PyUnicode_Substring(name, lastdot + 1, name_len); |
53 | if (tmp == NULL) |
54 | return NULL; |
55 | name = tmp; |
56 | /* "name" now holds a new reference to the substring */ |
57 | } else { |
58 | Py_INCREF(name); |
59 | } |
60 | |
61 | /* Encode to ASCII or Punycode, as needed */ |
62 | encoded = PyUnicode_AsEncodedString(name, "ascii" , NULL); |
63 | if (encoded != NULL) { |
64 | *hook_prefix = ascii_only_prefix; |
65 | } else { |
66 | if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) { |
67 | PyErr_Clear(); |
68 | encoded = PyUnicode_AsEncodedString(name, "punycode" , NULL); |
69 | if (encoded == NULL) { |
70 | goto error; |
71 | } |
72 | *hook_prefix = nonascii_prefix; |
73 | } else { |
74 | goto error; |
75 | } |
76 | } |
77 | |
78 | /* Replace '-' by '_' */ |
79 | modname = _PyObject_CallMethodId(encoded, &PyId_replace, "cc" , '-', '_'); |
80 | if (modname == NULL) |
81 | goto error; |
82 | |
83 | Py_DECREF(name); |
84 | Py_DECREF(encoded); |
85 | return modname; |
86 | error: |
87 | Py_DECREF(name); |
88 | Py_XDECREF(encoded); |
89 | return NULL; |
90 | } |
91 | |
92 | PyObject * |
93 | _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) |
94 | { |
95 | #ifndef MS_WINDOWS |
96 | PyObject *pathbytes = NULL; |
97 | #endif |
98 | PyObject *name_unicode = NULL, *name = NULL, *path = NULL, *m = NULL; |
99 | const char *name_buf, *hook_prefix; |
100 | const char *oldcontext; |
101 | dl_funcptr exportfunc; |
102 | PyModuleDef *def; |
103 | PyObject *(*p0)(void); |
104 | |
105 | name_unicode = PyObject_GetAttrString(spec, "name" ); |
106 | if (name_unicode == NULL) { |
107 | return NULL; |
108 | } |
109 | if (!PyUnicode_Check(name_unicode)) { |
110 | PyErr_SetString(PyExc_TypeError, |
111 | "spec.name must be a string" ); |
112 | goto error; |
113 | } |
114 | |
115 | name = get_encoded_name(name_unicode, &hook_prefix); |
116 | if (name == NULL) { |
117 | goto error; |
118 | } |
119 | name_buf = PyBytes_AS_STRING(name); |
120 | |
121 | path = PyObject_GetAttrString(spec, "origin" ); |
122 | if (path == NULL) |
123 | goto error; |
124 | |
125 | if (PySys_Audit("import" , "OOOOO" , name_unicode, path, |
126 | Py_None, Py_None, Py_None) < 0) { |
127 | goto error; |
128 | } |
129 | |
130 | #ifdef MS_WINDOWS |
131 | exportfunc = _PyImport_FindSharedFuncptrWindows(hook_prefix, name_buf, |
132 | path, fp); |
133 | #else |
134 | pathbytes = PyUnicode_EncodeFSDefault(path); |
135 | if (pathbytes == NULL) |
136 | goto error; |
137 | exportfunc = _PyImport_FindSharedFuncptr(hook_prefix, name_buf, |
138 | PyBytes_AS_STRING(pathbytes), |
139 | fp); |
140 | Py_DECREF(pathbytes); |
141 | #endif |
142 | |
143 | if (exportfunc == NULL) { |
144 | if (!PyErr_Occurred()) { |
145 | PyObject *msg; |
146 | msg = PyUnicode_FromFormat( |
147 | "dynamic module does not define " |
148 | "module export function (%s_%s)" , |
149 | hook_prefix, name_buf); |
150 | if (msg == NULL) |
151 | goto error; |
152 | PyErr_SetImportError(msg, name_unicode, path); |
153 | Py_DECREF(msg); |
154 | } |
155 | goto error; |
156 | } |
157 | |
158 | p0 = (PyObject *(*)(void))exportfunc; |
159 | |
160 | /* Package context is needed for single-phase init */ |
161 | oldcontext = _Py_PackageContext; |
162 | _Py_PackageContext = PyUnicode_AsUTF8(name_unicode); |
163 | if (_Py_PackageContext == NULL) { |
164 | _Py_PackageContext = oldcontext; |
165 | goto error; |
166 | } |
167 | m = p0(); |
168 | _Py_PackageContext = oldcontext; |
169 | |
170 | if (m == NULL) { |
171 | if (!PyErr_Occurred()) { |
172 | PyErr_Format( |
173 | PyExc_SystemError, |
174 | "initialization of %s failed without raising an exception" , |
175 | name_buf); |
176 | } |
177 | goto error; |
178 | } else if (PyErr_Occurred()) { |
179 | PyErr_Clear(); |
180 | PyErr_Format( |
181 | PyExc_SystemError, |
182 | "initialization of %s raised unreported exception" , |
183 | name_buf); |
184 | m = NULL; |
185 | goto error; |
186 | } |
187 | if (Py_IS_TYPE(m, NULL)) { |
188 | /* This can happen when a PyModuleDef is returned without calling |
189 | * PyModuleDef_Init on it |
190 | */ |
191 | PyErr_Format(PyExc_SystemError, |
192 | "init function of %s returned uninitialized object" , |
193 | name_buf); |
194 | m = NULL; /* prevent segfault in DECREF */ |
195 | goto error; |
196 | } |
197 | if (PyObject_TypeCheck(m, &PyModuleDef_Type)) { |
198 | Py_DECREF(name_unicode); |
199 | Py_DECREF(name); |
200 | Py_DECREF(path); |
201 | return PyModule_FromDefAndSpec((PyModuleDef*)m, spec); |
202 | } |
203 | |
204 | /* Fall back to single-phase init mechanism */ |
205 | |
206 | if (hook_prefix == nonascii_prefix) { |
207 | /* don't allow legacy init for non-ASCII module names */ |
208 | PyErr_Format( |
209 | PyExc_SystemError, |
210 | "initialization of %s did not return PyModuleDef" , |
211 | name_buf); |
212 | goto error; |
213 | } |
214 | |
215 | /* Remember pointer to module init function. */ |
216 | def = PyModule_GetDef(m); |
217 | if (def == NULL) { |
218 | PyErr_Format(PyExc_SystemError, |
219 | "initialization of %s did not return an extension " |
220 | "module" , name_buf); |
221 | goto error; |
222 | } |
223 | def->m_base.m_init = p0; |
224 | |
225 | /* Remember the filename as the __file__ attribute */ |
226 | if (PyModule_AddObjectRef(m, "__file__" , path) < 0) { |
227 | PyErr_Clear(); /* Not important enough to report */ |
228 | } |
229 | |
230 | PyObject *modules = PyImport_GetModuleDict(); |
231 | if (_PyImport_FixupExtensionObject(m, name_unicode, path, modules) < 0) |
232 | goto error; |
233 | |
234 | Py_DECREF(name_unicode); |
235 | Py_DECREF(name); |
236 | Py_DECREF(path); |
237 | |
238 | return m; |
239 | |
240 | error: |
241 | Py_DECREF(name_unicode); |
242 | Py_XDECREF(name); |
243 | Py_XDECREF(path); |
244 | Py_XDECREF(m); |
245 | return NULL; |
246 | } |
247 | |
248 | #endif /* HAVE_DYNAMIC_LOADING */ |
249 | |