Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00016 #include <iostream>
00017 #include "BodyCustomizerInterface.h"
00018 #include "Body.h"
00019 #include <cstdlib>
00020 #include <map>
00021 #include <boost/version.hpp>
00022 #include <boost/regex.hpp>
00023 #include <boost/tokenizer.hpp>
00024
00025 #if (BOOST_VERSION <= 103301)
00026 #include <boost/filesystem/path.hpp>
00027 #include <boost/filesystem/operations.hpp>
00028 #else
00029 #include <boost/filesystem.hpp>
00030 #endif
00031
00032 using namespace hrp;
00033 using namespace std;
00034 using namespace boost;
00035
00036 namespace {
00037
00038 #ifdef _WIN32
00039 # include <windows.h>
00040 const char* DLLSFX = ".dll";
00041 const char* PATH_DELIMITER = ";";
00042 typedef HINSTANCE DllHandle;
00043 inline DllHandle loadDll(const char* filename) { return LoadLibrary(filename); }
00044 inline void* resolveDllSymbol(DllHandle handle, const char* symbol) { return GetProcAddress(handle, symbol); }
00045 inline void unloadDll(DllHandle handle) { FreeLibrary(handle); }
00046 #else
00047 # include <dlfcn.h>
00048 #ifdef __darwin__
00049 const char* DLLSFX = ".dylib";
00050 #else
00051 const char* DLLSFX = ".so";
00052 #endif
00053 const char* PATH_DELIMITER = ":";
00054 typedef void* DllHandle;
00055 inline DllHandle loadDll(const char* filename) { return dlopen(filename, RTLD_LAZY); }
00056 inline void* resolveDllSymbol(DllHandle handle, const char* symbol) { return dlsym(handle, symbol); }
00057 inline void unloadDll(DllHandle handle) { dlclose(handle); }
00058 #endif
00059
00060 typedef std::map<std::string, BodyCustomizerInterface*> NameToInterfaceMap;
00061 NameToInterfaceMap customizerRepository;
00062 bool pluginLoadingFunctionsCalled = false;
00063
00064 inline string toNativePathString(const filesystem::path& path) {
00065 #if (BOOST_VERSION <= 103301)
00066 return path.native_file_string();
00067 #elif (BOOST_VERSION < 104600)
00068 return path.file_string();
00069 #else
00070 return path.string();
00071 #endif
00072 }
00073
00074 }
00075
00076
00077 static bool checkInterface(BodyCustomizerInterface* customizerInterface)
00078 {
00079 bool qualified = true
00080 && (customizerInterface->version == BODY_CUSTOMIZER_INTERFACE_VERSION)
00081 && customizerInterface->getTargetModelNames
00082 && customizerInterface->create
00083 && customizerInterface->destroy;
00084
00085
00086
00087
00088 return qualified;
00089 }
00090
00091
00092 static bool loadCustomizerDll(BodyInterface* bodyInterface, const std::string filename)
00093 {
00094 BodyCustomizerInterface* customizerInterface = 0;
00095
00096 DllHandle dll = loadDll(filename.c_str());
00097
00098 if(dll){
00099
00100 GetBodyCustomizerInterfaceFunc getCustomizerInterface =
00101 (GetBodyCustomizerInterfaceFunc)resolveDllSymbol(dll, "getHrpBodyCustomizerInterface");
00102
00103 if(!getCustomizerInterface){
00104 unloadDll(dll);
00105 } else {
00106 customizerInterface = getCustomizerInterface(bodyInterface);
00107
00108 if(customizerInterface){
00109
00110 if(!checkInterface(customizerInterface)){
00111 cerr << "Body customizer \"" << filename << "\" is incomatible and cannot be loaded.";
00112 } else {
00113 cerr << "Loading body customizer \"" << filename << "\" for ";
00114
00115 const char** names = customizerInterface->getTargetModelNames();
00116
00117 for(int i=0; names[i]; ++i){
00118 if(i > 0){
00119 cerr << ", ";
00120 }
00121 string name(names[i]);
00122 if(!name.empty()){
00123 customizerRepository[name] = customizerInterface;
00124 }
00125 cerr << names[i];
00126 }
00127 cerr << endl;
00128 }
00129 }
00130 }
00131 }
00132
00133 return (customizerInterface != 0);
00134 }
00135
00136
00147 int hrp::loadBodyCustomizers(const std::string pathString, BodyInterface* bodyInterface)
00148 {
00149 pluginLoadingFunctionsCalled = true;
00150
00151 int numLoaded = 0;
00152 #if (BOOST_VERSION < 104600)
00153 filesystem::path pluginPath(pathString, filesystem::native);
00154
00155 if(filesystem::exists(pluginPath)){
00156
00157 if(!filesystem::is_directory(pluginPath)){
00158 if(loadCustomizerDll(bodyInterface, toNativePathString(pluginPath))){
00159 numLoaded++;
00160 }
00161 } else {
00162 regex pluginNamePattern(string(".+Customizer") + DLLSFX);
00163 filesystem::directory_iterator end;
00164
00165 for(filesystem::directory_iterator it(pluginPath); it != end; ++it){
00166 const filesystem::path& filepath = *it;
00167 if(!filesystem::is_directory(filepath)){
00168 if(regex_match(filepath.leaf(), pluginNamePattern)){
00169 if(loadCustomizerDll(bodyInterface, toNativePathString(filepath))){
00170 numLoaded++;
00171 }
00172 }
00173 }
00174 }
00175 }
00176 }
00177 #elif (BOOST_VERSION >= 105000)
00178 filesystem::path pluginPath(pathString, (void *)filesystem::native);
00179
00180 if(filesystem::exists(pluginPath)){
00181
00182 if(!filesystem::is_directory(pluginPath)){
00183 if(loadCustomizerDll(bodyInterface, toNativePathString(pluginPath))){
00184 numLoaded++;
00185 }
00186 } else {
00187 regex pluginNamePattern(string(".+Customizer") + DLLSFX);
00188 filesystem::directory_iterator end;
00189
00190 for(filesystem::directory_iterator it(pluginPath); it != end; ++it){
00191 const filesystem::path& filepath = *it;
00192 if(!filesystem::is_directory(filepath)){
00193 if(regex_match(filepath.filename().string(), pluginNamePattern)){
00194 if(loadCustomizerDll(bodyInterface, toNativePathString(filepath))){
00195 numLoaded++;
00196 }
00197 }
00198 }
00199 }
00200 }
00201 }
00202 #else
00203 filesystem3::path pluginPath(pathString, (void *)filesystem3::native);
00204
00205 if(filesystem3::exists(pluginPath)){
00206
00207 if(!filesystem3::is_directory(pluginPath)){
00208 if(loadCustomizerDll(bodyInterface, toNativePathString(pluginPath))){
00209 numLoaded++;
00210 }
00211 } else {
00212 regex pluginNamePattern(string(".+Customizer") + DLLSFX);
00213 filesystem3::directory_iterator end;
00214
00215 for(filesystem3::directory_iterator it(pluginPath); it != end; ++it){
00216 const filesystem3::path& filepath = *it;
00217 if(!filesystem3::is_directory(filepath)){
00218 if(regex_match(filepath.filename().string(), pluginNamePattern)){
00219 if(loadCustomizerDll(bodyInterface, toNativePathString(filepath))){
00220 numLoaded++;
00221 }
00222 }
00223 }
00224 }
00225 }
00226 }
00227 #endif
00228 return numLoaded;
00229 }
00230
00231
00232 int hrp::loadBodyCustomizers(const std::string pathString)
00233 {
00234 return loadBodyCustomizers(pathString, Body::bodyInterface());
00235 }
00236
00237
00242 int hrp::loadBodyCustomizers(BodyInterface* bodyInterface)
00243 {
00244 int numLoaded = 0;
00245
00246 if(!pluginLoadingFunctionsCalled){
00247
00248 pluginLoadingFunctionsCalled = true;
00249
00250 char* pathListEnv = getenv("HRPMODEL_CUSTOMIZER_PATH");
00251
00252 if(pathListEnv){
00253 char_separator<char> sep(PATH_DELIMITER);
00254 string pathList(pathListEnv);
00255 tokenizer< char_separator<char> > paths(pathList, sep);
00256 tokenizer< char_separator<char> >::iterator p;
00257 for(p = paths.begin(); p != paths.end(); ++p){
00258 numLoaded = loadBodyCustomizers(*p, bodyInterface);
00259 }
00260 }
00261
00262 #ifndef _WIN32
00263 Dl_info info;
00264 if(dladdr((void*)&hrp::findBodyCustomizer, &info)){
00265 filesystem::path customizerPath =
00266 filesystem::path(info.dli_fname).branch_path().branch_path() / OPENHRP_RELATIVE_SHARE_DIR / "customizer";
00267 numLoaded += loadBodyCustomizers(customizerPath.string(), bodyInterface);
00268 }
00269 #else
00270 string customizerPath(OPENHRP_SHARE_DIR);
00271 customizerPath.append("/customizer");
00272 numLoaded += loadBodyCustomizers(customizerPath, bodyInterface);
00273 #endif
00274
00275 }
00276
00277 return numLoaded;
00278 }
00279
00280
00281 int hrp::loadBodyCustomizers()
00282 {
00283 return loadBodyCustomizers(Body::bodyInterface());
00284 }
00285
00286
00287 BodyCustomizerInterface* hrp::findBodyCustomizer(std::string modelName)
00288 {
00289 BodyCustomizerInterface* customizerInterface = 0;
00290
00291 NameToInterfaceMap::iterator p = customizerRepository.find(modelName);
00292 if(p != customizerRepository.end()){
00293 customizerInterface = p->second;
00294 }
00295
00296 return customizerInterface;
00297 }