11ae940a5870df2f706fa884afd533847f6b0b1a8Guido van Rossum
21ae940a5870df2f706fa884afd533847f6b0b1a8Guido van Rossum/* Support for dynamic loading of extension modules */
31ae940a5870df2f706fa884afd533847f6b0b1a8Guido van Rossum
479f25d9a7b853a9f491a0cfe4b81eeb9e2d19569Guido van Rossum#include "Python.h"
51ae940a5870df2f706fa884afd533847f6b0b1a8Guido van Rossum
696a8fb7e99aa8d612473a1dd87e4c1deb8408898Guido van Rossum/* ./configure sets HAVE_DYNAMIC_LOADING if dynamic loading of modules is
796a8fb7e99aa8d612473a1dd87e4c1deb8408898Guido van Rossum   supported on this platform. configure will then compile and link in one
896a8fb7e99aa8d612473a1dd87e4c1deb8408898Guido van Rossum   of the dynload_*.c files, as appropriate. We will call a function in
996a8fb7e99aa8d612473a1dd87e4c1deb8408898Guido van Rossum   those modules to get a function pointer to the module's init function.
101ae940a5870df2f706fa884afd533847f6b0b1a8Guido van Rossum*/
116ea909262526ebd1fb96b8fe2d9d36d98a4bca13Guido van Rossum#ifdef HAVE_DYNAMIC_LOADING
121ae940a5870df2f706fa884afd533847f6b0b1a8Guido van Rossum
1396a8fb7e99aa8d612473a1dd87e4c1deb8408898Guido van Rossum#include "importdl.h"
1496a8fb7e99aa8d612473a1dd87e4c1deb8408898Guido van Rossum
156ea909262526ebd1fb96b8fe2d9d36d98a4bca13Guido van Rossumextern dl_funcptr _PyImport_GetDynLoadFunc(const char *name,
16c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou                                           const char *shortname,
17c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou                                           const char *pathname, FILE *fp);
188e9ebfd337f18f7b707853a3f2f49cc6245c0596Guido van Rossum
193823420ca4432c20892cbff0267219fe16358a94Guido van Rossum
206ea909262526ebd1fb96b8fe2d9d36d98a4bca13Guido van Rossum
2179f25d9a7b853a9f491a0cfe4b81eeb9e2d19569Guido van RossumPyObject *
22f70ef4f8606f99744252a804229d53a4d97601c1Thomas Wouters_PyImport_LoadDynamicModule(char *name, char *pathname, FILE *fp)
231ae940a5870df2f706fa884afd533847f6b0b1a8Guido van Rossum{
24c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    PyObject *m;
25c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    char *lastdot, *shortname, *packagecontext, *oldcontext;
26c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    dl_funcptr p;
276ea909262526ebd1fb96b8fe2d9d36d98a4bca13Guido van Rossum
28c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    if ((m = _PyImport_FindExtension(name, pathname)) != NULL) {
29c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        Py_INCREF(m);
30c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        return m;
31c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    }
32c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    lastdot = strrchr(name, '.');
33c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    if (lastdot == NULL) {
34c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        packagecontext = NULL;
35c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        shortname = name;
36c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    }
37c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    else {
38c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        packagecontext = name;
39c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        shortname = lastdot+1;
40c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    }
4111a3f0c2bca1a8fdea396b989559f25fbc6fe65eGuido van Rossum
42c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    p = _PyImport_GetDynLoadFunc(name, shortname, pathname, fp);
43c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    if (PyErr_Occurred())
44c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        return NULL;
45c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    if (p == NULL) {
46c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        PyErr_Format(PyExc_ImportError,
47c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou           "dynamic module does not define init function (init%.200s)",
48c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou                     shortname);
49c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        return NULL;
50c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    }
51c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    oldcontext = _Py_PackageContext;
52c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    _Py_PackageContext = packagecontext;
53c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    (*p)();
54c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    _Py_PackageContext = oldcontext;
55c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    if (PyErr_Occurred())
56c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        return NULL;
571ae940a5870df2f706fa884afd533847f6b0b1a8Guido van Rossum
58c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    m = PyDict_GetItemString(PyImport_GetModuleDict(), name);
59c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    if (m == NULL) {
60c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        PyErr_SetString(PyExc_SystemError,
61c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou                        "dynamic module not initialized properly");
62c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        return NULL;
63c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    }
64c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    /* Remember the filename as the __file__ attribute */
65c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    if (PyModule_AddStringConstant(m, "__file__", pathname) < 0)
66c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        PyErr_Clear(); /* Not important enough to report */
67e81e9b1d3be5c2197235e3dc130c41f18a42edf7Martin v. Löwis
68c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    if (_PyImport_FixupExtension(name, pathname) == NULL)
69c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        return NULL;
70c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    if (Py_VerboseFlag)
71c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou        PySys_WriteStderr(
72c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou            "import %s # dynamically loaded from %s\n",
73c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou            name, pathname);
74c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    Py_INCREF(m);
75c83ea137d7e717f764e2f31fc2544f522de7d857Antoine Pitrou    return m;
761a8791e0b875df8e9428c2d9969f64e5967ac0b4Guido van Rossum}
7796a8fb7e99aa8d612473a1dd87e4c1deb8408898Guido van Rossum
7896a8fb7e99aa8d612473a1dd87e4c1deb8408898Guido van Rossum#endif /* HAVE_DYNAMIC_LOADING */
79