Warning, /DD4hep/GaudiPluginService/doc/README.md is written in an unsupported language. File is not indexed.
0001 # Gaudi::PluginService {#GaudiPluginService-readme}
0002
0003 ## Introduction
0004
0005 The Gaudi Plugin Service is a small tool to add to a C++ application the
0006 possibility of dynamically instantiate (via _factories_) objects from classes
0007 defined in plug-in (or component) libraries.
0008
0009 While being part of Gaudi, it only depends on a Posix system (support for other
0010 systems is possible, but very low priority).
0011
0012 ## Usage
0013
0014 To be able to use plug-ins from an application you need:
0015 - a base class (abstract or not) from a library
0016 - a library that provides a class that inherits from the base class
0017
0018 In the base class you should declare the signature of the the factory for your
0019 derived classes. For example, if your base class is called `Foo` and you want
0020 to instantiate the derived classes with one `std::string` argument, you can
0021 write something like:
0022 ```cpp
0023 #include <Gaudi/PluginService.h>
0024 #include <string>
0025 class Foo {
0026 public:
0027 using Factory = Gaudi::PluginService::Factory<Foo*( const std::string& )>;
0028
0029 /// Constructor
0030 Foo( const std::string& name );
0031
0032 // ...
0033 };
0034 ```
0035
0036 The templated class `Gaudi::PluginService::Factory` takes as template
0037 argument the _ideal_ signature of the factory. The in the above example, the
0038 actual signature of the factory is `std::unique_ptr<Foo>(const std::string&)`,
0039 but we declare is as returning `Foo*` for brevity.
0040
0041 The plug-in class `Bar` defined in the dynamically loaded library will require
0042 a declaration to the Plugin Service to use it, so in the source file you have to
0043 have something like:
0044 ```cpp
0045 #include "Bar.h"
0046 DECLARE_COMPONENT( Bar )
0047 ```
0048
0049 The library with `Foo` and the library with `Bar` will have to be linked against
0050 the library `libGaudiPluginService.so`.
0051
0052 To enable the automatic discovery of plugins, the library with `Bar` must be
0053 processed by the program `listcomponents` and the output must be stored in a
0054 file with extension `.components` in a directory in the `LD_LIBRARY_PATH`.
0055 For example, if the `lib` directory contains `libBar.so` and it is specified in
0056 the `LD_LIBRARY_PATH`, you can call the commands:
0057 ```sh
0058 listcomponents lib/libBar.so >> lib/MyApp.components
0059 ```
0060
0061 Note that the `.components` file does not need to be in the same directory as
0062 `libBar.so`.
0063
0064 The application code, linked against the library providing `Foo` can now
0065 instantiate objects of class `Bar` like this:
0066 ```cpp
0067 #include "Foo.h"
0068
0069 // ...
0070 std::unique_ptr<Foo> myBar = Foo::Factory::create( "Bar", "myBar" );
0071 // ...
0072 ```
0073
0074 where the first argument to the function `create` is the name of the class you
0075 want to instantiate, and the other arguments are passed to the constructor of
0076 the class.
0077
0078 ## Special cases
0079
0080 ### Factory aliases
0081
0082 Together with the simple usage described above, the Gaudi Plugin Service allows
0083 you to use aliases to refer to the plug-in class.
0084 For example, for a templated plug-in class you may have:
0085 ```cpp
0086 #include "TemplatedBar.h"
0087 typedef TemplatedBar<int, std::vector<double>> MyBar;
0088 DECLARE_COMPONENT( MyBar )
0089 ```
0090
0091 but to instantiate it you must call
0092 ```cpp
0093 auto b = Foo::Factory::create( "TemplatedBar<int, std::vector<double> >",
0094 "MyTemplatedBar" );
0095 ```
0096
0097 Which is error prone and unreadable, but you can declare the component class
0098 with and _id_ (an alias):
0099 ```cpp
0100 DECLARE_COMPONENT_WITH_ID( MyBar, "MyBar" )
0101 ```
0102
0103 (note that the _id_ must support the `<<` operator of `std::ostream`).
0104 The call in the application becomes:
0105 ```cpp
0106 auto b = Foo::Factory::create( "MyBar", "MyTemplatedBar" );
0107 ```
0108
0109 ### Namespaces
0110
0111 When dealing with components in namespaces, you have several ways to invoke
0112 `DECLARE_COMPONENT`. For example, if you have the class `Baz::Fun` you can
0113 declare it as a component class in any of the following ways:
0114 ```cpp
0115 DECLARE_COMPONENT( Baz::Fun )
0116
0117 using Baz::Fun;
0118 DECLARE_COMPONENT( Fun )
0119
0120 namespace Baz {
0121 DECLARE_COMPONENT( Fun )
0122 }
0123
0124 typedef Baz::Fun BF;
0125 DECLARE_COMPONENT( BF )
0126 ```
0127
0128 In all cases the name of the factory to be passed to the `create` function will
0129 be `Baz::Fun`.
0130
0131 ### Custom Factories
0132
0133 When using `DECLARE_COMPONENT`, we register as factory for our class a function
0134 equivalent to
0135 ```cpp
0136 std::unique_ptr<Foo> factory(Args... args) {
0137 return std::make_unique<Bar>(args...);
0138 }
0139 ```
0140 but it's possible to use custom factory functions. This is a rather convoluted
0141 example:
0142 ```cpp
0143 // -- declaration --
0144 struct MyInterface {
0145 virtual ~MyInterface() = default;
0146
0147 virtual const std::string& name() const = 0;
0148 };
0149
0150 struct BaseSetupHelper;
0151
0152 struct MyBase : MyInterface {
0153 using Factory = Gaudi::PluginService::Factory<MyInterface*( const std::string& )>;
0154
0155 const std::string& name() const override { return m_name; }
0156 private:
0157 friend BaseSetupHelper;
0158 std::string m_name;
0159 };
0160
0161 // -- implementation --
0162 struct MyComponent : MyBase {
0163 MyComponent() {}
0164 };
0165
0166 struct BaseSetupHelper {
0167 static void setName( MyBase* base, const std::string& name ) { base->m_name = name; }
0168 };
0169
0170 namespace
0171 {
0172 std::unique_ptr<MyInterface> creator( const std::string& name )
0173 {
0174 auto p = std::make_unique<MyComponent>();
0175 BaseSetupHelper::setName( p.get(), name );
0176 return std::move( p );
0177 }
0178 Gaudi::PluginService::DeclareFactory<MyComponent> _{creator};
0179 }
0180
0181 // -- use --
0182 void useComponent()
0183 {
0184 auto c = MyBase::Factory::create( "MyComponent", "TheName" );
0185 // ...
0186 }
0187
0188 ```