Diana Software
QDll.cc
Go to the documentation of this file.
1 #include "QDll.hh"
2 #include <dlfcn.h>
3 #include <sstream>
4 #include <sys/utsname.h>
5 #include "QMessage.hh"
6 #include "QStringHandler.hh"
7 
9 
10 QDLLManager::QDLLManager( const char *fname, const bool autoload )
11 {
12  // Try to open the library now and get any error message.
13  if(autoload) {
14  h=dlopen( fname, RTLD_GLOBAL | RTLD_NOW);
15  } else {
16  h=dlopen( fname, RTLD_NOW );
17  }
18  err=dlerror();
19 }
20 
22 {
23  // close the library if it isn't null
24 // if( h!=0 )
25 // dlclose(h);
26 }
27 
28 QError QDLLManager::GetSymbol(void **v, const char *sym_name)
29 {
30  // try extract a symbol from the library
31  // get any error message is there is any
32  if( h!=0 ) {
33  *v = dlsym( h, sym_name );
34  err=dlerror();
35  if( err==0 )
36  return QERR_SUCCESS;
37  else
38  return QError(QERR_UNKNOWN_ERR, std::string("Cannot find symbol: ") + std::string(sym_name));
39  } else {
40  return QError(QERR_UNKNOWN_ERR, std::string("Library not open so no symbol found.."));
41  }
42 }
43 
45 {
46  static QDLLLoader loader;
47 
48  return loader;
49 }
50 
52 {
53  fPluginLists.clear();
54  fFirstLoadCall = true;
55  fDoAutoLoad = false;
56 }
57 
58 QError QDLLLoader::Init(const std::string& pluginlist, const std::string& pluginPrefix)
59 {
60  if(fPluginLists.count(pluginlist) > 0) return QERR_SUCCESS;
61  // open file with list of plugin for each library
62  // and fill the [(prefix+plugin) - corrsponding library map
63 
64  // search for libraries path where the pluginList file should be...
65  struct utsname system;
66  uname(&system);
67  char* ldpath = NULL;
68  if(std::string(system.sysname) == "Darwin")
69  ldpath = getenv("DYLD_LIBRARY_PATH");
70  else
71  ldpath = getenv("LD_LIBRARY_PATH");
72  std::stringstream path(ldpath);
73  std::string libpath;
74  std::string fullpath;
75  std::ifstream file;
76  while(std::getline(path,libpath,':')) {
77  fullpath = libpath + "/" + pluginlist;
78  file.open(fullpath.c_str());
79  if(file.good()) break;
80  }
81  if(!file.good()) return QError(QERR_CANNOT_OPEN_FILE,std::string("Plugins: ") + fullpath + " not loaded");
82 
83 
84  std::string msg = std::string("Reading plugins from: ") + fullpath;
85  QMessageHandler::Get()->Send(DebugMsg,"QDLLLoader",msg);
86  // parse file
87  std::string line;
88  while(std::getline(file,line)) {
89  // Remove anything after the first # character
90  line=line.substr(0,line.find("#"));
91  // Remove leading and trailing spaces
93  // Skip empty lines
94  if(line.length()==0) continue;
95 
96  std::stringstream sline(line);
97  std::string word;
98  std::string library;
99  // The library name is first
100  std::getline(sline,library,':');
101  // Then handle all the modules listed on the line
102  while(sline >> word){
103  if(word == "autoload" && fDoAutoLoad) {
104  AutoLoadPlugin aplugin;
105  aplugin.library=library;
106  aplugin.fullPathLibrary = libpath+"/"+library;
107  bool overWritten = false;
108  for (size_t i=0;i<fAutoPluginsLib.size();i++) {
109  if(fAutoPluginsLib[i].library == library) {
110  fAutoPluginsLib[i] = aplugin;
111  overWritten = true;
112  }
113  }
114  if(!overWritten)
115  fAutoPluginsLib.push_back(aplugin);
116  }
117  else
118  fPluginsLib[word] = library;
119  }
120  }
121 
122  /*
123  std::map<std::string, std::string>::iterator plugLibIter;
124  for(plugLibIter = fPluginsLib.begin(); plugLibIter != fPluginsLib.end(); plugLibIter++)
125  std::cout<<plugLibIter->first<<" -- "<<plugLibIter->second<<std::endl;
126  */
127  fPluginPrefix = pluginPrefix;
128  fPluginLists.insert(pluginlist);
129  return QERR_SUCCESS;
130 }
131 
132 QError QDLLLoader::LoadPlugin(const std::string& pluginName)
133 {
134  QMessageHandler::Get()->Send(DebugMsg,"QDLLLoader",
135  "LoadPlugin " + pluginName);
136  if(fFirstLoadCall ) {
137  std::vector<AutoLoadPlugin>::const_iterator iter = fAutoPluginsLib.begin();
138  while(iter != fAutoPluginsLib.end()) {
139  const AutoLoadPlugin& autoPlugin = *iter;
140  QMessageHandler::Get()->Send(DebugMsg,"QDLLLoader",
141  "Autoloading: "
142  +autoPlugin.fullPathLibrary);
143  QDLLManager dll(autoPlugin.fullPathLibrary.c_str(),true);
144  const char* dllError = dll.LastError();
145  if(dllError) {
146  std::stringstream msg;
147  msg << "While loading plugin " << pluginName
148  << " attempt to autoload library "
149  << autoPlugin.fullPathLibrary
150  << ". Load failed!" << std::endl
151  << "DLL Error: " << dllError;
152  return QError(QERR_CANNOT_OPEN_FILE,msg.str());
153  } else {
154  std::string msg = "Autoloaded: " + autoPlugin.fullPathLibrary;
155  QMessageHandler::Get()->Send(DebugMsg,"QDLLLoader",msg);
156  }
157 
158 
159  iter++;
160  }
161  fFirstLoadCall = false;
162  }
163  // look for the plugin's library
164  std::map<std::string, std::string>::iterator plugLibIter = fPluginsLib.find(pluginName);
165  if(plugLibIter==fPluginsLib.end()) {
166  return QError(QERR_UNKNOWN_ERR,std::string("Plugin: ") + pluginName + " not found in libraries database");
167  }
168  else {
169  std::stringstream msg;
170  msg << "Found library\n\t" << pluginName << ":" <<
171  plugLibIter->second;
172  QMessageHandler::Get()->Send(DebugMsg,"QDLLLoader",msg.str());
173  }
174 
175  // open library
176  QDLLManager dll(plugLibIter->second.c_str());
177  const char* dllError = dll.LastError();
178  if(dllError) {
179  return QError(QERR_CANNOT_OPEN_FILE,std::string(plugLibIter->second.c_str()) + " - " + dllError );
180  }
181  // get symbol
182  void (*factory_func)(void);
183  std::string plugin = fPluginPrefix + pluginName;
184  QError derr = dll.GetSymbol((void**)&factory_func, plugin.c_str());
185  if(derr!=QERR_SUCCESS) return derr;
186  // execute symbol
187  (*factory_func)();
188  return QError(QERR_SUCCESS);
189 }
190 
192 
#define Q_END_NAMESPACE
Definition: QDiana.hh:22
#define Q_BEGIN_NAMESPACE
Definition: QDiana.hh:20
@ QERR_UNKNOWN_ERR
Definition: QError.hh:108
@ QERR_CANNOT_OPEN_FILE
Definition: QError.hh:33
@ QERR_SUCCESS
Definition: QError.hh:27
@ DebugMsg
Definition: QMessageDefs.hh:6
std::string library
Definition: QDll.hh:65
std::string fullPathLibrary
Definition: QDll.hh:66
bool fDoAutoLoad
Definition: QDll.hh:74
std::set< std::string > fPluginLists
Definition: QDll.hh:72
std::string fPluginPrefix
Definition: QDll.hh:71
static QDLLLoader & GetInstance()
Definition: QDll.cc:44
QDLLLoader()
Definition: QDll.cc:51
QError LoadPlugin(const std::string &name)
Definition: QDll.cc:132
std::map< std::string, std::string > fPluginsLib
Definition: QDll.hh:69
std::vector< AutoLoadPlugin > fAutoPluginsLib
Definition: QDll.hh:70
bool fFirstLoadCall
Definition: QDll.hh:73
QError Init(const std::string &pluginlist, const std::string &pluginPrefix)
Definition: QDll.cc:58
const char * err
Definition: QDll.hh:36
void * h
Definition: QDll.hh:35
QError GetSymbol(void **, const char *sym_name)
Definition: QDll.cc:28
QDLLManager(const char *fname, const bool autoload=false)
Definition: QDll.cc:10
const char * LastError()
Definition: QDll.hh:29
virtual ~QDLLManager()
Definition: QDll.cc:21
error class with error type and description
Definition: QError.hh:115
static QMessageHandler * Get()
Definition: QMessage.cc:24
void Send(MsgLevel l, const std::string &sender, const std::string &msg)
Definition: QMessage.cc:31
std::string & DoubleSwallowSpaces(std::string &s)
remove spaces and tabs from both the beginning and the end of s