00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "ArExport.h"
00028 #include "ariaOSDef.h"
00029 #ifdef WIN32
00030 #else
00031 #include <dlfcn.h>
00032 #endif
00033 #include "ArModuleLoader.h"
00034 #include "ArModule.h"
00035 #include "ArLog.h"
00036
00037
00038 std::map<std::string, ArModuleLoader::DllRef> ArModuleLoader::ourModMap;
00039
00040
00041 #ifdef WIN32
00042
00043 #define RTLD_NOW 0
00044 #define RTLD_GLOBAL 0
00045
00046 HINSTANCE dlopen(const char *fileName, int flag)
00047 {
00048 return(LoadLibrary(fileName));
00049 }
00050
00051 int dlclose(HINSTANCE handle)
00052 {
00053 FreeLibrary(handle);
00054 return(0);
00055 }
00056
00057 void *dlsym(HINSTANCE handle, char *symbol)
00058 {
00059 return(GetProcAddress(handle, symbol));
00060 }
00061
00062 const char *dlerror(void)
00063 {
00064 return(0);
00065 }
00066 #endif // WIN32
00067
00068
00100 ArModuleLoader::Status ArModuleLoader::load(const char *modName,
00101 ArRobot *robot,
00102 void *modArgument,
00103 bool quiet)
00104 {
00105 std::string name;
00106 std::map<std::string, DllRef>::iterator iter;
00107 DllRef handle;
00108 bool (*func)(ArRobot*,void*);
00109 bool ret;
00110
00111 name=modName;
00112 #ifdef WIN32
00113 if (strstr(modName, ".dll") == 0)
00114 name+=".dll";
00115 #else
00116 if (strstr(modName, ".so") == 0)
00117 name+=".so";
00118 #endif
00119
00120 iter=ourModMap.find(name);
00121 if (iter != ourModMap.end())
00122 return(STATUS_ALREADY_LOADED);
00123
00124 handle=dlopen(name.c_str(), RTLD_NOW | RTLD_GLOBAL);
00125
00126 if (!handle || dlerror() != NULL)
00127 {
00128 if (!quiet)
00129 ArLog::log(ArLog::Terse, "Failure to load module '%s': %s",
00130 name.c_str(), dlerror());
00131 return(STATUS_FAILED_OPEN);
00132 }
00133
00134 func=(bool(*)(ArRobot*,void*))dlsym(handle, "ariaInitModule");
00135 if (!func || dlerror() != NULL)
00136 {
00137 if (!quiet)
00138 ArLog::log(ArLog::Terse, "No module initializer for %s.", modName);
00139 ourModMap.insert(std::map<std::string, DllRef>::value_type(name,
00140 handle));
00141 return(STATUS_SUCCESS);
00142
00143
00144 }
00145 ret=(*func)(robot, modArgument);
00146
00147 if (ret)
00148 {
00149 ourModMap.insert(std::map<std::string, DllRef>::value_type(name,
00150 handle));
00151 return(STATUS_SUCCESS);
00152 }
00153 else
00154 {
00155 if (!quiet)
00156 ArLog::log(ArLog::Terse, "Module '%s' failed its init sequence",
00157 name.c_str());
00158 dlclose(handle);
00159 return(STATUS_INIT_FAILED);
00160 }
00161 }
00162
00163
00169 ArModuleLoader::Status ArModuleLoader::reload(const char *modName,
00170 ArRobot *robot,
00171 void *modArgument,
00172 bool quiet)
00173 {
00174 close(modName, quiet);
00175 return(load(modName, robot, modArgument, quiet));
00176 }
00177
00184 ArModuleLoader::Status ArModuleLoader::close(const char *modName,
00185 bool quiet)
00186 {
00187 std::string name;
00188 std::map<std::string, DllRef>::iterator iter;
00189 bool (*func)();
00190 bool funcRet;
00191 DllRef handle;
00192 Status ret=STATUS_SUCCESS;
00193
00194 name=modName;
00195 #ifdef WIN32
00196 if (strstr(modName, ".dll") == 0)
00197 name+=".dll";
00198 #else
00199 if (strstr(modName, ".so") == 0)
00200 name+=".so";
00201 #endif
00202
00203 iter=ourModMap.find(name.c_str());
00204 if (iter == ourModMap.end())
00205 {
00206 ArLog::log(ArLog::Terse, "Module '%s' could not be found to be closed.",
00207 modName);
00208 return(STATUS_NOT_FOUND);
00209 }
00210 else
00211 {
00212 handle=(*iter).second;
00213 func=(bool(*)())dlsym(handle, "ariaExitModule");
00214 if (!func)
00215 {
00216 if (!quiet)
00217 ArLog::log(ArLog::Verbose,
00218 "Failure to find module exit function for '%s'", (*iter).first.c_str());
00219
00220
00221
00222 ourModMap.erase(name);
00223 return STATUS_SUCCESS;
00224 }
00225 funcRet=(*func)();
00226 if (funcRet)
00227 ret=STATUS_SUCCESS;
00228 else
00229 {
00230 if (!quiet)
00231 ArLog::log(ArLog::Terse, "Module '%s' failed its exit sequence",
00232 modName);
00233 ret=STATUS_INIT_FAILED;
00234 }
00235 dlclose(handle);
00236 ourModMap.erase(name);
00237 }
00238
00239 return(ret);
00240 }
00241
00242 void ArModuleLoader::closeAll()
00243 {
00244 std::map<std::string, DllRef>::iterator iter;
00245
00246 while ((iter = ourModMap.begin()) != ourModMap.end())
00247 close((*iter).first.c_str());
00248
00249
00250 }