c ++动态库dlopen错误

时间:2011-06-10 11:14:34

标签: c++ dlopen

我有两个文件: RollDice.cpp

#include "RollDice.h"
#include "./IPlugins.cpp"
#include "./IPluginFunctions.cpp"

#include <iostream>

RollDice::RollDice(IPluginFunctions &iPluginFunctions) :
    IPlugins(iPluginFunctions) {
    //srand(time(NULL));
}

RollDice::~RollDice() {

}

void RollDice::callPlugin(std::string paramsText, std::string dataText) {
    std::cout << "RollDice ;)\n";
}

RollDice.h:

#ifndef ROLLDICE_H_
#define ROLLDICE_H_
#include "./IPlugins.h"
#include "./IPluginFunctions.h"

class RollDice: public IPlugins {
public:
    RollDice(IPluginFunctions &iPluginFunctions);
    virtual ~RollDice();

    virtual void callPlugin(std::string paramsText, std::string dataText);
};

extern "C" RollDice* create(IPluginFunctions &iPluginFunctions) {
    return new RollDice(iPluginFunctions);
}

extern "C" void destroy(RollDice *rollDice) {
    delete rollDice;
}

#endif /* ROLLDICE_H_ */

我使用以下命令创建.so文件: g ++ -shared -o RollDice.so RollDice.cpp

现在在我的应用程序中我想打开这个插件:

this->plugin = dlopen(directory.c_str(), RTLD_LAZY);
    if (!(this->plugin)) {
        std::cerr << "Cannot load library: " << dlerror() << '\n';
        return;
    }

    dlerror();

    this->createPlugin = (create_p*) dlsym(plugin, "create");
    const char* dlsymError = dlerror();
    if (dlsymError) {
        std::cerr << "Cannot load symbol create: " << dlsymError << '\n';
        return;
    }

    this->destroyPlugin = (destroy_p*) dlsym(plugin, "destroy");
    dlsymError = dlerror();
    if (dlsymError) {
        std::cerr << "Cannot load symbol destroy: " << dlsymError << '\n';
        return;
    }

但我收到消息: 无法加载库:./ RodDice.so:无效的ELF标题

你能帮我解决这个问题吗?

-fPIC

无效

编辑:

现在我用插件来构建插件:

g++ -shared -fPIC -o RollDice.so RollDice.h IPlugins.cpp IPluginFunctions.cpp

我有新问题: 无法加载符号create:./ RodDice.so:undefined symbol:create

当我使用nm查看RollDice中的符号时,我看不到“创建”

4 个答案:

答案 0 :(得分:2)

要检查的一件事似乎尚未提及,必须从共享库中导出确切名称“create”。

尝试

nm --dynamic --defined-only RollDice.so | grep create

如果你没有匹配,或者为'create'获得一些错位符号,那么你的dlsym(...,“create”)调用肯定会失败。

此外,一旦解决了名称查找问题,就应该认真考虑将RTLD_GLOBAL添加到dlopen标志中。 dlopen默认为RTLD_LOCAL,它与C ++共享库w.r.t的交互性很差。 RTTI,例外,类型信息等.RTLD_GLOBAL将减少意外。

另请考虑使用RTLD_NOW而不是RTLD_LAZY。如果您的插件库中有符号在dlopen时无法解析,那么您刚刚创建了一个定时炸弹。最好在dlopen时知道库是否能够满足所有必需的参考文献。

编辑:

我忽略了用'nm'检查'create'已经被建议了。然而,dlopen标志建议仍然很重要。

另外,你的编译行看起来很奇怪,特别是你在构建行上包含RollDice.h,而不是RollDice.cpp文件。

此外,在其他.cpp文件中包含.cpp文件不是标准做法。

我建议删除.cpp到.cpp包含,然后用-o分别编译各种.cpp文件,然后将它们合并到共享库中:

g++ -g -fPIC -c -o RollDice.o RollDice.cpp
g++ -g -fPIC -c -o IPluginFunctions.o IPluginFunctions.cpp
g++ -g -fPIC -c -o IPlugins.o IPlugins.cpp
g++ -g -fPIC -shared -o RollDice.so RollDice.o IPluginFunctions.o IPlugins.o

答案 1 :(得分:1)

您没有使用-fPIC构建共享库来生成与位置无关的代码,共享库需要IIRC。

快速谷歌加强了我的预感:http://www.fpx.de/fp/Software/tcl-c++/tcl-c++.html

所以使用:

g++ -shared -fPIC -o RollDice.so RollDice.cpp

看看是否有帮助。

导致错误的另一个原因是当您尝试使用为不同体系结构构建的库(例如ARM,32,64等)时,但我假设您没有构建插件.so in a与编译核心程序的环境不同的环境。

答案 2 :(得分:1)

不确定问题是什么,但readelfobjdump等工具可能会提供有关二进制状态的信息,可帮助您解决问题。

答案 3 :(得分:0)

这里有答案

C++ dlopen mini HOWTO

您遇到类方法签名

的问题