ARGoS
3
A parallel, multi-engine simulator for swarm robotics
|
00001 00007 #include "dynamic_loading.h" 00008 00009 #include <dirent.h> 00010 #include <cerrno> 00011 00012 namespace argos { 00013 00014 /****************************************/ 00015 /****************************************/ 00016 00017 CDynamicLoading::TDLHandleMap CDynamicLoading::m_tOpenLibs; 00018 const std::string CDynamicLoading::DEFAULT_PLUGIN_PATH = ARGOS_INSTALL_PREFIX "/lib/argos3/"; 00019 00020 /****************************************/ 00021 /****************************************/ 00022 00023 CDynamicLoading::TDLHandle CDynamicLoading::LoadLibrary(const std::string& str_lib) { 00024 TDLHandle tHandle; 00025 /* Check if the provided path is absolute or relative */ 00026 if(str_lib[0] == '/') { 00027 /* 00028 * Absolute path 00029 */ 00030 /* First check if the library is already loaded */ 00031 TDLHandleMap::iterator it = m_tOpenLibs.find(str_lib); 00032 if(it != m_tOpenLibs.end()) { 00033 /* Already loaded */ 00034 return m_tOpenLibs[str_lib]; 00035 } 00036 /* Not already loaded, load the library and bomb out in case of failure */ 00037 tHandle = ::dlopen(str_lib.c_str(), RTLD_LAZY); 00038 if(tHandle == NULL) { 00039 THROW_ARGOSEXCEPTION("Can't load library \"" 00040 << str_lib 00041 << "\", " 00042 << ::dlerror()); 00043 } 00044 /* Store the handle to the loaded library */ 00045 m_tOpenLibs[str_lib] = tHandle; 00046 return tHandle; 00047 } 00048 else { 00049 /* 00050 * Relative path, go through the plugin directories 00051 */ 00052 /* String to store the full path to a library */ 00053 std::string strLibPath; 00054 /* String to store the list of paths to search */ 00055 std::string strPluginPath = ".:" + DEFAULT_PLUGIN_PATH; 00056 /* Get variable ARGOS_PLUGIN_PATH from the environment */ 00057 if(::getenv("ARGOS_PLUGIN_PATH") != NULL) { 00058 /* Add value of the variable to list of paths to check */ 00059 strPluginPath += ":" + std::string(::getenv("ARGOS_PLUGIN_PATH")); 00060 } 00061 /* Add : at the end to make parsing easier */ 00062 if(strPluginPath[strPluginPath.length()-1] != ':') { 00063 strPluginPath.append(":"); 00064 } 00065 /* 00066 * Go through paths and try to load the library 00067 */ 00068 /* Parse the string */ 00069 std::istringstream issPluginPath(strPluginPath); 00070 std::string strDir; 00071 while(std::getline(issPluginPath, strDir, ':')) { 00072 /* Add '/' to dir if missing */ 00073 if(strDir[strDir.length()-1] != '/') { 00074 strDir.append("/"); 00075 } 00076 strLibPath = strDir + str_lib; 00077 /* First check if the library is already loaded */ 00078 TDLHandleMap::iterator it = m_tOpenLibs.find(strLibPath); 00079 if(it != m_tOpenLibs.end()) { 00080 /* Already loaded */ 00081 return m_tOpenLibs[strLibPath]; 00082 } 00083 /* Not already loaded, try and load the library */ 00084 tHandle = ::dlopen(strLibPath.c_str(), RTLD_LAZY); 00085 if(tHandle != NULL) { 00086 /* Store the handle to the loaded library */ 00087 m_tOpenLibs[strLibPath] = tHandle; 00088 return tHandle; 00089 } 00090 else { 00091 LOGERR << ::dlerror() 00092 << std::endl; 00093 } 00094 } 00095 /* If we get here, it's because no directory worked */ 00096 THROW_ARGOSEXCEPTION("Can't load library \"" 00097 << str_lib 00098 << "\"."); 00099 } 00100 } 00101 00102 /****************************************/ 00103 /****************************************/ 00104 00105 void CDynamicLoading::UnloadLibrary(const std::string& str_lib) { 00106 TDLHandleMap::iterator it = m_tOpenLibs.find(str_lib); 00107 if(it != m_tOpenLibs.end()) { 00108 UnloadLibrary(it->second); 00109 } 00110 else { 00111 THROW_ARGOSEXCEPTION("Can't load library \"" 00112 << str_lib 00113 << "\": library does not appear to have been loaded."); 00114 } 00115 } 00116 00117 /****************************************/ 00118 /****************************************/ 00119 00120 void CDynamicLoading::UnloadLibrary(TDLHandle t_lib) { 00121 ::dlclose(t_lib); 00122 } 00123 00124 /****************************************/ 00125 /****************************************/ 00126 00127 void CDynamicLoading::LoadAllLibraries() { 00128 /* String to store the full path to a library */ 00129 std::string strLibPath; 00130 /* String to store the list of paths to search */ 00131 std::string strPluginPath = DEFAULT_PLUGIN_PATH; 00132 /* Get variable ARGOS_PLUGIN_PATH from the environment */ 00133 if(::getenv("ARGOS_PLUGIN_PATH") != NULL) { 00134 /* Add value of the variable to list of paths to check */ 00135 strPluginPath += ":" + std::string(::getenv("ARGOS_PLUGIN_PATH")); 00136 } 00137 /* Add : at the end to make parsing easier */ 00138 if(strPluginPath[strPluginPath.length()-1] != ':') { 00139 strPluginPath.append(":"); 00140 } 00141 /* 00142 * Go through paths and load all the libraries 00143 */ 00144 /* Directory info */ 00145 DIR* ptDir; 00146 struct dirent* ptDirData; 00147 /* Parse the string */ 00148 std::istringstream issPluginPath(strPluginPath); 00149 std::string strDir; 00150 while(std::getline(issPluginPath, strDir, ':')) { 00151 /* Add '/' to dir if missing */ 00152 if(strDir[strDir.length()-1] != '/') { 00153 strDir.append("/"); 00154 } 00155 /* Try to open the directory */ 00156 ptDir = ::opendir(strDir.c_str()); 00157 if(ptDir != NULL) { 00158 /* Directory open, now go through the files in the directory */ 00159 while((ptDirData = ::readdir(ptDir)) != NULL) { 00160 /* We have a file, check that it is a library file */ 00161 if(std::string(ptDirData->d_name).rfind("." ARGOS_SHARED_LIBRARY_EXTENSION) != std::string::npos) { 00162 /* It's a library file, load it */ 00163 LoadLibrary(strDir + ptDirData->d_name); 00164 } 00165 if(std::string(ARGOS_SHARED_LIBRARY_EXTENSION) != std::string(ARGOS_MODULE_LIBRARY_EXTENSION)) { 00166 if(std::string(ptDirData->d_name).rfind("." ARGOS_MODULE_LIBRARY_EXTENSION) != std::string::npos) { 00167 /* It's a library file, load it */ 00168 LoadLibrary(strDir + ptDirData->d_name); 00169 } 00170 } 00171 } 00172 /* Close directory */ 00173 ::closedir(ptDir); 00174 } 00175 else { 00176 /* Error opening directory open, inform user without bombing out */ 00177 LOGERR << "[WARNING] Error opening directory \"" 00178 << strDir 00179 << "\": " 00180 << ::strerror(errno) 00181 << std::endl; 00182 } 00183 } 00184 } 00185 00186 /****************************************/ 00187 /****************************************/ 00188 00189 void CDynamicLoading::UnloadAllLibraries() { 00190 for(TDLHandleMap::iterator it = m_tOpenLibs.begin(); 00191 it != m_tOpenLibs.end(); 00192 ++it) { 00193 UnloadLibrary(it->second); 00194 } 00195 } 00196 00197 /****************************************/ 00198 /****************************************/ 00199 00200 }