DynamicLoader.cxx 13.3 KB
Newer Older
Kitware Robot's avatar
Kitware Robot committed
1 2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing#kwsys for details.  */
Kitware Robot's avatar
Kitware Robot committed
3 4 5 6
#if defined(_WIN32)
#  define NOMINMAX // hide min,max to not conflict with <limits>
#endif

Kitware Robot's avatar
Kitware Robot committed
7 8 9 10
#include "kwsysPrivate.h"
#include KWSYS_HEADER(DynamicLoader.hxx)

#include KWSYS_HEADER(Configure.hxx)
Kitware Robot's avatar
Kitware Robot committed
11
#include KWSYS_HEADER(Encoding.hxx)
Kitware Robot's avatar
Kitware Robot committed
12 13 14 15

// Work-around CMake dependency scanning limitation.  This must
// duplicate the above list of headers.
#if 0
Kitware Robot's avatar
Kitware Robot committed
16 17
#  include "Configure.hxx.in"
#  include "DynamicLoader.hxx.in"
Kitware Robot's avatar
Kitware Robot committed
18 19
#endif

Kitware Robot's avatar
Kitware Robot committed
20 21 22 23 24 25 26 27 28 29 30
// This file actually contains several different implementations:
// * NOOP for environments without dynamic libs
// * HP machines which uses shl_load
// * Mac OS X 10.2.x and earlier which uses NSLinkModule
// * Windows which uses LoadLibrary
// * BeOS / Haiku
// * FreeMiNT for Atari
// * Default implementation for *NIX systems (including Mac OS X 10.3 and
//   later) which use dlopen
//
// Each part of the ifdef contains a complete implementation for
Kitware Robot's avatar
Kitware Robot committed
31 32
// the static methods of DynamicLoader.

Kitware Robot's avatar
Kitware Robot committed
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
#define CHECK_OPEN_FLAGS(var, supported, ret)                                 \
  do {                                                                        \
    /* Check for unknown flags. */                                            \
    if ((var & AllOpenFlags) != var) {                                        \
      return ret;                                                             \
    }                                                                         \
                                                                              \
    /* Check for unsupported flags. */                                        \
    if ((var & (supported)) != var) {                                         \
      return ret;                                                             \
    }                                                                         \
  } while (0)

namespace KWSYS_NAMESPACE {

DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
  const std::string& libname)
{
  return DynamicLoader::OpenLibrary(libname, 0);
}
}

Kitware Robot's avatar
Kitware Robot committed
55 56
#if !KWSYS_SUPPORTS_SHARED_LIBS
// Implementation for environments without dynamic libs
Kitware Robot's avatar
Kitware Robot committed
57
#  include <string.h> // for strerror()
Kitware Robot's avatar
Kitware Robot committed
58 59 60 61

namespace KWSYS_NAMESPACE {

DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
Kitware Robot's avatar
Kitware Robot committed
62
  const std::string& libname, int flags)
Kitware Robot's avatar
Kitware Robot committed
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
{
  return 0;
}

int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
{
  if (!lib) {
    return 0;
  }

  return 1;
}

DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
  DynamicLoader::LibraryHandle lib, const std::string& sym)
{
  return 0;
}

const char* DynamicLoader::LastError()
{
  return "General error";
}

} // namespace KWSYS_NAMESPACE

#elif defined(__hpux)
Kitware Robot's avatar
Kitware Robot committed
90
// Implementation for HPUX machines
Kitware Robot's avatar
Kitware Robot committed
91 92
#  include <dl.h>
#  include <errno.h>
Kitware Robot's avatar
Kitware Robot committed
93

Kitware Robot's avatar
Kitware Robot committed
94
namespace KWSYS_NAMESPACE {
Kitware Robot's avatar
Kitware Robot committed
95

Kitware Robot's avatar
Kitware Robot committed
96
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
Kitware Robot's avatar
Kitware Robot committed
97
  const std::string& libname, int flags)
Kitware Robot's avatar
Kitware Robot committed
98
{
Kitware Robot's avatar
Kitware Robot committed
99 100
  CHECK_OPEN_FLAGS(flags, 0, 0);

Kitware Robot's avatar
Kitware Robot committed
101
  return shl_load(libname.c_str(), BIND_DEFERRED | DYNAMIC_PATH, 0L);
Kitware Robot's avatar
Kitware Robot committed
102 103 104 105
}

int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
{
Kitware Robot's avatar
Kitware Robot committed
106
  if (!lib) {
Kitware Robot's avatar
Kitware Robot committed
107
    return 0;
Kitware Robot's avatar
Kitware Robot committed
108
  }
Kitware Robot's avatar
Kitware Robot committed
109 110 111
  return !shl_unload(lib);
}

Kitware Robot's avatar
Kitware Robot committed
112 113
DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
  DynamicLoader::LibraryHandle lib, const std::string& sym)
Kitware Robot's avatar
Kitware Robot committed
114 115 116 117 118
{
  void* addr;
  int status;

  /* TYPE_PROCEDURE Look for a function or procedure. (This used to be default)
Kitware Robot's avatar
Kitware Robot committed
119 120
   * TYPE_DATA      Look for a symbol in the data segment (for example,
   * variables).
Kitware Robot's avatar
Kitware Robot committed
121 122
   * TYPE_UNDEFINED Look for any symbol.
   */
Kitware Robot's avatar
Kitware Robot committed
123
  status = shl_findsym(&lib, sym.c_str(), TYPE_UNDEFINED, &addr);
Kitware Robot's avatar
Kitware Robot committed
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
  void* result = (status < 0) ? (void*)0 : addr;

  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
}

const char* DynamicLoader::LastError()
{
  // TODO: Need implementation with errno/strerror
  /* If successful, shl_findsym returns an integer (int) value zero. If
   * shl_findsym cannot find sym, it returns -1 and sets errno to zero.
   * If any other errors occur, shl_findsym returns -1 and sets errno to one
   * of these values (defined in <errno.h>):
   * ENOEXEC
   * A format error was detected in the specified library.
   * ENOSYM
   * A symbol on which sym depends could not be found.
   * EINVAL
   * The specified handle is invalid.
   */

Kitware Robot's avatar
Kitware Robot committed
145
  if (errno == ENOEXEC || errno == ENOSYM || errno == EINVAL) {
Kitware Robot's avatar
Kitware Robot committed
146
    return strerror(errno);
Kitware Robot's avatar
Kitware Robot committed
147
  }
Kitware Robot's avatar
Kitware Robot committed
148 149 150 151 152 153
  // else
  return 0;
}

} // namespace KWSYS_NAMESPACE

Kitware Robot's avatar
Kitware Robot committed
154 155
#elif defined(__APPLE__) && (MAC_OS_X_VERSION_MAX_ALLOWED < 1030)
// Implementation for Mac OS X 10.2.x and earlier
Kitware Robot's avatar
Kitware Robot committed
156 157
#  include <mach-o/dyld.h>
#  include <string.h> // for strlen
Kitware Robot's avatar
Kitware Robot committed
158

Kitware Robot's avatar
Kitware Robot committed
159
namespace KWSYS_NAMESPACE {
Kitware Robot's avatar
Kitware Robot committed
160

Kitware Robot's avatar
Kitware Robot committed
161
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
Kitware Robot's avatar
Kitware Robot committed
162
  const std::string& libname, int flags)
Kitware Robot's avatar
Kitware Robot committed
163
{
Kitware Robot's avatar
Kitware Robot committed
164 165
  CHECK_OPEN_FLAGS(flags, 0, 0);

Kitware Robot's avatar
Kitware Robot committed
166 167 168
  NSObjectFileImageReturnCode rc;
  NSObjectFileImage image = 0;

Kitware Robot's avatar
Kitware Robot committed
169
  rc = NSCreateObjectFileImageFromFile(libname.c_str(), &image);
Kitware Robot's avatar
Kitware Robot committed
170
  // rc == NSObjectFileImageInappropriateFile when trying to load a dylib file
Kitware Robot's avatar
Kitware Robot committed
171
  if (rc != NSObjectFileImageSuccess) {
Kitware Robot's avatar
Kitware Robot committed
172
    return 0;
Kitware Robot's avatar
Kitware Robot committed
173
  }
Kitware Robot's avatar
Kitware Robot committed
174 175 176
  NSModule handle = NSLinkModule(image, libname.c_str(),
                                 NSLINKMODULE_OPTION_BINDNOW |
                                   NSLINKMODULE_OPTION_RETURN_ON_ERROR);
Kitware Robot's avatar
Kitware Robot committed
177 178 179 180
  NSDestroyObjectFileImage(image);
  return handle;
}

Kitware Robot's avatar
Kitware Robot committed
181
int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
Kitware Robot's avatar
Kitware Robot committed
182 183 184 185 186 187 188 189 190 191 192
{
  // NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED
  // With  this  option  the memory for the module is not deallocated
  // allowing pointers into the module to still be valid.
  // You should use this option instead if your code experience some problems
  // reported against Panther 10.3.9 (fixed in Tiger 10.4.2 and up)
  bool success = NSUnLinkModule(lib, NSUNLINKMODULE_OPTION_NONE);
  return success;
}

DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
Kitware Robot's avatar
Kitware Robot committed
193
  DynamicLoader::LibraryHandle lib, const std::string& sym)
Kitware Robot's avatar
Kitware Robot committed
194
{
Kitware Robot's avatar
Kitware Robot committed
195
  void* result = 0;
Kitware Robot's avatar
Kitware Robot committed
196
  // Need to prepend symbols with '_' on Apple-gcc compilers
Kitware Robot's avatar
Kitware Robot committed
197
  std::string rsym = '_' + sym;
Kitware Robot's avatar
Kitware Robot committed
198

Kitware Robot's avatar
Kitware Robot committed
199
  NSSymbol symbol = NSLookupSymbolInModule(lib, rsym.c_str());
Kitware Robot's avatar
Kitware Robot committed
200
  if (symbol) {
Kitware Robot's avatar
Kitware Robot committed
201
    result = NSAddressOfSymbol(symbol);
Kitware Robot's avatar
Kitware Robot committed
202
  }
Kitware Robot's avatar
Kitware Robot committed
203 204 205 206 207 208 209 210 211 212 213 214

  // Hack to cast pointer-to-data to pointer-to-function.
  return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
}

const char* DynamicLoader::LastError()
{
  return 0;
}

} // namespace KWSYS_NAMESPACE

Kitware Robot's avatar
Kitware Robot committed
215 216
#elif defined(_WIN32) && !defined(__CYGWIN__)
// Implementation for Windows win32 code but not cygwin
Kitware Robot's avatar
Kitware Robot committed
217
#  include <windows.h>
Kitware Robot's avatar
Kitware Robot committed
218

Kitware Robot's avatar
Kitware Robot committed
219 220
#  include <stdio.h>

Kitware Robot's avatar
Kitware Robot committed
221
namespace KWSYS_NAMESPACE {
Kitware Robot's avatar
Kitware Robot committed
222

Kitware Robot's avatar
Kitware Robot committed
223
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
Kitware Robot's avatar
Kitware Robot committed
224
  const std::string& libname, int flags)
Kitware Robot's avatar
Kitware Robot committed
225
{
Kitware Robot's avatar
Kitware Robot committed
226 227 228 229 230 231 232 233 234
  CHECK_OPEN_FLAGS(flags, SearchBesideLibrary, NULL);

  DWORD llFlags = 0;
  if (flags & SearchBesideLibrary) {
    llFlags |= LOAD_WITH_ALTERED_SEARCH_PATH;
  }

  return LoadLibraryExW(Encoding::ToWindowsExtendedPath(libname).c_str(), NULL,
                        llFlags);
Kitware Robot's avatar
Kitware Robot committed
235 236 237 238 239 240 241 242
}

int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
{
  return (int)FreeLibrary(lib);
}

DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
Kitware Robot's avatar
Kitware Robot committed
243
  DynamicLoader::LibraryHandle lib, const std::string& sym)
Kitware Robot's avatar
Kitware Robot committed
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
{
  // TODO: The calling convention affects the name of the symbol.  We
  // should have a tool to help get the symbol with the desired
  // calling convention.  Currently we assume cdecl.
  //
  // Borland:
  //   __cdecl    = "_func" (default)
  //   __fastcall = "@_func"
  //   __stdcall  = "func"
  //
  // Watcom:
  //   __cdecl    = "_func"
  //   __fastcall = "@_func@X"
  //   __stdcall  = "_func@X"
  //   __watcall  = "func_" (default)
  //
  // MSVC:
  //   __cdecl    = "func" (default)
  //   __fastcall = "@_func@X"
  //   __stdcall  = "_func@X"
  //
  // Note that the "@X" part of the name above is the total size (in
  // bytes) of the arguments on the stack.
Kitware Robot's avatar
Kitware Robot committed
267
  void* result;
Kitware Robot's avatar
Kitware Robot committed
268
#  if defined(__BORLANDC__) || defined(__WATCOMC__)
Kitware Robot's avatar
Kitware Robot committed
269
  // Need to prepend symbols with '_'
Kitware Robot's avatar
Kitware Robot committed
270 271
  std::string ssym = '_' + sym;
  const char* rsym = ssym.c_str();
Kitware Robot's avatar
Kitware Robot committed
272
#  else
Kitware Robot's avatar
Kitware Robot committed
273
  const char* rsym = sym.c_str();
Kitware Robot's avatar
Kitware Robot committed
274
#  endif
Kitware Robot's avatar
Kitware Robot committed
275
  result = (void*)GetProcAddress(lib, rsym);
Kitware Robot's avatar
Kitware Robot committed
276
// Hack to cast pointer-to-data to pointer-to-function.
Kitware Robot's avatar
Kitware Robot committed
277
#  ifdef __WATCOMC__
Kitware Robot's avatar
Kitware Robot committed
278
  return *(DynamicLoader::SymbolPointer*)(&result);
Kitware Robot's avatar
Kitware Robot committed
279
#  else
Kitware Robot's avatar
Kitware Robot committed
280
  return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
Kitware Robot's avatar
Kitware Robot committed
281
#  endif
Kitware Robot's avatar
Kitware Robot committed
282 283
}

Kitware Robot's avatar
Kitware Robot committed
284 285
#  define DYNLOAD_ERROR_BUFFER_SIZE 1024

Kitware Robot's avatar
Kitware Robot committed
286 287
const char* DynamicLoader::LastError()
{
Kitware Robot's avatar
Kitware Robot committed
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
  wchar_t lpMsgBuf[DYNLOAD_ERROR_BUFFER_SIZE + 1];

  DWORD error = GetLastError();
  DWORD length = FormatMessageW(
    FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error,
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    lpMsgBuf, DYNLOAD_ERROR_BUFFER_SIZE, NULL);

  static char str[DYNLOAD_ERROR_BUFFER_SIZE + 1];

  if (length < 1) {
    /* FormatMessage failed.  Use a default message.  */
    _snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE,
              "DynamicLoader encountered error 0x%X.  "
              "FormatMessage failed with error 0x%X",
              error, GetLastError());
    return str;
  }
Kitware Robot's avatar
Kitware Robot committed
306

Kitware Robot's avatar
Kitware Robot committed
307 308 309 310 311 312 313
  if (!WideCharToMultiByte(CP_UTF8, 0, lpMsgBuf, -1, str,
                           DYNLOAD_ERROR_BUFFER_SIZE, NULL, NULL)) {
    /* WideCharToMultiByte failed.  Use a default message.  */
    _snprintf(str, DYNLOAD_ERROR_BUFFER_SIZE,
              "DynamicLoader encountered error 0x%X.  "
              "WideCharToMultiByte failed with error 0x%X",
              error, GetLastError());
Kitware Robot's avatar
Kitware Robot committed
314
  }
Kitware Robot's avatar
Kitware Robot committed
315 316 317 318 319 320

  return str;
}

} // namespace KWSYS_NAMESPACE

Kitware Robot's avatar
Kitware Robot committed
321 322
#elif defined(__BEOS__)
// Implementation for BeOS / Haiku
Kitware Robot's avatar
Kitware Robot committed
323
#  include <string.h> // for strerror()
Kitware Robot's avatar
Kitware Robot committed
324

Kitware Robot's avatar
Kitware Robot committed
325 326
#  include <be/kernel/image.h>
#  include <be/support/Errors.h>
Kitware Robot's avatar
Kitware Robot committed
327

Kitware Robot's avatar
Kitware Robot committed
328
namespace KWSYS_NAMESPACE {
Kitware Robot's avatar
Kitware Robot committed
329 330 331

static image_id last_dynamic_err = B_OK;

Kitware Robot's avatar
Kitware Robot committed
332
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
Kitware Robot's avatar
Kitware Robot committed
333
  const std::string& libname, int flags)
Kitware Robot's avatar
Kitware Robot committed
334
{
Kitware Robot's avatar
Kitware Robot committed
335 336
  CHECK_OPEN_FLAGS(flags, 0, 0);

Kitware Robot's avatar
Kitware Robot committed
337 338
  // image_id's are integers, errors are negative. Add one just in case we
  //  get a valid image_id of zero (is that even possible?).
Kitware Robot's avatar
Kitware Robot committed
339
  image_id rc = load_add_on(libname.c_str());
Kitware Robot's avatar
Kitware Robot committed
340
  if (rc < 0) {
Kitware Robot's avatar
Kitware Robot committed
341 342
    last_dynamic_err = rc;
    return 0;
Kitware Robot's avatar
Kitware Robot committed
343
  }
Kitware Robot's avatar
Kitware Robot committed
344

Kitware Robot's avatar
Kitware Robot committed
345
  return rc + 1;
Kitware Robot's avatar
Kitware Robot committed
346 347 348 349
}

int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
{
Kitware Robot's avatar
Kitware Robot committed
350 351 352 353
  if (!lib) {
    last_dynamic_err = B_BAD_VALUE;
    return 0;
  } else {
Kitware Robot's avatar
Kitware Robot committed
354
    // The function dlclose() returns 0 on success, and non-zero on error.
Kitware Robot's avatar
Kitware Robot committed
355 356
    status_t rc = unload_add_on(lib - 1);
    if (rc != B_OK) {
Kitware Robot's avatar
Kitware Robot committed
357 358 359
      last_dynamic_err = rc;
      return 0;
    }
Kitware Robot's avatar
Kitware Robot committed
360
  }
Kitware Robot's avatar
Kitware Robot committed
361 362 363 364 365

  return 1;
}

DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
Kitware Robot's avatar
Kitware Robot committed
366
  DynamicLoader::LibraryHandle lib, const std::string& sym)
Kitware Robot's avatar
Kitware Robot committed
367 368
{
  // Hack to cast pointer-to-data to pointer-to-function.
Kitware Robot's avatar
Kitware Robot committed
369
  union
Kitware Robot's avatar
Kitware Robot committed
370 371 372 373 374 375 376
  {
    void* pvoid;
    DynamicLoader::SymbolPointer psym;
  } result;

  result.psym = NULL;

Kitware Robot's avatar
Kitware Robot committed
377 378 379
  if (!lib) {
    last_dynamic_err = B_BAD_VALUE;
  } else {
Kitware Robot's avatar
Kitware Robot committed
380 381 382
    // !!! FIXME: BeOS can do function-only lookups...does this ever
    // !!! FIXME:  actually _want_ a data symbol lookup, or was this union
    // !!! FIXME:  a leftover of dlsym()? (s/ANY/TEXT for functions only).
Kitware Robot's avatar
Kitware Robot committed
383 384 385
    status_t rc =
      get_image_symbol(lib - 1, sym.c_str(), B_SYMBOL_TYPE_ANY, &result.pvoid);
    if (rc != B_OK) {
Kitware Robot's avatar
Kitware Robot committed
386 387 388
      last_dynamic_err = rc;
      result.psym = NULL;
    }
Kitware Robot's avatar
Kitware Robot committed
389
  }
Kitware Robot's avatar
Kitware Robot committed
390 391 392 393 394
  return result.psym;
}

const char* DynamicLoader::LastError()
{
Kitware Robot's avatar
Kitware Robot committed
395
  const char* retval = strerror(last_dynamic_err);
Kitware Robot's avatar
Kitware Robot committed
396 397 398 399 400 401
  last_dynamic_err = B_OK;
  return retval;
}

} // namespace KWSYS_NAMESPACE

Kitware Robot's avatar
Kitware Robot committed
402 403
#elif defined(__MINT__)
// Implementation for FreeMiNT on Atari
Kitware Robot's avatar
Kitware Robot committed
404 405 406 407 408
#  define _GNU_SOURCE /* for program_invocation_name */
#  include <dld.h>
#  include <errno.h>
#  include <malloc.h>
#  include <string.h>
Kitware Robot's avatar
Kitware Robot committed
409

Kitware Robot's avatar
Kitware Robot committed
410
namespace KWSYS_NAMESPACE {
Kitware Robot's avatar
Kitware Robot committed
411

Kitware Robot's avatar
Kitware Robot committed
412
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
Kitware Robot's avatar
Kitware Robot committed
413
  const std::string& libname, int flags)
Kitware Robot's avatar
Kitware Robot committed
414
{
Kitware Robot's avatar
Kitware Robot committed
415 416
  CHECK_OPEN_FLAGS(flags, 0, NULL);

Kitware Robot's avatar
Kitware Robot committed
417
  char* name = (char*)calloc(1, libname.size() + 1);
Kitware Robot's avatar
Kitware Robot committed
418
  dld_init(program_invocation_name);
Kitware Robot's avatar
Kitware Robot committed
419 420
  strncpy(name, libname.c_str(), libname.size());
  dld_link(libname.c_str());
Kitware Robot's avatar
Kitware Robot committed
421
  return (void*)name;
Kitware Robot's avatar
Kitware Robot committed
422 423 424 425
}

int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
{
Kitware Robot's avatar
Kitware Robot committed
426
  dld_unlink_by_file((char*)lib, 0);
Kitware Robot's avatar
Kitware Robot committed
427 428 429 430 431
  free(lib);
  return 0;
}

DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
Kitware Robot's avatar
Kitware Robot committed
432
  DynamicLoader::LibraryHandle lib, const std::string& sym)
Kitware Robot's avatar
Kitware Robot committed
433 434 435 436 437 438 439
{
  // Hack to cast pointer-to-data to pointer-to-function.
  union
  {
    void* pvoid;
    DynamicLoader::SymbolPointer psym;
  } result;
Kitware Robot's avatar
Kitware Robot committed
440
  result.pvoid = dld_get_symbol(sym.c_str());
Kitware Robot's avatar
Kitware Robot committed
441 442 443 444 445 446 447 448 449 450
  return result.psym;
}

const char* DynamicLoader::LastError()
{
  return dld_strerror(dld_errno);
}

} // namespace KWSYS_NAMESPACE

Kitware Robot's avatar
Kitware Robot committed
451 452 453
#else
// Default implementation for *NIX systems (including Mac OS X 10.3 and
// later) which use dlopen
Kitware Robot's avatar
Kitware Robot committed
454
#  include <dlfcn.h>
Kitware Robot's avatar
Kitware Robot committed
455

Kitware Robot's avatar
Kitware Robot committed
456
namespace KWSYS_NAMESPACE {
Kitware Robot's avatar
Kitware Robot committed
457

Kitware Robot's avatar
Kitware Robot committed
458
DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(
Kitware Robot's avatar
Kitware Robot committed
459
  const std::string& libname, int flags)
Kitware Robot's avatar
Kitware Robot committed
460
{
Kitware Robot's avatar
Kitware Robot committed
461 462
  CHECK_OPEN_FLAGS(flags, 0, NULL);

Kitware Robot's avatar
Kitware Robot committed
463
  return dlopen(libname.c_str(), RTLD_LAZY);
Kitware Robot's avatar
Kitware Robot committed
464 465 466 467
}

int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
{
Kitware Robot's avatar
Kitware Robot committed
468
  if (lib) {
Kitware Robot's avatar
Kitware Robot committed
469 470
    // The function dlclose() returns 0 on success, and non-zero on error.
    return !dlclose(lib);
Kitware Robot's avatar
Kitware Robot committed
471
  }
Kitware Robot's avatar
Kitware Robot committed
472 473 474 475 476
  // else
  return 0;
}

DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
Kitware Robot's avatar
Kitware Robot committed
477
  DynamicLoader::LibraryHandle lib, const std::string& sym)
Kitware Robot's avatar
Kitware Robot committed
478 479
{
  // Hack to cast pointer-to-data to pointer-to-function.
Kitware Robot's avatar
Kitware Robot committed
480
  union
Kitware Robot's avatar
Kitware Robot committed
481 482 483 484
  {
    void* pvoid;
    DynamicLoader::SymbolPointer psym;
  } result;
Kitware Robot's avatar
Kitware Robot committed
485
  result.pvoid = dlsym(lib, sym.c_str());
Kitware Robot's avatar
Kitware Robot committed
486 487 488 489 490 491 492 493 494 495
  return result.psym;
}

const char* DynamicLoader::LastError()
{
  return dlerror();
}

} // namespace KWSYS_NAMESPACE
#endif