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

Linux下库文件学习(三)如何创建和使用库文件

2012-02-07 22:37 666 查看
最近在Linux下使用第三方库Protobuf时,遇到一个问题:编译出的可执行程序在运行时总报错:“error while loading shared libraries: libprotobuf.so.7: cannot open shared object file: No such file or directory”。于是花时间弄清楚原因,找到解决方案,跟大家共享一下。

库文件的创建和使用,通过具体的例子来介绍。

1. 准备源文件

建立一个新目录libtest,在libtest下新建两个目录a和so,a和so目录下均有cacl.h cacl.C test_cacl.C三个文件,内容如下:

****************************************************************************************************************************************

cacl.h

#ifndef CACL_H
#define CACL_H

int Add(int nLeft, int nRight);

#endif


****************************************************************************************************************************************

cacl.C

#include <stdio.h>

int Add(int nLeft, int nRight)
{
return nLeft + nRight;
}
****************************************************************************************************************************************

test_cacl.C

#include "cacl.h"
#include <stdio.h>

int main()
{
int nA   = 100;
int nB   = 200;
int nRev = Add(nA, nB);
printf("The sum is %d\n", nRev);

return 0;
}
****************************************************************************************************************************************

2. 静态库的创建和使用

(1) 在a目录下,编译生成cacl.o文件;

g++ -c cacl.C

(2) 在a目录下,使用ar命令封装生成静态库文件libcacl.a;

ar crv libcacl.a cacl.o

静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a

(3) 在a目录下,编译连接libcacl.a生成测试程序;

g++ -o testcacl test_cacl.C -L. -lcacl

(4) 在a目录下,可以正确运行testcacl,即使删除了libcacl.a文件(正是静态库的特点);

3. 动态库的创建和使用

(1) 在so目录下,编译生成cacl.o文件;

g++ -fPIC -c cacl.C

P.S.此处编译参数 -fPIC 一定不能省略,否则下一步将会失败;因为g++默认生成的.o文件是不带-fPIC选项,即生成的是静态链接文件,故下一步封装 生成动态库时会失败。

(2) 在so目录下,使用ar命令生成静态库文件libcacl.so;

g++ -shared -fPIC -o libcacl.so cacl.o

动态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.so

(3) 在so目录下,编译连接libcacl.a生成测试程序;

g++ -o testcacl test_cacl.C -L. -lcacl

(4) 在so目录下,可以正确运行testcacl;

若在当前目录下删除了libcacl.so,将会报错“testcacl: error while loading shared libraries: libcacl.so: cannot open shared object file: No such file or directory”,具体原因在Linux下库文件学习(二)如何设置库的路径中已经讲解地非常清楚,请大家自己去找解决方案;

4. 编译参数解析

-shared: 该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。当于一个可执行文件;

-fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的;

-L.: 表示要连接的库在当前目录中 ;

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

5. 优先级

若同一个目录下既有静态库.a,又有动态库.so,则编译链接时优先使用动态库,可通过如下方法验证。

(1) 先把cacl.h test_cacl.C这两个文件都拷贝到libtest目录下,然后将目录a中的libcacl.a和目录so中的libcacl.so拷贝到libtest目录下,使用命令“g++ -o testcacl test_cacl.C -L. -lcacl”编译链接生成可执行程序testcacl;

(2) 运行testcacl,运行结果正确;

(3) 删除libcacl.so之后,运行testcacl,会报错“testcacl: error while loading shared libraries: libcacl.so: cannot open shared object file: No such file or directory”。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: