MaCh3  2.6.1
Reference Guide
DynamicPlugin.hpp
Go to the documentation of this file.
1 
4 #pragma once
5 #include <dlfcn.h>
6 #include <memory>
7 #include <functional>
8 #include "CLI/API/plugin.hpp"
9 
10 namespace M3{
16  class DynamicPlugin: public IPlugin{
17  public:
20  DynamicPlugin(const std::string& sofile)
21  : DynamicPlugin(sofile.c_str()) {}
22 
25  DynamicPlugin(const char* sofile)
26  : m_handle(nullptr, &DynamicPlugin::dlcloser),
27  m_plugin(nullptr, nullptr){
28 
29 
30  m_handle.reset(dlopen(sofile, RTLD_NOW));
31  if (!m_handle) {
32  std::cerr << "dlopen failed - shared library '"<< sofile << "' not loaded: " << dlerror() << "\n";
33  throw std::runtime_error("dlopen failed");
34  }
35 
36  auto create = reinterpret_cast<create_plugin_t>(dlsym(m_handle.get(), "create_plugin"));
37  auto destroy = reinterpret_cast<destroy_plugin_t>(dlsym(m_handle.get(), "destroy_plugin"));
38 
39  if (!create || !destroy) {
40  std::cerr << "Invalid plugin: " << sofile << "\n";
41  m_handle.reset(nullptr);
42  throw std::runtime_error("Invalid plugin - missing create_plugin or destroy_plugin");
43  }
44 
45  try{
46  m_plugin = std::unique_ptr<IPlugin, destroy_plugin_t>(create(), destroy);
47  if (!m_plugin){
48  throw std::runtime_error("null pointer");
49  }
50  }
51  catch (...){
52  std::cerr << "Error instantiating plugin: " << sofile << "\n";
53  m_handle.reset(nullptr);
54  throw std::runtime_error("Error instantiating plugin");
55  }
56 
57  try{
58  m_parser = m_plugin->get_parser();
59  if (!m_parser){
60  throw std::runtime_error("null pointer");
61  }
62  }
63  catch(...){
64  std::cerr<< "Error retrieving parser" << "\n";
65  m_plugin.reset(nullptr);
66  m_handle.reset(nullptr);
67  throw std::runtime_error("Error retrieving parser");
68  }
69  }
70 
73  int Run() override {
74  return m_plugin->Run();
75  }
76 
82  return m_parser;
83  }
84 
86  virtual ~DynamicPlugin() = default;
87 
88  private:
89 
90  static void dlcloser(void* h) {
91  if (h) dlclose(h);
92  }
94  // using dlcloser rather than built in dlclose to avoid gcc warning about casting function pointer to void pointer
95  std::unique_ptr<void, decltype(&dlcloser)> m_handle;
96  std::unique_ptr<IPlugin, destroy_plugin_t> m_plugin;
97  };
98 }
Manages the lifecycle of a dynamically loaded plugin.
MaCh3ArgumentParser * get_parser() override
Get the argument parser for this plugin.
virtual ~DynamicPlugin()=default
Destructor closes the shared library handle.
DynamicPlugin(const char *sofile)
Constructor that loads a plugin from a shared library file.
std::unique_ptr< IPlugin, destroy_plugin_t > m_plugin
Smart pointer to plugin with custom deleter.
int Run() override
Run the plugin's main functionality.
static void dlcloser(void *h)
MaCh3ArgumentParser * m_parser
Pointer to the plugin's argument parser, owned by the shared library.
std::unique_ptr< void, decltype(&dlcloser)> m_handle
Handle to the loaded shared library.
DynamicPlugin(const std::string &sofile)
Constructor that loads a plugin from a shared library file.
Interface for MaCh3 plugins and modules.
Definition: plugin.hpp:16
Extended ArgumentParser with MaCh3-specific functionality.
Definition: m3argparse.hpp:17
Main namespace for MaCh3 software.
Plugin interface and registration macros for MaCh3.
M3::IPlugin *(* create_plugin_t)()
Function pointer type for plugin factory function.
Definition: plugin.hpp:58
void(* destroy_plugin_t)(M3::IPlugin *)
Function pointer type for plugin destructor function.
Definition: plugin.hpp:62