在 C++ 中使用动态 class 加载时出现链接器错误
Linker error while working with dynamic class loading in C++
我正在尝试将 class 动态加载到我的代码中。在 Polygon.hpp 中我有 class 声明,在 triangle.cpp 中有定义。我生成了 triangle.so。
我在 main.cpp 中加入了 Polygon.hpp。另外,我正在尝试创建多边形对象的向量,但在 vector.push_back 期间链接器抛出 "undefined reference" 错误。如果我注释掉 vector.push_back 一切正常。我知道我创建了一个向量 Polygon* 并使用它,但在我的情况下这是不可能的,因为这会导致现有遗留代码发生变化,这是不可取的。
有没有办法我可以使用这种方法。
这是代码:
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
将 triangle.cpp
编译为:g++ -std=c++11 main.cpp triangle.cpp -ldl
。
或者,如果您想使用共享库,请将 -ltriangle
添加到您的命令中。
您在 main.cpp
中定义了 vector<polygon> t;
,这将使 link 对抗 polygon
的 ctor/dtor,这就是 link错误。
解决问题:
- 要么直接关注@robert的回答link
polygon.cpp
- 或者避免在
main.cpp
中使用 polygon
的完整类型。
所以你应该定义 vector<polygon*> t;
和 push/pop polygon*
to/from 向量。
并且你不应该忘记在从向量中弹出时调用destroy_triangle()
,否则你会发生内存泄漏。
我正在尝试将 class 动态加载到我的代码中。在 Polygon.hpp 中我有 class 声明,在 triangle.cpp 中有定义。我生成了 triangle.so。 我在 main.cpp 中加入了 Polygon.hpp。另外,我正在尝试创建多边形对象的向量,但在 vector.push_back 期间链接器抛出 "undefined reference" 错误。如果我注释掉 vector.push_back 一切正常。我知道我创建了一个向量 Polygon* 并使用它,但在我的情况下这是不可能的,因为这会导致现有遗留代码发生变化,这是不可取的。 有没有办法我可以使用这种方法。 这是代码:
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
将 triangle.cpp
编译为:g++ -std=c++11 main.cpp triangle.cpp -ldl
。
或者,如果您想使用共享库,请将 -ltriangle
添加到您的命令中。
您在 main.cpp
中定义了 vector<polygon> t;
,这将使 link 对抗 polygon
的 ctor/dtor,这就是 link错误。
解决问题:
- 要么直接关注@robert的回答link
polygon.cpp
- 或者避免在
main.cpp
中使用polygon
的完整类型。
所以你应该定义 vector<polygon*> t;
和 push/pop polygon*
to/from 向量。
并且你不应该忘记在从向量中弹出时调用destroy_triangle()
,否则你会发生内存泄漏。