dynlib.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #pragma once
  2. #include "defaults.h"
  3. #include <util/generic/ptr.h>
  4. #include <util/generic/string.h>
  5. #define Y_GET_FUNC(dll, name) FUNC_##name((dll).Sym(#name))
  6. #define Y_GET_FUNC_OPTIONAL(dll, name) FUNC_##name((dll).SymOptional(#name))
  7. #ifdef _win32_
  8. #define DEFAULT_DLLOPEN_FLAGS 0
  9. #else
  10. #include <dlfcn.h>
  11. #ifndef RTLD_GLOBAL
  12. #define RTLD_GLOBAL (0)
  13. #endif
  14. #define DEFAULT_DLLOPEN_FLAGS (RTLD_NOW | RTLD_GLOBAL)
  15. #endif
  16. class TDynamicLibrary {
  17. public:
  18. TDynamicLibrary() noexcept;
  19. TDynamicLibrary(const TString& path, int flags = DEFAULT_DLLOPEN_FLAGS);
  20. ~TDynamicLibrary();
  21. void Open(const char* path, int flags = DEFAULT_DLLOPEN_FLAGS);
  22. void Close() noexcept;
  23. void* SymOptional(const char* name) noexcept;
  24. void* Sym(const char* name);
  25. bool IsLoaded() const noexcept;
  26. void SetUnloadable(bool unloadable); // Set to false to avoid unloading on destructor
  27. private:
  28. class TImpl;
  29. THolder<TImpl> Impl_;
  30. };
  31. // a wrapper for a symbol
  32. template <class TLib>
  33. class TExternalSymbol {
  34. private:
  35. TLib* PLib;
  36. TDynamicLibrary* DLib;
  37. TString lname;
  38. TString vname;
  39. public:
  40. TExternalSymbol() noexcept {
  41. PLib = nullptr;
  42. DLib = nullptr;
  43. }
  44. TExternalSymbol(const TExternalSymbol& es) {
  45. PLib = nullptr;
  46. DLib = nullptr;
  47. if (es.IsDynamic()) {
  48. Open(es.LibName().data(), es.VtblName().data());
  49. } else if (es.IsStatic()) {
  50. SetSym(es.Symbol());
  51. }
  52. }
  53. TExternalSymbol& operator=(const TExternalSymbol& es) {
  54. if (this != &es) {
  55. Close();
  56. if (es.IsDynamic()) {
  57. Open(es.LibName().data(), es.VtblName().data());
  58. } else if (es.IsStatic()) {
  59. SetSym(es.Symbol());
  60. }
  61. }
  62. return *this;
  63. }
  64. ~TExternalSymbol() {
  65. delete DLib;
  66. }
  67. // set the symbol from dynamic source
  68. void Open(const char* lib_name, const char* vtbl_name) {
  69. if (DLib != nullptr || PLib != nullptr) {
  70. return;
  71. }
  72. try {
  73. DLib = new TDynamicLibrary();
  74. DLib->Open(lib_name);
  75. PLib = (TLib*)DLib->Sym(vtbl_name);
  76. } catch (...) {
  77. delete DLib;
  78. DLib = nullptr;
  79. throw;
  80. }
  81. lname = lib_name;
  82. vname = vtbl_name;
  83. }
  84. // set the symbol from static source
  85. void SetSym(TLib* pl) noexcept {
  86. if (DLib == nullptr && PLib == nullptr) {
  87. PLib = pl;
  88. }
  89. }
  90. void Close() noexcept {
  91. delete DLib;
  92. DLib = 0;
  93. PLib = 0;
  94. lname.remove();
  95. vname.remove();
  96. }
  97. TLib* Symbol() const noexcept {
  98. return PLib;
  99. }
  100. const TString& LibName() const noexcept {
  101. return lname;
  102. }
  103. const TString& VtblName() const noexcept {
  104. return vname;
  105. }
  106. bool IsStatic() const noexcept {
  107. return DLib == nullptr && PLib != nullptr;
  108. }
  109. bool IsDynamic() const noexcept {
  110. return DLib && DLib->IsLoaded() && PLib != nullptr;
  111. }
  112. };