精华内容
下载资源
问答
  • 静态库和动态库

    千次阅读 2019-03-20 11:04:22
    静态库或静态链接库是一组例程,外部函数变量,它们在编译时在调用者中解析,并由编译器,链接器或绑定器复制到目标应用程序中,从而生成目标文件一个独立的可执行文件。动态链接只包括库的地址(而静态链接是...

            函数是可在整个程序中重用的代码块。使用它们可以节省时间,无需多次重写代码。与函数一样,库也可以节省时间,因为它们使函数可以在多个程序中重用。

           静态库或静态链接库是一组例程,外部函数和变量,它们在编译时在调用者中解析,并由编译器,链接器或绑定器复制到目标应用程序中,从而生成目标文件和一个独立的可执行文件。动态链接只包括库的地址(而静态链接是浪费空间动态链接运行时链接库。

           静态库虽然可以在多个程序中重用,但在编译时会被锁定到程序中。另一方面,动态共享库作为可执行文件之外的单独文件存在。

            使用静态库的缺点是它的代码被锁定到最终的可执行文件中,如果没有重新编译就无法修改。相反,可以修改动态库而无需重新编译。

           由于动态库位于可执行文件之外,因此程序只需在编译时制作库文件的一个副本。而使用静态库意味着程序中的每个文件都必须在编译时拥有它自己的库文件副本。

           使用动态库的缺点是程序更容易破坏。例如,如果动态库损坏,则可执行文件可能不再起作用。但是,静态库是不可触及的,因为它存在于可执行文件中。

           使用动态库的好处是,多个正在运行的应用程序可以使用相同的库,而无需每个应用程序拥有自己的副本。

           使用静态库的另一个好处是运行时的执行速度。因为它的目标代码(二进制)已经包含在可执行文件中,所以对多个函数的调用可以比动态库的代码更快地处理,而动态库的代码需要从可执行文件之外的文件中调用。

           这在实践中意味着什么?好吧,想象一下你是一个向数千名用户发布应用程序的开发人员。如果您想对应用程序进行一些更新,您是否需要重新发布整个程序,还是只想以修改后的库的形式发布更新?答案取决于您的应用程序可以承受的缺点。如果你有很多文件,静态库的多个副本意味着可执行文件的大小增加。但是,如果执行时间的好处超过节省空间的需要,那么静态库就是最佳选择。

     

    性能静态库共享库
    连接的时间它发生在编译过程的最后一步。程序放入内存后在将可执行文件和库添加到内存时,在链接过程中添加共享库。
    手段由链接器执行由操作系统执行
    空间静态库的大小要大得多,因为外部程序是在可执行文件中构建的。动态库要小得多,因为只有一个动态库副本保存在内存中。
    外部文件更改如果对外部文件应用了任何更改,则必须重新编译可执行文件。在共享库中,无需重新编译可执行文件。
    加载时间时间更长,因为每次执行时都会加载到内存中。它更快,因为共享库代码已经在内存中。
    兼容性从来没有兼容性问题,因为所有代码都在一个可执行模块中。程序取决于具有兼容的库。如果从系统中删除库,则从属程序将不起作用。

     

    分别什么时候使用他们?        

            如果你有很多文件,静态库的多个副本意味着可执行文件的大小增加,那就建议使用动态库,可以节省时间。如果执行时间的好处超过节省空间的需要,那么静态库就是最佳选择。

    展开全文
  • 主要介绍了xcode 详解创建静态库和动态库的方法的相关资料,这里对创建静态库和动态库的方法详细介绍,需要的朋友可以参考下
  • Linux 如何使用gcc生成静态库和动态库,使用GCC编译生成静态库和动态库的方法
  • Linux静态库和动态库学习总结 静态库和动态库的比较 使用静态库动态库的方法
  • 文档介绍了linux下静态库和动态库生成以及使用问题。文档介绍了linux下静态库和动态库生成以及使用问题。
  • 关于静态库和动态库的创建、调用。动态库有:MFC动态库、win动态库等。
  • C++静态库和动态库用法

    千次阅读 多人点赞 2018-07-19 23:50:11
    从事软件工作也有两年了,C++静态库和动态库也用了不少,但都是依葫芦画瓢,一直没具体去研究一下二者的区别,加载方式等,今天花时间看了几篇博客,重新学习了一下,做出如下笔记。 2、定义 静态库和动态库从字面意思来...

    1、前言

    从事软件工作也有两年了,C++静态库和动态库也用了不少,但都是依葫芦画瓢,一直没具体去研究一下二者的区别,加载方式等,今天花时间看了几篇博客,重新学习了一下,做出如下笔记。

    2、定义

    静态库和动态库从字面意思来看,区别就是静态和动态。而这里的静态和动态指的是库的链接阶段。可以看如下的编译过程。

    • 静态库:在链接阶段库将会与目标汇编后的目标文件.o一起打包生成可执行文件。成为可执行文件的一部分,后续此库就可以消失了。也就是说在编译的最后一步(链接阶段),如果程序需要使用静态库,在这一步都会一起打包到可执行文件中。
    • 动态库:而动态库在编译阶段都不会有什么动作,只有在程序运行时才被加载,也就是动态库的链接是发生在程序运行时期的,它和可执行文件是分开的,只是可执行文件在运行的某个时期调用了它。

    3、优缺点

    分清楚二者区别之后,二者的优缺点就自然可以分出来了。

    优点缺点
    静态库1、 使可执行文件依赖项少,已经被打包到可执行文件中了
    2、 编译阶段完成链接,执行期间代码装载速度快
    1、 使可执行文件变大
    2、 若作为其他库的依赖库,将会造成多余的副本,因为必须与目标文件打包
    3、 升级不方便,升级必须重新编译
    动态库1、 动态库可以实现进程之间资源共享,有一份就行
    2、 升级程序简单,不需要重新编译
    1、 运行期间在加载,将会减慢代码执行速度
    2、 增加程序的依赖项,必须跟着可执行文件一起

    4、文件形式

    TablesWindowsLinux
    静态库.libLibxxx.a
    动态库.dll与.liblibxxx.so

    5、生成和加载方式

    这里我仅讨论windows下的使用vs的情况。

    5.1、静态库:

    生成:

    在创建win32控制台程序或者win32项目的时候,勾选静态库就可以,进入项目后也可打开工程“属性面板”—》”配置属性”—》”常规”—》配置类型选择静态库。
    这里写图片描述
    创建好之后,里面在就正常的写函数或者类,将接口放在.h头文件中,编译后边生成了静态库。
    测试代码:

    • 头文件:
      这里写图片描述
    • 源文件:
      这里写图片描述
    • 生成静态库:
      这里写图片描述

    Vs中加载

    需要文件、接口头文件、.lib库文件。

    方式1

    步骤1:包头文件。工程“属性面板”—》”配置属性” —》“C/C++” —》” 常规”,在“附加包含目录”属性值中,键入StaticLib.h 头文件所在目录的路径或浏览至该目录。
    这里写图片描述
    步骤2:“属性面板”—》”配置属性”—》“链接器”—》”常规”,附加依赖库目录中输入,静态库所在目录;
    这里写图片描述
    步骤3:“属性面板”—》”配置属性”—》“链接器”—》”输入”,附加依赖库中输入静态库名StaticLib.lib。
    这里写图片描述
    步骤4:使用,引用头文件,即可使用里面的接口。
    这里写图片描述

    方式2

    步骤1同方式1。
    步骤二:
    打开工程“属性面板”—》”配置属性” —》“链接器”—》”命令行”,输入静态库的完整路径即可。
    这里写图片描述
    方式3:
    步骤1同方式1。
    步骤2:前提,加载的静态库属于同一解决方案。
    工程“属性面板”—》“通用属性”—》 “框架和引用”—》”添加引用”,将显示“添加引用”对话框。 “项目”选项卡列出了当前解决方案中的各个项目以及可以引用的所有库。 在“项目”选项卡中,选择 StaticLib。 单击“确定
    这里写图片描述
    方式4: 在文件中使用#pragma comment()指定.lib文件的位置。如图
    这里写图片描述

    5.2、动态库

    生成

    在创建win32控制台程序或者win32项目的时候,勾选Dll就可以,进入项目后发现自动生成一些文件。如图
    这里写图片描述
    我们还是正常定义和实现函数或者类,特别的是动态库生成的时候需要在接口前加上
    __declspec(dllexport),而导入的时候需要加__declspec(dllimport)。
    这里使用通常的宏定义做法,如图所示。
    头文件:
    这里写图片描述
    源文件:
    这里写图片描述
    生成动态库:
    这里写图片描述
    这里需要注意,生成两个有用文件,一个是.lib,一个是dll。这里的.lib本质上不同于静态库中的.lib。这里的.lib一般是一些索引信息,记录了dll中函数的入口和位置,dll中是函数的具体实现。而静态库中的lib包含了索引和实现。

    加载动态库

    加载动态库有两种方式,分为隐式加载和显示加载。

    隐式加载

    所需文件:接口.h头文件,dll文件,lib文件。
    .h和.lib加载方式与静态加载完全一致。但.dll文件必须放在环境变量指定的目录下。当然通常是与目标.exe文件放在一起。

    显示加载

    所需文件:dll文件。
    利用LoadLibrary()函数进行加载。如图
    这里写图片描述
    按道理不需要.h头文件,但是前提是你知道接口是啥样的。
    隐式加载和显示加载区别很明显,显示加载使用灵活,需要时加载,用完卸载,而隐式加载伴随着整个程序的生命周期。

    6、总结

    库分为静态库和动态库。静态库与可执行文件打包,动态库与可执行文件独立。静态库加载需要.lib和.h文件。动态库隐式加载需要.dll、.h、.lib文件,显示加载只需要.dll文件。

    展开全文
  • linux静态库和动态库

    2015-04-03 22:53:28
    linux静态库和动态库的区别
  • Linux下Gcc生成和使用静态库和动态库详解Linux下Gcc生成和使用静态库和动态库详解
  • Linux使用静态库和动态库

    千次阅读 2016-05-08 16:28:07
    Linux使用静态库和动态库

    Linux使用静态库和动态库

    (一)库的概念

    库是可以复用的代码,在一些大的项目中常常会用到库。
    本质上说:库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。
    一般说库是说两种:
    静态库:linux下.a文件、windows下.lib文件
    动态库:linux下.so文件、windows下.dll文件
    最近花了一些时间把linux下编译、链接等研究了一下,作为一个菜鸟记录并分享一蛤。


    (二)静态库与动态库

    程序的编译运行要经过以下步骤:

    1.源文件(.h .cpp等)
    2.预编译
    3.编译
    4.汇编(.o文件)
    5.链接
    6.运行

    在上述过程中,静态库是在链接阶段,将汇编生成的目标文件.o与引用到的库一起打包到可执行文件中,此种链接方式被称为静态链接。静态库其实一组目标文件(.o/.obj)的集合,即很多目标文件经过压缩打包后形成的一个文件,有一个说法称为:Archive即归档合并到一起。静态库在链接过程中被一起打包到可执行文件中,因此程序在运行时与函数库再无瓜葛,移植起来就很方便,但也因为这个原因会浪费空间资源,因为所有相关的目标文件与牵涉到的函数库都会被链接成一个可执行文件,如果10个100个可执行文件使用同一个静态库,就会造成大大的浪费;并且由于静态库是需要链接进入应用程序的,因此一旦对静态库进行修改,就需要对整个程序重新编译。

    与静态库不同,动态库不会被链接打包到目标代码中,而是在程序运行时才被载入。这样就解决了静态库浪费空间的缺点,动态库把对一些库函数的链接载入推迟到程序运行的时期,在内存中只存在一份拷贝,这样可以实现进程之间的资源共享。

    在linux和windows下静态库和动态库的概念以及使用方法有所不同,之后会慢慢学习分享。


    (三)Linux下使用静态库

    首先知道一个概念,也就是.h头文件,静态库.a文件的关系:
    .h头文件是编译时必须的,声明函数接口,编译时通过引用.h文件找到函数声明。
    .a文件是linux下静态库文件的后缀,通常以libxxxx.a的形式出现,在链接时必不可少。

    下面编写一个简单的四则运算库:
    首先是声明部分:

    //StaticMath.h
    #pragma once
    class StaticMath
    {
    public:
        StaticMath(void);
        ~StaticMath(void);
    
        static double add(double a,double b);
        static double sub(double a,double b);
        static double mul(double a,double b);
        static double div(double a,double b);
    
        void print();
    };

    接着编写对应的.cpp文件实现上述接口声明:

    //StaticMath.cpp
    #include "StaticMath.h"
    double StaticMath::add(double a,double b)
    {
        return a+b;
    }

    由于静态库是目标文件的集合,那么我们现在需要对上述文件进行预编译->编译->汇编步骤,生成对应的.o文件,通过g++ --help命令知道参数-c的描述是:

    这里写图片描述

    因此执行命令:

    g++ -c StaticMath.cpp

    将代码文件编译汇编成目标文件StaticMath.o
    然后,使用ar工具将目标文件打包成.a形式的静态库文件,这里的ar实际上可以理解为Archive的简写:

    ar -crv libstaticmath.a StaticMath.o

    如此生成静态库文件libstaticmath.a。

    PS:在以前做过的嵌入式项目里面,静态库的生成和使用大多通过一些自动化工具例如autogen、cmake等,一直没有搞懂其真正的原理,这下也算学习了一蛤。

    最后编写测试代码使用静态库

    //test.cpp
    #include <iostream>
    #include "StaticMath.h"
    int main()
    {
        double a=1.2;
        double b=2.4;
        std::cout << "a+b="<<StaticMath::add(a,b)<<std::endl;
        return 0;
    }

    因为在链接的过程中要使用静态库,这里编译的时候需要加入静态库所在目录和静态库的名字来作为编译选项,否则会出现问题:

    g++ -o test test.cpp -L ./ -lstaticmath

    最后可执行文件test正常执行:

    这里写图片描述


    (四)Linux下使用动态库

    动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。动态库在程序运行是才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只需要更新动态库即可,增量更新。

    同样的首先编写库文件。
    声明:

    //DynamicMath.h
    #pragma once
    class DynamicMath
    {
        public:
        DynamicMath();
        ~DynamicMath();
    
    
        static  double add(double a,double b);
        static  double sub(double a,double b);
        static  double mul(double a,double b);
        static  double div(double a,double b);
    };

    实现:

    //DynamicMath.cpp
    #include "DynamicMath.h"
    double DynamicMath::add(double a,double b)
    {
        return a+b;
    }

    生成动态库libxxxx.so

    g++ DynamicMath.cpp -fPIC -shared -o libdynamicmath.so

    -fPIC 创建与地址无关的编译程序(pic,position independent code),是为了能够在多个应用程序间共享。
    -shared指定生成动态链接库。

    使用动态库,测试代码:

    //test.cpp
    #include <iostream>
    #include "DynamicMath.h"
    int main()
    {
        double a=1.2;
        double b=2.4;
        std::cout << "a+b =" << DynamicMath::add(a,b)<<std::endl;
        return 0;
    }

    跟静态库使用类似,编译测试文件并加上合适的编译选项,生成可执行文件,并且通过ldd命令查看应用程序依赖的动态库及其相关信息:

    这里写图片描述

    最后动态库的使用有一个需要注意的地方:
    动态库是在运行时加载,这时候需要一个动态载入器(dynamic linker/loader),来得知动态库的绝对路径。
    对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH段—环境变量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/,/usr/lib 目录找到库文件后将其载入内存。
    什么意思呢?就是首先有一堆配置文件可以配置动态载入库搜索动态库的路径,ld会在这些路径中去寻找依赖的动态库,这样就有两个解决办法:
    1. 修改配置文件(/etc/ld.so.conf)添加我们创建的动态库的目录
    2. 将我们创建的动态库(.so)拷贝到默认的动态库目录下/lib或者/usr/lib

    关于上述第1点,我们可以这样做,在终端

    添加动态库目录
     echo /home/zhangxiao/learnlib/dynamiclib/ >> /etc/ld.so.conf
    配置生效
    ldconfig

    关于上述第2点,直接将生成动态库拷贝到/usr/lib目录下即可。

    参考:

    http://www.cnblogs.com/skynet/p/3372855.html
    http://blog.csdn.net/yusiguyuan/article/details/12649737

    展开全文
  • Jni中执行ndk-build,编译第三方静态库(.a)和动态库(.so)的Android.mk文件写法,这是Jni测试引用第三方静态库和动态库demo
  • Linux下gcc生成和使用静态库和动态库详解

    万次阅读 多人点赞 2016-05-31 17:54:25
    Linux下gcc生成和使用静态库和动态库详解(原文链接) 本文在原文的基础上做一些详细验证,部分稍有改动, 一、基本概念 1.1什么是库 1.2库的种类 1.3库存在的意义 1.4库文件是如何产生的在linux下 1.5库文件...

    本文在原文的基础上做一些详细验证,部分内容排版稍有调整
    本文地址:http://blog.csdn.net/CSqingchen/article/details/51546784

    一、基本概念

    1.1 什么是库

    在windows平台和linux平台下都大量存在着库。
    本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。
    由于windows和linux的平台不同(主要是编译器、汇编器和连接器的不同),因此二者库的二进制是不兼容的。
    本文仅限于介绍linux下的库。

    1.2 库的种类

    linux下的库有两种:静态库和共享库(动态库)。
    二者的不同点在于代码被载入的时刻不同。
    静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。
    共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。

    1.3 库存在的意义

    库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议。
    现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。
    共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。

    1.4 库文件是如何产生的在linux下

    静态库的后缀是.a,它的产生分两步

    1. 由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表
    2. ar命令将很多.o转换成.a,成为静态库
      动态库的后缀是.so,它由gcc加特定参数编译产生。
      具体方法参见后文实例。

    1.5 库文件是如何命名的,有没有什么规范

    在linux下,库文件一般放在/usr/lib和/lib下,
    静态库的名字一般为libxxxx.a,其中xxxx是该lib的名称
    动态库的名字一般为libxxxx.so.major.minor,xxxx是该lib的名称,major是主版本号, minor是副版本号

    1.6 如何知道一个可执行程序依赖哪些库

    ldd命令可以查看一个可执行程序依赖的共享库,
    例如$ ldd /bin/lnlibc.so.6
    => /lib/libc.so.6 (0×40021000)/lib/ld-linux.so.2
    => /lib/ld- linux.so.2 (0×40000000)
    可以看到ln命令依赖于libc库和ld-linux库

    1.7 可执行程序在执行的时候如何定位共享库文件

    当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。
    此时就需要系统动态载入器(dynamic linker/loader)
    对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH段—环境变量LD_LIBRARY_PATH—/etc/ld.so.cache文件列表—/lib/,/usr/lib目录找到库文件后将其载入内存
    如:export LD_LIBRARY_PATH='pwd'
    将当前文件目录添加为共享目录

    1.8 在新安装一个库之后如何让系统能够找到他

    如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。
    如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下
    1.编辑/etc/ld.so.conf文件,加入库文件所在目录的路径
    2.运行ldconfig 目录名字,该命令会重建/etc/ld.so.cache文件

    二、用gcc生成静态和动态链接库的示例

    我们通常把一些公用函数制作成函数库,供其它程序使用。
    函数库分为静态库和动态库两种。

    静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。

    动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。

    本文主要通过举例来说明在Linux中如何创建静态库和动态库,以及使用它们。

    为了便于阐述,我们先做一部分准备工作。

    2.1 准备好测试代码

    hello.h(见程序1)为该函数库的头文件。

    hello.c(见程序2)是函数库的源程序,其中包含公用函数hello,该函数将在屏幕上输出"Hello XXX!"。

    main.c(见程序3)为测试库文件的主程序,在主程序中调用了公用函数hello。

    测试机器环境:gcc version 4.8.4 ;ubuntu14.04.3

    三个程序放在文件夹~/testso
    程序1: hello.h

    #ifndef HELLO_H 
    #define HELLO_H 
        void hello(const char *name); 
    #endif
    

    程序2:hello.c

    #include <stdio.h> 
    void hello(const char *name) { 
        printf("Hello %s!\n", name); 
    }
    

    程序3:main.c

    #include  "hello.h"
    int main() 
     { 
         hello("everyone"); 
         return 0; 
     }
    

    2.2 问题的提出

    注意:这个时候,我们编译好的hello.o是无法通过gcc –o 编译的,这个道理非常简单,
    hello.c是一个没有main函数的.c程序,因此不够成一个完整的程序,如果使用gcc –o 编译并连接它,GCC将报错。
    无论静态库,还是动态库,都是由.o文件创建的。因此,我们必须将源程序hello.c通过gcc先编译成.o文件。
    这个时候我们有三种思路:
    1) 通过编译多个源文件,直接将目标代码合成一个.o文件。
    2) 通过创建静态链接库libmyhello.a,使得main函数调用hello函数时可调用静态链接库。
    3) 通过创建动态链接库libmyhello.so,使得main函数调用hello函数时可调用静态链接库。

    2.3 思路一:编译多个源文件

    在系统提示符下键入以下命令得到hello.o文件。
    gcc -c hello.c
    为什么不使用gcc –o hello hello.c这个道理我们之前已经说了,使用-c是什么意思呢?这涉及到gcc 编译选项的常识。

    gcc –o是将.c源文件编译成为一个可执行的二进制代码(-o选项其实是制定输出文件文件名,如果不加-c选项,gcc默认会编译连接生成可执行文件,文件的名称有-o选项指定),这包括调用作为GCC内的一部分真正的C编译器(ccl),以及调用GNU C编译器的输出中实际可执行代码的外部GNU汇编器(as)和连接器工具(ld)。
    gcc –c是使用GNU汇编器将源文件转化为目标代码之后就结束,在这种情况下,只调用了C编译器(ccl)和汇编器(as),而连接器(ld)并没有被执行,所以输出的目标文件不会包含作为Linux程序在被装载和执行时所必须的包含信息,但它可以在以后被连接到一个程序。
    我们运行ls命令看看是否生存了hello.o文件。
    $ ls
    hello.c hello.h hello.o main.c
    在ls命令结果中,我们看到了hello.o文件,本步操作完成。

    同理编译main
    $gcc –c main.c

    将两个文件链接成一个.o文件。
    $gcc hello.o main.o -o hello

    运行
    $ ./hello

    Hello everyone!

    完成^ ^!

    2.4 思路二:静态链接库

    下面我们先来看看如何创建静态库,以及使用它。

    静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将创建的静态库名为myhello,则静态库文件名就是libmyhello.a。在创建和使用静态库时,需要注意这点。创建静态库用ar命令。

    在系统提示符下键入以下命令将创建静态库文件libmyhello.a。
    $ ar rcs libmyhello.a hello.o

    我们同样运行ls命令查看结果:
    $ ls
    hello.c hello.h hello.o libmyhello.a main.c

    ls命令结果中有libmyhello.a。

    静态库制作完了,如何使用它内部的函数呢?只需要在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明静态库名,gcc将会从静态库中将公用函数连接到目标文件中。注意,gcc会在静态库名前加上前缀lib,然后追加扩展名.a得到的静态库文件名来查找静态库文件,因此,我们在写需要连接的库时,只写名字就可以,如libmyhello.a的库,只写:-lmyhello

    在程序3:main.c中,我们包含了静态库的头文件hello.h,然后在主程序main中直接调用公用函数hello。下面先生成目标程序hello,然后运行hello程序看看结果如何。

    $ gcc -o hello main.c -static -L. -lmyhello
    $ ./hello
    Hello everyone!

    我们删除静态库文件试试公用函数hello是否真的连接到目标文件 hello中了。
    $ rm libmyhello.a
    $ ./hello
    Hello everyone!

    程序照常运行,静态库中的公用函数已经连接到目标文件中了。
    静态链接库的一个缺点是,如果我们同时运行了许多程序,并且它们使用了同一个库函数,这样,在内存中会大量拷贝同一库函数。这样,就会浪费很多珍贵的内存和存储空间。使用了共享链接库的Linux就可以避免这个问题。

    共享函数库和静态函数在同一个地方,只是后缀有所不同。比如,在一个典型的Linux系统,标准的共享数序函数库是/usr/lib/libm.so。

    当一个程序使用共享函数库时,在连接阶段并不把函数代码连接进来,而只是链接函数的一个引用。当最终的函数导入内存开始真正执行时,函数引用被解析,共享函数库的代码才真正导入到内存中。这样,共享链接库的函数就可以被许多程序同时共享,并且只需存储一次就可以了。共享函数库的另一个优点是,它可以独立更新,与调用它的函数毫不影响。

    2.5 思路三、动态链接库(共享函数库)

    我们继续看看如何在Linux中创建动态库。我们还是从.o文件开始。

    动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀lib,但其文件扩展名为.so。例如:我们将创建的动态库名为myhello,则动态库文件名就是libmyhello.so。用gcc来创建动态库。

    在系统提示符下键入以下命令,得到动态库文件libmyhello.so。
    $ gcc -shared -fPIC -c hello.c 注:chenjim添加,原文没有,下一行会报错
    $ gcc -shared -fPIC -o libmyhello.so hello.o

    “PIC”命令行标记告诉GCC产生的代码不要包含对函数和变量具体内存位置的引用,这是因为现在还无法知道使用该消息代码的应用程序会将它连接到哪一段内存地址空间。这样编译出的hello.o可以被用于建立共享链接库。建立共享链接库只需要用GCC的”-shared”标记即可。

    我们照样使用ls命令看看动态库文件是否生成。
    $ ls
    hello.cpp hello.h hello.o libmyhello.so main.cpp
    调用动态链接库编译目标文件。

    在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明动态库名进行编译。我们先运行gcc命令生成目标文件,再运行它看看结果。

    如果直接用如下方法进行编译,并连接:
    $ gcc -o hello main.c -L. -lmyhello

    (使用”-lmyhello”标记来告诉GCC驱动程序在连接阶段引用共享函数库libmyhello.so。”-L.”标记告诉GCC函数库可能位于当前目录)

    $ ./hello
    ./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory

    错误提示,找不到动态库文件libmyhello.so。程序在运行时,会查找需要的动态库文件,顺序参考后文介绍。若找到,则载入动态库,否则将提示类似上述错误而终止程序运行。有多种方法可以解决,
    (1)我们将文件 libmyhello.so复制到目录/usr/lib中,再试试。
    $ sudo mv libmyhello.so /usr/lib
    (2)既然连接器会搜寻LD_LIBRARY_PATH所指定的目录,那么我们可以将这个环境变量设置成当前目录:
    export LD_LIBRARY_PATH=$(pwd)
    (3)sudo ldconfig ~/testso
    注: 当用户在某个目录下面创建或拷贝了一个动态链接库,若想使其被系统共享,可以执行一下"ldconfig 目录名"这个命令。此命令的功能在于让ldconfig将指定目录下的动态链接库被系统共享起来,意即:在缓存文件/etc/ld.so.cache中追加进指定目录下的共享库.本例让系统共享了~/tests目录下的动态链接库。


    下面的这个错误我没有遇到,不过也记录下,给遇到的人:
    { 这步后我没有成功,报错内容如下:/hello: error while loading shared libraries: /usr/lib/libmyhello.so: cannot restore segment prot after reloc: Permission denied
    google了一下,发现是SELinux搞的鬼,解决办法有两个:

    1. chcon -t texrel_shlib_t /usr/lib/libmyhello.so
      (chcon -t texrel_shlib_t “你不能share的库的绝对路径”)
    2. $vi /etc/sysconfig/selinux file
      或者用
      $gedit /etc/sysconfig/selinux file
      修改SELINUX=disabled
      重启

    这也进一步说明了动态库在程序运行时是需要的。
    可以查看程序执行时调用动态库的过程:
    $ ldd hello
    可以看到它是如何调用动态库中的函数的。
    linux-vdso.so.1 => (0x00007fffe8f9b000)
    libmyhello.so => /home/chenjw/testso/libmyhello.so (0x00007fbe807d5000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbe80410000)
    /lib64/ld-linux-x86-64.so.2 (0x000055dc016c2000)

    原文中说,使用静态库和使用动态库编译成目标程序使用的gcc命令完全一样,
    可能因为我们的环境不一样,上文我多加了一行编译命令gcc -shared -fPIC -c hello.c
    所以原文的验证,那当静态库和动态库同名时,gcc命令会使用哪个库文件呢?
    在我的环境没有意义,add by chenjim。

    2.6 编译参数解析

    最主要的是GCC命令行的一个选项:

    • -shared 该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件
    • l -fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
    • l -L.:表示要连接的库在当前目录中
    • l -ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称
    • l LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。
    • l 当然如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用 /sbin/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。
      调用动态库的时候有几个问题会经常碰到,有时,明明已经将库的头文件所在目录 通过 “-I” include进来了,库所在文件通过 “-L”参数引导,并指定了“-l”的库名,但通过ldd命令察看时,就是死活找不到你指定链接的so文件,这时你要作的就是通过修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题了。

    2.7 静态库链接时搜索路径顺序:

    1. ld会去找GCC命令中的参数-L

    2. 再找gcc的环境变量LIBRARY_PATH

    3. 再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的

    2.8 动态链接时、执行时搜索路径顺序:

    1. 编译目标代码时指定的动态库搜索路径;

    2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径;

    3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径;

    4. 默认的动态库搜索路径/lib;

    5. 默认的动态库搜索路径/usr/lib。

    2.9 有关环境变量:

    LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径

    LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径

    三、linux开发之文件夹和应用程序

    1. 应用程序(Applications)

    应用程序通常都有固定的文件夹,系统通用程序放在/usr/bin,日后系统管理员在本地计算机安装的程序通常放在/usr/local/bin或者/opt文件夹下。除了系统程序外,大部分个人用到的程序都放在/usr/local下,所以保持/usr的整洁十分重要。当升级或者重装系统的时候,只要把/usr/local的程序备份一下就可以了。

    一些其他的程序有自己特定的文件夹,比如X Window系统,通常安装在/usr/X11中,或者/usr/X11R6。GNU的编译器GCC,通常放置在/usr/bin或者/usr/local/bin中,不同的Linux版本可能位置稍有不同。

    2. 头文件(Head Files)

    在C语言和其他语言中,头文件声明了系统函数和库函数,并且定义了一些常量。对于C语言,头文件基本上散落于/usr/include和它的子文件夹下。其他的编程语言的库函数分布在编译器定义的地方,比如在一些Linux版本中,X Window系统库函数分布在/usr/include/X11,GNU C++的库函数分布在/usr/include/g++。这些系统库函数的位置对于编译器来说都是“标准位置”,即编译器能够自动搜寻这些位置。

    如果想引用位于标准位置之外的头文件,我们需要在调用编译器的时候加上-I标志,来显式的说明头文件所在文件夹。比如,
    $ gcc -I/usr/openwin/include hello.c

    会告诉编译器除了标准位置外,还要去/usr/openwin/include看看有没有所需的头文件。详细情况见编译器的使用手册(man gcc)。

    3. 库函数(Library Files)

    库函数就是函数的仓库,它们都经过编译,重用性不错。通常,库函数相互合作,来完成特定的任务。比如操控屏幕的库函数(cursers和ncursers库函数),数据库读取库函数(dbm库函数)等。

    系统调用的标准库函数一般位于/lib以及/usr/lib。C编译器(精确点说,连接器)需要知道库函数的位置。默认情况下,它只搜索标准C库函数。

    库函数文件通常开头字母是lib。后面的部分标示库函数的用途(比如C库函数用c标识, 数学库函数用m标示),小数点后的后缀表明库函数的类型:

    .a 指静态链接库
    .so 指动态链接库
    去/usr/lib看一下,你会发现,库函数都有动态和静态两个版本。

    与头文件一样,库函数通常放在标准位置,但我们也可以通过-L标识符,来添加新的搜索文件夹,-l指定特定的库函数文件。比如
    $ gcc -o x11fred -L/usr/openwin/lib x11fred.c -lX11
    上述命令就会在编译期间,链接位于/usr/openwin/lib文件夹下的libX11函数库,编译生成x11fred。

    静态链接库(Static Libraries)

    最简单的函数库就是一些函数的简单集合。调用库函数中的函数时,需要在调用函数中include定义库函数的头文件。我们用-l选项添加标准函数库之外的函数库。

    展开全文
  • gcc编译静态库和动态库

    千次阅读 2018-05-10 15:27:00
    gcc编译静态库和动态库 今天要用到静态库和动态库,于是写了几个例子来巩固一下基础。 hello1.c ———————————————————— include include void print2(char *arr) { char c; int i=0; ...
  • linux下用gcc生成静态库和动态库.doclinux下用gcc生成静态库和动态库.doclinux下用gcc生成静态库和动态库.doclinux下用gcc生成静态库和动态库.doclinux下用gcc生成静态库和动态库.doclinux下用gcc生成静态库和动态库...
  • iOS静态库和动态库合并

    千次阅读 2017-07-28 16:03:54
    查看库支持的框架: lipo -info framework下的二进制文件...合并静态库和动态库; lipo -create 第一个framework下二进制文件的绝对路径 第二个framework下二进制文件的绝对路径 -output 最终的二进制文件路径:
  • Windows下如何查看静态库和动态库

    千次阅读 2017-08-15 16:46:33
    Windows下如何查看静态库和动态库 首先找到Visual Studio Tools,然后点击Visual Studio x64 Win64 Command Prompt。1、Windows下查看静态库lib -list *.lib 或者 lib /list *.lib2、Windows下查看动态库dump ...
  • 1、Linux静态库和动态库的命名规则 静态函数库 静态库的名字一般是libxxx.a,利用静态库编译生成的文件比较大,因为整个静态库所有的数据都会被整合进目标代码中。 a)优点 编译后,可执行文件不需要外部支持; ...
  • 静态库和动态库运行时间的区别

    千次阅读 2018-12-28 14:05:44
    关于静态库和动态库的区别网上已经写了很多了,我就不再赘述,大家可以自行搜索。 这里我主要介绍静态库和动态库在运行时间上的区别。 我看书上写的是静态库比动态库在运行速度上快1%~5%。 然后我写了一段程序...
  • xcode 创建静态库和动态库

    千次阅读 2014-11-24 11:51:35
    1、linux中静态库和动态库区别: 库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。库分静态库和动态库两种。 静态库:这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个...
  • 这是静态库和动态库的编译源码,附带有动态库和静态库的编译方法,如果有任何疑问,请留言
  • Windows下使用静态库和动态库

    万次阅读 2016-05-10 23:26:39
    Windows下使用静态库和动态库
  • iOS利用Xcode制作静态库和动态库

    千次阅读 2017-03-25 23:46:51
    iOS利用Xcode制作静态库和动态库
  • 静态库和动态库 静态库 静态库文件后缀一般为 .a ,利用静态库编译成的可执行文件通常比较大,编译后的执行程序不需要外部函数库的支持。但是,如果一个程序依赖的静态库发生改变,那么这个程序就需要重新编译。 ...
  • Linux下C调用静态库和动态库

    千次阅读 2016-11-23 16:29:04
    Linux下C调用静态库和动态库本文主要介绍Linux下C调用静态库和动态库,使用的样例文件请点击这里. 样例文件welcome.c:#include #include"welcome.h"void welcome() { printf("welcome to my code world!\n"); } 这...
  • Linux编程——静态库和动态库

    千次阅读 2015-11-13 19:16:42
    库可以分为两种:静态库和动态库 静态库静态库就是一些目标文件的集合,以.a结尾。静态库在程序链接的时候使用,链接器会将程序中使用到函数的代码从库文件中拷贝到应用程序中。一旦链接完成,在执行程序的时候就...
  • android studio 简单demo实现将c++代码 编译成静态库和动态库 简单的makefile文件一看就明白
  • QT 静态库和动态库的使用方法

    千次阅读 2019-04-28 16:29:46
    QT 静态库和动态库的使用方法 背景知识:程序在编译成可执行文件时,会有四步过程: 1预处理(头文件和宏定义) g++ -E 1.cpp -o 1.i 2编译 将c代码编译成汇编代码 g++ -S 1.cpp -o 1.s 3汇编 将汇编代码编译成二...
  • linux下生成静态库和动态库

    千次阅读 多人点赞 2016-11-09 22:25:46
    linux下生成静态库和动态库 一、动态库静态库简介 库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。本质上来说库...
  • 在Linux下进行C/C++开发经常要创建和使用库,包括静态库和动态库(共享库)。 静态库文件的扩展名是.a,其命名规则是libxxx.a, 动态库的扩展名是.so,其命名规则是libxxx.so。 静态库和动态库在链接调用的是都是 -...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 353,560
精华内容 141,424
关键字:

静态库和动态库