diff --git a/examples/plugins/engine/CMakeLists.txt b/examples/plugins/engine/CMakeLists.txt index a4f3e812c2..e49ccb6d55 100644 --- a/examples/plugins/engine/CMakeLists.txt +++ b/examples/plugins/engine/CMakeLists.txt @@ -3,14 +3,22 @@ # accompanying file Copyright.txt for details. #------------------------------------------------------------------------------# +add_library(PluginEngineWriteExample + ExampleWritePlugin.cpp +) +target_link_libraries(PluginEngineWriteExample adios2::cxx11 adios2_core) + +add_library(PluginEngineReadExample + ExampleReadPlugin.cpp +) +target_link_libraries(PluginEngineReadExample adios2::cxx11 adios2_core) + add_executable(examplePluginEngine_write examplePluginEngine_write.cpp - ExampleWritePlugin.h ExampleWritePlugin.cpp ) -target_link_libraries(examplePluginEngine_write adios2::cxx11 adios2_core) +target_link_libraries(examplePluginEngine_write adios2::cxx11) add_executable(examplePluginEngine_read examplePluginEngine_read.cpp - ExampleReadPlugin.h ExampleReadPlugin.cpp ) -target_link_libraries(examplePluginEngine_read adios2::cxx11 adios2_core) +target_link_libraries(examplePluginEngine_read adios2::cxx11) diff --git a/examples/plugins/engine/ExampleReadPlugin.cpp b/examples/plugins/engine/ExampleReadPlugin.cpp index cb29f28a29..e0a1d8b2a6 100644 --- a/examples/plugins/engine/ExampleReadPlugin.cpp +++ b/examples/plugins/engine/ExampleReadPlugin.cpp @@ -133,3 +133,17 @@ void ExampleReadPlugin::DoClose(const int transportIndex) {} } // end namespace engine } // end namespace core } // end namespace adios2 + +extern "C" { + +adios2::core::engine::ExampleReadPlugin *EngineCreate(adios2::core::IO &io, + const std::string &name, + const adios2::Mode mode, + adios2::helper::Comm comm) +{ + return new adios2::core::engine::ExampleReadPlugin(io, name, mode, + comm.Duplicate()); +} + +void EngineDestroy(adios2::core::engine::ExampleReadPlugin *obj) { delete obj; } +} diff --git a/examples/plugins/engine/ExampleReadPlugin.h b/examples/plugins/engine/ExampleReadPlugin.h index b40efa6ce0..620fc1486c 100644 --- a/examples/plugins/engine/ExampleReadPlugin.h +++ b/examples/plugins/engine/ExampleReadPlugin.h @@ -80,4 +80,13 @@ class ExampleReadPlugin : public PluginEngineInterface } // end namespace engine } // end namespace core } // end namespace adios2 + +extern "C" { + +adios2::core::engine::ExampleReadPlugin * +EngineCreate(adios2::core::IO &io, const std::string &name, + const adios2::Mode mode, adios2::helper::Comm comm); +void EngineDestroy(adios2::core::engine::ExampleReadPlugin *obj); +} + #endif /* EXAMPLEREADPLUGIN_H_ */ diff --git a/examples/plugins/engine/ExampleWritePlugin.cpp b/examples/plugins/engine/ExampleWritePlugin.cpp index 48649827b6..cc18042e7e 100644 --- a/examples/plugins/engine/ExampleWritePlugin.cpp +++ b/examples/plugins/engine/ExampleWritePlugin.cpp @@ -113,3 +113,19 @@ void ExampleWritePlugin::WriteVarsFromIO() } // end namespace engine } // end namespace core } // end namespace adios2 + +extern "C" { + +adios2::core::engine::ExampleWritePlugin * +EngineCreate(adios2::core::IO &io, const std::string &name, + const adios2::Mode mode, adios2::helper::Comm comm) +{ + return new adios2::core::engine::ExampleWritePlugin(io, name, mode, + comm.Duplicate()); +} + +void EngineDestroy(adios2::core::engine::ExampleWritePlugin *obj) +{ + delete obj; +} +} diff --git a/examples/plugins/engine/ExampleWritePlugin.h b/examples/plugins/engine/ExampleWritePlugin.h index 732130deaa..e13eecb184 100644 --- a/examples/plugins/engine/ExampleWritePlugin.h +++ b/examples/plugins/engine/ExampleWritePlugin.h @@ -81,4 +81,13 @@ class ExampleWritePlugin : public PluginEngineInterface } // end namespace engine } // end namespace core } // end namespace adios2 + +extern "C" { + +adios2::core::engine::ExampleWritePlugin * +EngineCreate(adios2::core::IO &io, const std::string &name, + const adios2::Mode mode, adios2::helper::Comm comm); +void EngineDestroy(adios2::core::engine::ExampleWritePlugin *obj); +} + #endif /* EXAMPLEWRITEPLUGIN_H_ */ diff --git a/examples/plugins/engine/examplePluginEngine_read.cpp b/examples/plugins/engine/examplePluginEngine_read.cpp index d9c6b95317..68e980c798 100644 --- a/examples/plugins/engine/examplePluginEngine_read.cpp +++ b/examples/plugins/engine/examplePluginEngine_read.cpp @@ -15,9 +15,6 @@ #include #include "adios2.h" -#include "adios2/engine/plugin/PluginEngine.h" - -#include "ExampleReadPlugin.h" void testStreaming(adios2::Engine &reader, std::vector &myFloats, adios2::Variable &var) @@ -58,10 +55,6 @@ int main(int argc, char *argv[]) std::vector myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - /** Register Plugin with the PluginEngine **/ - adios2::core::engine::PluginEngine::RegisterPlugin< - adios2::core::engine::ExampleReadPlugin>("MyPlugin"); - try { /** ADIOS class factory of IO class objects */ @@ -73,7 +66,8 @@ int main(int argc, char *argv[]) /** Engine derived class, spawned to start IO operations */ io.SetEngine("Plugin"); - io.SetParameters({{"PluginName", "MyPlugin"}}); + io.SetParameters({{"PluginName", "ReadPlugin"}}); + io.SetParameters({{"PluginLibrary", "PluginEngineRead"}}); adios2::Engine reader = io.Open("TestPlugin", adios2::Mode::Read); auto var = io.InquireVariable("data"); diff --git a/examples/plugins/engine/examplePluginEngine_write.cpp b/examples/plugins/engine/examplePluginEngine_write.cpp index 5c87f4a7e1..9110995cd3 100644 --- a/examples/plugins/engine/examplePluginEngine_write.cpp +++ b/examples/plugins/engine/examplePluginEngine_write.cpp @@ -15,9 +15,6 @@ #include #include "adios2.h" -#include "adios2/engine/plugin/PluginEngine.h" - -#include "ExampleWritePlugin.h" void testStreaming(adios2::Engine &writer, std::vector &myFloats, adios2::Variable &var) @@ -49,10 +46,6 @@ int main(int argc, char *argv[]) std::vector myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; const std::size_t Nx = myFloats.size(); - /** Register Plugin with the PluginEngine **/ - adios2::core::engine::PluginEngine::RegisterPlugin< - adios2::core::engine::ExampleWritePlugin>("MyPlugin"); - try { /** ADIOS class factory of IO class objects */ @@ -69,7 +62,8 @@ int main(int argc, char *argv[]) /** Engine derived class, spawned to start IO operations */ io.SetEngine("Plugin"); - io.SetParameters({{"PluginName", "MyPlugin"}}); + io.SetParameters({{"PluginName", "WritePlugin"}}); + io.SetParameters({{"PluginLibrary", "PluginEngineWrite"}}); adios2::Engine writer = io.Open("TestPlugin", adios2::Mode::Write); if (streaming) diff --git a/source/adios2/engine/plugin/PluginEngine.cpp b/source/adios2/engine/plugin/PluginEngine.cpp index fe72c9ebd6..c88377658a 100644 --- a/source/adios2/engine/plugin/PluginEngine.cpp +++ b/source/adios2/engine/plugin/PluginEngine.cpp @@ -13,13 +13,14 @@ #include "PluginEngineInterface.h" #include -#include #include #include #include #include "adios2/helper/adiosDynamicBinder.h" +#include + namespace adios2 { namespace core @@ -31,27 +32,12 @@ namespace engine struct PluginEngine::Impl { - using Registry = - std::map>; - static Registry m_Registry; - - std::string m_PluginName; + std::string m_PluginName = "UserPlugin"; std::unique_ptr m_Binder; EngineCreateFun m_HandleCreate; EngineDestroyFun m_HandleDestroy; PluginEngineInterface *m_Plugin = nullptr; }; -PluginEngine::Impl::Registry PluginEngine::Impl::m_Registry; - -/******************************************************************************/ - -void PluginEngine::RegisterPlugin(const std::string pluginName, - EngineCreateFun create, - EngineDestroyFun destroy) -{ - PluginEngine::Impl::m_Registry.emplace(pluginName, - std::make_pair(create, destroy)); -} /******************************************************************************/ @@ -80,56 +66,50 @@ void PluginEngine::EndStep() { m_Impl->m_Plugin->EndStep(); } void PluginEngine::Init() { auto paramPluginNameIt = m_IO.m_Parameters.find("PluginName"); - if (paramPluginNameIt == m_IO.m_Parameters.end()) + if (paramPluginNameIt != m_IO.m_Parameters.end()) { - throw std::invalid_argument("PluginEngine: PluginName must be " - "specified in engine parameters"); + m_Impl->m_PluginName = paramPluginNameIt->second; } - m_Impl->m_PluginName = paramPluginNameIt->second; - // First we check to see if we can find the plugin currently registerd - auto registryEntryIt = - PluginEngine::Impl::m_Registry.find(m_Impl->m_PluginName); + std::string pluginPath; + if (!adios2sys::SystemTools::GetEnv("ADIOS2_PLUGIN_PATH", pluginPath)) + { + std::cout + << "PluginEngine Warning: Environment variable ADIOS2_PLUGIN_PATH" + " was not set. Checking current working directory for plugin " + "instead.\n"; + pluginPath = adios2sys::SystemTools::GetCurrentWorkingDirectory(); + } - if (registryEntryIt != PluginEngine::Impl::m_Registry.end()) + auto paramPluginLibraryIt = m_IO.m_Parameters.find("PluginLibrary"); + if (paramPluginLibraryIt == m_IO.m_Parameters.end()) { - m_Impl->m_HandleCreate = registryEntryIt->second.first; - m_Impl->m_HandleDestroy = registryEntryIt->second.second; + throw std::invalid_argument( + "PluginEngine: PluginLibrary must be specified in " + "engine parameters if no PluginName " + "is specified"); } - else + std::string &pluginLibrary = paramPluginLibraryIt->second; + + m_Impl->m_Binder.reset( + new helper::DynamicBinder(pluginLibrary, pluginPath)); + + m_Impl->m_HandleCreate = reinterpret_cast( + m_Impl->m_Binder->GetSymbol("EngineCreate")); + if (!m_Impl->m_HandleCreate) + { + throw std::runtime_error("PluginEngine: Unable to locate " + "EngineCreate symbol in specified plugin " + "library"); + } + + m_Impl->m_HandleDestroy = reinterpret_cast( + m_Impl->m_Binder->GetSymbol("EngineDestroy")); + if (!m_Impl->m_HandleDestroy) { - // It's not currently registered so try to load it from a shared - // library - // - auto paramPluginLibraryIt = m_IO.m_Parameters.find("PluginLibrary"); - if (paramPluginLibraryIt == m_IO.m_Parameters.end()) - { - throw std::invalid_argument( - "PluginEngine: PluginLibrary must be specified in " - "engine parameters if no PluginName " - "is specified"); - } - std::string &pluginLibrary = paramPluginLibraryIt->second; - - m_Impl->m_Binder.reset(new helper::DynamicBinder(pluginLibrary)); - - m_Impl->m_HandleCreate = reinterpret_cast( - m_Impl->m_Binder->GetSymbol("EngineCreate")); - if (!m_Impl->m_HandleCreate) - { - throw std::runtime_error("PluginEngine: Unable to locate " - "EngineCreate symbol in specified plugin " - "library"); - } - - m_Impl->m_HandleDestroy = reinterpret_cast( - m_Impl->m_Binder->GetSymbol("EngineDestroy")); - if (!m_Impl->m_HandleDestroy) - { - throw std::runtime_error("PluginEngine: Unable to locate " - "EngineDestroy symbol in specified plugin " - "library"); - } + throw std::runtime_error("PluginEngine: Unable to locate " + "EngineDestroy symbol in specified plugin " + "library"); } } diff --git a/source/adios2/engine/plugin/PluginEngine.h b/source/adios2/engine/plugin/PluginEngine.h index 3e8c5a8172..74c74ce370 100644 --- a/source/adios2/engine/plugin/PluginEngine.h +++ b/source/adios2/engine/plugin/PluginEngine.h @@ -18,14 +18,12 @@ #include // for unique_ptr #include // for string #include // for add_pointer -#include // for vector #include "adios2/common/ADIOSMacros.h" #include "adios2/common/ADIOSTypes.h" #include "adios2/core/Engine.h" #include "adios2/core/IO.h" #include "adios2/core/Variable.h" -#include "adios2/core/VariableCompound.h" #include "adios2/helper/adiosComm.h" namespace adios2 @@ -49,23 +47,6 @@ class PluginEngine : public Engine using EngineDestroyFun = std::function::type>; - static void RegisterPlugin(const std::string pluginName, - EngineCreateFun create, - EngineDestroyFun destroy); - static void RegisterPlugin(const std::string pluginName, - EngineCreatePtr create, EngineDestroyPtr destroy) - { - RegisterPlugin(pluginName, EngineCreateFun(create), - EngineDestroyFun(destroy)); - } - - // This is just a shortcut method to handle the case where the class type is - // directly available to the caller so a simple new and delete call is - // sufficient to create and destroy the engine object - template - static void RegisterPlugin(const std::string name); - -public: PluginEngine(IO &io, const std::string &name, const Mode mode, helper::Comm comm); virtual ~PluginEngine(); @@ -99,6 +80,4 @@ class PluginEngine : public Engine } // end namespace core } // end namespace adios2 -#include "PluginEngine.inl" - #endif /* ADIOS2_ENGINE_PLUGIN_PLUGINENGINE_H_ */ diff --git a/source/adios2/engine/plugin/PluginEngine.inl b/source/adios2/engine/plugin/PluginEngine.inl deleted file mode 100644 index 3006e45c53..0000000000 --- a/source/adios2/engine/plugin/PluginEngine.inl +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * PluginEngine.h Support for an engine implemented outside libadios2 - * - * Created on: July 5, 2021 - * Author: Chuck Atkins - * Caitlin Ross - */ - -#ifndef ADIOS2_ENGINE_PLUGIN_ENGINE_INL_ -#define ADIOS2_ENGINE_PLUGIN_ENGINE_INL_ -#ifndef ADIOS2_ENGINE_PLUGIN_PLUGINENGINE_H_ -#error "Inline file should only be included from it's header, never on it's own" -#endif - -#include "PluginEngine.h" - -namespace adios2 -{ -namespace core -{ -namespace engine -{ - -template -void PluginEngine::RegisterPlugin(const std::string name) -{ - EngineCreateFun createFun = - [](IO &io, const std::string &name, const Mode openMode, - helper::Comm comm) -> PluginEngineInterface * { - return new T(io, name, openMode, comm.Duplicate()); - }; - EngineDestroyFun destroyFun = [](Engine *obj) -> void { delete obj; }; - - RegisterPlugin(name, createFun, destroyFun); -} - -} // end namespace engine -} // end namespace core -} // end namespace adios2 - -#endif // ADIOS2_ENGINE_PLUGIN_ENGINE_INL_ diff --git a/source/adios2/helper/adiosDynamicBinder.cpp b/source/adios2/helper/adiosDynamicBinder.cpp index 42d7cfcc0b..1a9b586f5b 100644 --- a/source/adios2/helper/adiosDynamicBinder.cpp +++ b/source/adios2/helper/adiosDynamicBinder.cpp @@ -18,6 +18,7 @@ #include // for vector #include +#include namespace adios2 { @@ -30,6 +31,13 @@ struct DynamicBinder::Impl }; DynamicBinder::DynamicBinder(std::string libName) +{ + auto path = adios2sys::SystemTools::GetCurrentWorkingDirectory(); + DynamicBinder(libName, path); +} + +DynamicBinder::DynamicBinder(std::string libName, std::string libPath) +: m_Impl(new Impl) { std::vector libPrefixes; libPrefixes.emplace_back(""); @@ -61,7 +69,11 @@ DynamicBinder::DynamicBinder(std::string libName) { for (const std::string &suffix : libSuffixes) { - fileName = prefix + libName + suffix; + fileName = libPath + "/" + prefix + libName + suffix; + // Slashes in fileName is correct for unix-like systems + // ConvertToOutputPath() will change slashes if we're running on + // a Windows system + fileName = adios2sys::SystemTools::ConvertToOutputPath(fileName); m_Impl->m_LibraryHandle = adios2sys::DynamicLoader::OpenLibrary(fileName); searchedLibs.push_back(fileName); diff --git a/source/adios2/helper/adiosDynamicBinder.h b/source/adios2/helper/adiosDynamicBinder.h index 55247a0c9a..21f8f9d9de 100644 --- a/source/adios2/helper/adiosDynamicBinder.h +++ b/source/adios2/helper/adiosDynamicBinder.h @@ -27,6 +27,7 @@ class DynamicBinder public: DynamicBinder(std::string libName); + DynamicBinder(std::string libName, std::string libPath); ~DynamicBinder(); VoidSymbolPointer GetSymbol(std::string symbolName); diff --git a/testing/install/plugin/CMakeLists.txt b/testing/install/plugin/CMakeLists.txt index e566715800..2757112dba 100644 --- a/testing/install/plugin/CMakeLists.txt +++ b/testing/install/plugin/CMakeLists.txt @@ -9,20 +9,30 @@ enable_testing() find_package(adios2 REQUIRED) +option(BUILD_SHARED_LIBS "build shared libs" ON) + +add_library(PluginEngineWrite + ../../../examples/plugins/engine/ExampleWritePlugin.cpp +) +target_link_libraries(PluginEngineWrite adios2::cxx11 adios2::core) + +add_library(PluginEngineRead + ../../../examples/plugins/engine/ExampleReadPlugin.cpp +) +target_link_libraries(PluginEngineRead adios2::cxx11 adios2::core) + # add write test add_executable(adios_plugin_write_test ../../../examples/plugins/engine/examplePluginEngine_write.cpp - ../../../examples/plugins/engine/ExampleWritePlugin.cpp ) -target_link_libraries(adios_plugin_write_test adios2::cxx11 adios2::core) +target_link_libraries(adios_plugin_write_test adios2::cxx11) add_test(NAME adios_plugin_write_test COMMAND adios_plugin_write_test) # add read test add_executable(adios_plugin_read_test ../../../examples/plugins/engine/examplePluginEngine_read.cpp - ../../../examples/plugins/engine/ExampleReadPlugin.cpp ) -target_link_libraries(adios_plugin_read_test adios2::cxx11 adios2::core) +target_link_libraries(adios_plugin_read_test adios2::cxx11) add_test(NAME adios_plugin_read_test COMMAND adios_plugin_read_test) set_tests_properties(adios_plugin_read_test PROPERTIES DEPENDS adios_plugin_write_test)