动态库*.so在linux下用c和c++编程时经常会碰到,记录一下,以便日后查看。
一、编译动态库
下面通过一个例子来说明如何操作。我们将hello.c编译成libhello.so。hello.c文件定义了一个print函数,该函数使用了可变参数,该函数也是使用可变参数的一个例子。
hello.c:
#include <stdarg.h>
int print(const char *fmt, ...)
{
va_list va;
int ret = 0;
va_start(va, fmt);
ret = vprintf(fmt, va);
va_end(va);
return ret;
}
执行命令:gcc-o libhello.so hello.c -fPIC -shared
然后在当前目录下就可以看到我们要的动态库libhello.so。
如果要使用该动态库有以下几种方法:
1、将该动态库copy到/usr/lib目录下,该目录是动态库的默认路径。
2、在LD_LIBRARY_PATH环境变量中加入该动态库的路径
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:该动态库的绝对路径
3、修改/etc/ld.so.conf文件,把该库所在绝对路径添加到文件末尾,并执行ldconfig刷新。
二、链接动态库
编写main.c程序调用库中的函数,并编译生成可执行文件test。
main.c:
extern int print(const char *fmt, ...);
int main()
{
print("%s%s::%s:%d.\n", "this is a test", " program", __func__, __LINE__);
return 0;
}
执行命令:gcc-o test main.c -L. -lhello
然后在该目录下生成了可执行文件test
执行命令:lddtest查看该可执行文件所链接的所有动态库。
三、gcc、g++参数说明
1、gcc、g++在执行编译的步骤为:
a.预处理,生成.i的文件[预处理器cpp]
b.将预处理后的文件转换成汇编语言,生成文件.s[编译器egcs]
c.将汇编转(.s文件)生成目标代码(机器代码)生成.o的文件[汇编器as]
d.连接目标代码(.o文件)生成可执行程序[链接器ld]
2、常有参数说明
-c
只激活预处理,编译,和汇编,也就是他只把程序做成obj文件
例子用法:
gcc-c hello.c
他将生成.o的obj文件
-S
只激活预处理和编译,就是指把文件编译成为汇编代码。
例子用法
gcc-S hello.c
他将生成.s的汇编代码,你可以用文本编辑器察看
-E
只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面。
例子用法:
gcc-E hello.c > log.txt
gcc-E hello.c | more
-o
制定目标名称,缺省的时候,gcc编译出来的文件是a.out。
例子用法:
gcc -o hello hello.c
gcc-o hello.asm -S hello.c
-include file
包含某个代码,简单来说,就是便以某个文件,需要另一个文件的时候,就可以用它设
定,功能就相当于在代码中使用#include<filename>
例子用法:
gcchello.c -include ~/hello.h
-Idir
对于#include<file>,gcc/g++会到-I制定的目录查找,查找不到,然后将到系统的缺
省的头文件目录查找
-l-
就是取消前一个参数的功能,所以一般在-Idir之后使用
-C
在预处理的时候,不删除注释信息,一般和-E使用,有时候分析程序,用这个很方便的
-M
生成文件关联的信息。包含目标文件所依赖的所有源代码
例子用法:
gcc -M hello.c
-MM
和上面的那个一样,但是它将忽略由#include<file>造成的依赖关系。
-O0、-O1、 -O2、-O3
编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高,一般我们用-O2
-g
只是编译器,在编译的时候,产生调试信息。
-static
此选项将禁止使用动态库,所以,编译出来的东西,一般都很大,也不需要什么
动态连接库,就可以运行。
-share
此选项将尽量使用动态库,所以生成文件比较小,但是需要系统有动态库。
-w
不生成任何警告信息。
-Wall
生成所有警告信息。
-fPIC
表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
例子用法:
gcc -o libhello.so hello.c -fPIC -shared
-shared
该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接,相当于一个可执行文件。
例子用法:
gcc -o libhello.so hello.c -fPIC -shared
-llibrary
制定编译的时候使用的库library,编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称
例子用法:
gcc -o test main.c -L. -lhello
使用libhello.so库编译程序
-LDIR:表示要连接的库在DIR目录中
例子用法:
gcc -o test main.c -L. -lhello