目录
对于一个dll.cpp内容如下:
定义2个函数。我们只用到了add函数。
int add(int a,int b){
{
return a+b;
}}
int subtract(int a,int b)
{
return a-b;
}
一、生成 .a
将dll.cpp编译成dll.o
再将dll.o生成libadd.a
gcc -c dll.cpp
ar -rc libadd.a dll.o
二、生成 .so
生成 libadd.so
gcc -shared -o libadd.so dll.cpp
三、调用.a
main.cpp 内容如下:
#include <stdio.h>
//using namespace std;
int add(int a,int b);//函数声明一般应放在dll.h中 然后#include <dll.h>
int subtract(int a,int b);//函数声明同上
int main()
{
int a=20;
int b=10;
printf("%d+%d=%d\n",a, b, add(a,b));
//cout<<"a + b = "<<add(a,b)<<endl;
//cout<<"a - b = "<<subtract(a,b)<<endl;
return 0;
}
gcc -o main main.cpp -static -ladd
不加-static, 这个命令默认会优先使用动态库。加-static强制链接静态库。
四、调用.so
1.隐式调用
main.cpp如上所述,调用.so生成程序的命令如下:
gcc -o main main.cpp -ladd
此命令会生成main程序。 ldd main查看依赖的so,可以看到 libadd.so
[root@app1 so]# ldd main
linux-vdso.so.1 => (0x00007fff2bfd6000)
libadd.so (0x00007f739ef4c000)
libc.so.6 => /lib64/libc.so.6 (0x00007f739eb7f000)
/lib64/ld-linux-x86-64.so.2 (0x00007f739f14e000)
2.显式调用
显示调用是通过系统函数dlopen() 、dlsym(),等直接获取函数指针进行调用。
这里注意dlsym(handle, "_Z3addii")函数中,"_Z3addii"是dll.cpp中add 函数名称被 mangling(名称混淆)后的结果。如果想不被混淆,请加extern "C",如下:
extern "C"
{
int add(int a,int b)
{
return a+b;
}
}
main_load.cpp内容如下:
#include <stdio.h>
#include <dlfcn.h>//dlopen所在的头文件
int main()
{
typedef int (*AddProc)(int,int);
AddProc Add;
AddProc pt_str;
//int (*pt_str)(int, int);
/*加载库*/
void *handle = dlopen("./libadd.so", RTLD_LAZY);
if(!handle)
{
printf("dlopen error!\n");
return 1;
}
pt_str = (AddProc) dlsym(handle, "_Z3addii");
if(!pt_str)
{
printf("动态连接库库函数未找到\n");
return 1;
}
int a=20;
int b=10;
printf("%d+%d=%d\n",a, b, pt_str(a,b));;
/*卸载库*/
dlclose(handle);
return 0;
}
编译命令:
gcc -o main_load main_load.cpp -ldl
记得把系统库libdl.so带上。