/Python/dynload_shlib.c

http://unladen-swallow.googlecode.com/ · C · 143 lines · 117 code · 19 blank · 7 comment · 22 complexity · a0eb85cfbc7cfe88ce6025646105045b MD5 · raw file

  1. /* Support for dynamic loading of extension modules */
  2. #include "Python.h"
  3. #include "importdl.h"
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #if defined(__NetBSD__)
  7. #include <sys/param.h>
  8. #if (NetBSD < 199712)
  9. #include <nlist.h>
  10. #include <link.h>
  11. #define dlerror() "error in dynamic linking"
  12. #endif
  13. #endif /* NetBSD */
  14. #ifdef HAVE_DLFCN_H
  15. #include <dlfcn.h>
  16. #else
  17. #if defined(PYOS_OS2) && defined(PYCC_GCC)
  18. #include "dlfcn.h"
  19. #endif
  20. #endif
  21. #if (defined(__OpenBSD__) || defined(__NetBSD__)) && !defined(__ELF__)
  22. #define LEAD_UNDERSCORE "_"
  23. #else
  24. #define LEAD_UNDERSCORE ""
  25. #endif
  26. const struct filedescr _PyImport_DynLoadFiletab[] = {
  27. #ifdef __CYGWIN__
  28. {".dll", "rb", C_EXTENSION},
  29. {"module.dll", "rb", C_EXTENSION},
  30. #else
  31. #if defined(PYOS_OS2) && defined(PYCC_GCC)
  32. {".pyd", "rb", C_EXTENSION},
  33. {".dll", "rb", C_EXTENSION},
  34. #else
  35. #ifdef __VMS
  36. {".exe", "rb", C_EXTENSION},
  37. {".EXE", "rb", C_EXTENSION},
  38. {"module.exe", "rb", C_EXTENSION},
  39. {"MODULE.EXE", "rb", C_EXTENSION},
  40. #else
  41. {".so", "rb", C_EXTENSION},
  42. {"module.so", "rb", C_EXTENSION},
  43. #endif
  44. #endif
  45. #endif
  46. {0, 0}
  47. };
  48. static struct {
  49. dev_t dev;
  50. #ifdef __VMS
  51. ino_t ino[3];
  52. #else
  53. ino_t ino;
  54. #endif
  55. void *handle;
  56. } handles[128];
  57. static int nhandles = 0;
  58. dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname,
  59. const char *pathname, FILE *fp)
  60. {
  61. dl_funcptr p;
  62. void *handle;
  63. char funcname[258];
  64. char pathbuf[260];
  65. int dlopenflags=0;
  66. if (strchr(pathname, '/') == NULL) {
  67. /* Prefix bare filename with "./" */
  68. PyOS_snprintf(pathbuf, sizeof(pathbuf), "./%-.255s", pathname);
  69. pathname = pathbuf;
  70. }
  71. PyOS_snprintf(funcname, sizeof(funcname),
  72. LEAD_UNDERSCORE "init%.200s", shortname);
  73. if (fp != NULL) {
  74. int i;
  75. struct stat statb;
  76. fstat(fileno(fp), &statb);
  77. for (i = 0; i < nhandles; i++) {
  78. if (statb.st_dev == handles[i].dev &&
  79. statb.st_ino == handles[i].ino) {
  80. p = (dl_funcptr) dlsym(handles[i].handle,
  81. funcname);
  82. return p;
  83. }
  84. }
  85. if (nhandles < 128) {
  86. handles[nhandles].dev = statb.st_dev;
  87. #ifdef __VMS
  88. handles[nhandles].ino[0] = statb.st_ino[0];
  89. handles[nhandles].ino[1] = statb.st_ino[1];
  90. handles[nhandles].ino[2] = statb.st_ino[2];
  91. #else
  92. handles[nhandles].ino = statb.st_ino;
  93. #endif
  94. }
  95. }
  96. #if !(defined(PYOS_OS2) && defined(PYCC_GCC))
  97. dlopenflags = PyThreadState_GET()->interp->dlopenflags;
  98. #endif
  99. if (Py_VerboseFlag)
  100. PySys_WriteStderr("dlopen(\"%s\", %x);\n", pathname,
  101. dlopenflags);
  102. #ifdef __VMS
  103. /* VMS currently don't allow a pathname, use a logical name instead */
  104. /* Concatenate 'python_module_' and shortname */
  105. /* so "import vms.bar" will use the logical python_module_bar */
  106. /* As C module use only one name space this is probably not a */
  107. /* important limitation */
  108. PyOS_snprintf(pathbuf, sizeof(pathbuf), "python_module_%-.200s",
  109. shortname);
  110. pathname = pathbuf;
  111. #endif
  112. handle = dlopen(pathname, dlopenflags);
  113. if (handle == NULL) {
  114. const char *error = dlerror();
  115. if (error == NULL)
  116. error = "unknown dlopen() error";
  117. PyErr_SetString(PyExc_ImportError, error);
  118. return NULL;
  119. }
  120. if (fp != NULL && nhandles < 128)
  121. handles[nhandles++].handle = handle;
  122. p = (dl_funcptr) dlsym(handle, funcname);
  123. return p;
  124. }