Module.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // Copyright (c) 2013-2018 Josh Blum
  2. // SPDX-License-Identifier: BSL-1.0
  3. #include <Pothos/System/Paths.hpp>
  4. #include <Pothos/Plugin/Module.hpp>
  5. #include <Pothos/Plugin/Registry.hpp>
  6. #include <Pothos/Plugin/Exception.hpp>
  7. #include <Pothos/Object.hpp> //pulls in full Object implementation
  8. #include <Poco/SharedLibrary.h>
  9. #include <Poco/Platform.h>
  10. #include <Poco/Logger.h>
  11. #include <Poco/Format.h>
  12. #include <mutex>
  13. /***********************************************************************
  14. * Disabler for windows error messages
  15. **********************************************************************/
  16. #if POCO_OS == POCO_OS_WINDOWS_NT
  17. #include <windows.h>
  18. BOOL DL_SetThreadErrorMode(DWORD dwNewMode, LPDWORD lpOldMode);
  19. struct ErrorMessageDisableGuard
  20. {
  21. ErrorMessageDisableGuard(void)
  22. {
  23. DL_SetThreadErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX, &oldMode);
  24. }
  25. ~ErrorMessageDisableGuard(void)
  26. {
  27. DL_SetThreadErrorMode(oldMode, nullptr);
  28. }
  29. DWORD oldMode;
  30. };
  31. #else
  32. struct ErrorMessageDisableGuard
  33. {
  34. ErrorMessageDisableGuard(void){}
  35. ~ErrorMessageDisableGuard(void){}
  36. };
  37. #endif
  38. /***********************************************************************
  39. * Locking for plugin attach helper
  40. **********************************************************************/
  41. void registrySetActiveModuleLoading(const Pothos::PluginModule &module);
  42. std::vector<std::string> getPluginPaths(const Pothos::PluginModule &module);
  43. static std::mutex &getModuleMutex(void)
  44. {
  45. static std::mutex mutex;
  46. return mutex;
  47. }
  48. //where to store the version during module load
  49. static thread_local std::string *currentModuleVersion(nullptr);
  50. /***********************************************************************
  51. * Shared implementation for module data
  52. **********************************************************************/
  53. struct Pothos::PluginModule::Impl
  54. {
  55. Poco::SharedLibrary sharedLibrary;
  56. std::string path;
  57. std::vector<std::string> pluginPaths;
  58. std::string version;
  59. };
  60. /***********************************************************************
  61. * Module implementation
  62. **********************************************************************/
  63. const Pothos::PluginModule &Pothos::PluginModule::null(void)
  64. {
  65. static PluginModule nullModule;
  66. return nullModule;
  67. }
  68. Pothos::PluginModule::PluginModule(void)
  69. {
  70. return;
  71. }
  72. Pothos::PluginModule::PluginModule(const std::string &path):
  73. _impl(new Impl())
  74. {
  75. _impl->path = path;
  76. poco_debug(Poco::Logger::get("Pothos.PluginModule.load"), path);
  77. try
  78. {
  79. std::lock_guard<std::mutex> lock(getModuleMutex());
  80. registrySetActiveModuleLoading(*this);
  81. currentModuleVersion = &(_impl->version);
  82. ErrorMessageDisableGuard emdg;
  83. _impl->sharedLibrary.load(path);
  84. currentModuleVersion = nullptr;
  85. registrySetActiveModuleLoading(PluginModule());
  86. _impl->pluginPaths = ::getPluginPaths(*this);
  87. }
  88. catch(const Poco::LibraryLoadException &ex)
  89. {
  90. throw PluginModuleError("Pothos::PluginModule("+path+")", ex.displayText());
  91. }
  92. }
  93. Pothos::PluginModule::~PluginModule(void)
  94. {
  95. if (not _impl) return; //no private data
  96. if (not _impl.unique()) return; //this is not the last copy
  97. if (not _impl->sharedLibrary.isLoaded()) return; //module not loaded
  98. poco_debug(Poco::Logger::get("Pothos.PluginModule.unload"), _impl->sharedLibrary.getPath());
  99. for (const auto &pluginPath : this->getPluginPaths())
  100. {
  101. PluginRegistry::remove(pluginPath);
  102. }
  103. _impl->sharedLibrary.unload();
  104. }
  105. std::string Pothos::PluginModule::getFilePath(void) const
  106. {
  107. if (not _impl) return "";
  108. return _impl->path;
  109. }
  110. const std::vector<std::string> &Pothos::PluginModule::getPluginPaths(void) const
  111. {
  112. return _impl->pluginPaths;
  113. }
  114. Pothos::PluginModule::operator bool(void) const
  115. {
  116. return bool(_impl);
  117. }
  118. std::string Pothos::PluginModule::getVersion(void) const
  119. {
  120. if (not _impl) return "";
  121. return _impl->version;
  122. }
  123. Pothos::ModuleVersion::ModuleVersion(const std::string &version)
  124. {
  125. if (currentModuleVersion != nullptr) *currentModuleVersion = version;
  126. }
  127. #include <Pothos/Managed.hpp>
  128. static auto managedPluginModule = Pothos::ManagedClass()
  129. .registerConstructor<Pothos::PluginModule>()
  130. .registerConstructor<Pothos::PluginModule, const std::string &>()
  131. .registerMethod(POTHOS_FCN_TUPLE(Pothos::PluginModule, getFilePath))
  132. .registerMethod(POTHOS_FCN_TUPLE(Pothos::PluginModule, getPluginPaths))
  133. .commit("Pothos/PluginModule");