Наверняка, все знают чем отличается динамические библиотеки от статических. Но всё же я повторю. Когда вы используете статические библиотеки, их код внедряется в программный код вашей программы на этапе компиляции. Когда же вы используете динамические библиотеки, то их загрузка происходит уже после запуска приложения.
Что нам даст такой подход? А то, что наша программа сможет быть динамически расширяемой. А это даёт неограниченные возможности в масштабировании приложения. К тому же, если приложение большое и тяжелое, это позволит разгрузить его. У модульного программирования много преимуществ, не буду про это писать, а расскажу о своём примере.
Итак, мы создадим 2 библиотеки:
- одна будет содержать обычную функцию, при вызове которой мы будем получать текст в stdoutput;
- другая будет содержать класс, который содержит функцию на подобие той, что описана Выше.
Далее, мы создадим программу, подгружающую эти библиотеки и вызывающую функции из них.
Для начала, создадим файл test.cpp с следующим содержанием:
#include <iostream>
//Наша функция, которую мы будем запускать из нашего приложения.
extern "C" void test() {
std::cout << "This message from test.so function test" << std::endl;
}
Теперь скомпилируем это всё в библиотеку g++ -shared -o test.so test.cppНа выходе получаем test.so Теперь проверим есть ли у нашей библиотеки доступные функции. Воспользуемся командой nm, которая не заменима при работе с библиотеками или объектниками, выполним:
nm test.soВывод будет следующего вида:
Большая буква "T" напротив имени функции test, означает что она объявлена в текстовой области. Это как раз то, что нужно нам.
Дальше начнём создавать наш класс TestClass
header:
#ifndef TEST_CLASS_HPP
#define TEST_CLASS_HPP
#include <iostream>
class Test_Class{
public:
Test_Class(){};
~Test_Class(){};
virtual void test_func();
};
//Определяем тип класса
typedef Test_Class* new_class_t();
typedef void delete_class_t();
#endif
source: #include "test_class.h"
void Test_Class::test_func() {
std::cout << "This message from test.so class Test_Class function test" << std::endl;
}
//Внешняя функция создания класса
extern "C" Test_Class* new_class() {
return new Test_Class;
}
//Внешняя функция удаления класса
extern "C" void delete_class(Test_Class* temp) {
delete temp;
}
Скомпилируем:g++ -shared -o test_class.so test_class.cpp
Так, вроде всё готово, осталось создать саму программу, которая будет всем этим пользоваться.
main.cpp:
#include <iostream>
#include <dlfcn.h>
#include "test_class.h"
int open_function()
{
//Открываем динамическую библиотеку
void* handle = dlopen("./test.so", RTLD_LAZY);
//Проверяем на ошибки
if (!handle) {
std::cerr << dlerror() << std::endl;;
return 1;
}
//Определяем тип
typedef void (*test_t)();
//Загружаем нужную нам функцию.
test_t test = (test_t) dlsym(handle, "test");
//Проверяем на ошибки
if (dlerror()) {
std::cerr << dlerror() << std::endl;
dlclose(handle);
return 1;
}
//Исполняем функцию из библиотеки
test();
//Закрываем библиотеку
dlclose(handle);
return 0;
}
int open_class_function()
{
//Открываем динамическую библиотеку с классом
void *handle_c = dlopen("./test_class.so", RTLD_LAZY);
//Проверяем на ошибки
if (!handle_c) {
std::cerr << dlerror() << std::endl;;
return 1;
}
//Загружаем фукнции по созданию класса.
new_class_t* new_class = (new_class_t*) dlsym(handle_c, "new_class");
delete_class_t* delete_class = (delete_class_t*) dlsym(handle_c, "delete_class");
//Проверяем на ошибки
if (!new_class || !delete_class) {
std::cerr << dlerror() << std::endl;
return 1;
}
//Создаём класс
Test_Class* test_class = new_class();
//Исполняем функцию из класса
test_class->test_func();
//Удаляем класс
delete_class();
//Закрываем библиотеку
dlclose(handle_c);
//Выходим
}
int main() {
if(open_function() == 1) std::cout << "open_function missed" << std::endl;
if(open_class_function()==1) std::cout << "open_class_function missed" << std::endl;
return 0;
}
Компилируем g++ -o dlopen_example main.cpp -ldlВсё осталось только запустить и убедиться, что всё действительно работает!
Удачного Вам освоения dlopen!
sources




Комментариев нет:
Отправить комментарий