函数库一般分为静态库和动态库两种。

静态库:

是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为”.a”。

动态库:

与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为”.so”,gcc/g++在编译时默认使用动态库。无论静态库,还是动态库,都是由.o文件创建的。

动态库的编译:

下面通过一个例子来介绍如何生成一个动态库。建一个头文件:dynamic.h,三个.cpp文件:dynamic_a.cpp、dynamic_b.cpp、dynamic_c.cpp,我们将这几个文件编译成一个动态库:libdynamic.so。
//dynamic.h
#ifndef __DYNAMIC_H_
#define __DYNAMIC_H_
#include <iostream>
void dynamic_a();
void dynamic_b();
void dynamic_c();
#endif
//dynamic_a.cpp:
#include"dynamic.h"
void dynamic_a()
{
cout<<"this is in dynamic_a "<<endl;
}
 
//dynamic_b.cpp:
#include"dynamic.h"
void dynamic_b()
{
cout<<"this is in dynamic_b "<<endl;
}
 
//dynamic_c.cpp:
#include"dynamic.h"
void dynamic_c()
{
cout<<"this is in dynamic_c "<<endl;
}
 
将这几个文件编译成动态库libdynamic.so。编译命令如下:

g++ dynamic_a.cpp dynamic_b.cpp dynamic_c.cpp -fPIC -shared -o libdynamic.so
 

参数说明:

-shared:该选项指定生成动态连接库
-fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
 
 
在上面的部分,我们已经生成了一个libdynamic.so的动态链接库,现在我们用一个程序来调用这个动态链接库。文件名为:main.cpp
//main.cpp:
#include"dynamic.h"
int main()
{
dynamic_c();
dynamic_c();
dynamic_c();
return ;
}
将main.cpp与libdynamic.so链接成一个可执行文件main。命令如下:
 
g++ main.cpp -L. -ldynamic -o main

参数说明:

-L.:表示要连接的库在当前目录中
-ldynamic:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称
 
 
测试可执行程序main是否已经链接的动态库libdynamic.so,如果列出了libdynamic.so,那么就说明正常链接了。可以执行以下命令:
ldd main

 
如果运行:
./main
 
出现错误: error while loading shared libraries: libdynamic.so: cannot open shared object file: No such file or directory
 

错误原因

ld提示找不到库文件,而库文件就在当前目录中。
 
链接器ld默认的目录是/lib和/usr/lib,如果放在其他路径也可以,需要让ld知道库文件在哪里。
 

解决方法:

方法1:

编辑/etc/ld.so.conf文件,在新的一行中加入库文件所在目录;比如笔者应添加:
/home/neu/code/Dynamic_library
 
运行:
sudo ldconfig
目的是用ldconfig加载,以更新/etc/ld.so.cache文件;
 
 

方法2:

在/etc/ld.so.conf.d/目录下新建任何以.conf为后缀的文件,在该文件中加入库文件所在的目录;
运行:

sudo ldconfig

以更新/etc/ld.so.cache文件;

 
ld.so.cache的更新是递增式的,就像PATH系统环境变量一样,不是从头重新建立,而是向上累加。除非重新开机,才是从零开始建立ld.so.cache文件。

方法3:

在bashrc或profile文件里用LD_LIBRARY_PATH定义,然后用source加载。

方法4:

你可以直接采用在编译链接的时候告诉系统你的库在什么地方
 
执行main可以看看main是否调用了动态链接库中的函数。
./main

 

静态库的编译:

读者可以自己创建代码,笔者比较懒,就以以上代码演示,最好把生成的动态库的东西全部删掉。

1.编译静态库:
g++ -c dynamic_a.cpp dynamic_b.cpp dynamic_c.cpp  
 2.使用ar命令创建静态库文件(把目标文档归档)
 
ar cr libstatic.a dynamic_a.o dynamic_b.o dynamic_c.o  //cr标志告诉ar将object文件封装(archive)
 
 
参数说明:
         
          d 从指定的静态库文件中删除文件 
          m 把文件移动到指定的静态库文件中 
          p 把静态库文件中指定的文件输出到标准输出 
          q 快速地把文件追加到静态库文件中 
          r 把文件插入到静态库文件中 
          t 显示静态库文件中文件的列表 
          x 从静态库文件中提取文件 
          a 把新的目标文件(*.o)添加到静态库文件中现有文件之后 
 
 
使用nm -s 命令来查看.a文件的内容
nm -s libstatic.a 

 
3.链接静态库
g++ main.cpp -lstatic -L. -static -o main//这里的-static选项是告诉编译器,hello是静态库也可以用

                        //g++ main.cpp -lstatic -L.  -o main 
执行以下命令,因为笔者还是用的动态库的代码,所以结果一样
./main

gcc/g++实战之动态链接库与静态链接库编写的更多相关文章

  1. GCC编译过程与动态链接库和静态链接库

    1. 库的介绍 库是写好的现有的,成熟的,可以复用的代码.现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常. 本质上来说库是一种可执行代码的二进制形式,可 ...

  2. [转载]GCC 编译使用动态链接库和静态链接库--及先后顺序----及环境变量设置总结

    来自http://blog.csdn.net/benpaobagzb/article/details/51364005 GCC 编译使用动态链接库和静态链接库 1 库的分类 根据链接时期的不同,库又有 ...

  3. Linux下动态链接库和静态链接库

    第一部分:编译过程 先了解一下linux下C代码的编译过程,C代码的编译,一般分成四个阶段,包括:预编译,编译,汇编和链接,这四个阶段的分工是 预处理过程,负责头文件展开,宏替换,条件编译的选择,删除 ...

  4. Qt 共享库(动态链接库)和静态链接库的创建及调用

    前言: 编译器 Qt Creator, 系统环境 win7 64 位 1.创建共享库: 新建文件或项目->选择 Library 和 c++ 库->选择共享库->下一步(工程名为 sh ...

  5. 利用GCC编译器生成动态链接库和静态链接库

    转载请标明:http://www.cnblogs.com/winifred-tang94/ 1.编译过程 gcc –fPIC –c xxx.c 其中-fPIC是通知gcc编译器产生位置独立的目标代码. ...

  6. GCC 编译使用动态链接库和静态链接库

    1 库的分类 根据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. 有 ...

  7. GCC 编译使用动态链接库和静态链接库的方法

    1 库的分类 依据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的.所以生成的可执行文件就不受库的影响了.即使库被删除了,程序依旧能够成功执行. 有别于静态库,动态库的链接是在程 ...

  8. 【转】gcc 编译使用动态链接库和静态链接库

    1 库的分类 根据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. 有 ...

  9. linux动态链接库和静态链接库

    Linux下静态链接库与动态链接库的区别 引言 通常情况下,对函数库的链接是放在编译时期(compile time)完成的.所有相关的对象文件 (object file)与牵涉到的函数库(librar ...

随机推荐

  1. 1000个经常使用的Python库和演示样例代码

    以下是programcreek.com通过分析大量开源码,提取出的最经常使用的python库. 1. sys    (4627) 2. os    (4088)  3. re    (3563)  4 ...

  2. css新单位 vw , vh

    考虑到未来响应式设计的开发,如果你需要,浏览器的高度也可以基于百分比值调整.但使用基于百分比值并不总是相对于浏览器窗口的大小定义的最佳方式,比如字体大小不会随着你窗口改变而改变,如今css3引入的新单 ...

  3. 用rz,sz命令在windows和linux之间传输文件(转)

    转自http://www.linuxmine.com/178.html有很多人没有听说过ZModem协议,更不知道有rz/sz这样方便的工具: 下面一段是从SecureCRT的帮助中copy的: ZM ...

  4. C#创建COM组件供VB,PB,Delphi调用

    1  COM组件概述 COM是微软公司为了计算机工业的软件生产更加符合人类的行为方式开发的一种新的软件开发技术.在COM构架下,人们可以开发出各种各样的功能专一的组件,然后将它们按照需要组合起来,构成 ...

  5. JS遍历数组类型元素

    已停供用户不能再次停供,之前没太处理过多维数组的遍历,趁这个机会回顾一下js数组遍历 可以看出rows 获取了两条数据,为二维数组类型 方法 function batchTgWin() { var r ...

  6. shell脚本中执行mysql 语句,去除warning using a password on the command line interface can be insecure信息

    方法二:使用mysql参数的方法 mysql -u$user -p$pass -D $db -e "select host from user;"当然,可以通过将传参的方式来传递 ...

  7. 关于同一线程两次调用EnterCriticalSection的测试

    #include "stdafx.h" #include <iostream> using namespace std; #include <windows.h& ...

  8. jquery.zclip实现点击拷贝文字功能

    <script type="text/javascript" src="http://www.sitejs.cn/templets/skins/js/jquery- ...

  9. Eclipse中屏蔽日志

    如何在Eclipse中屏蔽日志 //屏蔽日志 Eclipse Java import org.apache.log4j.Level; import org.apache.log4j.Logger; L ...

  10. TabLayout+Fragment+ViewPager+FragmentStatePagerAdapter实现Tab标签

    首先来看下实现的效果吧: 最近在项目中实现这个效果的时候.尽管自己磕磕绊绊的实现了,可是知识确实模模糊糊的,今天天气异常的冷,在加上这个知识不太熟练,实在是没有心情进行接下来的计划,干脆借着这个时间, ...