blob: 16f15d9a8147655442ef576ccd49539aa1c853af [file] [log] [blame]
Guido van Rossum22a1d361999-12-20 21:18:49 +00001
2/* Support for dynamic loading of extension modules */
3
4#include "Python.h"
5#include "importdl.h"
6
7#include <sys/types.h>
8#include <sys/stat.h>
9#if defined(__NetBSD__) && (NetBSD < 199712)
10#include <nlist.h>
11#include <link.h>
12#define dlerror() "error in dynamic linking"
13#else
14#ifdef HAVE_DLFCN_H
15#include <dlfcn.h>
16#endif
17#endif
18
19#ifndef RTLD_LAZY
20#define RTLD_LAZY 1
21#endif
22
23
24const struct filedescr _PyImport_DynLoadFiletab[] = {
25 {".so", "rb", C_EXTENSION},
26 {"module.so", "rb", C_EXTENSION},
27 {0, 0}
28};
29
30static struct {
31 dev_t dev;
32 ino_t ino;
33 void *handle;
34} handles[128];
35static int nhandles = 0;
36
37
Guido van Rossum96a8fb71999-12-22 14:09:35 +000038dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
Guido van Rossum22a1d361999-12-20 21:18:49 +000039 const char *pathname, FILE *fp)
40{
41 dl_funcptr p;
42 void *handle;
Guido van Rossum96a8fb71999-12-22 14:09:35 +000043 char funcname[258];
44 char pathbuf[260];
45
46 if (strchr(pathname, '/') == NULL) {
47 /* Prefix bare filename with "./" */
48 sprintf(pathbuf, "./%-.255s", pathname);
49 pathname = pathbuf;
50 }
51
52 /* ### should there be a leading underscore for some platforms? */
53 sprintf(funcname, "init%.200s", shortname);
Guido van Rossum22a1d361999-12-20 21:18:49 +000054
55 if (fp != NULL) {
56 int i;
57 struct stat statb;
58 fstat(fileno(fp), &statb);
59 for (i = 0; i < nhandles; i++) {
60 if (statb.st_dev == handles[i].dev &&
61 statb.st_ino == handles[i].ino) {
62 p = (dl_funcptr) dlsym(handles[i].handle,
63 funcname);
64 return p;
65 }
66 }
67 if (nhandles < 128) {
68 handles[nhandles].dev = statb.st_dev;
69 handles[nhandles].ino = statb.st_ino;
70 }
71 }
72
73#ifdef RTLD_NOW
74 /* RTLD_NOW: resolve externals now
75 (i.e. core dump now if some are missing) */
76 handle = dlopen(pathname, RTLD_NOW);
77#else
78 if (Py_VerboseFlag)
79 printf("dlopen(\"%s\", %d);\n", pathname,
80 RTLD_LAZY);
81 handle = dlopen(pathname, RTLD_LAZY);
82#endif /* RTLD_NOW */
83 if (handle == NULL) {
84 PyErr_SetString(PyExc_ImportError, dlerror());
85 return NULL;
86 }
87 if (fp != NULL && nhandles < 128)
88 handles[nhandles++].handle = handle;
89 p = (dl_funcptr) dlsym(handle, funcname);
90 return p;
91}