DynamicLoader.cxx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  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
  32. // (default) 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. DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
  54. {
  55. return shl_load(libname, BIND_DEFERRED | DYNAMIC_PATH, 0L);
  56. }
  57. //----------------------------------------------------------------------------
  58. int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
  59. {
  60. return !shl_unload(lib);
  61. }
  62. //----------------------------------------------------------------------------
  63. DynamicLoader::SymbolPointer
  64. DynamicLoader::GetSymbolAddress(DynamicLoader::LibraryHandle lib, const char* sym)
  65. {
  66. void* addr;
  67. int status;
  68. /* TYPE_PROCEDURE Look for a function or procedure. (This used to be default)
  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<DynamicLoader::SymbolPointer*>(&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. DynamicLoader::LibraryHandle 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. NSModule handle = NSLinkModule(image, libname,
  133. NSLINKMODULE_OPTION_BINDNOW|NSLINKMODULE_OPTION_RETURN_ON_ERROR);
  134. NSDestroyObjectFileImage(image);
  135. return handle;
  136. }
  137. //----------------------------------------------------------------------------
  138. int DynamicLoader::CloseLibrary( DynamicLoader::LibraryHandle lib)
  139. {
  140. // NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED
  141. // With this option the memory for the module is not deallocated
  142. // allowing pointers into the module to still be valid.
  143. // You should use this option instead if your code experience some problems
  144. // reported against Panther 10.3.9 (fixed in Tiger 10.4.2 and up)
  145. bool success = NSUnLinkModule(lib, NSUNLINKMODULE_OPTION_NONE);
  146. return success;
  147. }
  148. //----------------------------------------------------------------------------
  149. DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
  150. DynamicLoader::LibraryHandle lib, const char* sym)
  151. {
  152. void *result=0;
  153. // Need to prepend symbols with '_' on Apple-gcc compilers
  154. size_t len = strlen(sym);
  155. char *rsym = new char[len + 1 + 1];
  156. strcpy(rsym, "_");
  157. strcat(rsym+1, sym);
  158. NSSymbol symbol = NSLookupSymbolInModule(lib, rsym);
  159. if(symbol)
  160. {
  161. result = NSAddressOfSymbol(symbol);
  162. }
  163. delete[] rsym;
  164. // Hack to cast pointer-to-data to pointer-to-function.
  165. return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
  166. }
  167. //----------------------------------------------------------------------------
  168. const char* DynamicLoader::LibPrefix()
  169. {
  170. return "lib";
  171. }
  172. //----------------------------------------------------------------------------
  173. const char* DynamicLoader::LibExtension()
  174. {
  175. // NSCreateObjectFileImageFromFile fail when dealing with dylib image
  176. // it returns NSObjectFileImageInappropriateFile
  177. //return ".dylib";
  178. return ".so";
  179. }
  180. //----------------------------------------------------------------------------
  181. const char* DynamicLoader::LastError()
  182. {
  183. return 0;
  184. }
  185. } // namespace KWSYS_NAMESPACE
  186. #endif //MAC_OS_X_VERSION_MIN_REQUIRED < 1030
  187. #endif // __APPLE__
  188. // ---------------------------------------------------------------
  189. // 3. Implementation for Windows win32 code
  190. #ifdef _WIN32
  191. #include <windows.h>
  192. #define DYNAMICLOADER_DEFINED 1
  193. namespace KWSYS_NAMESPACE
  194. {
  195. //----------------------------------------------------------------------------
  196. DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname)
  197. {
  198. DynamicLoader::LibraryHandle lh;
  199. #ifdef UNICODE
  200. wchar_t libn[MB_CUR_MAX];
  201. mbstowcs(libn, libname, MB_CUR_MAX);
  202. lh = LoadLibrary(libn);
  203. #else
  204. lh = LoadLibrary(libname);
  205. #endif
  206. return lh;
  207. }
  208. //----------------------------------------------------------------------------
  209. int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
  210. {
  211. return (int)FreeLibrary(lib);
  212. }
  213. //----------------------------------------------------------------------------
  214. DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
  215. DynamicLoader::LibraryHandle lib, const char* sym)
  216. {
  217. void *result;
  218. #ifdef __BORLANDC__
  219. // Need to prepend symbols with '_' on borland compilers
  220. size_t len = strlen(sym);
  221. char *rsym = new char[len + 1 + 1];
  222. strcpy(rsym, "_");
  223. strcat(rsym+1, sym);
  224. #else
  225. const char *rsym = sym;
  226. #endif
  227. #ifdef UNICODE
  228. wchar_t wsym[MB_CUR_MAX];
  229. mbstowcs(wsym, rsym, MB_CUR_MAX);
  230. result = GetProcAddress(lib, wsym);
  231. #else
  232. result = (void*)GetProcAddress(lib, rsym);
  233. #endif
  234. #ifdef __BORLANDC__
  235. delete[] rsym;
  236. #endif
  237. // Hack to cast pointer-to-data to pointer-to-function.
  238. return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
  239. }
  240. //----------------------------------------------------------------------------
  241. const char* DynamicLoader::LibPrefix()
  242. {
  243. #ifdef __MINGW32__
  244. return "lib";
  245. #else
  246. return "";
  247. #endif
  248. }
  249. //----------------------------------------------------------------------------
  250. const char* DynamicLoader::LibExtension()
  251. {
  252. return ".dll";
  253. }
  254. //----------------------------------------------------------------------------
  255. const char* DynamicLoader::LastError()
  256. {
  257. LPVOID lpMsgBuf;
  258. FormatMessage(
  259. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  260. NULL,
  261. GetLastError(),
  262. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  263. (LPTSTR) &lpMsgBuf,
  264. 0,
  265. NULL
  266. );
  267. static char* str = 0;
  268. delete [] str;
  269. str = strcpy(new char[strlen((char*)lpMsgBuf)+1], (char*)lpMsgBuf);
  270. // Free the buffer.
  271. LocalFree( lpMsgBuf );
  272. return str;
  273. }
  274. } // namespace KWSYS_NAMESPACE
  275. #endif //_WIN32
  276. // ---------------------------------------------------------------
  277. // 4. Implementation for default UNIX machines.
  278. // if nothing has been defined then use this
  279. #ifndef DYNAMICLOADER_DEFINED
  280. #define DYNAMICLOADER_DEFINED 1
  281. // Setup for most unix machines
  282. #include <dlfcn.h>
  283. namespace KWSYS_NAMESPACE
  284. {
  285. //----------------------------------------------------------------------------
  286. DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
  287. {
  288. return dlopen(libname, RTLD_LAZY);
  289. }
  290. //----------------------------------------------------------------------------
  291. int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
  292. {
  293. if (lib)
  294. {
  295. // The function dlclose() returns 0 on success, and non-zero on error.
  296. return !dlclose(lib);
  297. }
  298. // else
  299. return 0;
  300. }
  301. //----------------------------------------------------------------------------
  302. DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
  303. DynamicLoader::LibraryHandle lib, const char* sym)
  304. {
  305. // Hack to cast pointer-to-data to pointer-to-function.
  306. union
  307. {
  308. void* pvoid;
  309. DynamicLoader::SymbolPointer psym;
  310. } result;
  311. result.pvoid = dlsym(lib, sym);
  312. return result.psym;
  313. }
  314. //----------------------------------------------------------------------------
  315. const char* DynamicLoader::LibPrefix()
  316. {
  317. return "lib";
  318. }
  319. //----------------------------------------------------------------------------
  320. const char* DynamicLoader::LibExtension()
  321. {
  322. #ifdef __CYGWIN__
  323. return ".dll";
  324. #else
  325. return ".so";
  326. #endif
  327. }
  328. //----------------------------------------------------------------------------
  329. const char* DynamicLoader::LastError()
  330. {
  331. return dlerror();
  332. }
  333. } // namespace KWSYS_NAMESPACE
  334. #endif