pxmlw6n2f/Gazebo_Distributed_TCP/gazebo/common/Plugin.hh

415 lines
13 KiB
C++

/*
* 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 <Winsock2.h>
#endif
#ifndef _WIN32
#include <unistd.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <gazebo/gazebo_config.h>
#include <dlfcn.h>
#include <list>
#include <string>
#include <sdf/sdf.hh>
#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 T>
class PluginT
{
/// \brief plugin pointer type definition
public: typedef boost::shared_ptr<T> 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<std::string>::iterator iter;
std::list<std::string> 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
/// <a href="http://gazebosim.org/tutorials/?tut=plugins_world
/// &cat=write_plugin">reference</a>.
class WorldPlugin : public PluginT<WorldPlugin>
{
/// \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
/// <a href="http://gazebosim.org/tutorials?tut=plugins_model
/// &cat=write_plugin">reference</a>.
class ModelPlugin : public PluginT<ModelPlugin>
{
/// \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
/// <a href="http://gazebosim.org/tutorials?tut=plugins_hello_world
/// &cat=write_plugin">reference</a>.
class SensorPlugin : public PluginT<SensorPlugin>
{
/// \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
/// <a href="http://gazebosim.org/tutorials?tut=system_plugin
/// &cat=write_plugin">reference</a>
/// @todo how to make doxygen reference to the file gazebo.cc#g_plugins?
class SystemPlugin : public PluginT<SystemPlugin>
{
/// \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
/// <a href="http://gazebosim.org/tutorials?tut=plugins_hello_world
/// &cat=write_plugin">reference</a>.
class VisualPlugin : public PluginT<VisualPlugin>
{
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