// loads a single component in the current process. bool ComponentLoader::loadInProcess(string file, string libname, bool log_error) { path p(file); char* error; void* handle; bool success=false; // check if the library is already loaded // NOTE if this library has been loaded, you can unload and reload it to apply changes (may be you have updated the dynamic library) // anyway it is safe to do this only if there isn't any isntance whom type was loaded from this library std::vector<LoadedLib>::iterator lib = loadedLibs.begin(); while (lib != loadedLibs.end()) { // there is already a library with the same name if ( lib->shortname == libname) { log(Warning) <<"Library "<< lib->filename <<" already loaded... " ; bool can_unload = true; CompList::iterator cit; for( std::vector<std::string>::iterator ctype = lib->components_type.begin(); ctype != lib->components_type.end() && can_unload; ++ctype) { for ( cit = comps.begin(); cit != comps.end(); ++cit) { if( (*ctype) == cit->second.type ) { // the type of an allocated component was loaded from this library. it might be unsafe to reload the library log(Warning) << "can NOT reload library because of the instance " << cit->second.type <<"::"<<cit->second.instance->getName() <<endlog(); can_unload = false; } } } if( can_unload ) { log(Warning) << "try to RELOAD"<<endlog(); dlclose(lib->handle); // remove the library info from the vector std::vector<LoadedLib>::iterator lib_un = lib; loadedLibs.erase(lib_un); lib = loadedLibs.end(); } else return false; } else lib++; } handle = dlopen ( p.string().c_str(), RTLD_NOW | RTLD_GLOBAL ); if (!handle) { if ( log_error ) { log(Error) << "Could not load library '"<< p.string() <<"':"<<endlog(); log(Error) << dlerror() << endlog(); } return false; } //------------- if you get here, the library has been loaded ------------- log(Debug)<<"Succesfully loaded "<<libname<<endlog(); LoadedLib loading_lib(file, libname, handle); dlerror(); /* Clear any existing error */ // Lookup Component factories (multi component case): FactoryMap* (*getfactory)(void) = 0; vector<string> (*getcomponenttypes)(void) = 0; FactoryMap* fmap = 0; getfactory = (FactoryMap*(*)(void))( dlsym(handle, "getComponentFactoryMap") ); if ((error = dlerror()) == NULL) { // symbol found, register factories... fmap = (*getfactory)(); ComponentFactories::Instance().insert( fmap->begin(), fmap->end() ); log(Info) << "Loaded multi component library '"<< file <<"'"<<endlog(); getcomponenttypes = (vector<string>(*)(void))(dlsym(handle, "getComponentTypeNames")); if ((error = dlerror()) == NULL) { log(Debug) << "Components:"; vector<string> ctypes = getcomponenttypes(); for (vector<string>::iterator it = ctypes.begin(); it != ctypes.end(); ++it) log(Debug) <<" "<< *it; log(Debug) << endlog(); } loadedLibs.push_back(loading_lib); success = true; } // Lookup createComponent (single component case): dlerror(); /* Clear any existing error */ RTT::TaskContext* (*factory)(std::string) = 0; std::string(*tname)(void) = 0; factory = (RTT::TaskContext*(*)(std::string))(dlsym(handle, "createComponent") ); string create_error; error = dlerror(); if (error) create_error = error; tname = (std::string(*)(void))(dlsym(handle, "getComponentType") ); string gettype_error; error = dlerror(); if (error) gettype_error = error; if ( factory && tname ) { std::string cname = (*tname)(); if ( ComponentFactories::Instance().count(cname) == 1 ) { log(Warning) << "Component type name "<<cname<<" already used: overriding."<<endlog(); } ComponentFactories::Instance()[cname] = factory; log(Info) << "Loaded component type '"<< cname <<"'"<<endlog(); loading_lib.components_type.push_back( cname ); loadedLibs.push_back(loading_lib); success = true; } if (success) return true; log(Error) <<"Unloading "<< loading_lib.filename <<": not a valid component library:" <<endlog(); if (!create_error.empty()) log(Error) << " " << create_error << endlog(); if (!gettype_error.empty()) log(Error) << " " << gettype_error << endlog(); dlclose(handle); return false; }