您的位置:首页 > 运维架构 > Linux

C++ 中的共享库和静态库(Linux)

2016-12-20 17:03 204 查看
之前学习过VC环境下的动态库、静态库
C++中的动态库和静态库 (Windows)

http://zhweizhi.blog.51cto.com/10800691/1883814

而Linux环境下也有动态库、静态库,并且原理都是相似的

一、共享库的创建、使用
库:
在C/C++中,使用库(Library)的技术,可以将编译好的符号提供给第三方使用。库有两种:1、共享库 Shared Library (Linux下叫做 Dynamic-Link Library (DLL),动态库)2、静态库 Static Library
Linux下创建、使用共享库:步骤:


1、编译
g++ -c -fPIC example.cpp -o example.o


编译得到example.o文件

2、链接
g++ -shared example.o -o libexample.so
生成 *.so 文件

解释: PIC :(Position Independent Code) 位置无关代码

命名规范:
Linux下,动态库的规范命名 libXXXXX.so
前缀 lib*
后缀 *.so
其中,XXXXX是库的名称

交付:
交付 example.h 和 libexample.so
同时,告知此so文件使用的平台 (跨平台使用时可能会有问题)

使用:
经过交付应该得到 *.so 和 *.h文件了 (不得不再次强调Linux下文件后缀并没有实质意义,只是命名规范而已)




编译:
g++ -c test.cpp -o test.o
链接:

g++ test.o -o test.exe -L. -lexample (注意命名规范)


最后一列 -lXXXX 表示要加载的库的文件名,而-LXXX 表示库文件所在的路径

完整过程截图:




但这时生成的 test.exe运行时会报错:




加载共享库时出错:找不到这个文件或路径

要找的 *.so 文件就在当前路径下,但程序执行,却找不到,这是由于操作系统默认从标准位置寻找相应的库
/lib/use/lib/usr/local/lib
如果没找到依赖的库文件,则从LD_LIBRARY_PATH环境变量中寻找

也就是说,库文件
1、要么放在标准位置
2、要么放在 LD_LIBRARY_PATH指定的位置
才能被操作系统找到

所以使用export命令将当前路径添加至 LD_LIBRARY_PATH中:
export LD_LIBRARY_PATH=./


然后执行:



成功。

查看依赖的库:
readelf -d XXXXXX
可以查看一个可执行程序运行时所依赖的库,当运行程序显示 No such file or directory时,可以用该命令检查

标准C/C++库
libc.so : 标准C库(ANSIC)
libstdc++.so : 标准C++库(包含STL)
这些库不需要在命令行中指定,g++会默认链接到这两个库







在Makefile中创建动态库:

在动态库中使用别的动态库:
如果要调用其他第三方库,可以在链接时 后面附加链接选项:
g++ -shared example.o -o libexample.so -lxxxxxxx


在动态库中共享class类型:
直接按普通方式把 class 的头文件和cpp文件写出来就可以

库的标准目录结构
Linux下面可能会经常使用各种库,有的是系统自带的库,有的是第三方库。

通常的目录结构时:
libxxx/
-bin

-lib

-include

其中,bin下为程序,lib下为库文件,include为头文件

编译时指定共享库文件路径:
g++ -c -LXXXXXXXX

链接时指定头文件路径:
g++ -o -IXXXXXXXX


通常 在Makefile里定义两个变量
CXXFLAGS表示C++的编译选项
LDFLAGS表示链接选项
(用 "+=" )

二、静态库的创建、使用
静态库:static library
标准命名规范: libXXXX.a

生成静态库的方法:
1、编译,得到 *.o 文件
2、打包
ar -rcs libXXX.a file1.o file2.o ... fileN.o
(ar操作只是将 *.o 文件打包,并非“链接” )

具体操作:
g++ -c MyLib1.cpp -o MyLib1.o
g++ -c MyLib2.cpp -o MyLib2.o
ar -rcs libMyLib.a MyLib1.o MyLib2.o
接下来用nm 命令观察一下 MyLib.a 文件中的符号:




交付:
静态库的交付物:
1、头文件 *.h
2、库文件 libXXX.a
需要声明此静态库适用的平台

使用:
方法1、由于MyLib.a 本质就是 各种 *.o 打包的集合,因此可以像 *.o 文件一样使用

g++ main.cpp MyLib.a -o main.exe
本质相当于
g++ main.cpp MyLib1.o MyLib2.o -o main.exe


方法2、使用 -l选项,指定静态库
g++ main.cpp -o main.exe -L./ -lMyLib (注意命名规范)


比较:共享库和静态库的区别:
1、使用共享库:
最终的程序里没有相应代码,所以程序在运行时会寻找libXXXX.so,
2、使用静态库:
最终的程序里含有全部的代码,所以程序运行时不依赖 libXXXX.a的存在

三、静态库和共享库共存
如果同时存在 libXXX.a 和 libXXX.so事实上,当同时存在,默认优先连接的是 libXXX.so (共享库) 那么要强制链接静态库,有两种方式:1、使用全路径
g++ main.cpp build/libtest.a -o main.exe
2、-static 选项,强制所有库都使用静态库版本
g++ mian.cpp -o main.exe -static -L. -lMyLib
但这种方式必须要求所有的库都提供静态版本,少一个都不行,而centos 默认是不带libc.a 和 libc++.a的,因此 推荐使用第一种方式
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Linux 技术 Windows