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
40
44#include "gazebo/util/system.hh"
45
46namespace gazebo
47{
48 class Event;
49
52
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