1、前言
为什么要用库文件?大家写代码要用printf函数,包含stdio.h就可以用了,这就是调用了C库中的函数,比较通用的东西可以制作成库给大家使用。还有项目开发的时候,尤其是跨公司合作开发,源码不能随便给,我就把我的代码模块制作成库文件给你,你的代码加载我的库文件就可以生成方便调试你代码的应用程序。
2、静态编译
静态编译是把库文件合并进应用程序,好处就是换个设备可以直接运行,不和动态库一样还得将应用程序和库文件同时移动到新设备才能用。
2.1 编译静态库
mylib.c中保存下面的简单代码,提供了一个打印函数:
#include <stdio.h>
#include "mylib.h"
void LibTest()
{
printf("Exe LibTest In mylib.c\n");
}
对应的mylib.h文件如下:
#ifndef __MY_LIB_H__
#define __MY_LIB_H__
extern void LibTest(void);
#endif
将该.c文件编译为.o文件,执行命令:
gcc -c mylib.c -o mylib.o
编译生成静态库文件,执行命令:
ar -r libmylib.a mylib.o
其中-r表示创建新的库文件mylib.a并将mylib.o添加进去
2.2 使用静态库
在main.c文件中调用静态库文件中的代码:
#include <stdio.h>
#include "mylib.h"
int main()
{
LibTest();
return 0;
}
编译可执行程序:
gcc -o app main.c -L ./ -lmylib -static
其中,-L指定静态库的路径 -l指定静态库的名称,此处libmylib不需要加前面的lib,-static指定静态编译。
编译完成的app程序可以直接手动发起运行,运行结果如下:
3、动态编译
动态库在程序运行的时候实时加载,不需要编译进应用程序,这样做的好处是减少应用程序的体积,坏处就是移动程序的时候需要对应移动动态库。
3.1 编译动态库
还使用上面的代码,执行以下命令生成动态库文件:
gcc mylib.c -fPIC -shared -o libmylib.so
其中-fPIC表示生成位置无关代码,-shared表示生成动态库文件
3.2 使用动态库
将动态库拷贝至/usr/lib:
cp libmylib.so /usr/lib
编译可执行程序:
gcc -o appDT main.c -L. -lmylib
编译出来的程序直接运行即可,考虑访问库文件的权限,加sudo运行:
3.3 体积比较
对比编译静态库的可执行程序和动态库的可执行程序大小,可以验证前面的说法:
3.4 动态库的动态加载使用
动态加载调用代码如下:
#include <stdio.h>
#include <dlfcn.h>
typedef void (*pJustPtf)(void);
int main()
{
void * handle = NULL;
pJustPtf ptf = NULL;
// 打开当前目录下的so库文件
handle = dlopen ("./libmylib.so", RTLD_LAZY);
if(handle != NULL)
{
// 从库文件中查找LibTest函数
ptf = dlsym(handle, "LibTest");
// 调用LibTest函数
ptf();
}
return 0;
}
使用以下命令编译可执行程序:
gcc main.c -o app123 -ldl
直接运行即可: