Home | History | Annotate | Download | only in Python
      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     lastdot = PyUnicode_FindChar(name, '.', 0, name_len, -1);
     46     if (lastdot < -1) {
     47         return NULL;
     48     } else if (lastdot >= 0) {
     49         tmp = PyUnicode_Substring(name, lastdot + 1, name_len);
     50         if (tmp == NULL)
     51             return NULL;
     52         name = tmp;
     53         /* "name" now holds a new reference to the substring */
     54     } else {
     55         Py_INCREF(name);
     56     }
     57 
     58     /* Encode to ASCII or Punycode, as needed */
     59     encoded = PyUnicode_AsEncodedString(name, "ascii", NULL);
     60     if (encoded != NULL) {
     61         *hook_prefix = ascii_only_prefix;
     62     } else {
     63         if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) {
     64             PyErr_Clear();
     65             encoded = PyUnicode_AsEncodedString(name, "punycode", NULL);
     66             if (encoded == NULL) {
     67                 goto error;
     68             }
     69             *hook_prefix = nonascii_prefix;
     70         } else {
     71             goto error;
     72         }
     73     }
     74 
     75     /* Replace '-' by '_' */
     76     modname = _PyObject_CallMethodId(encoded, &PyId_replace, "cc", '-', '_');
     77     if (modname == NULL)
     78         goto error;
     79 
     80     Py_DECREF(name);
     81     Py_DECREF(encoded);
     82     return modname;
     83 error:
     84     Py_DECREF(name);
     85     Py_XDECREF(encoded);
     86     return NULL;
     87 }
     88 
     89 PyObject *
     90 _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp)
     91 {
     92 #ifndef MS_WINDOWS
     93     PyObject *pathbytes = NULL;
     94 #endif
     95     PyObject *name_unicode = NULL, *name = NULL, *path = NULL, *m = NULL;
     96     const char *name_buf, *hook_prefix;
     97     char *oldcontext;
     98     dl_funcptr exportfunc;
     99     PyModuleDef *def;
    100     PyObject *(*p0)(void);
    101 
    102     name_unicode = PyObject_GetAttrString(spec, "name");
    103     if (name_unicode == NULL) {
    104         return NULL;
    105     }
    106 
    107     name = get_encoded_name(name_unicode, &hook_prefix);
    108     if (name == NULL) {
    109         goto error;
    110     }
    111     name_buf = PyBytes_AS_STRING(name);
    112 
    113     path = PyObject_GetAttrString(spec, "origin");
    114     if (path == NULL)
    115         goto error;
    116 
    117 #ifdef MS_WINDOWS
    118     exportfunc = _PyImport_FindSharedFuncptrWindows(hook_prefix, name_buf,
    119                                                     path, fp);
    120 #else
    121     pathbytes = PyUnicode_EncodeFSDefault(path);
    122     if (pathbytes == NULL)
    123         goto error;
    124     exportfunc = _PyImport_FindSharedFuncptr(hook_prefix, name_buf,
    125                                              PyBytes_AS_STRING(pathbytes),
    126                                              fp);
    127     Py_DECREF(pathbytes);
    128 #endif
    129 
    130     if (exportfunc == NULL) {
    131         if (!PyErr_Occurred()) {
    132             PyObject *msg;
    133             msg = PyUnicode_FromFormat(
    134                 "dynamic module does not define "
    135                 "module export function (%s_%s)",
    136                 hook_prefix, name_buf);
    137             if (msg == NULL)
    138                 goto error;
    139             PyErr_SetImportError(msg, name_unicode, path);
    140             Py_DECREF(msg);
    141         }
    142         goto error;
    143     }
    144 
    145     p0 = (PyObject *(*)(void))exportfunc;
    146 
    147     /* Package context is needed for single-phase init */
    148     oldcontext = _Py_PackageContext;
    149     _Py_PackageContext = PyUnicode_AsUTF8(name_unicode);
    150     if (_Py_PackageContext == NULL) {
    151         _Py_PackageContext = oldcontext;
    152         goto error;
    153     }
    154     m = p0();
    155     _Py_PackageContext = oldcontext;
    156 
    157     if (m == NULL) {
    158         if (!PyErr_Occurred()) {
    159             PyErr_Format(
    160                 PyExc_SystemError,
    161                 "initialization of %s failed without raising an exception",
    162                 name_buf);
    163         }
    164         goto error;
    165     } else if (PyErr_Occurred()) {
    166         PyErr_Clear();
    167         PyErr_Format(
    168             PyExc_SystemError,
    169             "initialization of %s raised unreported exception",
    170             name_buf);
    171         m = NULL;
    172         goto error;
    173     }
    174     if (Py_TYPE(m) == NULL) {
    175         /* This can happen when a PyModuleDef is returned without calling
    176          * PyModuleDef_Init on it
    177          */
    178         PyErr_Format(PyExc_SystemError,
    179                      "init function of %s returned uninitialized object",
    180                      name_buf);
    181         m = NULL; /* prevent segfault in DECREF */
    182         goto error;
    183     }
    184     if (PyObject_TypeCheck(m, &PyModuleDef_Type)) {
    185         Py_DECREF(name_unicode);
    186         Py_DECREF(name);
    187         Py_DECREF(path);
    188         return PyModule_FromDefAndSpec((PyModuleDef*)m, spec);
    189     }
    190 
    191     /* Fall back to single-phase init mechanism */
    192 
    193     if (hook_prefix == nonascii_prefix) {
    194         /* don't allow legacy init for non-ASCII module names */
    195         PyErr_Format(
    196             PyExc_SystemError,
    197             "initialization of * did not return PyModuleDef",
    198             name_buf);
    199         goto error;
    200     }
    201 
    202     /* Remember pointer to module init function. */
    203     def = PyModule_GetDef(m);
    204     if (def == NULL) {
    205         PyErr_Format(PyExc_SystemError,
    206                      "initialization of %s did not return an extension "
    207                      "module", name_buf);
    208         goto error;
    209     }
    210     def->m_base.m_init = p0;
    211 
    212     /* Remember the filename as the __file__ attribute */
    213     if (PyModule_AddObject(m, "__file__", path) < 0)
    214         PyErr_Clear(); /* Not important enough to report */
    215     else
    216         Py_INCREF(path);
    217 
    218     if (_PyImport_FixupExtensionObject(m, name_unicode, path) < 0)
    219         goto error;
    220 
    221     Py_DECREF(name_unicode);
    222     Py_DECREF(name);
    223     Py_DECREF(path);
    224 
    225     return m;
    226 
    227 error:
    228     Py_DECREF(name_unicode);
    229     Py_XDECREF(name);
    230     Py_XDECREF(path);
    231     Py_XDECREF(m);
    232     return NULL;
    233 }
    234 
    235 #endif /* HAVE_DYNAMIC_LOADING */
    236