dynload_shlib.c 4.09 KB
Newer Older
1 2 3 4 5 6 7 8

/* Support for dynamic loading of extension modules */

#include "Python.h"
#include "importdl.h"

#include <sys/types.h>
#include <sys/stat.h>
9

10 11 12
#if defined(__NetBSD__)
#include <sys/param.h>
#if (NetBSD < 199712)
13 14 15
#include <nlist.h>
#include <link.h>
#define dlerror() "error in dynamic linking"
16 17 18
#endif
#endif /* NetBSD */

19 20
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
21 22 23 24
#else
#if defined(PYOS_OS2) && defined(PYCC_GCC)
#include "dlfcn.h"
#endif
25 26
#endif

27
#if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__)
28 29 30 31 32
#define LEAD_UNDERSCORE "_"
#else
#define LEAD_UNDERSCORE ""
#endif

Barry Warsaw's avatar
Barry Warsaw committed
33 34 35 36 37
/* The .so extension module ABI tag, supplied by the Makefile via
   Makefile.pre.in and configure.  This is used to discriminate between
   incompatible .so files so that extensions for different Python builds can
   live in the same directory.  E.g. foomodule.cpython-32.so
*/
38 39

const struct filedescr _PyImport_DynLoadFiletab[] = {
40
#ifdef __CYGWIN__
41 42
    {".dll", "rb", C_EXTENSION},
    {"module.dll", "rb", C_EXTENSION},
Barry Warsaw's avatar
Barry Warsaw committed
43
#else  /* !__CYGWIN__ */
44
#if defined(PYOS_OS2) && defined(PYCC_GCC)
45 46
    {".pyd", "rb", C_EXTENSION},
    {".dll", "rb", C_EXTENSION},
Barry Warsaw's avatar
Barry Warsaw committed
47
#else  /* !(defined(PYOS_OS2) && defined(PYCC_GCC)) */
48
#ifdef __VMS
49 50 51 52
    {".exe", "rb", C_EXTENSION},
    {".EXE", "rb", C_EXTENSION},
    {"module.exe", "rb", C_EXTENSION},
    {"MODULE.EXE", "rb", C_EXTENSION},
Barry Warsaw's avatar
Barry Warsaw committed
53 54 55
#else  /* !__VMS */
    {"." SOABI ".so", "rb", C_EXTENSION},
    {"module." SOABI ".so", "rb", C_EXTENSION},
56
    {".so", "rb", C_EXTENSION},
57
    {"module.so", "rb", C_EXTENSION},
Barry Warsaw's avatar
Barry Warsaw committed
58 59 60
#endif  /* __VMS */
#endif  /* defined(PYOS_OS2) && defined(PYCC_GCC) */
#endif  /* __CYGWIN__ */
61
    {0, 0}
62 63 64
};

static struct {
65
    dev_t dev;
66
#ifdef __VMS
67
    ino_t ino[3];
68
#else
69
    ino_t ino;
70
#endif
71
    void *handle;
72 73 74 75
} handles[128];
static int nhandles = 0;


76
dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
77
                                    const char *pathname, FILE *fp)
78
{
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
    dl_funcptr p;
    void *handle;
    char funcname[258];
    char pathbuf[260];
    int dlopenflags=0;

    if (strchr(pathname, '/') == NULL) {
        /* Prefix bare filename with "./" */
        PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
        pathname = pathbuf;
    }

    PyOS_snprintf(funcname, sizeof(funcname),
                  LEAD_UNDERSCORE "PyInit_%.200s", shortname);

    if (fp != NULL) {
        int i;
        struct stat statb;
        fstat(fileno(fp), &statb);
        for (i = 0; i < nhandles; i++) {
            if (statb.st_dev == handles[i].dev &&
                statb.st_ino == handles[i].ino) {
                p = (dl_funcptr) dlsym(handles[i].handle,
                                       funcname);
                return p;
            }
        }
        if (nhandles < 128) {
            handles[nhandles].dev = statb.st_dev;
108
#ifdef __VMS
109 110 111
            handles[nhandles].ino[0] = statb.st_ino[0];
            handles[nhandles].ino[1] = statb.st_ino[1];
            handles[nhandles].ino[2] = statb.st_ino[2];
112
#else
113
            handles[nhandles].ino = statb.st_ino;
114
#endif
115 116
        }
    }
117

118
#if !(defined(PYOS_OS2) && defined(PYCC_GCC))
119
    dlopenflags = PyThreadState_GET()->interp->dlopenflags;
120
#endif
121

122 123 124
    if (Py_VerboseFlag)
        PySys_WriteStderr("dlopen(\"%s\", %x);\n", pathname,
                          dlopenflags);
125

126
#ifdef __VMS
127 128 129 130 131 132 133 134
    /* VMS currently don't allow a pathname, use a logical name instead */
    /* Concatenate 'python_module_' and shortname */
    /* so "import vms.bar" will use the logical python_module_bar */
    /* As C module use only one name space this is probably not a */
    /* important limitation */
    PyOS_snprintf(pathbuf, sizeof(pathbuf), "python_module_%-.200s",
                  shortname);
    pathname = pathbuf;
135 136
#endif

137 138 139 140 141 142 143 144 145 146 147 148 149
    handle = dlopen(pathname, dlopenflags);

    if (handle == NULL) {
        const char *error = dlerror();
        if (error == NULL)
            error = "unknown dlopen() error";
        PyErr_SetString(PyExc_ImportError, error);
        return NULL;
    }
    if (fp != NULL && nhandles < 128)
        handles[nhandles++].handle = handle;
    p = (dl_funcptr) dlsym(handle, funcname);
    return p;
150
}