Plugin.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 #ifndef _GZ_PLUGIN_HH_
18 #define _GZ_PLUGIN_HH_
19 
20 #ifndef _WIN32
21  #include <unistd.h>
22 #endif
23 
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 
27 #include <gazebo/gazebo_config.h>
28 #include <dlfcn.h>
29 
30 #include <list>
31 #include <string>
32 
33 #include <sdf/sdf.hh>
34 #include <boost/filesystem.hpp>
35 
38 #include "gazebo/common/Console.hh"
40 
44 #include "gazebo/util/system.hh"
45 
46 namespace gazebo
47 {
48  class Event;
49 
52 
56  {
69  };
70 
71 
74  template<class T>
75  class PluginT
76  {
78  public: typedef boost::shared_ptr<T> TPtr;
79 
81  public: PluginT()
82  {
83  this->dlHandle = nullptr;
84  }
85 
87  public: virtual ~PluginT()
88  {
89  // dlclose has been disabled due to segfaults in the test suite
90  // This workaround is detailed in #1026 and #1066. After the test
91  // or gazebo execution the plugin is not loaded in memory anymore
92  // \todo Figure out the right thing to do.
93 
94  // dlclose(this->dlHandle);
95  }
96 
98  public: std::string GetFilename() const
99  {
100  return this->filename;
101  }
102 
104  public: std::string GetHandle() const
105  {
106  return this->handleName;
107  }
108 
114  public: static TPtr Create(const std::string &_filename,
115  const std::string &_name)
116  {
117  TPtr result;
118  // PluginPtr result;
119  std::string filename(_filename);
120  std::list<std::string> pluginPaths =
121  common::SystemPaths::Instance()->GetPluginPaths();
122  std::ostringstream errorStream;
123 
124  // helper function to find and dlopen a plugin file
125  // returns void * dlHandle
126  auto findAndDlopenPluginFile = [](
127  const std::string &_pluginFilename,
128  const std::list<std::string> &_pluginPaths,
129  std::ostringstream &_errorStream) -> void *
130  {
131  struct stat st;
132  bool found = false;
133  std::string fullname;
134  std::list<std::string>::const_iterator iter;
135 
136  for (iter = _pluginPaths.begin();
137  iter!= _pluginPaths.end(); ++iter)
138  {
139  fullname = (*iter)+std::string("/")+_pluginFilename;
140  fullname = boost::filesystem::path(fullname)
141  .make_preferred().string();
142  if (stat(fullname.c_str(), &st) == 0)
143  {
144  found = true;
145  break;
146  }
147  }
148 
149  if (!found)
150  fullname = _pluginFilename;
151 
152  void *dlHandle = dlopen(fullname.c_str(), RTLD_LAZY|RTLD_GLOBAL);
153  if (!dlHandle)
154  {
155  _errorStream << "Failed to load plugin " << fullname << ": "
156  << dlerror() << "\n";
157  }
158  return dlHandle;
159  };
160 
161  // This logic is to support different extensions on each OS
162  // see issue #800
163  //
164  // Linux: lib*.so
165  // macOS: lib*.so, lib*.dylib
166  // Windows: *.dll
167  //
168  // Assuming that most plugin names are specified as lib*.so,
169  // replace prefix and suffix depending on the OS.
170  // On macOS, first try the lib*.so name, then try lib*.dylib
171 #ifdef _WIN32
172  {
173  // replace .so with .dll
174  size_t soSuffix = filename.rfind(".so");
175  if (soSuffix != std::string::npos)
176  {
177  const std::string winSuffix(".dll");
178  filename.replace(soSuffix, winSuffix.length(), winSuffix);
179  }
180  size_t libPrefix = filename.find("lib");
181  if (libPrefix == 0)
182  {
183  // remove the lib prefix
184  filename.erase(0, 3);
185  }
186  }
187 #endif // ifdef _WIN32
188 
189  // Try to find and dlopen plugin with the following pattern:
190  // Linux: lib*.so
191  // macOS: lib*.so
192  // Windows: *.dll
193  void *dlHandle = findAndDlopenPluginFile(filename, pluginPaths,
194  errorStream);
195 #ifdef __APPLE__
196  if (!dlHandle)
197  {
198  // lib*.so file could not be found or opened, try lib*.dylib
199  size_t soSuffix = filename.rfind(".so");
200  if (soSuffix != std::string::npos)
201  {
202  const std::string macSuffix(".dylib");
203  filename.replace(soSuffix, macSuffix.length(), macSuffix);
204  }
205  }
206  // macOS: lib*.dylib
207  dlHandle = findAndDlopenPluginFile(filename, pluginPaths, errorStream);
208 #endif // ifdef __APPLE__
209 
210  if (!dlHandle)
211  {
212  gzerr << errorStream.str();
213  return result;
214  }
215 
216  fptr_union_t registerFunc;
217  const char *registerName = "RegisterPlugin";
218 
219  registerFunc.ptr = dlsym(dlHandle, registerName);
220 
221  if (!registerFunc.ptr)
222  {
223  gzerr << "Failed to resolve " << registerName
224  << ": " << dlerror();
225  return result;
226  }
227 
228  // Register the new controller.
229  result.reset(registerFunc.func());
230  result->dlHandle = dlHandle;
231 
232  result->handleName = _name;
233  result->filename = filename;
234 
235  return result;
236  }
237 
240  public: PluginType GetType() const
241  {
242  return this->type;
243  }
244 
253  protected: template <typename V> void LoadParam(const sdf::ElementPtr &_sdf,
254  const std::string &_name, V &_target,
255  V _defaultValue = V()) const
256  {
257  auto result = _sdf->Get<V>(_name, _defaultValue);
258 
259  if (!result.second)
260  {
261  gzmsg << this->handleName.c_str() << " Plugin missing <"
262  << _name.c_str() << ">, defaults to "
263  << result.first << std::endl;
264  }
265  else
266  {
267  gzmsg << this->handleName.c_str() << " Plugin <"
268  << _name.c_str() << "> set to "
269  << result.first << std::endl;
270  }
271  _target = result.first;
272  }
273 
283  protected: void LoadParam(sdf::ElementPtr &_sdf,
284  const std::string &_name, std::string &_target,
285  const char* _defaultValue) const
286  {
287  this->LoadParam<std::string>(_sdf, _name, _target, _defaultValue);
288  }
289 
291  protected: PluginType type;
292 
294  protected: std::string filename;
295 
297  protected: std::string handleName;
298 
300  private: typedef union
301  {
302  T *(*func)();
303  void *ptr;
304  } fptr_union_t;
305 
307  private: void *dlHandle;
308  };
309 
314  class WorldPlugin : public PluginT<WorldPlugin>
315  {
317  public: WorldPlugin()
318  {this->type = WORLD_PLUGIN;}
319 
321  public: virtual ~WorldPlugin() {}
322 
329  public: virtual void Load(physics::WorldPtr _world,
330  sdf::ElementPtr _sdf) = 0;
331 
332  public: virtual void Init() {}
333  public: virtual void Reset() {}
334  };
335 
339  class ModelPlugin : public PluginT<ModelPlugin>
340  {
342  public: ModelPlugin()
343  {this->type = MODEL_PLUGIN;}
344 
346  public: virtual ~ModelPlugin() {}
347 
354  public: virtual void Load(physics::ModelPtr _model,
355  sdf::ElementPtr _sdf) = 0;
356 
358  public: virtual void Init() {}
359 
361  public: virtual void Reset() {}
362  };
363 
368  class SensorPlugin : public PluginT<SensorPlugin>
369  {
371  public: SensorPlugin()
372  {this->type = SENSOR_PLUGIN;}
373 
375  public: virtual ~SensorPlugin() {}
376 
383  public: virtual void Load(sensors::SensorPtr _sensor,
384  sdf::ElementPtr _sdf) = 0;
385 
387  public: virtual void Init() {}
388 
390  public: virtual void Reset() {}
391  };
392 
397  class SystemPlugin : public PluginT<SystemPlugin>
398  {
400  public: SystemPlugin()
401  {this->type = SYSTEM_PLUGIN;}
402 
404  public: virtual ~SystemPlugin() {}
405 
411  public: virtual void Load(int _argc = 0, char **_argv = nullptr) = 0;
412 
416  public: virtual void Init() {}
417 
419  public: virtual void Reset() {}
420  };
421 
425  class VisualPlugin : public PluginT<VisualPlugin>
426  {
427  public: VisualPlugin()
428  {this->type = VISUAL_PLUGIN;}
429 
436  public: virtual void Load(rendering::VisualPtr _visual,
437  sdf::ElementPtr _sdf) = 0;
438 
442  public: virtual void Init() {}
443 
445  public: virtual void Reset() {}
446  };
447 
448 
450 
455 #define GZ_REGISTER_MODEL_PLUGIN(classname) \
456  extern "C" GZ_PLUGIN_VISIBLE gazebo::ModelPlugin *RegisterPlugin(); \
457  gazebo::ModelPlugin *RegisterPlugin() \
458  {\
459  return new classname();\
460  }
461 
466 #define GZ_REGISTER_WORLD_PLUGIN(classname) \
467  extern "C" GZ_PLUGIN_VISIBLE gazebo::WorldPlugin *RegisterPlugin(); \
468  gazebo::WorldPlugin *RegisterPlugin() \
469  {\
470  return new classname();\
471  }
472 
477 #define GZ_REGISTER_SENSOR_PLUGIN(classname) \
478  extern "C" GZ_PLUGIN_VISIBLE gazebo::SensorPlugin *RegisterPlugin(); \
479  gazebo::SensorPlugin *RegisterPlugin() \
480  {\
481  return new classname();\
482  }
483 
488 #define GZ_REGISTER_SYSTEM_PLUGIN(classname) \
489  extern "C" GZ_PLUGIN_VISIBLE gazebo::SystemPlugin *RegisterPlugin(); \
490  gazebo::SystemPlugin *RegisterPlugin() \
491  {\
492  return new classname();\
493  }
494 
499 #define GZ_REGISTER_VISUAL_PLUGIN(classname) \
500  extern "C" GZ_PLUGIN_VISIBLE gazebo::VisualPlugin *RegisterPlugin(); \
501  gazebo::VisualPlugin *RegisterPlugin() \
502  {\
503  return new classname();\
504  }
505 }
506 
507 #endif
default namespace for gazebo
Forward declarations and typedefs for sensors.
static SystemPaths * Instance()
Get an instance of the singleton.
Definition: SingletonT.hh:36
A plugin with access to physics::Model.
Definition: Plugin.hh:340
virtual void Load(physics::ModelPtr _model, sdf::ElementPtr _sdf)=0
Load function.
virtual void Init()
Override this method for custom plugin initialization behavior.
Definition: Plugin.hh:358
virtual void Reset()
Override this method for custom plugin reset behavior.
Definition: Plugin.hh:361
virtual ~ModelPlugin()
Destructor.
Definition: Plugin.hh:346
ModelPlugin()
Constructor.
Definition: Plugin.hh:342
A class which all plugins must inherit from.
Definition: Plugin.hh:76
std::string GetFilename() const
Get the name of the handler.
Definition: Plugin.hh:98
std::string handleName
Short name.
Definition: Plugin.hh:297
PluginType type
Type of plugin.
Definition: Plugin.hh:291
boost::shared_ptr< T > TPtr
plugin pointer type definition
Definition: Plugin.hh:78
void LoadParam(const sdf::ElementPtr &_sdf, const std::string &_name, V &_target, V _defaultValue=V()) const
Load parameter value from _sdf and store it to the given reference, using the supplied default value ...
Definition: Plugin.hh:253
PluginType GetType() const
Returns the type of the plugin.
Definition: Plugin.hh:240
static TPtr Create(const std::string &_filename, const std::string &_name)
a class method that creates a plugin from a file name.
Definition: Plugin.hh:114
PluginT()
Constructor.
Definition: Plugin.hh:81
std::string GetHandle() const
Get the short name of the handler.
Definition: Plugin.hh:104
void LoadParam(sdf::ElementPtr &_sdf, const std::string &_name, std::string &_target, const char *_defaultValue) const
Load parameter value from _sdf and store it to the given reference, using the supplied default value ...
Definition: Plugin.hh:283
std::string filename
Path to the shared library file.
Definition: Plugin.hh:294
virtual ~PluginT()
Destructor.
Definition: Plugin.hh:87
A plugin with access to physics::Sensor.
Definition: Plugin.hh:369
SensorPlugin()
Constructor.
Definition: Plugin.hh:371
virtual void Init()
Override this method for custom plugin initialization behavior.
Definition: Plugin.hh:387
virtual void Reset()
Override this method for custom plugin reset behavior.
Definition: Plugin.hh:390
virtual void Load(sensors::SensorPtr _sensor, sdf::ElementPtr _sdf)=0
Load function.
virtual ~SensorPlugin()
Destructor.
Definition: Plugin.hh:375
A plugin loaded within the gzserver on startup.
Definition: Plugin.hh:398
SystemPlugin()
Constructor.
Definition: Plugin.hh:400
virtual void Init()
Initialize the plugin.
Definition: Plugin.hh:416
virtual ~SystemPlugin()
Destructor.
Definition: Plugin.hh:404
virtual void Reset()
Override this method for custom plugin reset behavior.
Definition: Plugin.hh:419
virtual void Load(int _argc=0, char **_argv=nullptr)=0
Load function.
A plugin with access to rendering::Visual.
Definition: Plugin.hh:426
virtual void Load(rendering::VisualPtr _visual, sdf::ElementPtr _sdf)=0
Load function.
virtual void Init()
Initialize the plugin.
Definition: Plugin.hh:442
virtual void Reset()
Override this method for custom plugin reset behavior.
Definition: Plugin.hh:445
VisualPlugin()
Definition: Plugin.hh:427
A plugin with access to physics::World.
Definition: Plugin.hh:315
virtual ~WorldPlugin()
Destructor.
Definition: Plugin.hh:321
virtual void Init()
Definition: Plugin.hh:332
virtual void Load(physics::WorldPtr _world, sdf::ElementPtr _sdf)=0
Load function.
WorldPlugin()
Constructor.
Definition: Plugin.hh:317
virtual void Reset()
Definition: Plugin.hh:333
#define gzmsg
Output a message.
Definition: Console.hh:41
PluginType
Used to specify the type of plugin.
Definition: Plugin.hh:56
#define gzerr
Output an error message.
Definition: Console.hh:50
@ SYSTEM_PLUGIN
A System plugin.
Definition: Plugin.hh:64
@ GUI_PLUGIN
A GUI plugin.
Definition: Plugin.hh:68
@ VISUAL_PLUGIN
A Visual plugin.
Definition: Plugin.hh:66
@ SENSOR_PLUGIN
A Sensor plugin.
Definition: Plugin.hh:62
@ MODEL_PLUGIN
A Model plugin.
Definition: Plugin.hh:60
@ WORLD_PLUGIN
A World plugin.
Definition: Plugin.hh:58
boost::shared_ptr< World > WorldPtr
Definition: PhysicsTypes.hh:90
boost::shared_ptr< Model > ModelPtr
Definition: PhysicsTypes.hh:94
std::shared_ptr< Visual > VisualPtr
Definition: RenderTypes.hh:114
std::shared_ptr< Sensor > SensorPtr
Definition: SensorTypes.hh:64
Forward declarations for the common classes.
Definition: Animation.hh:27