dynlib.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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. TExternalSymbol& operator=(const TExternalSymbol& es) {
  53. if (this != &es) {
  54. Close();
  55. if (es.IsDynamic())
  56. Open(es.LibName().data(), es.VtblName().data());
  57. else if (es.IsStatic())
  58. SetSym(es.Symbol());
  59. }
  60. return *this;
  61. }
  62. ~TExternalSymbol() {
  63. delete DLib;
  64. }
  65. // set the symbol from dynamic source
  66. void Open(const char* lib_name, const char* vtbl_name) {
  67. if (DLib != nullptr || PLib != nullptr)
  68. return;
  69. try {
  70. DLib = new TDynamicLibrary();
  71. DLib->Open(lib_name);
  72. PLib = (TLib*)DLib->Sym(vtbl_name);
  73. } catch (...) {
  74. delete DLib;
  75. DLib = nullptr;
  76. throw;
  77. }
  78. lname = lib_name;
  79. vname = vtbl_name;
  80. }
  81. // set the symbol from static source
  82. void SetSym(TLib* pl) noexcept {
  83. if (DLib == nullptr && PLib == nullptr)
  84. PLib = pl;
  85. }
  86. void Close() noexcept {
  87. delete DLib;
  88. DLib = 0;
  89. PLib = 0;
  90. lname.remove();
  91. vname.remove();
  92. }
  93. TLib* Symbol() const noexcept {
  94. return PLib;
  95. }
  96. const TString& LibName() const noexcept {
  97. return lname;
  98. }
  99. const TString& VtblName() const noexcept {
  100. return vname;
  101. }
  102. bool IsStatic() const noexcept {
  103. return DLib == nullptr && PLib != nullptr;
  104. }
  105. bool IsDynamic() const noexcept {
  106. return DLib && DLib->IsLoaded() && PLib != nullptr;
  107. }
  108. };