1.库概述
库可以分为静态库和动态库,静态库编译时必须存在,程序运行时不需要。
动态库也称共享库,其代码不会链接到目标文件之中,只有当动态库可访问时,应用程序才能正确地执行动态库函数。执行动态库有两种方式:隐式调用和显示调用。隐式调用也称共享库的静态加载,动态库函数在应用程序开始执行时会自动载入内存,进程结束时又自动卸载。编译方式与静态库一致。显示调用也称共享库的动态加载,调用时必须遵守dlopen等函数的规则实现调用。
在Unix中,使用ar命令可以创建或操作静态库,其格式为:
ar [drqtpmx] [option] archivefile objfile ….
参数
意义
-r
将objfile文件插入静态库尾或替换静态库中同名文件
-x
从静态库文件中抽取文件objfile
-t
打印静态库的成员文件列表
-d
从静态库文件中删除文件objfile
-s
重置静态库文件索引
-v
创建文件冗余信息
-c
创建静态库文件
例子:抽取静态库/usr/lib/lic.a中的文件
# ar –x /usr/lib/libc.a
例子:组织文件xcvt.o和xstat.o创建静态库libccc.a。
# ar –r libccc.a xcvt.o xstat.o
2. 静态库编程
2.1 设计库源码
/******pr1.c*****/
void pirnt1()
{
printf(“this is the first lib src/n”);
}
/*******pr2.c***********/
void print2()
{
printf(“this is the second lib src/n”);
}
2.2. 编译生成库文件
gcc –O –c pr1.c pr2.c
分别产生pr1.o, pr2.o文件
链接静态库
ar –rsv libpr.a pr1.o pr2.o
2.3 测试程序源码
/********main.c************/
int main()
{
print1();
print2();
}
2.4 编译运行
gcc –O –o main main.c –L./ -lpr
3. 动态库编程
3.1 库源码
/*******pr1.c********/
int p=2;
void print()
{
printf(“This is the first dll src!/n”);
}
/*******pr2.c*********/
int p = 3;
void print()
{
printf(“This is the second dll src!/n”);
}
3.2 编译生成动态库
gcc –O –fpic –shared –o d1.so pr1.c
gcc –O –fpic –shared –o d2.so pr2.c
3.3. 动态库的隐式调用
/*****main.c*****/
int main()
{
print();
}
cp d1.so dll.so 或cp d2.so dll.so
编译:gcc –O –o main main.c ./dll.so
3.4. 动态库的显式调用
#include <dlfcn.h>
int main()
{
void *pHandle;//动态库句柄
void (*pFunc)();//函数指针
int *p;
pHandle = dlopen(“./dll.so”, RTLD_NOW);
if(!pHandle)
{
printf(“Cann’t find dll.so/n”);
return 1;
}
pFunc = (void(*)())dlsym(pHandle, “print”);
if(pFunc)
{
pFunc();
}
else
{
printf(“Can’t find func print/n”);
}
p = (int *)dlsym(pHandle, “p”);
if(p)
{
printf(“p=%d/n”, *p);
}
else
{
printf(“Can’t find int p/n”);
}
dlclose(pHandle);
return 0;
}
不给自己一点轻松的机会,好象世界的每个角落都需要自己的脚去留个痕迹,才叫人生。