Загрузка таких файлов с помощью dlsym не может загрузить библиотеку

Я реализую API, который загружает плагины из файлов .so. Для их загрузки я использую функцию dlsym(). Чтобы проверить, работает ли это, я внедрил тестовый плагин (ниже) и, чтобы упростить задачу, я загружаю только функцию «инициализировать». Чтобы скомпилировать свой код, я сначала создаю файл .so с помощью следующей команды:

      g++ -Wall -shared -rdynamic -fPIC plugin_test.cpp -o plugin_test.so

После этого я запускаю plugin_manager.cpp следующим образом:

      g++ plugin_manager.cpp -o -plugin_manager.o -ldl

Но после запуска a.out и ввода правильного имени файла я получаю сообщение об ошибке, что не могу загрузить файл .so. Кто-нибудь знает, как решить эту проблему?

plugin_manager.cpp

      #include <dlfcn.h>
      #include <stdio.h>
      #include <stdlib.h>
      #include <string>
      #include <iostream>
      #include "plugin_interface.h"
      using namespace std;
      //typedef void (*test_function)(void);

      int main(void) {
       const char *error;
       void *module;
       //test_function initialize_test;
       //void (*initialize_test) (void);
       //test_function analyze_test;
       //test_function finalize_test;
       //load the DL library
       string filename;
       cout << "File :: " << endl;
       cin >> filename;
       module = dlopen(filename.c_str(), RTLD_LAZY);
       if (!module) {
           fprintf(stderr, "ERROR! Couldn't load library: %s\n",
           dlerror());
           exit(1);
       }

        //get and check symbol
        dlerror();
        initialize_f* initialize_function = (initialize_f*) dlsym(module, "initialize");
        if ((error = dlerror())) {
        fprintf(stderr, "ERROR %s\n", error);
        exit(1);
        }

        //create instance of the class
        PluginInterface* plugin = initialize_function();

        //use the class
        plugin->initialize();
        //call "initialize" function from the test plug-in
        //(*initialize_test)();

        dlclose(module); //close the DL library
        return 0;
        }

plugin_interface.h

    #ifndef PLUGIN_INTERFACE_H_INCLUDED
    #define PLUGIN_INTERFACE_H_INCLUDED

    class PluginInterface{

    public:
        virtual void initialize() = 0;
        virtual void analyze() = 0;
        virtual void finalize() = 0;
    };

    //Definition of the pointer
    typedef PluginInterface* initialize_f();
    #endif // PLUGIN_INTERFACE_H_INCLUDED

test_plugin.cpp

         #include <iostream>
         #include "plugin_interface.h"
         using namespace std;

         class bbb :public PluginInterface {
           public:

         virtual void initialize(){
         cout << "Initialization";
         }

         void analyze(){
         cout << "Analysis";
         } 
         void finalize(){
         cout << "Finalization";
         }

         };

         //The functions we load must be qualified as extern "C" to avoid the symbol name being mangled
         extern "C" PluginInterface* initialize(){
         return new bbb();
         }
         int main()
         {


         //bbb* a = maker();
         //a->initialize();
         //Creating an instance and calling the "initialize" function with in
         PluginInterface* p = initialize();
         p->initialize(); 


         return 0;
         }

person bl618515    schedule 17.07.2014    source источник
comment
Вы пробовали полный путь или используете относительный путь.   -  person cup    schedule 17.07.2014
comment
Ага, пробовал оба. Мне также не удалось скомпилировать пример 2. Я думаю, что я не использую правильные команды   -  person bl618515    schedule 17.07.2014
comment
Как вы компилируете? Как вы тестируете?   -  person Basile Starynkevitch    schedule 17.07.2014
comment
Файл находится в вашей LD_LIBRARY_PATH?   -  person cup    schedule 17.07.2014
comment
Я написал команды, которые я использую выше. Сначала я создаю .so, затем запускаю plugin_manager.   -  person bl618515    schedule 17.07.2014
comment
Что вы имеете в виду под этим @cup? Жаль, что у меня мало опыта.   -  person bl618515    schedule 17.07.2014
comment
Как говорит @Basile Starynkevitch, добавьте файл . в конец вашего LD_LIBRARY_PATH, т.е. из строки cmd, экспортируйте LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH   -  person cup    schedule 17.07.2014
comment
@cup: добавление . перед перед LD_LIBRARY_PATH представляет собой огромный риск для безопасности ...., его следует по крайней мере поставить в конце LD_LIBRARY_PATH   -  person Basile Starynkevitch    schedule 17.07.2014
comment
Проблема решена, я забыл один / в пути к файлу. Спасибо ребята!   -  person bl618515    schedule 17.07.2014


Ответы (1)


Прочитайте внимательно и несколько раз dlopen(3) справочная страница.

Когда путь к файлу не содержит /, происходит определенная обработка.

Вы должны dlopen указать путь, например ./foo.so (в противном случае добавьте . в конец вашей переменной окружения LD_LIBRARY_PATH, но это может создать угрозу безопасности, поэтому я не советую этого делать)

(всегда проверяйте результат NULL вызовами функций dlopen и dlsym и отображайте dlerror() в случае ошибки)

Кстати, ваш менеджер плагинов должен быть скомпилирован с:

      g++ -Wall -g plugin_manager.cpp -o -plugin_manager -ldl

Не упоминайте plugin_manager.o

person Basile Starynkevitch    schedule 17.07.2014
comment
Спасибо за подсказку, но я попробовал и таким образом, и получил тот же результат. Даже с полным путем к файлу это не сработало. На самом деле я попытался запустить код примера 2 из здесь и получил ту же ошибку - person bl618515; 17.07.2014
comment
Проблема решена, я забыл один / в пути к файлу. Спасибо ребята! - person bl618515; 17.07.2014