当前位置:网站首页>Dlopen() implements dynamic loading of third-party libraries
Dlopen() implements dynamic loading of third-party libraries
2022-07-03 13:53:00 【yolo_ yyh】
Catalog
One 、 Function introduction
Dynamic loading is also called runtime loading , That is, we can decide when to load the specified module when the program is running . In this way, only the necessary modules are loaded when the process starts , Reduced memory usage , Besides, the biggest advantage is , It can be realized without restarting the program , Reload the module . This technology is also called “ Hot update ”.
Let's first look at the function prototype and functions :
// Open the dynamic link library file in the specified mode , And return the handle
void *dlopen(const char *filename, int flags);
// Get the address of the symbol in the shared object or executable file through the handle
void *dlsym(void *handle, const char *symbol);
// Uninstall the open library
int dlclose(void *handle);A simple example to achieve dlopen The dynamic loading function of :
libcaculator.so The main methods of dynamic library are as follows :
int add(int a,int b)
{
return (a + b);
}
int sub(int a, int b)
{
return (a - b);
}
int mul(int a, int b)
{
return (a * b);
}
int div(int a, int b)
{
return (a / b);
}Compile and package commands :
gcc -fPIC -shared caculatoe.cc -o libcaculator.so
And then in demo.cc Use in dlopen Open the dynamic library and call the related functions
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
// DLL path
#define LIB_CACULATE_PATH "./libcaculator.so"
// A function pointer
typedef int (*CAC_FUNC)(int, int);
int main()
{
void *handle;
char *error;
CAC_FUNC cac_func = NULL;
// Open the DLL
handle = dlopen(LIB_CACULATE_PATH, RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
// Clear previous errors
dlerror();
// Get a function
*(void **) (&cac_func) = dlsym(handle, "add");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
exit(EXIT_FAILURE);
}
printf("add: %d\n", (*cac_func)(2,7));
cac_func = (CAC_FUNC)dlsym(handle, "sub");
printf("sub: %d\n", cac_func(9,2));
cac_func = (CAC_FUNC)dlsym(handle, "mul");
printf("mul: %d\n", cac_func(3,2));
cac_func = (CAC_FUNC)dlsym(handle, "div");
printf("div: %d\n", cac_func(8,2));
// Close DLL
dlclose(handle);
exit(EXIT_SUCCESS);
}Compile command :
gcc demo.cc -o demo -ldl
Need links dl library
Compiler error :
./libcaculator.so: undefined symbol: add
use nm see libcaculator.so The generated symbols are as follows :
0000000000004020 b completed.8060
w __cxa_finalize
0000000000001040 t deregister_tm_clones
00000000000010b0 t __do_global_dtors_aux
0000000000003e88 d __do_global_dtors_aux_fini_array_entry
0000000000004018 d __dso_handle
0000000000003e90 d _DYNAMIC
0000000000001158 t _fini
00000000000010f0 t frame_dummy
0000000000003e80 d __frame_dummy_init_array_entry
0000000000002118 r __FRAME_END__
0000000000004000 d _GLOBAL_OFFSET_TABLE_
w __gmon_start__
0000000000002000 r __GNU_EH_FRAME_HDR
0000000000001000 t _init
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
0000000000001070 t register_tm_clones
0000000000004020 d __TMC_END__
00000000000010f9 T _Z3addii
000000000000113e T _Z3divii
0000000000001127 T _Z3mulii
0000000000001111 T _Z3subiiYou can see add Method was renamed by the compiler to _Z3addii, This is because C++ Code at compile time , The compiler does special processing , To support function overloading , The function will be renamed .
The solution is to use extern C, Let the compiler C Language approach to code .
modify caculator.cc The documents are as follows :
#ifdef __cplusplus
extern "C" {
#endif
int add(int a,int b)
{
return (a + b);
}
int sub(int a, int b)
{
return (a - b);
}
int mul(int a, int b)
{
return (a * b);
}
int dv(int a, int b)
{
return (a / b);
}
#ifdef __cplusplus
}
#endifThen recompile and run demo that will do

Two 、 Achieve hot update
Modify the file implementation again
demo.h The code is as follows :
#ifndef DEMO_H
#define DEMO_H
#include <stdio.h>
// #include <stdlib.h>
#include <dlfcn.h>
// DLL path
#define LIB_CACULATE_PATH "./libcaculator.so"
// A function pointer
typedef int (*CAC_FUNC)(int, int);
void test(int x);
#endifdemo.cc as follows :
#include "demo.h"
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <thread>
#include <atomic>
void *handle;
std::thread th;
std::atomic<int> flag(0);
std::atomic<bool> start(false);
int hash_load = 0;
void test (int x) {
printf("%d\n", x);
}
void load() {
char *error;
CAC_FUNC cac_func = NULL;
struct stat attr;
time_t start_time;
while(start) {
if (stat(LIB_CACULATE_PATH, &attr) == 0 && attr.st_ino != -1) {
if (attr.st_mtim.tv_sec != start_time && flag == 1) {
printf("start time: %ld, last_time:%ld\n", start_time, attr.st_mtim.tv_sec);
printf("need to close first\n");
start_time = attr.st_mtim.tv_sec;
flag = 0;
dlclose(handle);
}
if (!flag) {
printf("need to open\n");
// Open the DLL
handle = dlopen(LIB_CACULATE_PATH, RTLD_LAZY);
if (!handle) {
// fprintf(stderr, "%s\n", dlerror());
printf("%s\n", dlerror());
continue;
}
// Clear previous errors
start_time = attr.st_mtim.tv_sec;
dlerror();
flag = 1;
// Get a function
*(void **) (&cac_func) = dlsym(handle, "add");
if ((error = dlerror()) != NULL) {
printf("%s\n", error);
continue;
}
printf("add: %d\n", (*cac_func)(2,7));
}
}
sleep(1);
}
return ;
}
void toload() {
start = true;
th = std::thread(load);
}
void tounload() {
start = false;
th.join();
printf("unload \n");
dlclose(handle);
}
int main()
{
toload();
sleep(10);
tounload();
return 0;
}
It's time to rerun demo The executable of , Then modify and recompile libcaculator.so That is to say libcaculator.so Hot update of , The operation results are as follows :

边栏推荐
- NFT新的契机,多媒体NFT聚合平台OKALEIDO即将上线
- 解决MySql 1045 Access denied for user ‘root‘@‘localhost‘ (using password: YES)
- The network card fails to start after the cold migration of the server hard disk
- GoLand 2021.1: rename the go project
- Go language web development series 29: Gin framework uses gin contrib / sessions library to manage sessions (based on cookies)
- Unity embeddedbrowser browser plug-in event communication
- MySQL 数据处理值增删改
- Heap structure and heap sort heapify
- 【被动收入如何挣个一百万】
- JSON serialization case summary
猜你喜欢

Go language unit test 5: go language uses go sqlmock and Gorm to do database query mock

Go language unit test 3: go language uses gocovey library to do unit test

Setting up remote links to MySQL on Linux

MyCms 自媒体商城 v3.4.1 发布,使用手册更新

掌握Cypress命令行选项,是真正掌握Cypress的基础

RichView TRVStyle ListStyle 列表样式(项目符号编号)

常见的几种最优化方法Matlab原理和深度分析

Ocean CMS vulnerability - search php

MySQL 数据处理值增删改

物联网毕设 --(STM32f407连接云平台检测数据)
随机推荐
SQL Injection (GET/Search)
Summary of common error reporting problems and positioning methods of thrift
MySQL installation, uninstallation, initial password setting and general commands of Linux
Mastering the cypress command line options is the basis for truly mastering cypress
项目协作的进度如何推进| 社区征文
双向链表(我们只需要关注插入和删除函数)
静态链表(数组的下标代替指针)
Go language web development series 27: Gin framework: using gin swagger to implement interface documents
php 迷宫游戏
研发团队资源成本优化实践
Universal dividend source code, supports the dividend of any B on the BSC
Resource Cost Optimization Practice of R & D team
常见的几种最优化方法Matlab原理和深度分析
Qt学习19 Qt 中的标准对话框(上)
Leetcode-1175.Prime Arrangements
Qt学习23 布局管理器(二)
User and group command exercises
The solution of Chinese font garbled code in keil5
顺序表(C语言实现)
Golang — template