blob: ac8cd4286bffa2663121db67b31d8ff5942adccb [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>
Martin v. Löwis8a57f002001-10-18 21:24:04 +00009
Martin v. Löwis0eb1ed52001-10-18 11:45:19 +000010#if defined(__NetBSD__)
11#include <sys/param.h>
12#if (NetBSD < 199712)
Guido van Rossum22a1d361999-12-20 21:18:49 +000013#include <nlist.h>
14#include <link.h>
15#define dlerror() "error in dynamic linking"
Martin v. Löwis8a57f002001-10-18 21:24:04 +000016#endif
17#endif /* NetBSD */
18
Guido van Rossum22a1d361999-12-20 21:18:49 +000019#ifdef HAVE_DLFCN_H
20#include <dlfcn.h>
Andrew MacIntyred9400542002-02-26 11:41:34 +000021#else
22#if defined(PYOS_OS2) && defined(PYCC_GCC)
23#include "dlfcn.h"
24#endif
Guido van Rossum22a1d361999-12-20 21:18:49 +000025#endif
Guido van Rossum22a1d361999-12-20 21:18:49 +000026
Martin v. Löwis0eb1ed52001-10-18 11:45:19 +000027#if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__)
Guido van Rossumc8fcdcb2000-10-25 22:07:45 +000028#define LEAD_UNDERSCORE "_"
29#else
30#define LEAD_UNDERSCORE ""
31#endif
32
Guido van Rossum22a1d361999-12-20 21:18:49 +000033
34const struct filedescr _PyImport_DynLoadFiletab[] = {
Tim Peters98dc0652000-10-05 19:24:26 +000035#ifdef __CYGWIN__
Tim Peters98dc0652000-10-05 19:24:26 +000036 {".dll", "rb", C_EXTENSION},
Guido van Rossumfef12432001-01-10 21:17:27 +000037 {"module.dll", "rb", C_EXTENSION},
Tim Peters98dc0652000-10-05 19:24:26 +000038#else
Andrew MacIntyred9400542002-02-26 11:41:34 +000039#if defined(PYOS_OS2) && defined(PYCC_GCC)
40 {".pyd", "rb", C_EXTENSION},
41 {".dll", "rb", C_EXTENSION},
42#else
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +000043#ifdef __VMS
44 {".exe", "rb", C_EXTENSION},
45 {".EXE", "rb", C_EXTENSION},
46 {"module.exe", "rb", C_EXTENSION},
47 {"MODULE.EXE", "rb", C_EXTENSION},
48#else
Guido van Rossum22a1d361999-12-20 21:18:49 +000049 {".so", "rb", C_EXTENSION},
50 {"module.so", "rb", C_EXTENSION},
Tim Peters98dc0652000-10-05 19:24:26 +000051#endif
Andrew MacIntyred9400542002-02-26 11:41:34 +000052#endif
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +000053#endif
Guido van Rossum22a1d361999-12-20 21:18:49 +000054 {0, 0}
55};
56
57static struct {
58 dev_t dev;
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +000059#ifdef __VMS
60 ino_t ino[3];
61#else
Guido van Rossum22a1d361999-12-20 21:18:49 +000062 ino_t ino;
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +000063#endif
Guido van Rossum22a1d361999-12-20 21:18:49 +000064 void *handle;
65} handles[128];
66static int nhandles = 0;
67
68
Guido van Rossum96a8fb71999-12-22 14:09:35 +000069dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
Guido van Rossum22a1d361999-12-20 21:18:49 +000070 const char *pathname, FILE *fp)
71{
72 dl_funcptr p;
73 void *handle;
Guido van Rossum96a8fb71999-12-22 14:09:35 +000074 char funcname[258];
75 char pathbuf[260];
Martin v. Löwisf0473d52001-07-18 16:17:16 +000076 int dlopenflags=0;
Guido van Rossum96a8fb71999-12-22 14:09:35 +000077
78 if (strchr(pathname, '/') == NULL) {
79 /* Prefix bare filename with "./" */
Jeremy Hylton518ab1c2001-11-28 20:42:20 +000080 PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
Guido van Rossum96a8fb71999-12-22 14:09:35 +000081 pathname = pathbuf;
82 }
83
Jeremy Hylton518ab1c2001-11-28 20:42:20 +000084 PyOS_snprintf(funcname, sizeof(funcname),
Martin v. Löwis1a214512008-06-11 05:26:20 +000085 LEAD_UNDERSCORE "PyInit_%.200s", shortname);
Guido van Rossum22a1d361999-12-20 21:18:49 +000086
87 if (fp != NULL) {
88 int i;
89 struct stat statb;
90 fstat(fileno(fp), &statb);
91 for (i = 0; i < nhandles; i++) {
92 if (statb.st_dev == handles[i].dev &&
93 statb.st_ino == handles[i].ino) {
94 p = (dl_funcptr) dlsym(handles[i].handle,
95 funcname);
96 return p;
97 }
98 }
99 if (nhandles < 128) {
100 handles[nhandles].dev = statb.st_dev;
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +0000101#ifdef __VMS
102 handles[nhandles].ino[0] = statb.st_ino[0];
103 handles[nhandles].ino[1] = statb.st_ino[1];
104 handles[nhandles].ino[2] = statb.st_ino[2];
105#else
Guido van Rossum22a1d361999-12-20 21:18:49 +0000106 handles[nhandles].ino = statb.st_ino;
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +0000107#endif
Guido van Rossum22a1d361999-12-20 21:18:49 +0000108 }
109 }
110
Andrew MacIntyred9400542002-02-26 11:41:34 +0000111#if !(defined(PYOS_OS2) && defined(PYCC_GCC))
Nicholas Bastin2786d902004-03-25 02:16:23 +0000112 dlopenflags = PyThreadState_GET()->interp->dlopenflags;
Andrew MacIntyred9400542002-02-26 11:41:34 +0000113#endif
Martin v. Löwisf0473d52001-07-18 16:17:16 +0000114
Guido van Rossum22a1d361999-12-20 21:18:49 +0000115 if (Py_VerboseFlag)
Martin v. Löwis507a4852004-10-03 08:51:35 +0000116 PySys_WriteStderr("dlopen(\"%s\", %x);\n", pathname,
117 dlopenflags);
Martin v. Löwisf0473d52001-07-18 16:17:16 +0000118
Martin v. Löwisc16f3bd2003-05-03 09:14:54 +0000119#ifdef __VMS
120 /* VMS currently don't allow a pathname, use a logical name instead */
121 /* Concatenate 'python_module_' and shortname */
122 /* so "import vms.bar" will use the logical python_module_bar */
123 /* As C module use only one name space this is probably not a */
124 /* important limitation */
125 PyOS_snprintf(pathbuf, sizeof(pathbuf), "python_module_%-.200s",
126 shortname);
127 pathname = pathbuf;
128#endif
129
Martin v. Löwisf0473d52001-07-18 16:17:16 +0000130 handle = dlopen(pathname, dlopenflags);
131
Guido van Rossum22a1d361999-12-20 21:18:49 +0000132 if (handle == NULL) {
Hye-Shik Chang23f391c2006-01-04 01:30:17 +0000133 const char *error = dlerror();
Neal Norwitz67715f02005-11-09 06:59:35 +0000134 if (error == NULL)
135 error = "unknown dlopen() error";
136 PyErr_SetString(PyExc_ImportError, error);
Guido van Rossum22a1d361999-12-20 21:18:49 +0000137 return NULL;
138 }
139 if (fp != NULL && nhandles < 128)
140 handles[nhandles++].handle = handle;
141 p = (dl_funcptr) dlsym(handle, funcname);
142 return p;
143}