linux 静态库头,C++:静态库、动态库、头文件

C++中提供某个库,往往有三种方法:

头文件(.h)+静态库(.a)

头文件(.h)+动态库(.so)

头文件(.h)+源代码(.cpp)

注意,动态函数库同共享函数库是一个东西(在linux上叫共享对象库, 文件后缀是.so ,windows上叫动态加载函数库, 文件后缀是.dll)共享库/动态库   也就是.so的库

共享库的命名

每个共享函数库都有个特殊的名字,称作“soname”。soname名字命名必须以“lib”作为前缀,然后是函数库的名字,然后是“.so”,最后是版本号信息。不过有个特例,就是非常底层的C库函数都不是以lib开头这样命名的。

/usr/lib/libreadline.so.3 是一个完全的完整的soname

每个共享函数库都有一个真正的名字(“real name”),它是包含真正库函数代码的文件。真名有一个主版本号,和一个发行版本号。最后一个发行版本号是可选的,可以没有。主版本号和发行版本号使你可以知道你到底是安装了什么版本的库函数。另外,还有一个名字是编译器编译的时候需要的函数库的名字,这个名字就是简单的soname名字,而不包含任何版本号信息。

另外,编译器在请求库时使用的名称(我将其称为“链接器名称”),这只是没有任何版本号的soname。

管理共享库的关键是这些名称的分离。程序在内部列出他们需要的共享库时,应该只列出他们需要的soname。相反,创建共享库时,只能创建具有特定文件名的库(具有更详细的版本信息)。当您安装新版本的库时,将其安装在几个特殊目录之一中,然后运行程序ldconfig(8)。ldconfig检查现有文件,并将声名创建为真实名称的符号链接,以及设置缓存文件/etc/ld.so.cache(稍后描述)。

LINUX,库的使用

1.1 静态库命名规则

Linux静态库命名规范,必须是"lib[your_library_name].a":lib为前缀,中间是静态库名,扩展名为.a。

1.2 若想要创建一个静态库

首先写静态库头文件和源文件

f1de9f886c3e

Linux创建静态库过程如下:

-  首先,将代码文件编译成目标文件.o(StaticMath.o)

f1de9f886c3e

也就是做到汇编结束这一步,这里,把头文件和源文件放在同一目录,g++源文件即可(源文件中include头文件)

然后,通过ar工具将目标文件打包成.a静态库文件

f1de9f886c3e

生成了静态库libstaticmath.a

如下

f1de9f886c3e

注意这个目录下的东西,包含头文件,源文件,和生成的静态库

1.3 使用静态库

编写测试代码

f1de9f886c3e

include 静态库的头文件

Linux下使用静态库,只需要在编译的时候,指定静态库的搜索路径(-L选项)、指定静态库名(不需要lib前缀和.a后缀,-l选项)

如:# g++ TestStaticLibrary.cpp -L../StaticLibrary -lstaticmath

f1de9f886c3e

-  -L:表示要连接的库所在目录

-  -l:指定链接时需要的动态库,编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.a或.so来确定库的名称。

2.1 动态库命名规则:

动态链接库的名字形式为 libxxx.so,前缀是lib,后缀名为".so"。

-  针对于实际库文件,每个共享库都有个特殊的名字"soname"。在程序启动后,程序通过这个名字来告诉动态加载器该载入哪个共享库。

- 在文件系统中,soname仅是一个链接到实际动态库的链接。对于动态库而言,每个库实际上都有另一个名字给编译器来用。它是一个指向实际库镜像文件的链接文件(lib+soname+.so)。

2.2 创建动态库

编写四则运算动态库代码:

f1de9f886c3e

首先,生成目标文件,此时要加编译器选项-fpic

f1de9f886c3e

fPIC 创建与地址无关的编译程序(pic,position independent code),是为了能够在多个应用程序间共享。  这里生成了.o文件,也就是做到汇编之后

然后,生成动态库,此时要加链接器选项-shared

f1de9f886c3e

-shared指定生成动态链接库。

f1de9f886c3e

此时文件夹中生成了动态库 libdynmath.so*

2.3 使用

测试代码:

f1de9f886c3e

编译的时候(和静态库一样)

g++ TestDynamicLibrary.cpp -L../DynamicLibrary -ldynmath

但此时还没法运行,因为还找不到这个动态库

如何定位和执行动态库呢:

1)        当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。此时就需要系统动态载入器(dynamic linker/loader)。

2)        对于elf格式(也就是linux下可执行文件的默认格式)的可执行程序,是由ld-linux.so*来完成的,它先后搜索:

1、elf文件的 DT_RPATH段,也即编译时指定的搜索路径

2、环境变量LD_LIBRARY_PATH制定的路径  (不需要root权限)

3、/etc/ld.so.cache文件列表指定的路径  (修改这个需要root权限)

4、默认路径/lib/,/usr/lib 目录       (也需要root权限)

找到库文件后将其载入内存。

如何让系统能够找到它:

-  如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。

-  如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下:

--  编辑/etc/ld.so.conf文件,加入库文件所在目录的路径

--  运行ldconfig ,该命令会重建/etc/ld.so.cache文件

或者

也可以把路劲加入到LD_LIBRARY_PATH里,此时不需要root权限 如下:

export LD_LIBRARY_PATH=/export/apps/anaconda2/2.4.1/lib/:$LD_LIBRARY_PATH (在开头添加)

但这样只是临时修改,重启或者打开新的shell需要重新设置

如果想永久添加:

~/.bashrc或者~/.bash_profile中加入 export 语句,前者在每次登陆和每次打开 shell 都读取一次,后者只在登陆时读取一次。

我的习惯是加到~/.bashrc中,在该文件的未尾,可采用如下语句来使设置生效:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib(在末尾添加)

3 库相关命令

3.1   .nm命令

有时候可能需要查看一个库中到底有哪些函数,nm命令可以打印出库中的涉及到的所有符号。库既可以是静态的也可以是动态的。nm列出的符号有很多,常见的有三种:

-  一种是在库中被调用,但并没有在库中定义(表明需要其他库支持),用U表示;

-  一种是库中定义的函数,用T表示,这是最常见的;

-  一种是所谓的弱态"符号,它们虽然在库中被定义,但是可能被其他库中的同名符号覆盖,用W表示。

$nm libhello.h

3.2   ldd命令

ldd命令可以查看一个可执行程序依赖的共享库,例如我们编写的四则运算动态库依赖下面这些库:

f1de9f886c3e

此时,后面有地址的,都是链接器能找到的库

如果找不到的库,会出现这样:

f1de9f886c3e

3.3 查找库

可以使用ls /usr/lib |grep lib查看自己是否有需要的库文件,当然还需查看其它库文件目录:echo $LD_LIBRARY_PATH里面一般可以看到七八个已经定义好的库文件搜索路径。

也可使用 pkg-config

f1de9f886c3e

其有一些常用参数

f1de9f886c3e

也可用

sudo updatedb

locate eigen3                                 (库名称)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值