vector — ошибка компоновщика при работе с динамической загрузкой класса в Stack Overflow

Я пытаюсь загрузить класс динамически в мой код. В Polygon.hpp у меня есть объявление класса, а в triangle.cpp есть определение. Я сгенерировал triangle.so.
Я включил Polygon.hpp в мой main.cpp. Также я пытаюсь создать вектор объекта многоугольника, но во время работы vector.push_back компоновщик выдает ошибку «неопределенная ссылка». Если я закомментирую vector.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

0

Решение

Вы определили vector<polygon> t; в main.cpp, который сделает это, чтобы связать с polygonэто ctor / dtor, это ошибка ссылки.

Чтобы решить проблему:

  1. Либо следуйте ответу @ Роберта, чтобы напрямую связаться polygon.cpp
  2. Или избегайте использования полного типа polygon в вашем main.cpp,

Так что вы должны определить vector<polygon*> t; вместо этого, и нажмите / поп polygon* в / из вектора.

И не стоит забывать звонить destroy_triangle() когда вы всплываете из вектора, в противном случае у вас утечка памяти.

1

Другие решения

Скомпилируйте triangle.cppтоже: g++ -std=c++11 main.cpp triangle.cpp -ldl,
Или, если вы хотите использовать общую библиотеку добавить -ltriangle к вашей команде.

1

По вопросам рекламы [email protected]