Общая библиотека, как сделать ссылку на символ?
У меня есть: car.cc
#include "car.h"
#include <iostream>
using namespace std;
extern "C" Car* create_object()
{
return new Car;
}
Car::Car() {
this->maxGear = 2;
this->currentGear = 1;
this->speed = 0;
}
void Car::shift(int gear) {
if (gear < 1 || gear > maxGear) {
return;
}
currentGear = gear;
}
void Car::brake() {
speed -= (5 * this->getCurrentGear());
std::cout<<"THE SPEED IS:" <<speed<<std::endl;
}
extern "C" void destroy_object( Car* object )
{
delete object;
}
car.h
#ifndef VEHICLES_CAR_H
#define VEHICLES_CAR_H
// A very simple car class
class Car {
public:
Car();
void shift(int gear);
void accelerate();
void brake();
private:
int maxGear;
int currentGear;
int speed;
};
#endif /* VEHICLES_CAR_H */
test.cc
#include "/home/car.h"
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int main()
{
/* on Linux, use "./myclass.so" */
void* handle = dlopen("/usr/lib/libCarTest.so", RTLD_LAZY);
int (*result)(int);
if (!handle)
{
}
/*dlsym(handle,"accelerate");
cout<<"IN HERE: "<<endl;
dlsym(handle,"brake");
dlclose(handle);*/
Car* (*create)();
void (*destroy)(Car*);
dlerror();
create = (Car* (*)())dlsym(handle, "create_object");
destroy = (void (*)(Car*))dlsym(handle, "destroy_object");
Car* carr = (Car*)create();
carr->brake();
destroy( carr );
dlclose(handle);
/*
Car carr;
carr.brake();
* compilation g++ test.cpp -o tst /path/libcar.so
*/
return 0;
}
После создания libMyLib.so
и установить его в /usr/lib
я попытался скомпилировать test.cc с помощью: g++ test.cc -o tst -ldl
, ПОЧЕМУ мне нужно включить -lMyLib?
Есть ли способ скомпилировать код без libMyLib.so
? Во вторых почему dlsym(handle,"brake")
не работает? Если я изменю dlsym (Автомобиль * (*).... с dlsym(handle,"brake")
я ничего не получаю Зачем?
понимать
1 ответ
ПОЧЕМУ мне нужно включить -lMyLib?
Потому что вам нужно ссылку на Car::brake
метод.
Во-вторых, почему не работает dlsym(ручка,"тормоз")?
Потому что нет brake
условное обозначение. Метод Car::brake
имеет сложное искаженное (определяемое реализацией) имя. Вы можете увидеть это в выводе nm -D
,
AFAIK, вы можете решить это
- делая все методы
Car
виртуальный (они будут вызываться через указатель, поэтому связывание не потребуется) - делать это по-старому, т.е. экспортировать бесплатную функцию
brake()
что бы назватьCar::brake
метод из.so - делая все публичные методы
Car
inline
и определяя их в шапке. - эмуляция подхода виртуальной таблицы (как мы делаем это в C)
Сочетание последних двух подходов:
class Car {
public:
void brake() { brake_impl(this); }
private:
void (*brake_impl)(Car*);
void do_brake(); // this would be the actual implementation
Car() : brake_impl([] (Car* c){ c->do_brake(); }) { ... }
};
Конечно, вы можете разделить реализацию и интерфейс, чтобы не было такой путаницы.