【问题标题】:How to dlsym load QString Function如何 dlsym 加载 QString 函数
【发布时间】:2015-03-12 04:53:54
【问题描述】:

我正在尝试使用 Qt for linux 系统编写 C++ 工具。我的工具使用共享库 我正在编写一个库来将数据推送到数据库。类似头文件中的方法

QString pushdata(QVariantMap params);

这个函数放入 lib 调用 libpushdata.so。我想加载动态 lib.so 我正在使用 dlfcn.h 和类似的方法:

void *handle;
QString (*pushdata)(QVariantMap*);
handle = dlopen("libpushdata.so", RTLD_LAZY);
if (!handle) {
    fputs(dlerror(), stderr);
    exit(1);
}
pushdata=dlsym(handle,"pushdata");

构建程序时出现错误:

从‘void*’到‘QString()(QVariantMap)的无效转换

我在谷歌上搜索如何使用动态加载库并获得类似here 的指令 和here 任何人都可以告诉我如何在共享库中加载我的方法QString pushdata(QVariantMap params)。我正在使用 EclipseCentos 6.5Qt4.8

【问题讨论】:

    标签: c++ linux qt shared-libraries dynamic-loading


    【解决方案1】:

    您可以使用QLibrary 动态调用函数。以下示例在运行时从共享库调用函数:

    #include <QLibrary>
    #include <QDebug>
    
    typedef QString (*call_func)(QVariantMap* arg1);
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        QLibrary library( "dynamic_library" );
        library.load();
        if( !library.isLoaded() )
        {
            qDebug() << "Cannot load library.";
            return 0;
        }
        call_func func = (call_func)library.resolve( "pushdata" );
        if(func)
        {
            func(variantMap);
        }
    
        return a.exec();
    }
    

    【讨论】:

    • 感谢@Nejat,我尝试了你的方法,仍然得到错误error while loading shared libraries: liblibtest.so: cannot open shared object file: No such file or directory
    • 你把so文件放在可执行文件旁边吗?
    • 您是否将库链接到您的应用程序?或者你想动态加载它?
    • 我也将我的应用程序链接到库,但它仍然错误。当我 cd 到包含应用程序的目录并使用 exprot LD_LIBRARY_PATH=/root/Desktop/loaddl/Debug./application 应用程序正常运行时,调试文件夹包含 lib.so @@ 。所以你能告诉我如何运行应用程序而不使用 exprot LD_LIBRARY_PATH 只使用 ./application 运行
    • 如果您想将库链接到您的应用程序,则无需使用QLibrary。您可以简单地包含头文件并使用类。在这种情况下,只需将 so 文件放在可执行文件旁边,并在您的 pro 文件中添加一些行,以告诉动态链接器在与应用程序相同的目录中查找,请参阅:stackoverflow.com/questions/23896643/…
    【解决方案2】:

    您可以使用 Qt 插件机制,如 answered by Nejat

    如果您坚持只使用dlopen(3)dlsym,请注意:

    • 传递共享库的完整文件路径(例如dlopen("./foo.so", RTLD_NOW)不仅dlopen("foo.so" ...) ...)并始终测试dlopen的成功
    • 当心name mangling,所以在你的插件中将dlsym-ed 函数声明为extern "C"
    • 显式转换结果指针:

      typedef QString pushdata_sig_t(QVariantMap*);
      pushdata_sig_t* pushdata 
        = reinterpret_cast<pushdata_sig_t*>(dlsym(handle,"pushdata"));
      if (!pushdata) 
        { std::cerr << "dlsym failed:" << dlerror ()
                    << std::endl; 
          exit(EXIT_FAILURE); }
      

    至少阅读C++ dlopen mini howto

    【讨论】:

      猜你喜欢
      • 2019-08-17
      • 1970-01-01
      • 1970-01-01
      • 2013-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多