1.GCC编译理论介绍
gcc完成编译需要四部:预处理、编译、汇编、链接。
阶段一预处理:gcc -E test.c -o test.i
阶段二编译: gcc -S test.i -o test.S
阶段三汇编: gcc -c test.S -o test.o
阶段四链接: gcc test.o -o test
在linux中,静态库文件为.a文件 动态库文件为.so文件(与windows中的lib静态库 与dll动态库类似),.a文件为静态链接,在编译的第四阶段一块链接进入主程序,如果静态库改变,则需要一起重新编译;动态库是在执行的时候通过符号表动态链接,动态库改变,接口不变的前提下,则无需重新编译主程序。
2.linux静态库的制作与使用
//file list
add.c add.h test.c
//add.c
#include "add.h"
int add(int a,int b)
{
printf("*************add**************\n");
return (a+b);
}
//add.h
#include <stdio.h>
int add(int a,int b);
//test.c
#include <stdio.h>
#include "add.h"
int main(int argc,char *argv[])
{
#if 1
int a = 0,b = 1,sum;
//sum = a+b;
sum = add(a,b);
printf("%s sum = %d\n",__FUNCTION__,sum);
#endif
return 0;
}
制作静态库,生成可执行文件
gcc -c add.c -o add.o
ar rc libmyadd.a *.o
gcc test.c libmyadd.a
生成文件
add.c add.h add.o a.out libmyadd.a test.c
//执行结果
*************add**************
main sum = 1
静态库其实是由.o文件生成的,可以使用binutils工具readelf、objdump等工具查看.a文件。
readelf -a libmyadd.a
objdump -S libmyadd.a
3.linux动态库的制作与使用
制作动态库,生成可执行文件
gcc -c -fPIC add.c
gcc -shared -fPIC -o libmyadd.so add.o
cp libmyadd.so /usr/lib/libmyadd.so
//默认从usr/lib路径进行查找so文件
gcc -o test test.c -L. -lmyadd
生成文件
add.c add.h add.o libmyadd.so test test.c
//执行结果
*************add**************
main sum = 1
静态库可以隐藏源代码,提高编译的速度,这个.a已经经过了编译汇编的过程。;
动态库同样也可以使用binutils工具进行查看
readelf -a libmyadd.so
objdump -S libmyadd.so
另:
一般在做大型项目时候,会分为多个团队进行负责,会或多或少的使用静态库和动态库。
静态库使用:为隐藏源代码、架构清晰代码分离会考虑使用静态库libtest.a,一般为多个libtest1.a libtest2.a等;
动态库使用:为节省内存等考量会考虑使用动态库libtest.so,一般为多个libtest1.so libtest2.so等,在使用到此模块的时候才会进行加载,不使用便可以进行释放;一般使用
dlopen dlclose进行实现。
4.项目中实际应用动态库
add.c add.h test1.c
//test1.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#define LIB_MYADD_PATH "/usr/lib/libmyadd.so" //为动态库的文件路径
typedef int(*ADD_FUNC)(int,int);
int main(int argv,char *argc[])
{
void* handle;
char *error;
ADD_FUNC add_func=NULL;
//dlopen
handle = dlopen(LIB_MYADD_PATH,RTLD_LAZY);
if(!handle)
{
fprintf(stderr,"%s\n",dlerror());
exit(EXIT_FAILURE);
}
fprintf(stderr,"%s\n",dlerror());
*(void**)(&add_func) = dlsym(handle,"add");
if((error = dlerror())!=NULL)
{
fprintf(stderr,"%s\n",dlerror());
exit(EXIT_FAILURE);
}
printf("add: %d\n",(*add_func)(1,2));
//dlclose
dlclose(handle);
exit(EXIT_SUCCESS);
}
制作动态库,生成可执行文件
gcc -shared -fPIC -o libmyadd.so add.o
cp libmyadd.so /usr/lib/libmyadd.so
gcc -rdynamic -o test1 test1.c -ldl
生成文件
add.c add.h add.o libmyadd.so test1 test1.c
执行结果与上面是一样的;