当前位置:网站首页>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 :

边栏推荐
- 从零开始的基于百度大脑EasyData的多人协同数据标注
- The network card fails to start after the cold migration of the server hard disk
- pytorch 载入历史模型时更换gpu卡号,map_location设置
- Richview trvstyle liststyle list style (bullet number)
- IBEM mathematical formula detection data set
- KEIL5出现中文字体乱码的解决方法
- 3D视觉——2.人体姿态估计(Pose Estimation)入门——OpenPose含安装、编译、使用(单帧、实时视频)
- IBEM 数学公式检测数据集
- Depth and breadth first traversal of tree (regardless of binary tree)
- Comprehensive case of MySQL data addition, deletion, modification and query
猜你喜欢

Richview trvstyle liststyle list style (bullet number)

Go: send the get request and parse the return JSON (go1.16.4)

使用Tensorflow进行完整的深度神经网络CNN训练完成图片识别案例2

Qt学习19 Qt 中的标准对话框(上)

Several common optimization methods matlab principle and depth analysis

解决MySql 1045 Access denied for user ‘root‘@‘localhost‘ (using password: YES)

Resource Cost Optimization Practice of R & D team

【BW16 应用篇】安信可BW16模组与开发板更新固件烧录说明

Flutter动态化 | Fair 2.5.0 新版本特性

物联网毕设 --(STM32f407连接云平台检测数据)
随机推荐
Qt学习24 布局管理器(三)
Field problems in MySQL
There is nothing new under the sun. Can the meta universe go higher?
MyCms 自媒体商城 v3.4.1 发布,使用手册更新
IBEM mathematical formula detection data set
The latest BSC can pay dividends. Any B usdt Shib eth dividend destruction marketing can
The shadow of the object at the edge of the untiy world flickers, and the shadow of the object near the far point is normal
Common network state detection and analysis tools
ThreadPoolExecutor realizes multi-threaded concurrency and obtains the return value (elegant and concise way)
【BW16 应用篇】安信可BW16模组与开发板更新固件烧录说明
TensorBoard可视化处理案例简析
Replace the GPU card number when pytorch loads the historical model, map_ Location settings
Error handling when adding files to SVN:.... \conf\svnserve conf:12: Option expected
Go language unit test 4: go language uses gomonkey to test functions or methods
SQL Injection (GET/Search)
SQL Injection (GET/Select)
Golang — template
Mobile phones and computers can be used, whole people, spoof code connections, "won't you Baidu for a while" teach you to use Baidu
Shell timing script, starting from 0, CSV format data is regularly imported into PostgreSQL database shell script example
使用vscode查看Hex或UTF-8编码