/* * Copyright (C) 2012 Open Source Robotics Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef _GZ_PLUGIN_HH_ #define _GZ_PLUGIN_HH_ #ifdef _WIN32 // Ensure that Winsock2.h is included before Windows.h, which can get // pulled in by anybody (e.g., Boost). // This was put here because all the plugins are going to use it // This doesn't guarantee something else won't cause it, // but this saves putting this in every plugin #include #endif #ifndef _WIN32 #include #endif #include #include #include #include #include #include #include #include "gazebo/common/CommonTypes.hh" #include "gazebo/common/SystemPaths.hh" #include "gazebo/common/Console.hh" #include "gazebo/common/Exception.hh" #include "gazebo/physics/PhysicsTypes.hh" #include "gazebo/sensors/SensorTypes.hh" #include "gazebo/rendering/RenderTypes.hh" #include "gazebo/util/system.hh" namespace gazebo { class Event; /// \addtogroup gazebo_common Common /// \{ /// \enum PluginType /// \brief Used to specify the type of plugin. enum PluginType { /// \brief A World plugin WORLD_PLUGIN, /// \brief A Model plugin MODEL_PLUGIN, /// \brief A Sensor plugin SENSOR_PLUGIN, /// \brief A System plugin SYSTEM_PLUGIN, /// \brief A Visual plugin VISUAL_PLUGIN, /// \brief A GUI plugin GUI_PLUGIN }; /// \class PluginT Plugin.hh common/common.hh /// \brief A class which all plugins must inherit from template class PluginT { /// \brief plugin pointer type definition public: typedef boost::shared_ptr TPtr; /// \brief Constructor public: PluginT() { this->dlHandle = NULL; } /// \brief Destructor public: virtual ~PluginT() { // dlclose has been disabled due to segfaults in the test suite // This workaround is detailed in #1026 and #1066. After the test // or gazebo execution the plugin is not loaded in memory anymore // \todo Figure out the right thing to do. // dlclose(this->dlHandle); } /// \brief Get the name of the handler public: std::string GetFilename() const { return this->filename; } /// \brief Get the short name of the handler public: std::string GetHandle() const { return this->handleName; } /// \brief a class method that creates a plugin from a file name. /// It locates the shared library and loads it dynamically. /// \param[in] _filename the path to the shared library. /// \param[in] _name short name of the plugin /// \return Shared Pointer to this class type public: static TPtr Create(const std::string &_filename, const std::string &_name) { TPtr result; // PluginPtr result; struct stat st; bool found = false; std::string fullname, filename(_filename); std::list::iterator iter; std::list pluginPaths = common::SystemPaths::Instance()->GetPluginPaths(); #ifdef __APPLE__ // This is a hack to work around issue #800, // error loading plugin libraries with different extensions { size_t soSuffix = filename.rfind(".so"); const std::string macSuffix(".dylib"); if (soSuffix != std::string::npos) filename.replace(soSuffix, macSuffix.length(), macSuffix); } #endif // ifdef __APPLE__ for (iter = pluginPaths.begin(); iter!= pluginPaths.end(); ++iter) { fullname = (*iter)+std::string("/")+filename; if (stat(fullname.c_str(), &st) == 0) { found = true; break; } } if (!found) fullname = filename; fptr_union_t registerFunc; std::string registerName = "RegisterPlugin"; void *dlHandle = dlopen(fullname.c_str(), RTLD_LAZY|RTLD_GLOBAL); if (!dlHandle) { gzerr << "Failed to load plugin " << fullname << ": " << dlerror() << "\n"; return result; } registerFunc.ptr = dlsym(dlHandle, registerName.c_str()); if (!registerFunc.ptr) { gzerr << "Failed to resolve " << registerName << ": " << dlerror(); return result; } // Register the new controller. result.reset(registerFunc.func()); result->dlHandle = dlHandle; result->handleName = _name; result->filename = filename; return result; } /// \brief Returns the type of the plugin /// \return type of the plugin public: PluginType GetType() const { return this->type; } /// \brief Type of plugin protected: PluginType type; /// \brief Path to the shared library file protected: std::string filename; /// \brief Short name protected: std::string handleName; /// \brief Pointer to shared library registration function definition private: typedef union { T *(*func)(); void *ptr; } fptr_union_t; /// \brief Handle used for closing the dynamic library. private: void *dlHandle; }; /// \class WorldPlugin Plugin.hh common/common.hh /// \brief A plugin with access to physics::World. See /// reference. class WorldPlugin : public PluginT { /// \brief Constructor public: WorldPlugin() {this->type = WORLD_PLUGIN;} /// \brief Destructor public: virtual ~WorldPlugin() {} /// \brief Load function /// /// Called when a Plugin is first created, and after the World has been /// loaded. This function should not be blocking. /// \param[in] _world Pointer the World /// \param[in] _sdf Pointer the the SDF element of the plugin. public: virtual void Load(physics::WorldPtr _world, sdf::ElementPtr _sdf) = 0; public: virtual void Init() {} public: virtual void Reset() {} }; /// \brief A plugin with access to physics::Model. See /// reference. class ModelPlugin : public PluginT { /// \brief Constructor public: ModelPlugin() {this->type = MODEL_PLUGIN;} /// \brief Destructor public: virtual ~ModelPlugin() {} /// \brief Load function /// /// Called when a Plugin is first created, and after the World has been /// loaded. This function should not be blocking. /// \param[in] _model Pointer to the Model /// \param[in] _sdf Pointer to the SDF element of the plugin. public: virtual void Load(physics::ModelPtr _model, sdf::ElementPtr _sdf) = 0; /// \brief Override this method for custom plugin initialization behavior. public: virtual void Init() {} /// \brief Override this method for custom plugin reset behavior. public: virtual void Reset() {} }; /// \class SensorPlugin Plugin.hh common/common.hh /// \brief A plugin with access to physics::Sensor. See /// reference. class SensorPlugin : public PluginT { /// \brief Constructor public: SensorPlugin() {this->type = SENSOR_PLUGIN;} /// \brief Destructor public: virtual ~SensorPlugin() {} /// \brief Load function /// /// Called when a Plugin is first created, and after the World has been /// loaded. This function should not be blocking. /// \param[in] _sensor Pointer the Sensor. /// \param[in] _sdf Pointer the the SDF element of the plugin. public: virtual void Load(sensors::SensorPtr _sensor, sdf::ElementPtr _sdf) = 0; /// \brief Override this method for custom plugin initialization behavior. public: virtual void Init() {} /// \brief Override this method for custom plugin reset behavior. public: virtual void Reset() {} }; /// \brief A plugin loaded within the gzserver on startup. See /// reference /// @todo how to make doxygen reference to the file gazebo.cc#g_plugins? class SystemPlugin : public PluginT { /// \brief Constructor public: SystemPlugin() {this->type = SYSTEM_PLUGIN;} /// \brief Destructor public: virtual ~SystemPlugin() {} /// \brief Load function /// /// Called before Gazebo is loaded. Must not block. /// \param _argc Number of command line arguments. /// \param _argv Array of command line arguments. public: virtual void Load(int _argc = 0, char **_argv = NULL) = 0; /// \brief Initialize the plugin /// /// Called after Gazebo has been loaded. Must not block. public: virtual void Init() {} /// \brief Override this method for custom plugin reset behavior. public: virtual void Reset() {} }; /// \brief A plugin loaded within the gzserver on startup. See /// reference. class VisualPlugin : public PluginT { public: VisualPlugin() {this->type = VISUAL_PLUGIN;} /// \brief Load function /// /// Called when a Plugin is first created, and after the World has been /// loaded. This function should not be blocking. /// \param[in] _visual Pointer the Visual Object. /// \param[in] _sdf Pointer the the SDF element of the plugin. public: virtual void Load(rendering::VisualPtr _visual, sdf::ElementPtr _sdf) = 0; /// \brief Initialize the plugin /// /// Called after Gazebo has been loaded. Must not block. public: virtual void Init() {} /// \brief Override this method for custom plugin reset behavior. public: virtual void Reset() {} }; /// \} /// \brief Plugin registration function for model plugin. Part of the shared /// object interface. This function is called when loading the shared library /// to add the plugin to the registered list. /// \return the name of the registered plugin #define GZ_REGISTER_MODEL_PLUGIN(classname) \ extern "C" GZ_COMMON_VISIBLE gazebo::ModelPlugin *RegisterPlugin(); \ gazebo::ModelPlugin *RegisterPlugin() \ {\ return new classname();\ } /// \brief Plugin registration function for world plugin. Part of the shared /// object interface. This function is called when loading the shared library /// to add the plugin to the registered list. /// \return the name of the registered plugin #define GZ_REGISTER_WORLD_PLUGIN(classname) \ extern "C" GZ_COMMON_VISIBLE gazebo::WorldPlugin *RegisterPlugin(); \ gazebo::WorldPlugin *RegisterPlugin() \ {\ return new classname();\ } /// \brief Plugin registration function for sensors. Part of the shared object /// interface. This function is called when loading the shared library to add /// the plugin to the registered list. /// \return the name of the registered plugin #define GZ_REGISTER_SENSOR_PLUGIN(classname) \ extern "C" GZ_COMMON_VISIBLE gazebo::SensorPlugin *RegisterPlugin(); \ gazebo::SensorPlugin *RegisterPlugin() \ {\ return new classname();\ } /// \brief Plugin registration function for system plugin. Part of the /// shared object interface. This function is called when loading the shared /// library to add the plugin to the registered list. /// \return the name of the registered plugin #define GZ_REGISTER_SYSTEM_PLUGIN(classname) \ extern "C" GZ_COMMON_VISIBLE gazebo::SystemPlugin *RegisterPlugin(); \ GZ_COMMON_VISIBLE \ gazebo::SystemPlugin *RegisterPlugin() \ {\ return new classname();\ } /// \brief Plugin registration function for visual plugin. Part of the /// shared object interface. This function is called when loading the shared /// library to add the plugin to the registered list. /// \return the name of the registered plugin #define GZ_REGISTER_VISUAL_PLUGIN(classname) \ extern "C" GZ_COMMON_VISIBLE gazebo::VisualPlugin *RegisterPlugin(); \ gazebo::VisualPlugin *RegisterPlugin() \ {\ return new classname();\ } } #endif