blob: 2b0e74ee17f306d6877cc16591f1f779a6d6c53b [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[] = {
Tim Peters98dc0652000-10-05 19:24:26 +000025#ifdef __CYGWIN__
26 {".pyd", "rb", C_EXTENSION},
27 {".dll", "rb", C_EXTENSION},
28#else
Guido van Rossum22a1d361999-12-20 21:18:49 +000029 {".so", "rb", C_EXTENSION},
30 {"module.so", "rb", C_EXTENSION},
Tim Peters98dc0652000-10-05 19:24:26 +000031#endif
Guido van Rossum22a1d361999-12-20 21:18:49 +000032 {0, 0}
33};
34
35static struct {
36 dev_t dev;
37 ino_t ino;
38 void *handle;
39} handles[128];
40static int nhandles = 0;
41
42
Guido van Rossum96a8fb71999-12-22 14:09:35 +000043dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
Guido van Rossum22a1d361999-12-20 21:18:49 +000044 const char *pathname, FILE *fp)
45{
46 dl_funcptr p;
47 void *handle;
Guido van Rossum96a8fb71999-12-22 14:09:35 +000048 char funcname[258];
49 char pathbuf[260];
50
51 if (strchr(pathname, '/') == NULL) {
52 /* Prefix bare filename with "./" */
53 sprintf(pathbuf, "./%-.255s", pathname);
54 pathname = pathbuf;
55 }
56
57 /* ### should there be a leading underscore for some platforms? */
58 sprintf(funcname, "init%.200s", shortname);
Guido van Rossum22a1d361999-12-20 21:18:49 +000059
60 if (fp != NULL) {
61 int i;
62 struct stat statb;
63 fstat(fileno(fp), &statb);
64 for (i = 0; i < nhandles; i++) {
65 if (statb.st_dev == handles[i].dev &&
66 statb.st_ino == handles[i].ino) {
67 p = (dl_funcptr) dlsym(handles[i].handle,
68 funcname);
69 return p;
70 }
71 }
72 if (nhandles < 128) {
73 handles[nhandles].dev = statb.st_dev;
74 handles[nhandles].ino = statb.st_ino;
75 }
76 }
77
78#ifdef RTLD_NOW
79 /* RTLD_NOW: resolve externals now
80 (i.e. core dump now if some are missing) */
81 handle = dlopen(pathname, RTLD_NOW);
82#else
83 if (Py_VerboseFlag)
84 printf("dlopen(\"%s\", %d);\n", pathname,
85 RTLD_LAZY);
86 handle = dlopen(pathname, RTLD_LAZY);
87#endif /* RTLD_NOW */
88 if (handle == NULL) {
89 PyErr_SetString(PyExc_ImportError, dlerror());
90 return NULL;
91 }
92 if (fp != NULL && nhandles < 128)
93 handles[nhandles++].handle = handle;
94 p = (dl_funcptr) dlsym(handle, funcname);
95 return p;
96}