c++动态库dlopen错误

c++ dynamic library dlopen error

本文关键字:错误 dlopen 动态 c++      更新时间:2023-10-16

我有两个文件: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++-共享-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;
    }

但我得到的信息是:无法加载库:/RollDice.so:ELF标头无效

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

-fPIC

对没有帮助

编辑:

现在我正在用构建插件

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

我有了新的问题:无法加载符号创建:/RollDice.so:未定义符号:创建

当我使用CCD_ 2来查看RollDice中的符号时;创建";

需要检查的一件事似乎还没有提到,那就是必须从共享库中导出确切的名称"create"。

尝试

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

如果您没有得到匹配项,或者为"create"得到了一些损坏的符号,那么您的dlsym(…,"create")调用必然会失败。

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

还可以考虑使用RTLD_NOW而不是RTLD_LAZY。如果你的插件库中有一些符号在dlopen时无法解析,那么你只是创建了一个滴答作响的定时炸弹。最好在dlopen时知道库是否能够满足所有必需的引用。

编辑:

我忽略了用"nm"检查"create"的建议。然而,dlopen flags的建议仍然很重要。

此外,您的编译行在我看来非常奇怪,尤其是您在构建行中包含了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

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

快速搜索一下强化了我的直觉:http://www.fpx.de/fp/Software/tcl-c++/tcl-c++.html

所以使用:

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

看看这是否有帮助。

导致这种错误的另一件事是,当你试图使用为不同架构(如ARM、32、64等)构建的库时,但我假设你没有构建插件。因此,在与编译核心程序不同的环境中。

不确定问题出在哪里,但readelf和objdump等工具可能会提供有关二进制状态的信息,帮助您解决问题。

这里有答案

C++dlopen迷你HOWTO

类方法签名有问题