c++ 静态库与动态库

 

1.库的文件格式

库分为静态库,动态库,在不同系统下后缀不同。

2.库的调用与生成

2.1库的调用

2.1.1 在链接和执行阶段都涉及库的调用(访问)。.h文件(头文件)是库的接口。.h文件提供给库的使用者,使用者通过.h来调用库中的API。
2.1.2 库中包含的是函数的实现(一堆函数的实现),这些函数在编写的时候同样要包含1中的头文件,然后生成库。
2.1.3 有了接口,函数就知道去包含这些接口的库中寻找实现的代码,找这些库就需要知道库的名字,所在的位置(路径),否则程序只能通过编译,在链接的时候会出现问题。这些信息都是在makefile中给出的。-L 后面跟的是库的路径 -l后边跟的是库的“核心”名字。完整的库名字,比如libtest.so(动态库)、libtest.a(静态库),其核心名字为test、test,即在makefile中链接库的时候需要去掉完整名字的首尾部。

2.2 库的生成

2.2.1 Makefile生成库的指令:
(1)静态库(生成libtest.a)

add_static:
    ar -rcs libtest.a add.o
add.o:
    gcc -c -fPIC -ggdb add.cpp          # (debug调模式)
    gcc -c -fPIC -Os add.cpp            # (release发布模式)

中间文件是add.o,最后生成的静态库名字是libtest.a

 (2)动态库(libtest.so)

add_share:    gcc -shared -o ../bin/libtest.so ../project_makefile/*.o  # (*.o  包含了 add.o)

add.o:
    gcc -c -fPIC -ggdb add.cpp          # (debug调模式)
    gcc -c -Os -fPIC add.cpp            # (release发布模式)

中间文件是add.o,最后生成的静态库名字是libtest.so

2.2.2 由库生成可执行文件的过程
(1)由静态库生成

test_static:
    g++ -o teststatic test.cpp -L ../lib -l test

静态库生成可执行文件test_static,test_s中会包含静态库的代码。文件会比较大。

(2)由动态库生成

test_dynamic:
    g++ -o testdynamic test.cpp -L ../bin -l test 

-L 设置的路径将被优先搜索,然后才是搜索系统的环境变量中的路径,比如/usr/lib 等路径。

动态库生成可执行文件test_dynamic的时候,test_dynamic中不好含库的代码,在执行的时候再去找这个库。故文件体积比较小。

2.3 动态库

2.3.1 动态库的环境变量设置

在可执行文件执行的过程中,需要通过配置环境变量找到动态库,并加载动态库文件。(-L 是在链接的过程中库的路径,链接动态库生成可执行文件过程,是在可执行文件中记录对动态库的引用,因此这里会寻找一次动态库生成一个记录放在可执行文件中。等到运行时候会通过这个记录去寻找动态库,而寻找的路径需要配置环境变量给出)
(1)在/etc/ld.so.conf 中添加搜索路径
    直接在/etc/ld.so.conf 中添加路径,或者在/etc/ld.so.conf.d/ 目录下(sudo)新建一个.conf文件,然后将绝对路径添加进去。
    运行sudo /sbin/ldconfig 命令。ldconfig ,简单的说,它的作用就是将/etc/ld.so.conf列出的路径下的库文件缓存到/etc/ld.so.cache 以供使用。
(2)在环境变量 LD_LIBRARY_PATH 中指明库的搜索路径。
设置方式:     

export LD_LIBRARY_PATH=/opt/gtk/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/

可以用下面的命令查看 LD_LIBRAY_PATH 的设置内容:

echo $LD_LIBRARY_PATH

这种方式只能在当前终端起作用,如果新打开一个终端就不会起作用了。
(3)修改~/.bashrc 中的环境变量

vim ~/.bashrc
source ~/.bashrc # 使得修改内容生效

 

2.3.2 由动态库再链接生成动态库


同样.cpp中要留有头文件(.h)这个接口,或者在.cpp文件中直接给出目录,或者在makefile中用-I指定。
.cpp中不能出现main()函数,makefile文件中必须包含子动态库的目录和名字,用 -shared -fPIC 等命令
一步生成即可,因为子动态库就相当于.o文件。如果要分步生成,需要规定好哪一步用 -I 指定头文件目录,哪一步链接子动态库的再做研究。
(1)生成动态库

gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so 

(2)一步生成可执行文件        

g++  mutiply.cpp -shared -fPIC -o libmul.so  -I /home/wyz/桌面/ku -L /home/wyz/桌面/ku -l test  # 链接了头文件,以及子动态库

注:子动态库中的函数不能直接被主函数调用,若想用此子动态库中的函数,需要主函数直接链接这个子动态库。
首先。.h  文件是对库中函数的声明。.h在.c文件中是展开的过程。现有a.out a.c,b.so、b.h ,c.so 、c.h 5个文件,a.out-->b.so c.so;b.so-->c.so其中,如果b.so要想用c.so中的函数,就要在b.so中 #include“c.h”也就是先声明要使用的函数,保证gcc在编译这一步可以通过;然后在makefile中 -l c.so,保证ldd在链接这一步可以通过。
然后。a.c中如果想用c中的库有两种方式:
<1>通过b链接,这时需要在b.so的头文件b.h中包含c.h,即#incldue“c.h”,这样在a.c编译的时候,会将b.h展开一次,再将其包含的c. h再展开,这样就对b.so和c.so中的函数进行了声明,gcc编译通过,即a.c可以用c库中的函数了。然后在生成进程a.out的makefile中必须把b.so c.so 都链上,这样ldd通过,即成功链接成了a.out。最后,在执行a.out时候要把b.so 和c.so都放到环境变量指定的目录中。
 <2>单独调用c库,在a.c 中直接包含c.h,即inculde"c.h",同样在链接成a.out中的makefile中链接上c.so
其次。在a.c中如果只用b.so中的函数,需要在a.c中 include“ b.h”这时候gcc编译会通过;然后在ldd(链接)这一步,在链接成a.out的makefile中把b.so 和c.so都连接上。最后在执行a.out的时候同样要把所有动态库都放到环境变量指定的目录中。


2.4 一些关键字和指令(待补充)

# makefile 中
-wl-rpath-link
-werror
-static

# shell 中
ldd       # 查看文件依赖哪些动态库 ldd  a.out   或者ldd libtest.so

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值