PYTHIA  8.312
Plugins.h
1 // Plugins.h is a part of the PYTHIA event generator.
2 // Copyright (C) 2024 Philip Ilten, Manuel Szewc, and Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL v2 or later, see COPYING for details.
4 // Please respect the MCnet Guidelines, see GUIDELINES for details.
5 
6 // Header file for the runtime loading of plugins.
7 
8 #ifndef Pythia8_Plugins_H
9 #define Pythia8_Plugins_H
10 
11 #include "Pythia8/Pythia.h"
12 
13 // Allow the use of dlopen without warnings for some GCC versions.
14 #if defined (__GNUC__) && ((__GNUC__ + 0) < 5)
15 #pragma GCC system_header
16 #endif
17 
18 namespace Pythia8 {
19 
20 //==========================================================================
21 
22 // Demangle a symbol name, if the necessary demangling libraries are present.
23 
24 string demangle(string name);
25 
26 //==========================================================================
27 
28 // Determine a plugin type.
29 
30 string type_plugin(string libName, string className,
31  Logger* loggerPtr = nullptr);
32 
33 //==========================================================================
34 
35 // Load a plugin library with dlopen.
36 
37 shared_ptr<void> dlopen_plugin(string libName, Logger* loggerPtr);
38 
39 //==========================================================================
40 
41 // Load a symbol from a plugin library.
42 
43 template <typename T> function<T> dlsym_plugin(void* libPtr, string symbol) {
44  return (T*)dlsym(libPtr, symbol.c_str());}
45 
46 template <typename T> function<T> dlsym_plugin(shared_ptr<void> libPtr,
47  string symbol) {
48  return (T*)dlsym( static_cast<void*>(libPtr.get()), symbol.c_str());}
49 
50 //==========================================================================
51 
52 // Load a plugin, given a full set of arguments.
53 
54 template <typename T> shared_ptr<T> make_plugin(
55  string libName, string className, Pythia* pythiaPtr,
56  Settings* settingsPtr, Logger* loggerPtr) {
57 
58  // Set up the available pointers.
59  if (loggerPtr == nullptr && pythiaPtr != nullptr)
60  loggerPtr = &pythiaPtr->logger;
61  if (settingsPtr == nullptr && pythiaPtr != nullptr)
62  settingsPtr = &pythiaPtr->settings;
63 
64  // Load the library.
65  shared_ptr<void> libPtr = dlopen_plugin(libName, loggerPtr);
66  if (libPtr == nullptr) return shared_ptr<T>(nullptr);
67 
68  // Check the plugin object type.
69  string objType = type_plugin(libName, className, loggerPtr);
70  if (objType != typeid(T).name()) {
71  string msg = "class " + className + " from library " + libName +
72  " must be loaded as type " + demangle(objType);
73  if (loggerPtr != nullptr) loggerPtr->errorMsg("make_plugin", msg);
74  else cout << msg << "\n";
75  return shared_ptr<T>(nullptr);
76  }
77 
78  // Check the pointers required by the plugin object.
79  for (string ptr : {"PYTHIA", "SETTINGS", "LOGGER"}) {
80  auto ptrsObject =
81  dlsym_plugin<bool()>(libPtr, "REQUIRE_" + ptr + "_" + className);
82  if (dlerror() != nullptr) continue;
83  if (!ptrsObject()) continue;
84  if (ptr == "PYTHIA" && pythiaPtr != nullptr) continue;
85  if (ptr == "SETTINGS" && settingsPtr != nullptr) continue;
86  if (ptr == "LOGGER" && loggerPtr != nullptr) continue;
87  string msg = "class " + className + " requires a " + ptr + " pointer";
88  if (loggerPtr != nullptr) loggerPtr->errorMsg("make_plugin", msg);
89  else cout << msg << "\n";
90  return shared_ptr<T>(nullptr);
91  }
92 
93  // Load the symbol to construct the plugin object.
94  auto newObject =
95  dlsym_plugin<T*(Pythia*, Settings*, Logger*)>(libPtr, "NEW_" + className);
96  const char* error = dlerror();
97  if (error != nullptr) {
98  string msg = "class " + className + " not available from library " +
99  libName;
100  if (loggerPtr != nullptr) loggerPtr->errorMsg("make_plugin", msg);
101  else cout << msg << "\n";
102  return shared_ptr<T>(nullptr);
103  }
104 
105  // Construct the plugin object shared pointer.
106  return shared_ptr<T>(
107  newObject(pythiaPtr, settingsPtr, loggerPtr),
108  // Use a custom destructor.
109  [libPtr, className](T* objectPtr) {
110 
111  // Destroy the plugin object.
112  auto deleteObject =
113  dlsym_plugin<void(T*)>(libPtr, "DELETE_" + className);
114  if (dlerror() == nullptr && deleteObject != nullptr)
115  deleteObject(objectPtr);});
116 
117 }
118 
119 //==========================================================================
120 
121 // Load a plugin, given no pointers.
122 
123 template <typename T> shared_ptr<T> make_plugin(
124  string libName, string className) {return make_plugin<T>(
125  libName, className, nullptr, nullptr, nullptr);}
126 
127 //==========================================================================
128 
129 // Load a plugin, given a Pythia pointer.
130 template <typename T> shared_ptr<T> make_plugin(
131  string libName, string className, Pythia* pythiaPtr) {
132  return make_plugin<T>(
133  libName, className, pythiaPtr, nullptr, nullptr);}
134 
135 //==========================================================================
136 
137 // Load a plugin, given a Pythia pointer and command vector pointer.
138 
139 template <typename T> shared_ptr<T> make_plugin(
140  string libName, string className, Pythia* pythiaPtr,
141  const vector<string>& cmnds) {
142  pythiaPtr->settings.registerPluginLibrary(libName);
143  for (string cmnd : cmnds) pythiaPtr->readString(cmnd);
144  return make_plugin<T>(libName, className, pythiaPtr);
145 }
146 
147 //==========================================================================
148 
149 // Load a plugin, given a Pythia pointer, command file, and subrun.
150 
151 template <typename T> shared_ptr<T> make_plugin(
152  string libName, string className, Pythia* pythiaPtr,
153  string fileName, int subrun = SUBRUNDEFAULT) {
154  pythiaPtr->settings.registerPluginLibrary(libName);
155  if (fileName != "") pythiaPtr->readFile(fileName, subrun);
156  return make_plugin<T>(libName, className, pythiaPtr);
157 }
158 
159 //==========================================================================
160 
161 // Macro to declare a plugin class.
162 
163 #define PYTHIA8_PLUGIN_CLASS(BASE, CLASS, PYTHIA, SETTINGS, LOGGER) \
164  extern "C" { \
165  bool REQUIRE_PYTHIA_##CLASS() {return PYTHIA;} \
166  bool REQUIRE_SETTINGS_##CLASS() {return SETTINGS;} \
167  bool REQUIRE_LOGGER_##CLASS() {return LOGGER;} \
168  const char* TYPE_##CLASS() {return typeid(BASE).name();} \
169  CLASS* NEW_##CLASS(Pythia* pythiaPtr, Settings* settingsPtr, \
170  Logger* loggerPtr) { \
171  return new CLASS(pythiaPtr, settingsPtr, loggerPtr);} \
172  void DELETE_##CLASS(CLASS* ptr) {delete ptr;}}
173 
174 //==========================================================================
175 
176 // Macro to register settings for a plugin library.
177 
178 #define PYTHIA8_PLUGIN_SETTINGS(METHOD) \
179  extern "C" { \
180  void REGISTER_SETTINGS(Settings* settingsPtr) {METHOD(settingsPtr);}}
181 
182 //==========================================================================
183 
184 // Macro to register an XML settings index file.
185 
186 #define PYTHIA8_PLUGIN_XML(INDEX) \
187  extern "C" {const char* RETURN_XML() {return INDEX;}}
188 
189 //==========================================================================
190 
191 // Macro to return compatible Pythia versions and the compiled version.
192 
193 #define PYTHIA8_PLUGIN_VERSIONS(...) \
194  extern "C" { \
195  bool CHECK_COMPATIBLE_VERSION(int ver) {set<int> vers = {__VA_ARGS__}; \
196  return vers.find(ver) != vers.end();} \
197  bool CHECK_COMPILED_VERSION(int ver) { \
198  return ver == PYTHIA_VERSION_INTEGER;}}
199 
200 //==========================================================================
201 
202 } // end namespace Pythia8
203 
204 #endif // Pythia8_Plugins_H
string demangle(string name)
Demangle a symbol name, if the necessary demangling libraries are present.
Definition: Plugins.cc:47
shared_ptr< T > make_plugin(string libName, string className, Pythia *pythiaPtr, Settings *settingsPtr, Logger *loggerPtr)
Load a plugin, given a full set of arguments.
Definition: Plugins.h:54
Settings settings
Settings: databases of flags/modes/parms/words to control run.
Definition: Pythia.h:332
string type_plugin(string libName, string className, Logger *loggerPtr=nullptr)
Determine a plugin type.
Definition: Plugins.cc:118
Definition: Logger.h:23
void errorMsg(string loc, string message, string extraInfo="", bool showAlways=false)
Errors indicate an issue that might cause the current event to fail.
Definition: Logger.cc:35
shared_ptr< void > dlopen_plugin(string libName, Logger *loggerPtr)
Load a plugin library with dlopen.
Definition: Plugins.cc:55
function< T > dlsym_plugin(void *libPtr, string symbol)
Load a symbol from a plugin library.
Definition: Plugins.h:43
bool readFile(string fileName, bool warn=true, int subrun=SUBRUNDEFAULT)
Read in updates for settings or particle data from user-defined file.
Definition: Pythia.cc:431
bool registerPluginLibrary(string libName, string startFile="")
Register the settings from a plugin library.
Definition: Settings.cc:626
Header for classes to set beam momentum and interaction vertex spread.
Definition: Analysis.h:20
The Pythia class contains the top-level routines to generate an event.
Definition: Pythia.h:71
bool readString(string, bool warn=true, int subrun=SUBRUNDEFAULT)
Read in one update for a setting or particle data from a single line.
Definition: Pythia.cc:365
Logger logger
Logger: for diagnostic messages, errors, statistics, etc.
Definition: Pythia.h:329
Definition: Settings.h:195