Plugin.hh
00001 /*
00002  * Copyright 2011 Nate Koenig & Andrew Howard
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  *
00016 */
00017 #ifndef PLUGIN_HH
00018 #define PLUGIN_HH
00019 
00020 #include <string>
00021 #include <unistd.h>
00022 #include <sys/types.h>
00023 #include <list>
00024 #include <sys/stat.h>
00025 
00026 #include "common/CommonTypes.hh"
00027 #include "common/SystemPaths.hh"
00028 #include "common/Console.hh"
00029 #include "common/Exception.hh"
00030 
00031 #include "physics/PhysicsTypes.hh"
00032 #include "sensors/SensorTypes.hh"
00033 #include "sdf/sdf.h"
00034 
00035 #include "gazebo_config.h"
00036 
00037 #ifdef HAVE_DL
00038 #include <dlfcn.h>
00039 #elif HAVE_LTDL
00040 #include <ltdl.h>
00041 #endif
00042 
00043 
00044 namespace gazebo
00045 {
00046   class Event;
00047 
00050 
00052   template<class T>
00053   class PluginT
00054   {
00055     public: typedef boost::shared_ptr<T> TPtr;
00056 
00058     public: std::string GetFilename() const
00059     {
00060       return this->filename;
00061     }
00062 
00064     public: std::string GetHandle() const
00065     {
00066       return this->handle;
00067     }
00068 
00069     public: static TPtr Create(const std::string &_filename, 
00070                                     const std::string &_handle)
00071     {
00072       TPtr result;
00073       //PluginPtr result;
00074       struct stat st;
00075       bool found = false;
00076       std::string fullname;
00077       std::list<std::string>::iterator iter;
00078       std::list<std::string> pluginPaths= common::SystemPaths::Instance()->GetPluginPaths();
00079     
00080       for (iter=pluginPaths.begin(); iter!=pluginPaths.end(); ++iter)
00081       {
00082         fullname = (*iter)+std::string("/")+_filename;
00083         if (stat(fullname.c_str(), &st) == 0) 
00084         {
00085           found=true; 
00086           break;
00087         }
00088       }
00089     
00090       if (!found) 
00091         fullname = _filename;
00092       std::string registerName = "RegisterPlugin";
00093 
00094     typedef T *(*fptr)();
00095     typedef union
00096     {
00097       fptr func;
00098       void *ptr;
00099     } fptr_union;
00100     fptr_union registerFunc;
00101    
00102     #ifdef HAVE_DL
00103       void* handle = dlopen(fullname.c_str(), RTLD_LAZY|RTLD_GLOBAL);
00104       if (!handle)
00105       {
00106         gzerr << "Failed to load plugin " << fullname << ": " << dlerror() << "\n";
00107         return result;
00108       }
00109 
00110       registerFunc.ptr = dlsym(handle, registerName.c_str());
00111 
00112       if(!registerFunc.ptr)
00113       {
00114         gzerr << "Failed to resolve " << registerName << ": " << dlerror();
00115         return result;
00116       }
00117     
00118       // Register the new controller.
00119       result.reset( registerFunc.func() );
00120     
00121     #elif HAVE_LTDL
00122     
00123       static bool init_done = false;
00124     
00125       if (!init_done)
00126       {
00127         int errors = lt_dlinit();
00128         if (errors)
00129         {
00130           gzerr << "Error(s) initializing dynamic loader (" 
00131             << errors << ", " << lt_dlerror() << ")";
00132           return NULL;
00133         }
00134         else
00135           init_done = true;
00136       }
00137     
00138       lt_dlhandle handle = lt_dlopenext(fullname.c_str());
00139     
00140       if (!handle)
00141       {
00142         gzerr << "Failed to load " << fullname << ": " << lt_dlerror();
00143         return NULL;
00144       }
00145 
00146       T *(*registerFunc)() = (T *(*)())lt_dlsym(handle, registerName.c_str());
00147       resigsterFunc.ptr = lt_dlsym(handle, registerName.c_str());
00148       if(!registerFunc.ptr)
00149       {
00150         gzerr << "Failed to resolve " << registerName << ": " << lt_dlerror();
00151         return NULL;
00152       }
00153     
00154       // Register the new controller.
00155       result.result( registerFunc.func() );
00156     
00157     #else // HAVE_LTDL
00158     
00159       gzthrow("Cannot load plugins as libtool is not installed.");
00160     
00161     #endif // HAVE_LTDL
00162     
00163       result->handle = _handle;
00164       result->filename = _filename;
00165     
00166       return result;
00167     }
00168 
00169     protected: std::string filename;
00170     protected: std::string handle;
00171   };
00172 
00173   class WorldPlugin : public PluginT<WorldPlugin>
00174   {
00176     public: virtual void Load(physics::WorldPtr &_world,
00177                               sdf::ElementPtr &_sdf) = 0;
00178     public: virtual void Init() {};
00179     public: virtual void Reset() {};
00180   };
00181 
00182   class ModelPlugin : public PluginT<ModelPlugin>
00183   {
00185     public: virtual void Load(physics::ModelPtr &_model, 
00186                               sdf::ElementPtr &_sdf ) = 0;
00187     public: virtual void Init() {};
00188     public: virtual void Reset() {};
00189   };
00190 
00191   class SensorPlugin : public PluginT<SensorPlugin>
00192   {
00194     public: virtual void Load(
00195                 sensors::SensorPtr &_sensor, sdf::ElementPtr &_sdf) = 0;
00196     public: virtual void Init() {};
00197     public: virtual void Reset() {};
00198   };
00199 
00200   class SystemPlugin : public PluginT<SystemPlugin>
00201   {
00203     public: virtual void Load() = 0;
00204     public: virtual void Init() {}
00205     public: virtual void Reset() {};
00206   };
00207 
00209 
00210 #define GZ_REGISTER_MODEL_PLUGIN(classname) \
00211 extern "C" gazebo::ModelPlugin *RegisterPlugin(); \
00212 gazebo::ModelPlugin *RegisterPlugin() \
00213 {\
00214   return new classname();\
00215 }
00216 
00217 #define GZ_REGISTER_WORLD_PLUGIN(classname) \
00218 extern "C" gazebo::WorldPlugin *RegisterPlugin(); \
00219 gazebo::WorldPlugin *RegisterPlugin() \
00220 {\
00221   return new classname();\
00222 }
00223 
00224 #define GZ_REGISTER_SENSOR_PLUGIN(classname) \
00225 extern "C" gazebo::SensorPlugin *RegisterPlugin(); \
00226 gazebo::SensorPlugin *RegisterPlugin() \
00227 {\
00228   return new classname();\
00229 }
00230 
00231 #define GZ_REGISTER_SYSTEM_PLUGIN(classname) \
00232 extern "C" gazebo::SystemPlugin *RegisterPlugin(); \
00233 gazebo::SystemPlugin *RegisterPlugin() \
00234 {\
00235   return new classname();\
00236 }
00237 }
00238 #endif