GaudiPluginService/doc/README.md
Go to the documentation of this file.
1 Gaudi Plugin Service Instructions {#GaudiPluginService-readme}
2 ==================================
3 
4 Introduction
5 ------------
6 
7 The Gaudi Plugin Service is a small tool to add to a C++ application the
8 possibility of dynamically instantiate (via _factories_) objects from classes
9 defined in plug-in (or component) libraries.
10 
11 While being part of Gaudi, it only depends on a Posix system (support for other
12 systems is possible, but very low priority).
13 
14 
15 Usage
16 ------
17 
18 To be able to use plug-ins from an application you need:
19 
20 - a base class (abstract or not) from a library
21 - a library that provides a class that inherits from the base class
22 
23 In the base class you should declare the signature of the the factory for your
24 derived classes. For example, if your base class is called `Foo` and you want
25 to instantiate the derived classes with one `std::string` argument, you can
26 write something like:
27 
28  #include <Gaudi/PluginService.h>
29  #include <string>
30  class Foo {
31  public:
32  typedef Gaudi::PluginService::Factory1<Foo*, const std::string&> Factory;
33 
34  /// Constructor
35  Foo(const std::string& name);
36 
37  // ...
38  };
39 
40 The templated class `Gaudi::PluginService::Factory1` takes as first template
41 argument the return type of the factory and as second argument the type of the
42 first argument of the factory function (with all the required qualifiers
43 explicit). There are several variants of the class for different number of
44 arguments required by the constructor (`Factory0`, `Factory1`, `Factory2`, ...).
45 
46 The plug-in class `Bar` defined in the dynamically loaded library will require
47 a declaration to the Plugin Service to use it, so in the source file you have to
48 have something like:
49 
50  #include "Bar.h"
51  DECLARE_COMPONENT(Bar)
52 
53 The library with `Foo` and the library with `Bar` will have to be linked against
54 the library `libGaudiPluginService.so`.
55 
56 To enable the automatic discovery of plugins, the library with `Bar` must be
57 processed by the program `listcomponents` and the output must be stored in a
58 file with extension `.comonents` in a directory in the `LD_LIBRARY_PATH`.
59 For example, if the `lib` directory contains `libBar.so` and it is specified in
60 the `LD_LIBRARY_PATH`, you can call the commands:
61 
62  listcomponents libBar.so >> lib/MyApp.components
63 
64 Note that the `.components` file does not need to be in the same directory as
65 `libBar.so`.
66 
67 The application code, linked against the library providing `Foo` can now
68 instantiate objects of class `Bar` like this:
69 
70  #include "Foo.h"
71 
72  // ...
73  Foo* myBar = Foo::Factory::create("Bar", "myBar");
74  // ...
75 
76 where the first argument to the function `create` is the name of the class you
77 want to instantiate, and the other arguments are passed to the constructor of
78 the class.
79 
80 
81 Special cases
82 -------------
83 
84 ### Factory aliases
85 
86 Together with the simple usage described above, the Gaudi Plugin Service allows
87 you to give to use aliases to refer to the plug-in class.
88 For example, for a templated plug-in class you may have:
89 
90  #include "TemplatedBar.h"
91  typedef TemplatedBar<int, std::vector<double> > MyBar;
92  DECLARE_COMPONENT(MyBar)
93 
94 but to instantiate it you must call
95 
96  Foo* b = Foo::Factory::create("TemplatedBar<int, std::vector<double> >",
97  "MyTemplatedBar");
98 
99 Which is error prone and unreadable, but you can declare the component class
100 with and _id_ (an alias):
101 
102  DECLARE_COMPONENT_WITH_ID(MyBar, "MyBar")
103 
104 (note that the _id_ must support the `<<` operator of `std::ostream`).
105 The call in the application becomes:
106 
107  Foo* b = Foo::Factory::create("MyBar", "MyTemplatedBar");
108 
109 
110 ### Namespaces
111 
112 You cannot use namespace delimiters in the call to `DECLARE_COMPONENT`, but you
113 can still use namespaces for you component classes. For example, if you have the
114 class `Baz::Fun` you can declare it as a component class in any of the following
115 ways:
116 
117  using Baz::Fun;
118  DECLARE_COMPONENT(Fun)
119 
120  namespace Baz {
121  DECLARE_COMPONENT(Fun)
122  }
123 
124  typedef Baz::Fun BF;
125  DECLARE_COMPONENT(BF)
126 
127 In all cases the name of the factory to be passed to the `create` function will
128 be "Baz::Fun".