dlopen系列函数
包含的头文件:
#include <dlfcn.h>
使用的函数有以下4个:
1) void * dlopen( const char * pathname, int mode)
参数pathname: 动态库so名称;
参数mode: 打开方式,有以下选项
RTLD_DEEPBIND -- 动态库里的函数优先调用本动态库的符号,优先级甚至高于LD_PRELOAD
RTLD_LAZY -- 等有需要时才解析出符号,所以如果有未定义的符号,在没调用之前也不执行解析
RTLD_NOW -- 在dlopen返回前,解析出所有的未定义符号,如果解析不出来,返回NULL
RTLD_GLOBAL 动态库中符号表全局打开,因此符号可被其后打开的其它库重定位
RTLD_LOCAL 与RTLD_GLOBAL作用相反,动态库中符号表非全局打开,定义的符号不能被其后打开的其它库重定位
返回值:
打开错误返回NULL
成功,返回库引用
2) void* dlsym(void* handle,const char* symbol)
参数handle: 动态库应用或者RTLD_NEXT(在当前库之后load进来的动态库中寻找第一次出现的符号)
参数symbol: 符号名称
返回值:符号函数指针
3) int dlclose (void *handle)
关闭指定句柄的动态链接库
4) char* dlerror();
返回值:返回加载失败的报错信息
实例:
plugin.h头文件中定义接口
#ifndef __PLUGIN_H__ #define __PLUGIN_H__ #include "stdio.h" class IPlugin { public: virtual void print()=0; }; #endif
main.cpp
#include "plugin.h" #include <dlfcn.h> #include <stdlib.h> #include <stdio.h> typedef IPlugin* (*func)(); int main() { void* handle = dlopen("/home/hongrui/work/dlopen/libplugin.so", RTLD_NOW); if (!handle) { printf("dlopen:%s\n",dlerror()); return -1; } func getInterface = (func)dlsym(handle, "getInterface"); if (getInterface == NULL) { printf("dlsym:%s\n", dlerror()); return -1; } IPlugin* plugin = getInterface(); plugin->print();
dlclose(handle); return 0; }
编译main.cpp 生成可执行文件
g++ main.cpp -o main -ldl
plugin.cpp是动态库cpp
#include "plugin.h" #include "stdio.h" class CPlugin : public IPlugin { public: CPlugin() {} virtual ~CPlugin(){} virtual void print() { printf("this is plugin\n"); } }; extern "C" __attribute__ ((visibility("default"))) IPlugin* getInterface() { return new CPlugin; }
编译plguin.cpp生成动态库libplugin.so
g++ -fvisibility=hidden -fpic -shared plugin.cpp -o libplugin.so -ldl
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现