我想在运行时加载库。我有一个基类" base“和两个派生类"Derived1”和"Derived2“,它们应该在运行时加载。我使用来自这个答案的方法进行了一些小的修改。当我只定义一个派生类时,代码编译得很完美,但是当定义了几个派生类时,它就无法编译了。编译错误如下:
multiple definitions of 'create'
我认为问题是"C“不允许函数名重载。如何解决这个问题呢?
重要的一点是,由于我不知道存在多少.so
文件,所以我希望为所有.so
文件设置一个处理程序。守则的详情如下:
base.hpp
class Base {
public:
virtual ~Base() {}
virtual void foo() const = 0;
};
using Base_creator_t = Base *(*)();
derived1.hpp
#include "Interface.hpp"
class Derived1: public Base {
public:
void foo() const override {}
};
extern "C" {
Base * create() {
return new Derived1;
}
}
derived2.hpp
#include "Interface.hpp"
class Derived2: public Base {
public:
void foo() const override {}
};
extern "C" {
Base * create() {
return new Derived2;
}
}
动态共享库处理程序:Derived_factory.hpp
#include <dlfcn.h>
class Derived_factory {
public:
Derived_factory(char* path) {
handler = dlopen(path, RTLD_NOW);
if (! handler) {
throw std::runtime_error(dlerror());
}
Reset_dlerror();
creator = reinterpret_cast<Base_creator_t>(dlsym(handler, "create"));
Check_dlerror();
}
std::unique_ptr<Base> create() const {
return std::unique_ptr<Base>(creator());
}
~Derived_factory() {
if (handler) {
dlclose(handler);
}
}
private:
void * handler = nullptr;
Base_creator_t creator = nullptr;
static void Reset_dlerror() {
dlerror();
}
static void Check_dlerror() {
const char * dlsym_error = dlerror();
if (dlsym_error) {
throw std::runtime_error(dlsym_error);
}
}
};
main.cpp
#include "Derived_factory.hpp"
int main(){
Derived_factory factoryOne("Derived1.so");
std::unique_ptr<Base> baseOne = factoryOne.create();
baseOne->foo();
Derived_factory factoryTwo("Derived2.so");
std::unique_ptr<Base> baseTwo = factoryTwo.create();
baseTwo->foo();
return 0;
}
发布于 2020-10-01 04:06:09
您要做的是在两个不同的可加载模块中拥有相同的功能。但是,您所做的是将这两个实现(具有相同的名称和签名!)将此函数转换为主模块,这当然会导致多个定义错误。
您应该做的是将create
函数放入*.cpp
文件中,即derived1.cpp
和derived2.cpp
,从*.hpp
文件中省略它们的定义,并从这些*.cpp
文件编译共享对象。我已经修改了您的项目以实现这一点,请参阅现场演示。
发布于 2020-10-01 02:53:32
问题不是extern "C"
。问题是同一个函数有多个定义。
Base * create()
与Base * create()
是无法区分的
https://stackoverflow.com/questions/64153803
复制相似问题