예제 #1
0
// 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;
}