| /* Support for dynamic loading of extension modules */ | |
| #include "Python.h" | |
| #include "pycore_fileutils.h" // struct _Py_stat_struct | |
| #include "pycore_import.h" // _PyImport_GetDLOpenFlags() | |
| #include "pycore_importdl.h" | |
| #include "pycore_interp.h" // _PyInterpreterState.dlopenflags | |
| #include "pycore_pystate.h" // _PyInterpreterState_GET() | |
| #include <sys/types.h> | |
| #include <sys/stat.h> | |
| #if defined(__NetBSD__) | |
| #include <sys/param.h> | |
| #if (NetBSD < 199712) | |
| #include <nlist.h> | |
| #include <link.h> | |
| #define dlerror() "error in dynamic linking" | |
| #endif | |
| #endif /* NetBSD */ | |
| #ifdef HAVE_DLFCN_H | |
| #include <dlfcn.h> | |
| #endif | |
| #if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__) | |
| #define LEAD_UNDERSCORE "_" | |
| #else | |
| #define LEAD_UNDERSCORE "" | |
| #endif | |
| /* 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 | |
| */ | |
| const char *_PyImport_DynLoadFiletab[] = { | |
| #ifdef __CYGWIN__ | |
| "." SOABI ".dll", | |
| ".dll", | |
| #else /* !__CYGWIN__ */ | |
| "." SOABI ".so", | |
| #ifdef ALT_SOABI | |
| "." ALT_SOABI ".so", | |
| #endif | |
| #ifndef Py_GIL_DISABLED | |
| #ifdef SOABI_PLATFORM | |
| ".abi" PYTHON_ABI_STRING "-" SOABI_PLATFORM ".so", | |
| #endif /* SOABI_PLATFORM */ | |
| ".abi" PYTHON_ABI_STRING ".so", | |
| #endif /* Py_GIL_DISABLED */ | |
| #ifdef SOABI_PLATFORM | |
| ".abi" PYTHON_ABI_STRING "t-" SOABI_PLATFORM ".so", | |
| #endif /* SOABI_PLATFORM */ | |
| ".abi" PYTHON_ABI_STRING "t.so", | |
| ".so", | |
| #endif /* __CYGWIN__ */ | |
| NULL, | |
| }; | |
| dl_funcptr | |
| _PyImport_FindSharedFuncptr(const char *prefix, | |
| const char *shortname, | |
| const char *pathname, FILE *fp) | |
| { | |
| 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 "%.20s_%.200s", prefix, shortname); | |
| if (fp != NULL) { | |
| struct _Py_stat_struct status; | |
| if (_Py_fstat(fileno(fp), &status) == -1) | |
| return NULL; | |
| } | |
| dlopenflags = _PyImport_GetDLOpenFlags(_PyInterpreterState_GET()); | |
| handle = dlopen(pathname, dlopenflags); | |
| if (handle == NULL) { | |
| PyObject *mod_name; | |
| PyObject *path; | |
| PyObject *error_ob; | |
| const char *error = dlerror(); | |
| if (error == NULL) | |
| error = "unknown dlopen() error"; | |
| error_ob = PyUnicode_DecodeLocale(error, "surrogateescape"); | |
| if (error_ob == NULL) | |
| return NULL; | |
| mod_name = PyUnicode_FromString(shortname); | |
| if (mod_name == NULL) { | |
| Py_DECREF(error_ob); | |
| return NULL; | |
| } | |
| path = PyUnicode_DecodeFSDefault(pathname); | |
| if (path == NULL) { | |
| Py_DECREF(error_ob); | |
| Py_DECREF(mod_name); | |
| return NULL; | |
| } | |
| PyErr_SetImportError(error_ob, mod_name, path); | |
| Py_DECREF(error_ob); | |
| Py_DECREF(mod_name); | |
| Py_DECREF(path); | |
| return NULL; | |
| } | |
| p = (dl_funcptr) dlsym(handle, funcname); | |
| return p; | |
| } |