DynamicLoader.cxx 9.8 KB

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