使用 extern "C" 时 C++ 代码中的函数重载
Posted
技术标签:
【中文标题】使用 extern "C" 时 C++ 代码中的函数重载【英文标题】:Overloading of functions in C++ code when using extern "C" 【发布时间】:2020-10-01 10:48:33 【问题描述】:我想在运行时加载库。我有一个基类“Base”和两个派生类“Derived1”和“Derived2”,它们应该在运行时加载。我正在使用来自this answer 的方法,并进行了一些小的修改。当我只定义一个派生类时,代码编译得很好,但是当定义了几个派生类时,它编译失败。编译错误如下:
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;
【问题讨论】:
您在头文件中定义(实现)create
函数。包含此头文件的每个源文件都将具有该定义。如果将头文件包含在两个不同的源文件中,它们都链接到一个库或可执行文件中,则会出现多个定义错误。在头文件中声明函数,并在单个源文件(每个库一个)中定义。
derived1.hpp
包括interface.hpp
。你的意思是base.hpp
?请发布您的实际代码。
如你所说,C 不支持函数重载。您需要为函数的每个变体使用不同的名称(create_Derived1()
、create_Derived2()
等)。
【参考方案1】:
问题不是extern "C"
。问题是你有多个相同函数的定义。
Base * create()
与 Base * create()
无法区分
【讨论】:
【参考方案2】:您要做的是在两个不同的可加载模块中具有相同的功能。但是您正在做的是将此函数的两个实现(具有相同的名称和签名!)放入主模块,这当然会导致多重定义错误。
您应该做的是将create
函数放入*.cpp
文件中,即derived1.cpp
和derived2.cpp
,从*.hpp
文件中省略它们的定义,并从这些@987654327 中编译共享对象@ 文件。我已修改您的项目以实现此目的,请参阅live demo。
【讨论】:
以上是关于使用 extern "C" 时 C++ 代码中的函数重载的主要内容,如果未能解决你的问题,请参考以下文章