DynamicLoader.cxx 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. /*=========================================================================
  2. Program: KWSys - Kitware System Library
  3. Module: $RCSfile$
  4. Copyright (c) Kitware, Inc., Insight Consortium. All rights reserved.
  5. See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even
  7. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  8. PURPOSE. See the above copyright notices for more information.
  9. =========================================================================*/
  10. #include "kwsysPrivate.h"
  11. #include KWSYS_HEADER(DynamicLoader.hxx)
  12. #include KWSYS_HEADER(Configure.hxx)
  13. #ifdef __APPLE__
  14. #if MAC_OS_X_VERSION_MIN_REQUIRED < 1030
  15. #include <string.h> // for strlen
  16. #endif //MAC_OS_X_VERSION_MIN_REQUIRED < 1030
  17. #endif // __APPLE__
  18. #ifdef __hpux
  19. #include <errno.h>
  20. #endif //__hpux
  21. // Work-around CMake dependency scanning limitation. This must
  22. // duplicate the above list of headers.
  23. #if 0
  24. # include "DynamicLoader.hxx.in"
  25. # include "Configure.hxx.in"
  26. #endif
  27. // This file is actually 3 different implementations.
  28. // 1. HP machines which uses shl_load
  29. // 2. Mac OS X 10.2.x and earlier which uses NSLinkModule
  30. // 3. Windows which uses LoadLibrary
  31. // 4. Most unix systems (including Mac OS X 10.3 and later) which use dlopen (default)
  32. // Each part of the ifdef contains a complete implementation for
  33. // the static methods of DynamicLoader.
  34. namespace KWSYS_NAMESPACE
  35. {
  36. //----------------------------------------------------------------------------
  37. DynamicLoader::DynamicLoader()
  38. {
  39. }
  40. //----------------------------------------------------------------------------
  41. DynamicLoader::~DynamicLoader()
  42. {
  43. }
  44. }
  45. // ---------------------------------------------------------------
  46. // 1. Implementation for HPUX machines
  47. #ifdef __hpux
  48. #include <dl.h>
  49. #define DYNAMICLOADER_DEFINED 1
  50. namespace KWSYS_NAMESPACE
  51. {
  52. //----------------------------------------------------------------------------
  53. LibHandle DynamicLoader::OpenLibrary(const char* libname )
  54. {
  55. return shl_load(libname, BIND_DEFERRED | DYNAMIC_PATH, 0L);
  56. }
  57. //----------------------------------------------------------------------------
  58. int DynamicLoader::CloseLibrary(LibHandle lib)
  59. {
  60. return !shl_unload(lib);
  61. }
  62. //----------------------------------------------------------------------------
  63. DynamicLoaderFunction
  64. DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
  65. {
  66. void* addr;
  67. int status;
  68. /* TYPE_PROCEDURE Look for a function or procedure.
  69. * TYPE_DATA Look for a symbol in the data segment (for example, variables).
  70. * TYPE_UNDEFINED Look for any symbol.
  71. */
  72. status = shl_findsym (&lib, sym, TYPE_UNDEFINED, &addr);
  73. void* result = (status < 0) ? (void*)0 : addr;
  74. // Hack to cast pointer-to-data to pointer-to-function.
  75. return *reinterpret_cast<DynamicLoaderFunction*>(&result);
  76. }
  77. //----------------------------------------------------------------------------
  78. const char* DynamicLoader::LibPrefix()
  79. {
  80. return "lib";
  81. }
  82. //----------------------------------------------------------------------------
  83. const char* DynamicLoader::LibExtension()
  84. {
  85. return ".sl";
  86. }
  87. //----------------------------------------------------------------------------
  88. const char* DynamicLoader::LastError()
  89. {
  90. // TODO: Need implementation with errno/strerror
  91. /* If successful, shl_findsym returns an integer (int) value zero. If
  92. * shl_findsym cannot find sym, it returns -1 and sets errno to zero.
  93. * If any other errors occur, shl_findsym returns -1 and sets errno to one
  94. * of these values (defined in <errno.h>):
  95. * ENOEXEC
  96. * A format error was detected in the specified library.
  97. * ENOSYM
  98. * A symbol on which sym depends could not be found.
  99. * EINVAL
  100. * The specified handle is invalid.
  101. */
  102. if( errno == ENOEXEC
  103. || errno == ENOSYM
  104. || errno == EINVAL )
  105. {
  106. return strerror(errno);
  107. }
  108. // else
  109. return 0;
  110. }
  111. } // namespace KWSYS_NAMESPACE
  112. #endif //__hpux
  113. // ---------------------------------------------------------------
  114. // 2. Implementation for Mac OS X 10.2.x and earlier
  115. #ifdef __APPLE__
  116. #if MAC_OS_X_VERSION_MIN_REQUIRED < 1030
  117. #include <mach-o/dyld.h>
  118. #define DYNAMICLOADER_DEFINED 1
  119. namespace KWSYS_NAMESPACE
  120. {
  121. //----------------------------------------------------------------------------
  122. LibHandle DynamicLoader::OpenLibrary(const char* libname )
  123. {
  124. NSObjectFileImageReturnCode rc;
  125. NSObjectFileImage image = 0;
  126. rc = NSCreateObjectFileImageFromFile(libname, &image);
  127. // rc == NSObjectFileImageInappropriateFile when trying to load a dylib file
  128. if( rc != NSObjectFileImageSuccess )
  129. {
  130. return 0;
  131. }
  132. return NSLinkModule(image, libname,
  133. NSLINKMODULE_OPTION_PRIVATE|NSLINKMODULE_OPTION_BINDNOW);
  134. }
  135. //----------------------------------------------------------------------------
  136. int DynamicLoader::CloseLibrary( LibHandle lib)
  137. {
  138. bool success = NSUnLinkModule(lib, NSUNLINKMODULE_OPTION_NONE);
  139. return success;
  140. }
  141. //----------------------------------------------------------------------------
  142. DynamicLoaderFunction DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
  143. {
  144. void *result=0;
  145. // Need to prepend symbols with '_' on Apple-gcc compilers
  146. size_t len = strlen(sym);
  147. char *rsym = new char[len + 1 + 1];
  148. strcpy(rsym, "_");
  149. strcat(rsym+1, sym);
  150. NSSymbol symbol = NSLookupSymbolInModule(lib, rsym);
  151. if(symbol)
  152. {
  153. result = NSAddressOfSymbol(symbol);
  154. }
  155. delete[] rsym;
  156. // Hack to cast pointer-to-data to pointer-to-function.
  157. return *reinterpret_cast<DynamicLoaderFunction*>(&result);
  158. }
  159. //----------------------------------------------------------------------------
  160. const char* DynamicLoader::LibPrefix()
  161. {
  162. return "lib";
  163. }
  164. //----------------------------------------------------------------------------
  165. const char* DynamicLoader::LibExtension()
  166. {
  167. // NSCreateObjectFileImageFromFile fail when dealing with dylib image
  168. // it returns NSObjectFileImageInappropriateFile
  169. //return ".dylib";
  170. return ".so";
  171. }
  172. //----------------------------------------------------------------------------
  173. const char* DynamicLoader::LastError()
  174. {
  175. return 0;
  176. }
  177. } // namespace KWSYS_NAMESPACE
  178. #endif //MAC_OS_X_VERSION_MIN_REQUIRED < 1030
  179. #endif // __APPLE__
  180. // ---------------------------------------------------------------
  181. // 3. Implementation for Windows win32 code
  182. #ifdef _WIN32
  183. #include <windows.h>
  184. #define DYNAMICLOADER_DEFINED 1
  185. namespace KWSYS_NAMESPACE
  186. {
  187. //----------------------------------------------------------------------------
  188. LibHandle DynamicLoader::OpenLibrary(const char* libname)
  189. {
  190. LibHandle lh;
  191. #ifdef UNICODE
  192. wchar_t libn[MB_CUR_MAX];
  193. mbstowcs(libn, libname, MB_CUR_MAX);
  194. lh = LoadLibrary(libn);
  195. #else
  196. lh = LoadLibrary(libname);
  197. #endif
  198. return lh;
  199. }
  200. //----------------------------------------------------------------------------
  201. int DynamicLoader::CloseLibrary(LibHandle lib)
  202. {
  203. return (int)FreeLibrary(lib);
  204. }
  205. //----------------------------------------------------------------------------
  206. DynamicLoaderFunction DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
  207. {
  208. void *result;
  209. #ifdef __BORLANDC__
  210. // Need to prepend symbols with '_' on borland compilers
  211. size_t len = strlen(sym);
  212. char *rsym = new char[len + 1 + 1];
  213. strcpy(rsym, "_");
  214. strcat(rsym+1, sym);
  215. #else
  216. const char *rsym = sym;
  217. #endif
  218. #ifdef UNICODE
  219. wchar_t wsym[MB_CUR_MAX];
  220. mbstowcs(wsym, rsym, MB_CUR_MAX);
  221. result = GetProcAddress(lib, wsym);
  222. #else
  223. result = (void*)GetProcAddress(lib, rsym);
  224. #endif
  225. #ifdef __BORLANDC__
  226. delete[] rsym;
  227. #endif
  228. // Hack to cast pointer-to-data to pointer-to-function.
  229. return *reinterpret_cast<DynamicLoaderFunction*>(&result);
  230. }
  231. //----------------------------------------------------------------------------
  232. const char* DynamicLoader::LibPrefix()
  233. {
  234. return "";
  235. }
  236. //----------------------------------------------------------------------------
  237. const char* DynamicLoader::LibExtension()
  238. {
  239. return ".dll";
  240. }
  241. //----------------------------------------------------------------------------
  242. const char* DynamicLoader::LastError()
  243. {
  244. LPVOID lpMsgBuf;
  245. FormatMessage(
  246. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  247. NULL,
  248. GetLastError(),
  249. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  250. (LPTSTR) &lpMsgBuf,
  251. 0,
  252. NULL
  253. );
  254. static char* str = 0;
  255. delete [] str;
  256. str = strcpy(new char[strlen((char*)lpMsgBuf)+1], (char*)lpMsgBuf);
  257. // Free the buffer.
  258. LocalFree( lpMsgBuf );
  259. return str;
  260. }
  261. } // namespace KWSYS_NAMESPACE
  262. #endif //_WIN32
  263. // ---------------------------------------------------------------
  264. // 4. Implementation for default UNIX machines.
  265. // if nothing has been defined then use this
  266. #ifndef DYNAMICLOADER_DEFINED
  267. #define DYNAMICLOADER_DEFINED 1
  268. // Setup for most unix machines
  269. #include <dlfcn.h>
  270. namespace KWSYS_NAMESPACE
  271. {
  272. //----------------------------------------------------------------------------
  273. LibHandle DynamicLoader::OpenLibrary(const char* libname )
  274. {
  275. return dlopen(libname, RTLD_LAZY);
  276. }
  277. //----------------------------------------------------------------------------
  278. int DynamicLoader::CloseLibrary(LibHandle lib)
  279. {
  280. if (lib)
  281. {
  282. // The function dlclose() returns 0 on success, and non-zero on error.
  283. return !dlclose(lib);
  284. }
  285. // else
  286. return 0;
  287. }
  288. //----------------------------------------------------------------------------
  289. DynamicLoaderFunction DynamicLoader::GetSymbolAddress(LibHandle lib, const char* sym)
  290. {
  291. void* result = dlsym(lib, sym);
  292. // Hack to cast pointer-to-data to pointer-to-function.
  293. return *reinterpret_cast<DynamicLoaderFunction*>(&result);
  294. }
  295. //----------------------------------------------------------------------------
  296. const char* DynamicLoader::LibPrefix()
  297. {
  298. return "lib";
  299. }
  300. //----------------------------------------------------------------------------
  301. const char* DynamicLoader::LibExtension()
  302. {
  303. #ifdef __CYGWIN__
  304. return ".dll";
  305. #else
  306. return ".so";
  307. #endif
  308. }
  309. //----------------------------------------------------------------------------
  310. const char* DynamicLoader::LastError()
  311. {
  312. return dlerror();
  313. }
  314. } // namespace KWSYS_NAMESPACE
  315. #endif