DAS  3.0
Das Analysis System
PluginLoader

Description

Agnostic plugin loader.

Introduction to plugins in C++

Todo:
Handle (multiple git repos in) MetaInfo (#99)

Introduction to plugins in C++

Todo:
Handle (multiple git repos in) MetaInfo (#99)

#include <PluginLoader.h>

+ Collaboration diagram for PluginLoader:

Public Member Functions

 PluginLoader (const std::filesystem::path &file, int steering=none)
 
 PluginLoader (PluginLoader &&other)
 
 ~PluginLoader () noexcept
 
std::filesystem::path Which () const
 
template<Plugin P>
auto Get () const
 
 PluginLoader (const std::filesystem::path &file, int steering=none)
 
 PluginLoader (PluginLoader &&other)
 
 ~PluginLoader () noexcept
 
std::filesystem::path Which () const
 
template<Plugin P>
auto Get () const
 

Private Attributes

std::filesystem::path file
 
std::vector< std::unique_ptr< IPlugin > > plugins
 
void * handle
 
int steering
 

Constructor & Destructor Documentation

◆ PluginLoader() [1/4]

PluginLoader ( const std::filesystem::path &  file,
int  steering = none 
)
inline

Standard constructor.

Runs dlopen() and dlsym(), creates T, and throws if anything looks bad.

Note
Use the DARWIN_EXPORT_PLUGIN() macro to provide the function used by dlsym to instantiate the plugin.
Note
dlopen checks that the plugin exists.
Parameters
filepath to .so or .dylib file
56  : file(file)
57  , handle(nullptr)
59  {
60  using namespace std;
61 
62  if (steering & verbose)
63  cout << "PluginLoader: Loading plugin from " << file << endl;
64 
66  handle = dlopen(file.c_str(), RTLD_LAZY);
67  if (!handle) {
68  string what = file.string() + " could not be loaded"s;
69  const char * error = dlerror();
70  if (error != nullptr)
71  what += ": "s + error;
72  BOOST_THROW_EXCEPTION( invalid_argument(what) );
73  }
74 
75  typedef vector<unique_ptr<IPlugin>> * create_t();
76  auto CreatePlugin = (create_t *) dlsym(handle, "CreatePlugin");
77  if (!CreatePlugin) {
78  string what = "`CreatePlugin` could not be found"s;
79  const char * error = dlerror();
80  if (error != nullptr)
81  what += ": "s + error;
82  BOOST_THROW_EXCEPTION( runtime_error(what) );
83  }
84  vector<unique_ptr<IPlugin>> * iplugins = CreatePlugin();
85  if (iplugins == nullptr)
86  BOOST_THROW_EXCEPTION( runtime_error("`CreatePlugin` returns a nullptr") );
87  plugins = std::move(*iplugins);
88  ranges::for_each(plugins, [file](unique_ptr<IPlugin>& p) { p->SetPath(file); });
89  }
90  catch (boost::exception& e) {
91  namespace DE = Darwin::Exceptions;
92  BOOST_THROW_EXCEPTION( DE::PluginException(file, e) );
93  }

◆ PluginLoader() [2/4]

PluginLoader ( PluginLoader &&  other)
inline

Move constructor.

98  : file(other.file)
99  , plugins(std::move(other.plugins))
100  , handle(std::move(other.handle))
101  {
102  using namespace std;
103 
104  if (steering & verbose)
105  cout << "PluginLoader: Moving plugin from " << file << endl;
106 
107  other.file.clear();
108  other.plugins.clear();
109  other.handle = nullptr;
110  }

◆ ~PluginLoader() [1/2]

~PluginLoader ( )
inlinenoexcept

Closes the plugin handle.

115  {
116  using namespace std;
117 
118  if (steering & verbose)
119  cout << "PluginLoader: Closing plugin from " << file << endl;
120 
121  plugins.clear(); // Delete plugins _before_ closing the handle.
122 
123  if (!handle) return;
124  int code = dlclose(handle);
125  if (code != 0)
126  cerr << orange << "The plugin(s) loaded from " << file
127  << " closed with error " << code << def << '\n';
128  }

◆ PluginLoader() [3/4]

PluginLoader ( const std::filesystem::path &  file,
int  steering = none 
)
inline

Standard constructor.

Runs dlopen() and dlsym(), creates T, and throws if anything looks bad.

Note
Use the DARWIN_EXPORT_PLUGIN() macro to provide the function used by dlsym to instantiate the plugin.
Note
dlopen checks that the plugin exists.
Parameters
filepath to .so or .dylib file
56  : file(file)
57  , handle(nullptr)
59  {
60  using namespace std;
61 
62  if (steering & verbose)
63  cout << "PluginLoader: Loading plugin from " << file << endl;
64 
66  handle = dlopen(file.c_str(), RTLD_LAZY);
67  if (!handle) {
68  string what = file.string() + " could not be loaded"s;
69  const char * error = dlerror();
70  if (error != nullptr)
71  what += ": "s + error;
72  BOOST_THROW_EXCEPTION( invalid_argument(what) );
73  }
74 
75  typedef vector<unique_ptr<IPlugin>> * create_t();
76  auto CreatePlugin = (create_t *) dlsym(handle, "CreatePlugin");
77  if (!CreatePlugin) {
78  string what = "`CreatePlugin` could not be found"s;
79  const char * error = dlerror();
80  if (error != nullptr)
81  what += ": "s + error;
82  BOOST_THROW_EXCEPTION( runtime_error(what) );
83  }
84  vector<unique_ptr<IPlugin>> * iplugins = CreatePlugin();
85  if (iplugins == nullptr)
86  BOOST_THROW_EXCEPTION( runtime_error("`CreatePlugin` returns a nullptr") );
87  plugins = std::move(*iplugins);
88  ranges::for_each(plugins, [file](unique_ptr<IPlugin>& p) { p->SetPath(file); });
89  }
90  catch (boost::exception& e) {
91  namespace DE = Darwin::Exceptions;
92  BOOST_THROW_EXCEPTION( DE::PluginException(file, e) );
93  }

◆ PluginLoader() [4/4]

PluginLoader ( PluginLoader &&  other)
inline

Move constructor.

98  : file(other.file)
99  , plugins(std::move(other.plugins))
100  , handle(std::move(other.handle))
101  {
102  using namespace std;
103 
104  if (steering & verbose)
105  cout << "PluginLoader: Moving plugin from " << file << endl;
106 
107  other.file.clear();
108  other.plugins.clear();
109  other.handle = nullptr;
110  }

◆ ~PluginLoader() [2/2]

~PluginLoader ( )
inlinenoexcept

Closes the plugin handle.

115  {
116  using namespace std;
117 
118  if (steering & verbose)
119  cout << "PluginLoader: Closing plugin from " << file << endl;
120 
121  plugins.clear(); // Delete plugins _before_ closing the handle.
122 
123  if (!handle) return;
124  int code = dlclose(handle);
125  if (code != 0)
126  cerr << orange << "The plugin(s) loaded from " << file
127  << " closed with error " << code << def << '\n';
128  }

Member Function Documentation

◆ Get() [1/2]

auto Get ( ) const
inline

Access to plugin's raw pointers.

137  {
138  using namespace std;
139  auto convert = [this](IPlugin * plugin) -> P * {
140  auto ptr = dynamic_cast<P*>(plugin);
141  if (ptr == nullptr) {
142  string what = "Invalid plugin type for ";
143  what += file;
144  BOOST_THROW_EXCEPTION( logic_error(what) );
145  }
146  return ptr;
147  };
148  return plugins | views::transform(&unique_ptr<IPlugin>::get)
149  | views::transform(convert);
150  }

◆ Get() [2/2]

auto Get ( ) const
inline

Access to plugin's raw pointers.

137  {
138  using namespace std;
139  auto convert = [this](IPlugin * plugin) -> P * {
140  auto ptr = dynamic_cast<P*>(plugin);
141  if (ptr == nullptr) {
142  string what = "Invalid plugin type for ";
143  what += file;
144  BOOST_THROW_EXCEPTION( logic_error(what) );
145  }
146  return ptr;
147  };
148  return plugins | views::transform(&unique_ptr<IPlugin>::get)
149  | views::transform(convert);
150  }

◆ Which() [1/2]

std::filesystem::path Which ( ) const
inline

Get plugin location.

132 { return file; }

◆ Which() [2/2]

std::filesystem::path Which ( ) const
inline

Get plugin location.

132 { return file; }

Member Data Documentation

◆ file

std::filesystem::path file
private

plugin location

◆ handle

void * handle
private

pointer to object return by dlopen()

◆ plugins

std::vector< std::unique_ptr< IPlugin > > plugins
private

pointers to function return from the function called by dlopen

◆ steering

int steering
private

The documentation for this class was generated from the following file:
Ntupliser_cfg.cerr
cerr
Definition: Ntupliser_cfg.py:105
Darwin::Exceptions::PluginException
Exception type to throw from plugins.
Definition: exceptions.h:132
Step::def
static const char * def
Definition: Step.h:36
Ntupliser_cfg.p
p
Definition: Ntupliser_cfg.py:178
P
P
Definition: Core-gitclone-lastrun.txt:6
Darwin::Tools::plugin
@ plugin
activate -p to run a plugin
Definition: Options.h:35
CreatePlugin
PluginsVec * CreatePlugin()
Definition: BadPlugin.cc:9
Darwin::Tools::PluginLoader::file
std::filesystem::path file
plugin location
Definition: PluginLoader.h:38
Darwin::Tools::PluginLoader::steering
int steering
Definition: PluginLoader.h:41
Darwin::Exceptions
Handling of exceptions.
Definition: darwin.h:37
Darwin::Tools::verbose
@ verbose
bit for debug mode (-v is always available)
Definition: Options.h:29
orange
static const char * orange
Definition: colours.h:6
Darwin::Tools::PluginLoader::plugins
std::vector< std::unique_ptr< IPlugin > > plugins
pointers to function return from the function called by dlopen
Definition: PluginLoader.h:39
Darwin::Tools::PluginLoader::handle
void * handle
pointer to object return by dlopen()
Definition: PluginLoader.h:40