Back to home page

EIC code displayed by LXR

 
 

    


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 ```