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

1 库的分类

根据链接时期的不同,库又有静态库和动态库之分。

静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行。

有别于静态库,动态库的链接是在程序执行的时候被链接的。所以,即使程序编译完,库仍须保留在系统上,以供程序运行时调用。(TODO:链接动态库时链接阶段到底做了什么)

2 静态库和动态库的比较

链接静态库其实从某种意义上来说也是一种粘贴复制,只不过它操作的对象是目标代码而不是源码而已。因为静态库被链接后库就直接嵌入可执行文件中了,这样就带来了两个问题。

首先就是系统空间被浪费了。这是显而易见的,想象一下,如果多个程序链接了同一个库,则每一个生成的可执行文件就都会有一个库的副本,必然会浪费系统空间。

再者,人非圣贤,即使是精心调试的库,也难免会有错。一旦发现了库中有bug,挽救起来就比较麻烦了。必须一一把链接该库的程序找出来,然后重新编译。

而动态库的出现正弥补了静态库的以上弊端。因为动态库是在程序运行时被链接的,所以磁盘上只须保留一份副本,因此节约了磁盘空间。如果发现了bug或要升级也很简单,只要用新的库把原来的替换掉就行了。

那么,是不是静态库就一无是处了呢?

答曰:非也非也。不是有句话么:存在即是合理。静态库既然没有湮没在滔滔的历史长河中,就必然有它的用武之地。想象一下这样的情况:如果你用libpcap库编了一个程序,要给被人运行,而他的系统上没有装pcap库,该怎么解决呢?最简单的办法就是编译该程序时把所有要链接的库都链接它们的静态库,这样,就可以在别人的系统上直接运行该程序了。

所谓有得必有失,正因为动态库在程序运行时被链接,故程序的运行速度和链接静态库的版本相比必然会打折扣。然而瑕不掩瑜,动态库的不足相对于它带来的好处在现今硬件下简直是微不足道的,所以链接程序在链接时一般是优先链接动态库的,除非用-static参数指定链接静态库。

动态链接库

1. 创建动态链接库

代码如下:

#include<stdio.h>
void hello()
{
  printf("hello world/n");
}

用命令gcc -shared hello.c -o libhello.so编译为动态库。可以看到,当前目录下多了一个文件libhello.so。

2. 再编辑一个测试文件test.c,内容如下

代码如下:

#include<stdio.h>
int main()
{
  printf("call hello()");
  hello();
}

编译 gcc test.c -lhello
-l 选项告诉编译器要使用hello这个库。奇怪的地方是动态库的名字是libhello.so,这里却使用hello.
但这样还不行,编译会出错。

In function `main':
test.c:(.text+0x1d): undefined reference to `hello'
collect2: ld returned 1 exit status
这是因为hello这个库在我们自己的路径中,编译器找不到。
需要使用-L选项,告诉hello库的位置
gcc test.c -lhello -L. -o test
-L .告诉编译器在当前目录中查找库文件

3. 编译成功后执行./test, 仍然出错

说找不到库

有两种方法:

一、可以把当前路径加入 /etc/ld.so.conf中然后运行ldconfig,或者以当前路径为参数运行ldconfig(要有root权限才行)。

二、把当前路径加入环境变量LD_LIBRARY_PATH中

当然,如果你觉得不会引起混乱的话,可以直接把该库拷入/lib,/usr/lib/等位置(无可避免,这样做也要有权限),这样链接器和加载器就都可以准确的找到该库了。

我们采用第二种方法:
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
这样,再执行就成功了。

下面再讲讲静态链接库

仍使用刚才的hello.c和test.c。
1. gcc -c hello.c 注意这里没有使用-shared选项
2. 把目标文件归档    ar -r libhello.a hello.o
    程序 ar 配合参数 -r 创建一个新库 libhello.a 并将命令行中列出的对象文件插入。采用这种方法,如果库不存在的话,参数 -r 将创建一个新的库,而如果库存在的话,将用新的模块替换原来的模块。
3. 在程序中链接静态库
           gcc test.c -lhello -L. -static -o hello.static
或者   gcc test.c libhello.a -L. -o hello.static

生成的hello.static就不再依赖libhello.a了

两个有用的命令

file程序是用来判断文件类型的,在file命令下,所有文件都会原形毕露的。
顺便说一个技巧。有时在 windows下用浏览器下载tar.gz或tar.bz2文件,后缀名会变成奇怪的tar.tar,到Linux有些新手就不知怎么解压了。但 Linux下的文件类型并不受文件后缀名的影响,所以我们可以先用命令file xxx.tar.tar看一下文件类型,然后用tar加适当的参数解压。

另外,还可以借助程序ldd实用程序来判断。
ldd是用来打印目标程序(由命令行参数指定)所链接的所有动态库的信息的,如果目标程序没有链接动态库,则打印“not a dynamic executable”,ldd的用法请参考manpage。

(0)

相关推荐

  • 浅析C/C++中动态链接库的创建和调用

    DLL 有助于共享数据和资源.多个应用程序可同时访问内存中单个DLL 副本的内容.DLL 是一个包含可由多个程序同时使用的代码和数据的库.下面为你介绍C/C++中动态链接库的创建和调用. 动态连接库的创建步骤: 创建Dll有两种方式. 一.创建Non-MFC DLL动态链接库 1.打开File -> New -> Project选项,选择Win32 Dynamic-Link Library ->sample project ->工程名:DllDemo 2.新建一个.h文件DllDe

  • Python调用C/C++动态链接库的方法详解

    本文以实例讲解了Python调用C/C++ DLL动态链接库的方法,具体示例如下: 示例一: 首先,在创建一个DLL工程(本例创建环境为VS 2005),头文件: //hello.h #ifdef EXPORT_HELLO_DLL #define HELLO_API __declspec(dllexport) #else #define HELLO_API __declspec(dllimport) #endif extern "C" { HELLO_API int IntAdd(in

  • 链接库动态链接库详细介绍

    windows中,链接库分为两种类型:静态链接库.lib和动态链接库.dll.其中动态链接库在被使用的时候,通常还提供一个.lib,称为引入库,它主要提供被Dll导出的函数和符号名称,使得链接的时候能够找到dll中对应的函数映射. 静态链接库和动态链接库的作用相似,都是提供给其他程序进行调用的资源.其中,动态链接库的调用方法分隐式调用(静态导入调用)和显示调用(动态导入调用). 编译环境: Microsoft Visual Stdio 2010 -------------------------

  • 在C语言中调用C++做的动态链接库

    今天在做东西的时候遇到一个问题,就是如何在C语言中调用C++做的动态链接库so文件 如果你有一个c++做的动态链接库.so文件,而你只有一些相关类的声明, 那么你如何用c调用呢,别着急,本文通过一个小小的例子,让你能够很爽的搞定. 链接库头文件: head.h class A { public: A(); virtual ~A(); int gt(); int pt(); private: int s; }; firstso.cpp #include <iostream> #include &

  • VC6.0如何创建以及调用动态链接库实例详解

    小弟在公司的职责,在上篇博客中已经简约介绍.这边博客主要介绍技术的应用而不在细究原理.因为公司项目着急,出结果要紧,并且咱也不是专注搞研究的,所以,基本懂了原理后,直接上手工作,搞出demo来最好. 至于公司工作情况,今天暂且略过,当然也不是一两句能够表达清楚的.后面会有相应的工作总结,敬请期待-- 现在,废话少说,直奔主题--VC6.0中创建动态链接库. 作为客户与后台的中介,为了更好的调节两方的关系,我明智滴选择了webservice以及动态链接库.在与客户c++使动态链接库方式,而与后台j

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

    1 库的分类 根据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行. 有别于静态库,动态库的链接是在程序执行的时候被链接的.所以,即使程序编译完,库仍须保留在系统上,以供程序运行时调用.(TODO:链接动态库时链接阶段到底做了什么) 2 静态库和动态库的比较 链接静态库其实从某种意义上来说也是一种粘贴复制,只不过它操作的对象是目标代码而不是源码而已.因为静态库被链接后库

  • Go编译32位GNU静态链接库的方法

    Go链接库系统的难用可谓是人尽皆知,不同Go版本编译出来的不兼容,而且只支持GNU的,不能编译出Windows上的dll和lib. 本次有需求是将Go代码编译成32位GNU静态链接库. Go代码 编写代码如下: package main import "C" //export Add func Add(a, b int32) int32 { return a + b } func main() {} 注意我们必须把想要导出的函数显式使用//export Add注释标明,否则编译后不会产

  • C++封装静态链接库和使用的详细步骤

    目录 零碎记事 为什么要把程序封装成库 博主的环境 封装步骤 准备好待封装的程序 开始封装 配置项目 编译 找到编译好的静态库 打包 使用静态库使用步骤包含头文件 添加链接路径 源文件设置 项目设置 零碎记事 距离上次发博客已经有一年半了,转眼间我也是从做图像研究到了做游戏开发,说起来看看前面的博文,本来就有前兆的东西呢(笑)......因为主要还是在使用虚幻引擎,所以C++的东西会碰到多一些. 以后程序技术方面的文章就放博客,游戏设计相关的杂谈就放知乎那边吧,博主的知乎可以通过友链过去. B站

  • Linux静态链接库与模板类的处理方式

    在阅读本文之前,小编先给大家介绍一篇相关文章:Linux静态链接库使用类模板的快速排序算法 大家首先看下以上的文章对理解下面的知识点会有很大的帮助. 当模板遇到静态链接库会发生什么呢. 我们先按照常规思路去考虑一个静态链接库的步骤: 1.将某些功能提取出来,放进一个cpp文件,并将接口或者对外导出的类放在头文件中 2.gcc -c编译该文件,生成.o 3.ar命令将.o文件打包成.a,即静态链接库 4.编译main函数,并将该静态链接库链接,生成可执行文件. OK,按照这个思路,我们将之前写的快

  • 详解C++的JSON静态链接库JsonCpp的使用方法

    JsonCpp部署方法: 在http://sourceforge.net/projects/jsoncpp/中下载最新版本的jsoncpp库源码. 之后将jsoncpp-src-版本号-tar.gz解压出来,打开makefiles中的jsoncpp.sln进行编译,之后build文件夹下的vs71\debug\lib_json中会有一个.lib静态链接库. JsonCpp主要包含三种类型的class:Value Reader Writer. jsoncpp中所有对象.类名都在namespace

  • dev-c++创建lib(静态链接库)文件的实现步骤

    目录 第一步:制作静态链接库 第二步:链接静态链接库 方法一:使用项目 方法二:修改编译选项 第三步:使用库函数 方法一 方法二: 虽说dev-c++适合初学者,但是它的功能还是很强大的.那如何用它制作一个lib(静态链接库)呢? 第一步:制作静态链接库 1.打开dev-c++,选择“新建-项目”,如下图所示. 2.选择“Static Library”,并选择编程语言(c和c++无所谓)以及给项目设置名称. 3.选择你要保存的位置. 4.在新建的文件里添加函数,我这里添加了两个:一个叫hello

  • Linux静态链接库使用类模板的快速排序算法

    快速排序的本质是从数组中选一个参考值ref,比该参考值的大的,将其放在ref的右边,比ref小的放在左边,然后不断的对两边重复执行该动作 我们先列出来快速排序的步骤: 1.从数组中选一个参考值ref,比该参考值的大的,将其放在ref的右边, 上面的动作将数组划分为两部分: A ref B A是比ref小的数组元素集合,它仍然是数组,B是比ref大的元素集合,它也仍然是数组 2.在对ref左右两边的元素重复上述动作,直到A和B都只剩下一个元素,那么排序就算完成了. 重点是如何分别选出来两个集合A和

  • GCC 编译c程序的方法及过程解析

    目前 Linux 下最常用的 C 语言编译器是 GCC ( GNU Compiler Collection ),它是 GNU 项目中符合 ANSI C 标准的编译系统,能够编译用 C . C++ 和 Object C 等语言编写的程序. GCC 不仅功能非常强大,结构也异常灵活.最值得称道的一点就是它可以通过不同的前端模块来支持各种语言,如Java . Fortran . Pascal . Modula-3 和 Ada 等.开放.自由和灵活是 Linux 的魅力所在,而这一点在 GCC 上的体现

  • C++静态链接与动态链接详解

    目录 一.GCC工作流程 二.静态链接与动态链接 1.静态链接 2.动态链接 总结 一.GCC工作流程 预处理:把#头文件展开,进行宏替换,去掉注释(生成.i文件) 编译:把预处理后的文件生成汇编文件(.s文件),主要是检查语法.语义问题 汇编:把汇编文件生成目标文件(.o文件) 链接:将函数库中相应的代码组合到目标文件,生成可执行文件(默认a.out文件) o文件不会立即执行,因为可能出现:一个.cpp文件中的函数引用了另一个.cpp文件中定义的符号/调用了某个库文件中的函数.链接的目的就是将

随机推荐