File indexing completed on 2025-01-30 09:17:01
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DD4hep/Plugins.h>
0016 #include <cstdlib>
0017
0018 using namespace dd4hep;
0019
0020 namespace {
0021 inline int* s_debug_value() {
0022 static int s_debug_value = ::getenv("DD4HEP_TRACE") == 0 ? 0 : 1;
0023 return &s_debug_value;
0024 }
0025 }
0026
0027 bool PluginService::debug() {
0028 return *s_debug_value() ? true : false;
0029 }
0030
0031 bool PluginService::setDebug(bool new_value) {
0032 int *ptr = s_debug_value();
0033 bool old_value = *ptr;
0034 *ptr = new_value ? 1 : 0;
0035 return old_value;
0036 }
0037
0038 #if defined(__linux) && !defined(__APPLE__)
0039 #define DD4HEP_PARSERS_NO_ROOT
0040 #endif
0041
0042 #include <DD4hep/Printout.h>
0043 #if !defined(DD4HEP_PARSERS_NO_ROOT)
0044 #include <TSystem.h>
0045 #else
0046 #include <dlfcn.h>
0047 #endif
0048 #include <cstring>
0049
0050
0051 #define MAKE_GAUDI_PLUGIN_SERVICE_ENTRY(n,v) "dd4hep_pluginmgr_" #n "_V" #v
0052 #define MAKE_FUNC(name,version) MAKE_GAUDI_PLUGIN_SERVICE_ENTRY(name,version)
0053
0054 namespace {
0055 struct PluginInterface {
0056 int (*getDebug)();
0057 int (*setDebug)(int new_value);
0058 PluginService::stub_t (*create)(const char* identifier, const char* signature);
0059 void (*add)(const char* identifier,
0060 PluginService::stub_t&& creator_stub,
0061 const char* signature,
0062 const char* return_type);
0063 PluginInterface() noexcept(false);
0064 static PluginInterface& instance() noexcept(false) {
0065 static PluginInterface s_instance;
0066 return s_instance;
0067 }
0068 };
0069
0070 template <typename FUNCTION> struct _FP {
0071 union { void* ptr; FUNCTION fcn; } fptr;
0072 _FP(FUNCTION func) { fptr.fcn = func; }
0073 _FP(void* _p) { fptr.ptr = _p; }
0074 };
0075
0076 template <typename T>
0077 static inline T get_func(void* handle, const char* plugin, const char* entry) {
0078 #if !defined(DD4HEP_PARSERS_NO_ROOT)
0079 _FP<Func_t> fun(gSystem->DynFindSymbol(plugin,entry));
0080 _FP<T> fp(fun.fptr.ptr);
0081 if ( handle ) {}
0082 #else
0083 _FP<T> fp(::dlsym(handle, entry));
0084 if ( !fp.fptr.ptr ) fp.fptr.ptr = ::dlsym(0, entry);
0085 #endif
0086 if ( 0 == fp.fptr.ptr ) {
0087 std::string err = "dd4hep:PluginService: Failed to access symbol "
0088 "\""+std::string(entry)+"\" in plugin library "+std::string(plugin)+
0089 " ["+std::string(::strerror(errno))+"]";
0090 throw std::runtime_error(err);
0091 }
0092 return fp.fptr.fcn;
0093 }
0094
0095 PluginInterface::PluginInterface() noexcept(false)
0096 : getDebug(0), setDebug(0), create(nullptr), add(nullptr)
0097 {
0098 void* handle = 0;
0099 const char* plugin_name = ::getenv("DD4HEP_PLUGINMGR");
0100 #if defined(__linux) && !defined(__APPLE__)
0101 if ( 0 == plugin_name ) plugin_name = "libDD4hepGaudiPluginMgr.so";
0102 #else
0103 if ( 0 == plugin_name ) plugin_name = "libDD4hepGaudiPluginMgr";
0104 #endif
0105 #if defined(DD4HEP_PARSERS_NO_ROOT)
0106 struct handle_guard {
0107 void* _handle {nullptr};
0108 handle_guard(void* hdl) : _handle(hdl) {
0109 }
0110 ~handle_guard() {
0111 if ( _handle ) ::dlclose(_handle);
0112 _handle = nullptr;
0113 }
0114 };
0115 static handle_guard _guard(nullptr);
0116 if ( nullptr == _guard._handle ) {
0117 _guard._handle = handle = ::dlopen(plugin_name, RTLD_LAZY | RTLD_GLOBAL);
0118 }
0119 if ( !handle ) {
0120 throw std::runtime_error("Failed to load plugin manager library: "+std::string(plugin_name));
0121 }
0122 #else
0123 if ( 0 != gSystem->Load(plugin_name) ) {}
0124 #endif
0125 getDebug = get_func< int (*) ()>(handle, plugin_name,MAKE_FUNC(getdebug,DD4HEP_PLUGINSVC_VERSION));
0126 setDebug = get_func< int (*) (int)>(handle, plugin_name,MAKE_FUNC(setdebug,DD4HEP_PLUGINSVC_VERSION));
0127 create = get_func< PluginService::stub_t (*)(const char*,
0128 const char*)>(handle, plugin_name,MAKE_FUNC(create,DD4HEP_PLUGINSVC_VERSION));
0129 add = get_func< void (*) (const char* identifier,
0130 PluginService::stub_t&& creator_stub,
0131 const char* signature,
0132 const char* return_type)>(handle, plugin_name,MAKE_FUNC(add_factory,DD4HEP_PLUGINSVC_VERSION));
0133 }
0134 }
0135
0136
0137 PluginDebug::PluginDebug(int dbg) noexcept(false) : m_debug(0) {
0138 m_debug = PluginInterface::instance().setDebug(dbg);
0139 }
0140
0141
0142 PluginDebug::~PluginDebug() noexcept(false) {
0143 PluginInterface::instance().setDebug(m_debug);
0144 }
0145
0146
0147 std::string PluginDebug::missingFactory(const std::string& name) const {
0148 std::string factoryname = "Create("+name+")";
0149 std::string msg = "\t\tNo factory with name " + factoryname + " for type " + name + " found.\n"
0150 "\t\tPlease check library load path and/or plugin factory name.";
0151 return msg;
0152 }
0153
0154 PluginService::stub_t PluginService::getCreator(const std::string& id, const std::type_info& info) {
0155 return PluginInterface::instance().create(id.c_str(), info.name());
0156 }
0157
0158 void PluginService::addFactory(const std::string& id,
0159 PluginService::stub_t&& stub,
0160 const std::type_info& signature_type,
0161 const std::type_info& return_type)
0162 {
0163 if ( PluginService::debug() ) {
0164 printout(INFO,"PluginService","+++ Declared factory[%s] with signature %s type:%s.",
0165 id.c_str(),signature_type.name(),return_type.name());
0166 }
0167 PluginInterface::instance().add(id.c_str(),std::move(stub),signature_type.name(),return_type.name());
0168 }
0169
0170 void PluginService::print_bad_cast(const std::string& id,
0171 const stub_t& stub,
0172 const std::type_info& signature,
0173 const char* msg) {
0174 bool dbg = PluginInterface::instance().getDebug();
0175 if ( dbg ) {
0176 std::stringstream str;
0177 str << "Factory requested: " << id << " (" << typeid(signature).name() << ") :" << msg;
0178 printout(ERROR,"PluginService","%s", str.str().c_str());
0179 str.str("");
0180 if ( !any_has_value(stub) ) {
0181 str << "Stub is invalid!";
0182 printout(ERROR,"PluginService","%s", str.str().c_str());
0183 }
0184 }
0185 }