All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Plugin.hh
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2014 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 #include <unistd.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 
24 #include <gazebo/gazebo_config.h>
25 #include <dlfcn.h>
26 
27 #include <list>
28 #include <string>
29 
30 #include <sdf/sdf.hh>
31 
34 #include "gazebo/common/Console.hh"
36 
40 #include "gazebo/util/system.hh"
41 
42 namespace gazebo
43 {
44  class Event;
45 
48 
52  {
63  };
64 
65 
68  template<class T>
70  {
72  public: typedef boost::shared_ptr<T> TPtr;
73 
75  public: PluginT()
76  {
77  this->dlHandle = NULL;
78  }
79 
81  public: virtual ~PluginT()
82  {
83  // dlclose has been disabled due to segfaults in the test suite
84  // This workaround is detailed in #1026 and #1066. After the test
85  // or gazebo execution the plugin is not loaded in memory anymore
86  // \todo Figure out the right thing to do.
87 
88  // dlclose(this->dlHandle);
89  }
90 
92  public: std::string GetFilename() const
93  {
94  return this->filename;
95  }
96 
98  public: std::string GetHandle() const
99  {
100  return this->handle;
101  }
102 
108  public: static TPtr Create(const std::string &_filename,
109  const std::string &_handle)
110  {
111  TPtr result;
112  // PluginPtr result;
113  struct stat st;
114  bool found = false;
115  std::string fullname, filename(_filename);
116  std::list<std::string>::iterator iter;
117  std::list<std::string> pluginPaths =
118  common::SystemPaths::Instance()->GetPluginPaths();
119 
120 #ifdef __APPLE__
121  // This is a hack to work around issue #800,
122  // error loading plugin libraries with different extensions
123  {
124  size_t soSuffix = filename.rfind(".so");
125  const std::string macSuffix(".dylib");
126  if (soSuffix != std::string::npos)
127  filename.replace(soSuffix, macSuffix.length(), macSuffix);
128  }
129 #endif // ifdef __APPLE__
130 
131  for (iter = pluginPaths.begin();
132  iter!= pluginPaths.end(); ++iter)
133  {
134  fullname = (*iter)+std::string("/")+filename;
135  if (stat(fullname.c_str(), &st) == 0)
136  {
137  found = true;
138  break;
139  }
140  }
141 
142  if (!found)
143  fullname = filename;
144 
145  fptr_union_t registerFunc;
146  std::string registerName = "RegisterPlugin";
147 
148  void *dlHandle = dlopen(fullname.c_str(), RTLD_LAZY|RTLD_GLOBAL);
149  if (!dlHandle)
150  {
151  gzerr << "Failed to load plugin " << fullname << ": "
152  << dlerror() << "\n";
153  return result;
154  }
155 
156  registerFunc.ptr = dlsym(dlHandle, registerName.c_str());
157 
158  if (!registerFunc.ptr)
159  {
160  gzerr << "Failed to resolve " << registerName
161  << ": " << dlerror();
162  return result;
163  }
164 
165  // Register the new controller.
166  result.reset(registerFunc.func());
167  result->dlHandle = dlHandle;
168 
169  result->handle = _handle;
170  result->filename = filename;
171 
172  return result;
173  }
174 
177  public: PluginType GetType() const
178  {
179  return this->type;
180  }
181 
183  protected: PluginType type;
184 
186  protected: std::string filename;
187 
189  protected: std::string handle;
190 
192  private: typedef union
193  {
194  T *(*func)();
195  void *ptr;
196  } fptr_union_t;
197 
199  private: void *dlHandle;
200  };
201 
206  class GAZEBO_VISIBLE WorldPlugin : public PluginT<WorldPlugin>
207  {
209  public: WorldPlugin()
210  {this->type = WORLD_PLUGIN;}
211 
213  public: virtual ~WorldPlugin() {}
214 
221  public: virtual void Load(physics::WorldPtr _world,
222  sdf::ElementPtr _sdf) = 0;
223 
224  public: virtual void Init() {}
225  public: virtual void Reset() {}
226  };
227 
231  class GAZEBO_VISIBLE ModelPlugin : public PluginT<ModelPlugin>
232  {
234  public: ModelPlugin()
235  {this->type = MODEL_PLUGIN;}
236 
238  public: virtual ~ModelPlugin() {}
239 
246  public: virtual void Load(physics::ModelPtr _model,
247  sdf::ElementPtr _sdf) = 0;
248 
250  public: virtual void Init() {}
251 
253  public: virtual void Reset() {}
254  };
255 
260  class GAZEBO_VISIBLE SensorPlugin : public PluginT<SensorPlugin>
261  {
263  public: SensorPlugin()
264  {this->type = SENSOR_PLUGIN;}
265 
267  public: virtual ~SensorPlugin() {}
268 
275  public: virtual void Load(sensors::SensorPtr _sensor,
276  sdf::ElementPtr _sdf) = 0;
277 
279  public: virtual void Init() {}
280 
282  public: virtual void Reset() {}
283  };
284 
289  class GAZEBO_VISIBLE SystemPlugin : public PluginT<SystemPlugin>
290  {
292  public: SystemPlugin()
293  {this->type = SYSTEM_PLUGIN;}
294 
296  public: virtual ~SystemPlugin() {}
297 
303  public: virtual void Load(int _argc = 0, char **_argv = NULL) = 0;
304 
308  public: virtual void Init() {}
309 
311  public: virtual void Reset() {}
312  };
313 
317  class GAZEBO_VISIBLE VisualPlugin : public PluginT<VisualPlugin>
318  {
319  public: VisualPlugin()
320  {this->type = VISUAL_PLUGIN;}
321 
328  public: virtual void Load(rendering::VisualPtr _visual,
329  sdf::ElementPtr _sdf) = 0;
330 
334  public: virtual void Init() {}
335 
337  public: virtual void Reset() {}
338  };
339 
341 
346 #define GZ_REGISTER_MODEL_PLUGIN(classname) \
347  extern "C" GAZEBO_VISIBLE gazebo::ModelPlugin *RegisterPlugin(); \
348  GAZEBO_VISIBLE \
349  gazebo::ModelPlugin *RegisterPlugin() \
350  {\
351  return new classname();\
352  }
353 
358 #define GZ_REGISTER_WORLD_PLUGIN(classname) \
359  extern "C" GAZEBO_VISIBLE gazebo::WorldPlugin *RegisterPlugin(); \
360  GAZEBO_VISIBLE \
361  gazebo::WorldPlugin *RegisterPlugin() \
362  {\
363  return new classname();\
364  }
365 
370 #define GZ_REGISTER_SENSOR_PLUGIN(classname) \
371  extern "C" GAZEBO_VISIBLE gazebo::SensorPlugin *RegisterPlugin(); \
372  GAZEBO_VISIBLE \
373  gazebo::SensorPlugin *RegisterPlugin() \
374  {\
375  return new classname();\
376  }
377 
382 #define GZ_REGISTER_SYSTEM_PLUGIN(classname) \
383  extern "C" GAZEBO_VISIBLE gazebo::SystemPlugin *RegisterPlugin(); \
384  GAZEBO_VISIBLE \
385  gazebo::SystemPlugin *RegisterPlugin() \
386  {\
387  return new classname();\
388  }
389 
394 #define GZ_REGISTER_VISUAL_PLUGIN(classname) \
395  extern "C" GAZEBO_VISIBLE gazebo::VisualPlugin *RegisterPlugin(); \
396  GAZEBO_VISIBLE \
397  gazebo::VisualPlugin *RegisterPlugin() \
398  {\
399  return new classname();\
400  }
401 }
402 
403 #endif