【问题标题】:Overloading of functions in C++ code when using extern "C"使用 extern "C" 时 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() 等)。

标签: c++ inheritance virtual-functions


【解决方案1】:

问题不是extern "C"。问题是你有多个相同函数的定义。

Base * create()Base * create() 无法区分

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-15
      • 1970-01-01
      • 2014-12-21
      • 1970-01-01
      • 1970-01-01
      • 2016-08-15
      • 1970-01-01
      • 2014-12-24
      相关资源
      最近更新 更多