在c++中使用动态类加载时的链接器错误

Linker error while working with dynamic class loading in C++

本文关键字:链接 错误 类加载 动态 c++      更新时间:2023-10-16

我正在尝试动态加载类到我的代码。在Polygon.hpp中,我有类声明,在triangle.cpp中有定义。我生成了一个三角形。我在main.cpp中包含了Polygon.hpp。此外,我试图创建一个多边形对象的矢量,但在矢量期间。Push_back链接器抛出"未定义引用"错误。如果我把向量注释掉。一切都很好。我知道我创建了一个矢量多边形*并使用它,但这在我的情况下是不可能的,因为这会导致现有遗留代码的变化,这是不可取的。我能不能用这个方法。下面是代码:

Polygon.hpp

#ifndef POLYGON_HPP                                                          
#define POLYGON_HPP                                                          
class polygon {
protected:
    double side_length_;
public:
    polygon()
       : side_length_(0) {}
 virtual ~polygon(){}
 void set_side_length(double side_length) {
    side_length_ = side_length;
 }
 polygon (const polygon &obj);
 virtual double area();
};
// the types of the class factories                                          
typedef polygon* create_t();
typedef void destroy_t(polygon*);
#endif

triangle.cpp

#include "polygon.hpp"
#include <cmath>
double polygon::area() {
    return side_length_ * side_length_ * sqrt(3) / 2;
}
polygon::polygon(const polygon &obj)
{
    this->side_length_ = obj.side_length_;
}

// the class factories                                                             
extern "C" polygon* create() {
   return new polygon;
}
extern "C" void destroy(polygon* p) {
  delete p;
}

编译和生成。so:

g++ -fPIC -c traingle.cpp
g++ -shared -o traingle.so traingle.o

main.cpp

#include "polygon.hpp"
#include <iostream>
#include <vector>
#include <dlfcn.h>
using namespace std;
int main() {
using std::cout;
using std::cerr;
vector<polygon> t;   //creating a vector of polygon
// load the triangle library                                             
void* triangle = dlopen("./triangle.so", RTLD_LAZY);
if (!triangle) {
    cerr << "Cannot load library: " << dlerror() << 'n';
    return 1;
}
// reset errors                                                          
dlerror();
// load the symbols                                                      
create_t* create_triangle = (create_t*) dlsym(triangle, "create");
const char* dlsym_error = dlerror();
if (dlsym_error) {
    cerr << "Cannot load symbol create: " << dlsym_error << 'n';
    return 1;
}
destroy_t* destroy_triangle = (destroy_t*) dlsym(triangle, "destroy");
dlsym_error = dlerror();
if (dlsym_error) {
    cerr << "Cannot load symbol destroy: " << dlsym_error << 'n';
    return 1;
}
// create an instance of the class                                       
polygon* poly = create_triangle();
t.push_back(*poly);  //---> this is where the linking error is happening
// use the class                                                         
poly->set_side_length(7);
    cout << "The area is: " << poly->area() << 'n';
// destroy the class                                                     
destroy_triangle(poly);
// unload the triangle library                                           
dlclose(triangle);
}
编译:

$ g++ -std=c++11 main.cpp -ldl
/tmp/cc4RdzvX.o: In function `void   __gnu_cxx::new_allocator<polygon>::construct<polygon, polygon const&>(polygon*,  polygon const&)':
main.cpp: (.text._ZN9__gnu_cxx13new_allocatorI7polygonE9constructIS1_JRKS1_EEEvPT_DpOT0_[_ZN9__gnu_cxx13new_allocatorI7polygonE9constructIS1_JRKS1_EEEvPT_DpOT0_]+0x48): undefined reference to `polygon::polygon(polygon const&)'
/tmp/cc4RdzvX.o: In function `void std::_Construct<polygon, polygon&>(polygon*, polygon&)':
main.cpp:(.text._ZSt10_ConstructI7polygonJRS0_EEvPT_DpOT0_[_ZSt10_ConstructI7polygonJRS0_EEvPT_DpOT0_]+0x44): undefined reference to `polygon::polygon(polygon const&)'
collect2: error: ld returned 1 exit status

您在main.cpp中定义了vector<polygon> t;,这将使其链接到polygon的ctor/dtor,这是链接错误。

解决方法:

  1. 要么跟随@robert的回答直接链接polygon.cpp
  2. 或者避免在main.cpp中使用polygon的完整类型。

所以你应该定义vector<polygon*> t;,并将polygon*推入/弹出向量。

当你从向量弹出时,你不应该忘记调用destroy_triangle(),否则你会有内存泄漏

编译triangle.cpp: g++ -std=c++11 main.cpp triangle.cpp -ldl。或者,如果您想使用共享库,请将-ltriangle添加到命令中。