GSLAM  3.0.0
Registry.h
1 // GSLAM - A general SLAM framework and benchmark
2 // Copyright 2018 PILAB Inc. All rights reserved.
3 // https://github.com/zdzhaoyong/GSLAM
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // * Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright notice,
11 // this list of conditions and the following disclaimer in the documentation
12 // and/or other materials provided with the distribution.
13 // * Neither the name of Google Inc. nor the names of its contributors may be
14 // used to endorse or promote products derived from this software without
15 // specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
28 //
29 // Author: zd5945@126.com (Yong Zhao)
30 //
31 // Registry is used to load/get gslam plugins as Svar or SharedLibrary
32 
33 #ifndef GSLAM_REGISTRY_H
34 #define GSLAM_REGISTRY_H
35 #include "SharedLibrary.h"
36 #include "Svar.h"
37 
38 namespace GSLAM {
39 
40 class Registry
41 {
42 public:
43  typedef std::set<std::string> FilePathList;
44  Registry(){
45  updatePaths();
46  }
47 
48  static Svar load(std::string pluginName){
49  SharedLibraryPtr plugin=get(pluginName);
50  if(!plugin)
51  {
52  std::cerr<<"Unable to load plugin "<<pluginName<<std::endl;
53  std::cerr<<"PATH=";
54  for(std::string p:instance()._libraryFilePath)
55  std::cerr<<p<<":";
56  std::cerr<<std::endl;
57  return Svar();
58  }
59  if(!plugin->hasSymbol("svarInstance"))
60  {
61  std::cerr<<"Unable to find symbol svarInstance."<<std::endl;
62  return Svar();
63  }
64 
65  GSLAM::Svar* (*getInst)()=(GSLAM::Svar* (*)())plugin->getSymbol("svarInstance");
66  if(!getInst){
67  std::cerr<<"No svarInstance found in "<<pluginName<<std::endl;
68  return Svar();
69  }
70  GSLAM::Svar* inst=getInst();
71  if(!inst){
72  std::cerr<<"svarInstance returned null.\n";
73  return Svar();
74  }
75 
76  return *inst;
77  }
78 
79  static Registry& instance()
80  {
81  static std::shared_ptr<Registry> reg(new Registry);
82  return *reg;
83  }
84 
85  static SharedLibraryPtr get(std::string pluginName)
86  {
87  if(pluginName.empty()) return SharedLibraryPtr();
88  Registry& inst=instance();
89  pluginName=inst.getPluginName(pluginName);
90 
91  if(inst._registedLibs[pluginName].is<SharedLibraryPtr>())
92  return inst._registedLibs.Get<SharedLibraryPtr>(pluginName);
93 
94  // find out and load the SharedLibrary
95  for(std::string dir:inst._libraryFilePath)
96  {
97  std::string pluginPath=dir+"/libgslam_"+pluginName;
98  if(!fileExists(pluginPath)) continue;
99  SharedLibraryPtr lib(new SharedLibrary(pluginPath));
100  if(lib->isLoaded())
101  {
102  inst._registedLibs.set(pluginName,lib);
103  return lib;
104  }
105  }
106 
107  // find out and load the SharedLibrary
108  for(std::string dir:inst._libraryFilePath)
109  {
110  std::string pluginPath=dir+"/"+pluginName;
111  if(!fileExists(pluginPath)) continue;
112  SharedLibraryPtr lib(new SharedLibrary(pluginPath));
113  if(lib->isLoaded())
114  {
115  inst._registedLibs.set(pluginName,lib);
116  return lib;
117  }
118  }
119 
120  // find out and load the SharedLibrary
121  for(std::string dir:inst._libraryFilePath)
122  {
123  std::string pluginPath=dir+"/lib"+pluginName;
124  if(!fileExists(pluginPath)) continue;
125  SharedLibraryPtr lib(new SharedLibrary(pluginPath));
126  if(lib->isLoaded())
127  {
128  inst._registedLibs.set(pluginName,lib);
129  return lib;
130  }
131  }
132  // failed to find the library
133  return SharedLibraryPtr();
134  }
135 
136  static bool erase(std::string pluginName)
137  {
138  if(pluginName.empty()) return false;
139  Registry& inst=instance();
140  pluginName=inst.getPluginName(pluginName);
141  inst._registedLibs.set(pluginName,Svar());
142  return true;
143  }
144 
145  std::set<std::string>& paths(){return _libraryFilePath;}
146 protected:
147  static bool fileExists(const std::string& filename)
148  {
149  return access( filename.c_str(), 0 ) == 0;
150  }
151 
152  static void convertStringPathIntoFilePathList(const std::string& paths,FilePathList& filepath)
153  {
154  #if defined(WIN32) && !defined(__CYGWIN__)
155  char delimitor = ';';
156  if(paths.find(delimitor)==std::string::npos) delimitor=':';
157  #else
158  char delimitor = ':';
159  if(paths.find(delimitor)==std::string::npos) delimitor=';';
160  #endif
161 
162  if (!paths.empty())
163  {
164  std::string::size_type start = 0;
165  std::string::size_type end;
166  while ((end = paths.find_first_of(delimitor,start))!=std::string::npos)
167  {
168  filepath.insert(std::string(paths,start,end-start));
169  start = end+1;
170  }
171 
172  std::string lastPath(paths,start,std::string::npos);
173  if (!lastPath.empty())
174  filepath.insert(lastPath);
175  }
176 
177  }
178  std::string getPluginName(std::string pluginName)
179  {
180  std::string suffix;
181  size_t idx=pluginName.find_last_of('.');
182  if(idx!=std::string::npos)
183  suffix=pluginName.substr(idx);
184  if(suffix!=SharedLibrary::suffix())
185  {
186  pluginName+=SharedLibrary::suffix();
187  }
188 
189  std::string folder=getFolderPath(pluginName);
190  pluginName=getFileName(pluginName);
191  if(folder.size()){
192  _libraryFilePath.insert(folder);
193  }
194  return pluginName;
195  }
196 
197  void updatePaths()
198  {
199  _libraryFilePath.clear();
200 
201  char** argv=svar.get<char**>("argv",nullptr);
202  if(argv)
203  {
204  _libraryFilePath.insert(getFolderPath(argv[0]));//application folder
205  }
206  _libraryFilePath.insert(".");
207 
208  FilePathList envs={"GSLAM_LIBRARY_PATH","GSLAM_LD_LIBRARY_PATH"};
209  FilePathList paths;
210 #ifdef __linux
211 
212 #if defined(__ia64__) || defined(__x86_64__)
213  paths.insert("/usr/lib/:/usr/lib64/:/usr/local/lib/:/usr/local/lib64/");
214 #else
215  paths.insert("/usr/lib/:/usr/local/lib/");
216 #endif
217  envs.insert("LD_LIBRARY_PATH");
218 #elif defined(__CYGWIN__)
219  envs.insert("PATH");
220  paths.insert("/usr/bin/:/usr/local/bin/");
221 #elif defined(WIN32)
222  envs.insert("PATH");
223 #endif
224  for(std::string env:envs)
225  {
226  std::string ptr=svar.GetString(env,"");
227  if(!ptr.empty())
228  convertStringPathIntoFilePathList(ptr,_libraryFilePath);
229  }
230  for(std::string ptr:paths)
231  convertStringPathIntoFilePathList(ptr,_libraryFilePath);
232  }
233 
234  inline std::string getFolderPath(const std::string& path) {
235  auto idx = std::string::npos;
236  if ((idx = path.find_last_of('/')) == std::string::npos)
237  idx = path.find_last_of('\\');
238  if (idx != std::string::npos)
239  return path.substr(0, idx);
240  else
241  return "";
242  }
243 
244  inline std::string getBaseName(const std::string& path) {
245  std::string filename = getFileName(path);
246  auto idx = filename.find_last_of('.');
247  if (idx == std::string::npos)
248  return filename;
249  else
250  return filename.substr(0, idx);
251  }
252 
253  inline std::string getFileName(const std::string& path) {
254  auto idx = std::string::npos;
255  if ((idx = path.find_last_of('/')) == std::string::npos)
256  idx = path.find_last_of('\\');
257  if (idx != std::string::npos)
258  return path.substr(idx + 1);
259  else
260  return path;
261  }
262 
263 
264 
265  std::set<std::string> _libraryFilePath;// where to search?
266  Svar _registedLibs; // already loaded
267 };
268 
269 }
270 
271 #endif
Definition: Registry.h:40
void set(const std::string &name, const T &def, bool parse_dot=false)
Set the child "name" to "create<T>(def)".
bool is() const
Is holding a type T value?
The SharedLibrary class dynamically loads shared libraries at run-time.
Definition: SharedLibrary.h:109
Definition: Camera.h:45
The Svar class, A Tiny Modern C++ Header Brings Unified Interface for Different Languages.
Definition: Svar.h:561
static std::string suffix()
Returns the path of the library, as specified in a call to load() or the constructor.
Definition: SharedLibrary.h:238