linux的动态链接库的调用
基本同windows,但后缀名格式为.so,具体主要代码如下:
隐式调用:
需要h和so,添加路径等。
生成动态链接库的文件:
testso.h:
void func(); //若为c++工程,需加extern "C"
testso.c:
#include"testso.h"
#include<stdio.h>
void func(){
printf("im a so");
}
编译成动态链接库:
生成的so文件名字格式为:lib名字.so
-fPIC:编译选项,用于生成与路径无关的代码。
-shared:链接选项,用于生成动态库而不是可执行文件
调用着main.c:
#include"testso.h" //需引用头文件
#include<stdio.h>
void main(){
func();
}
编译执行程序:
-L加依赖的so所在目录,.表示当前目录
-l加依赖的so名字,默认lib+名字+.so为so文件名字
此步执行不当会报错:
还要在shell里执行如下命令告诉so文件位置:
此步执行不当会报错:
注:./或.均可,都表示当前目录
因为链接器ld默认的目录是/lib和/usr/lib,如果放在其他路径也可以,需要让ld知道库文件在哪里。
方法:
1,临时使用,方法如上,关闭当前shell后自动取消设定:
shell里执行:
export LD_LIBRARY_PATH=so所在路径
2,永久使用,重启计算机依旧可以使用:
在/etc/ld.so.conf.d/下创建*.conf文件
在文件中键入/opt/lib
命令行键入sudo ldconfig
3,编译时直接写清动态库所在地址:
gcc main.c -L . -lxxx -Wl,rpath=./
执行成功:
linux的ldd命令只能查看到程序隐式调用的动态链接库,看不到显示链接的动态链接库。
显式调用:
仅需so,且不需要添加路径等。执行程序要引用头文件#include"dlfcn.h"。
动态连接库内:
#include<stdio.h>
void func(){
printf("im a so");
}
编译成动态链接库:
gcc -shared -fPIC testso.c -o test.so
引用文件内主要流程:
#include<stdio.h>
#include"dlfcn.h"
void main(){
typedef void (*PLUGIN_CREATE)(); //定义函数指针
PLUGIN_CREATE CreateProc;
void* hinstLib = dlopen("./test.so", RTLD_LAZY); //打开so文件
if(hinstLib == NULL )
{
printf("Failed load library\n");
return -1;
}
CreateProc = (PLUGIN_CREATE)dlsym(hinstLib, "func"); //根据函数名获取so文件里的函数`在这里插入代码片`
if(CreateProc != NULL)
{
printf("Failed load function\n");
return -1;
}
CreateProc();
dlclose(hinstLib); //使用完毕,取消映射
}
编译:
gcc main.c -ldl -o main
//-ldl表示程序使用了动态链接库
注: 同windows,若想在有新的的so增加时,完全不需要改动代码,即插件化编程。就需要读取so所在的目录:
DIR *dir = opendir("路径");
然后循环读取路径下的所有so:
vector<string> vstrPluginNames;
for(;;)
{
struct dirent *pentry = readdir(dir);
if(pentry == 0)
break;
if(strcmp(pentry->d_name, ".") == 0)
continue;
if(strcmp(pentry->d_name, "..") == 0)
continue;
string str = "./alcohol-plugin/";
str += pentry->d_name;
vstrPluginNames.push_back(str);
}
之后就可以从vstrPluginNames内取出所有的so文件。
注: 动态链接库中隐式调用动态链接库:
a中打印im a,b中调用a后再打印and im b,mian调用b
#include"dlfcn.h"
#include<stdio.h>
#include"test.h"
void main(){
void (*PLUGIN_CREATE)();
void* hinstLib = dlopen("./test.so", RTLD_LAZY); //打开so文件
if(hinstLib == NULL )
{
printf(“Failed load library\n”);
return -1;
}
PLUGIN_CREATE = dlsym(hinstLib, “func”); //根据函数名获取so文件里的函数在这里插入代码片
(*PLUGIN_CREATE)();
dlclose(hinstLib); //使用完毕,取消映射
}