【问题标题】:Loading so files with dlsym, cannot load library使用 dlsym 加载 so 文件,无法加载库
【发布时间】:2014-07-17 13:20:14
【问题描述】:

我正在实现一个从 .so 文件加载插件的 API。要加载它们,我正在使用 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;
         }

【问题讨论】:

  • 您尝试过完整路径名还是使用相对路径名。
  • 是的,两个都试过了。我也未能编译Example 2。我想我没有使用正确的命令
  • 如何编译?你是怎么测试的?
  • 文件是否存在于您的 LD_LIBRARY_PATH 中?
  • 正如@Basile Starynkevitch 所说,添加一个 .到 LD_LIBRARY_PATH 的末尾,即从 cmd 行,导出 LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

标签: c++ plugins shared-libraries dlsym


【解决方案1】:

仔细阅读 并多次阅读 dlopen(3) 手册页。

当文件路径不包含任何/ 时,会发生一些特定的处理。

你应该dlopen 一个类似./foo.so 的路径(否则在LD_LIBRARY_PATH 环境变量的末尾添加.,但这可能会带来安全风险,所以我不建议这样做)

(始终针对NULL 测试dlopendlsym 函数调用的结果,并在失败时显示dlerror()

顺便说一句,你的插件管理器应该编译为:

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

别提plugin_manager.o

【讨论】:

  • 感谢您的提示,但我也尝试过这种方式,并得到了相同的结果。即使使用完整的文件路径,它也无法正常工作。我实际上尝试从 here 运行示例 2 代码并得到相同的错误
  • 问题解决了,我忘记了文件路径中有一个“/”。谢谢大家!
猜你喜欢
  • 1970-01-01
  • 2014-01-21
  • 2018-05-10
  • 1970-01-01
  • 2017-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多