dl.hpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #pragma once
  2. //dynamic linking support
  3. #include <nall/intrinsics.hpp>
  4. #include <nall/path.hpp>
  5. #include <nall/stdint.hpp>
  6. #include <nall/string.hpp>
  7. #include <nall/utility.hpp>
  8. #if defined(PLATFORM_WINDOWS)
  9. #include <nall/windows/utf8.hpp>
  10. #else
  11. #include <dlfcn.h>
  12. #endif
  13. namespace nall {
  14. struct library {
  15. library() = default;
  16. ~library() { close(); }
  17. library& operator=(const library&) = delete;
  18. library(const library&) = delete;
  19. explicit operator bool() const { return open(); }
  20. auto open() const -> bool { return handle; }
  21. auto open(const string&, const string& = "") -> bool;
  22. auto openAbsolute(const string&) -> bool;
  23. auto sym(const string&) -> void*;
  24. auto close() -> void;
  25. private:
  26. uintptr handle = 0;
  27. };
  28. #if defined(PLATFORM_LINUX) || defined(PLATFORM_BSD)
  29. inline auto library::open(const string& name, const string& path) -> bool {
  30. if(handle) close();
  31. if(path) handle = (uintptr)dlopen(string(path, "lib", name, ".so"), RTLD_LAZY);
  32. if(!handle) handle = (uintptr)dlopen(string(Path::user(), ".local/lib/lib", name, ".so"), RTLD_LAZY);
  33. if(!handle) handle = (uintptr)dlopen(string("/usr/local/lib/lib", name, ".so"), RTLD_LAZY);
  34. if(!handle) handle = (uintptr)dlopen(string("lib", name, ".so"), RTLD_LAZY);
  35. return handle;
  36. }
  37. inline auto library::openAbsolute(const string& name) -> bool {
  38. if(handle) close();
  39. handle = (uintptr)dlopen(name, RTLD_LAZY);
  40. return handle;
  41. }
  42. inline auto library::sym(const string& name) -> void* {
  43. if(!handle) return nullptr;
  44. return dlsym((void*)handle, name);
  45. }
  46. inline auto library::close() -> void {
  47. if(!handle) return;
  48. dlclose((void*)handle);
  49. handle = 0;
  50. }
  51. #elif defined(PLATFORM_MACOS)
  52. inline auto library::open(const string& name, const string& path) -> bool {
  53. if(handle) close();
  54. if(path) handle = (uintptr)dlopen(string(path, "lib", name, ".dylib"), RTLD_LAZY);
  55. if(!handle) handle = (uintptr)dlopen(string(Path::user(), ".local/lib/lib", name, ".dylib"), RTLD_LAZY);
  56. if(!handle) handle = (uintptr)dlopen(string("/usr/local/lib/lib", name, ".dylib"), RTLD_LAZY);
  57. if(!handle) handle = (uintptr)dlopen(string("lib", name, ".dylib"), RTLD_LAZY);
  58. return handle;
  59. }
  60. inline auto library::openAbsolute(const string& name) -> bool {
  61. if(handle) close();
  62. handle = (uintptr)dlopen(name, RTLD_LAZY);
  63. return handle;
  64. }
  65. inline auto library::sym(const string& name) -> void* {
  66. if(!handle) return nullptr;
  67. return dlsym((void*)handle, name);
  68. }
  69. inline auto library::close() -> void {
  70. if(!handle) return;
  71. dlclose((void*)handle);
  72. handle = 0;
  73. }
  74. #elif defined(PLATFORM_WINDOWS)
  75. inline auto library::open(const string& name, const string& path) -> bool {
  76. if(handle) close();
  77. if(path) {
  78. string filepath = {path, name, ".dll"};
  79. handle = (uintptr)LoadLibraryW(utf16_t(filepath));
  80. }
  81. if(!handle) {
  82. string filepath = {name, ".dll"};
  83. handle = (uintptr)LoadLibraryW(utf16_t(filepath));
  84. }
  85. return handle;
  86. }
  87. inline auto library::openAbsolute(const string& name) -> bool {
  88. if(handle) close();
  89. handle = (uintptr)LoadLibraryW(utf16_t(name));
  90. return handle;
  91. }
  92. inline auto library::sym(const string& name) -> void* {
  93. if(!handle) return nullptr;
  94. return (void*)GetProcAddress((HMODULE)handle, name);
  95. }
  96. inline auto library::close() -> void {
  97. if(!handle) return;
  98. FreeLibrary((HMODULE)handle);
  99. handle = 0;
  100. }
  101. #else
  102. inline auto library::open(const string&, const string&) -> bool { return false; }
  103. inline auto library::openAbsolute(const string&) -> bool { return false; }
  104. inline auto library::sym(const string&) -> void* { return nullptr; }
  105. inline auto library::close() -> void {}
  106. #endif
  107. }