使用 extern "C" 时 C++ 代码中的函数重载

Overloading of functions in C++ code when using extern "C"

我想在 运行 时间加载库。我有一个基础 class“Base”和两个派生的 classes“Derived1”和“Derived2”,它们应该在 运行 时加载。我正在使用 this answer 中的方法并进行一些小的修改。当我只定义一个派生 class 时,代码可以完美编译,但是当定义了多个派生 class 时,代码将无法编译。编译错误如下:

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;
}

问题不在于extern "C"。问题是您对 同一个 函数有多个定义。

Base * create()Base * create()

没有区别

您要做的是在两个不同的可加载模块中具有相同的功能。但是您正在做的是将此函数的两个实现(具有相同的名称和签名!)放入主模块,这当然会导致多重定义错误。

您应该做的是将 create 函数放入 *.cpp 文件,即 derived1.cppderived2.cpp,从 *.hpp 中省略它们的定义] 文件,并从这些 *.cpp 文件编译共享对象。我修改了您的项目以实现此目的,请参阅 live demo