我正在尝试实现类似于此处描述的设计:
http://www.linuxjournal.com/article/3687

我有一个核心项目,可以将其编译为可执行二进制文件。我还希望使用dlopen()在运行时加载共享库。现在,我面临的问题是,在核心项目以及所有已加载的库中应该都知道一些类。我以为我会将它们放到另一个共享库中,该共享库在编译时会链接到所有这些库。一切似乎都可以正常编译,但是在加载共享库ConnectionModule.so时,dlopen不返回句柄,并且dlerror表示“未定义符号:_ZTV17PipelineProcessor”,其中PipelineProcessor是在共享库中定义和实现的类,应该在每个附加的共享库中进行编译。

有没有人知道我的实现有什么问题,或者这种设计注定会失败?

一些代码在这里:

在运行时加载库

#include "../SharedHeaders/SharedInEveryLibrary.h"
// ...
map<string, maker_t*, less<string> > module_library;
// ...
void *hndl = dlopen(library_file_path, RTLD_NOW | RTLD_GLOBAL);
if (hndl == nullptr) {
    Logger::error << "Could not load library " << library_file_name << ": " << dlerror() << endl;
    exit(-1);
}


ConditionModule.h(应在运行时加载)

#pragma once
#include "../SharedHeaders/SharedInEveryLibrary.h"

class ConditionModule : public B {
    public:
        A* processRequest(X* data) override; // implemented at ConditionModule.cpp
};

extern "C" {
    A *maker() {
        return new ConditionModule;
    }
    class proxy {
        public:
            proxy() {
                module_library["condition_module"] = maker;
            }
    };
    proxy p;
}


...当然还有SharedInEveryLibrary.h的某些内容

class Z; // gets implemented later, I guess it's not important

struct X {
    int something;
    // ...
};

class A {
    public:
        virtual void setSomeData(X* v_some_data);
        virtual A* process(Z* data) = 0;
    protected:
        X* some_data;
};

class B : public A {
    public:
        A* process(Z* data) override;
        virtual A* processRequest(X* data) = 0;
};

typedef A* maker_t();
extern map<string, maker_t*, less<string> > module_library;


编辑-----
忘记了,我目前仅使用Linux作为编译目标进行开发。

最佳答案

这种设计没有错。但是,当您使用dlopen()共享库时,所有符号都需要解析。您的错误意味着您没有..的路径,因此您的库依赖于LD_LIBRARY_PATH。要检查它需要什么库,请使用

ldd <your library.so>


将此库所在的目录添加到LD_LIBRARY_PATH。

关于c++ - 无法在运行时加载动态共享库,包括C++中的另一个共享库,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32340236/

10-13 05:53