精华内容
参与话题
问答
  • 什么是动态库

    千次阅读 2014-02-20 00:28:31
    一直以来很困惑如何在linux中编译库文件和使用库文件,今天看了一篇文章才终于搞...转:如何用gcc编译生成动态链接库*.so文件 动态库 问:我源文件为main.c, x.c, y.c, z.c,头文件为x.h,y.h,z.h 如何编译成.s

    转自:http://gui323.blog.51cto.com/3168443/798329


    一直以来很困惑如何在linux中编译库文件和使用库文件,今天看了一篇文章才终于搞明白。以下为转载文章,仅供学习,如有侵权请告知。

    转:如何用gcc编译生成动态链接库*.so文件 动态库
    问:我源文件为main.c, x.c, y.c, z.c,头文件为x.h,y.h,z.h
    如何编译成.so动态库?
    编译器用gcc
    最好能给出详细参数解释,谢谢


    答:
    # 声称动代连接库,假设名称为libtest.so
    gcc x.c y.c z.c -fPIC -shared -o libtest.so


    # 将main.c和动态连接库进行连接生成可执行文件
    gcc main.c -L. -ltest -o main


    # 输出LD_LIBRARY_PATH环境变量,一边动态库装载器能够找到需要的动态库
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.


    # 测试是否动态连接,如果列出libtest.so,那么应该是连接正常了
    ldd main


    # 执行就不用说了吧 


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


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


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


    LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。
    当然如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用
    /sbin/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。


    举例:
    动态链接库*.so的编译与使用- -
                                          


    动态库*.so在linux下用c和c++编程时经常会碰到,最近在网站找了几篇文章介绍动态库的编译和链接,总算搞懂了这个之前一直不太了解得东东,这里做个笔记,也为其它正为动态库链接库而苦恼的兄弟们提供一点帮助。
    1、动态库的编译


    下面通过一个例子来介绍如何生成一个动态库。这里有一个头文件:so_test.h,三个.c文件:test_a.c、test_b.c、test_c.c,我们将这几个文件编译成一个动态库:libtest.so。


    so_test.h:


    #include <stdio.h>
    #include <stdlib.h>
    void test_a();
    void test_b();
    void test_c();
    //---------------------------------------
    test_a.c:
    #include "so_test.h"
    void test_a()
    {
        printf("this is in test_a...\n");
    }
    //--------------------------------------
    test_b.c:
    #include "so_test.h"
    void test_b()
    {
        printf("this is in test_b...\n");
    }
    //------------------------------------------
    test_c.c:
    #include "so_test.h"
    void test_c()
    {
        printf("this is in test_c...\n");
    }


    将这几个文件编译成一个动态库:libtest.so
    $ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so
    2、动态库的链接


    在1、中,我们已经成功生成了一个自己的动态链接库libtest.so,下面我们通过一个程序来调用这个库里的函数。程序的源文件为:test.c。


    test.c:
    #include "so_test.h"
    int main()
    {
        test_a();
        test_b();
        test_c();
        return 0;
    }
    l         将test.c与动态库libtest.so链接生成执行文件test:
    $ gcc test.c -L. -ltest -o test


    l         测试是否动态连接,如果列出libtest.so,那么应该是连接正常了
    $ ldd test
             执行test,可以看到它是如何调用动态库中的函数的。
    3、编译参数解析
    最主要的是GCC命令行的一个选项:
              -shared 该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件


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


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


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


             LD_LIBRARY_PATH:这个环境变量指示动态连接器可以装载动态库的路径。


             当然如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用 /sbin/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。
    4、注意


           调用动态库的时候有几个问题会经常碰到,有时,明明已经将库的头文件所在目录 通过 “-I” include进来了,库所在文件通过 “-L”参数引导,并指定了“-l”的库名,但通过ldd命令察看时,就是死活找不到你指定链接的so文件,这时你要作的就是通过修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题了。
    展开全文
  • C++静态库与动态库(比较透彻)

    千次阅读 多人点赞 2018-03-13 19:18:07
    这次分享的宗旨是——让大家学会创建与使用静态库、动态库,知道静态库与动态库的区别,知道使用的时候如何选择。这里不深入介绍静态库、动态库的底层格式,内存布局等,有兴趣的同学,推荐一本书《程序员的自我修养...

    这次分享的宗旨是——让大家学会创建与使用静态库、动态库,知道静态库与动态库的区别,知道使用的时候如何选择。这里不深入介绍静态库、动态库的底层格式,内存布局等,有兴趣的同学,推荐一本书《程序员的自我修养——链接、装载与库》。

    1、一个程序从源文件编译生成可执行文件的步骤:

    预编译 -->  编译 -->  汇编 --> 链接

    (1)预编译,即预处理,主要处理在源代码文件中以“#”开始的预编译指令,如宏展开、处理条件编译指令、处理#include指令等。

    (2)编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析以及优化后生成相应的汇编代码文件。

    (3)汇编是将汇编代码转变成二进制文件。

    (4)链接将二进制文件链接成一个可执行的命令,主要是把分散的数据和代码收集并合成一个单一的可加载并可执行的的文件。链接可以发生在代码静态编译、程序被加载时以及程序执行时。链接过程的主要工作是符号解析和重定位。

    2、库 

    库是一组目标文件的包,就是一些最常用的代码编译成目标文件后打包存放。而最常见的库就是运行时库(Runtime Library),如C运行库CRT.

    库一般分为两种:静态库(.a 、.lib)动态库(.so 、.dll )所谓静态、动态是指链接过程。 

    3、静态库与动态库

    区别:

    (1)lib是编译时用到的,dll是运行时用到的。如果要完成源代码的编译,只需要lib;如果要使动态链接的程序运行起来,只需要dll。
    (2)如果有dll文件,那么lib一般是一些索引信息,记录了dll中函数的入口和位置,dll中是函数的具体内容;如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。使用静态编译的lib文件,在运行程序时不需要再挂动态库,缺点是导致应用程序比较大,而且失去了动态库的灵活性,发布新版本时要发布新的应用程序才行。
    (3)动态链接的情况下,有两个文件:一个是LIB文件,一个是DLL文件。LIB包含被DLL导出的函数名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到DLL文件。在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中相应函数代码的地址,从而节省了内存资源。DLL和LIB文件必须随应用程序一起发行,否则应用程序会产生错误。如果不想用lib文件或者没有lib文件,可以用WIN32 API函数LoadLibrary、GetProcAddress装载。

    ------这里主要讲动态库的优点特性。--------

    静态库:函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。在使用静态库的情况下,在编译链接可执行文件时,链接器从库中复制这些函数和数据并把它们和应用程序的其它模块组合起来创建最终的可执行文件(.EXE文件)。
    在使用动态库的时候,往往提供两个文件:一个引入库和一个DLL。引入库包含被DLL导出的函数和变量的符号名,DLL包含实际的函数和数据。在编译链接可执行文件时,只需要链接引入库,DLL中的函数代码和数据并不复制到可执行文件中,在运行的时候,再去加载DLL,访问DLL中导出的函数。

    静态库有两个重大缺点:

    1)空间浪费

    2)静态链接对程序的更新、部署和发布会带来很多麻烦。一旦程序中有任何模块更新,整个程序就要重新链接,发布给用户。

    动态链接的基本思想:把程序按照模块拆分成各个相对独立的部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不是想静态链接一样把所有的程序模块都链接成一个单独的可执行文件。

    特点:

    1)代码共享,所有引用该动态库的可执行目标文件共享一份相同的代码与数据。

    2)程序升级方便,应用程序不需要重新链接新版本的动态库来升级,理论上只要简单地将旧的目标文件覆盖掉。

    3)在运行时可以动态地选择加载各种应用程序模块


    什么是库

    库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常

    本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。库有两种:静态库(.a.lib)和动态库(.so.dll)。

    所谓静态、动态是指链接。回顾一下,将一个程序编译成可执行程序的步骤:

     

    图:编译过程

    静态库

    之所以成为【静态库】,是因为在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。因此对应的链接方式称为静态链接。

    试想一下,静态库与汇编生成的目标文件一起链接为可执行文件,那么静态库必定跟.o文件格式相似。其实一个静态库可以简单看成是一组目标文件(.o/.obj文件)的集合,即很多目标文件经过压缩打包后形成的一个文件。静态库特点总结:

    l  静态库对函数库的链接是放在编译时期完成的。

    l  程序在运行时与函数库再无瓜葛,移植方便。

    l  浪费空间和资源,因为所有相关的目标文件与牵涉到的函数库被链接合成一个可执行文件。

    下面编写一些简单的四则运算C++类,将其编译成静态库给他人用,头文件如下所示:

    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();

    };

     

    Linux下使用ar工具、Windowsvs使用lib.exe,将目标文件压缩到一起,并且对其进行编号和索引,以便于查找和检索。一般创建静态库的步骤如图所示:

     

    图:创建静态库过程

    Linux下创建与使用静态库

    Linux静态库命名规则

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

    创建静态库(.a

    通过上面的流程可以知道,Linux创建静态库过程如下:

    l  首先,将代码文件编译成目标文件.oStaticMath.o

    g++ -c StaticMath.cpp

    注意带参数-c,否则直接编译为可执行文件

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

    ar -crv libstaticmath.a StaticMath.o

    生成静态库libstaticmath.a

     

    大一点的项目会编写makefile文件(CMake等等工程管理工具)来生成静态库,输入多个命令太麻烦了。

    使用静态库

    编写使用上面创建的静态库的测试代码:

    测试代码:

    #include "StaticMath.h"

    #include <iostream>

    using namespace std;

     

    int main(int argccharargv[])

    {

        double a = 10;

        double b = 2;

     

        cout << "a + b = " << StaticMath::add(a, b) << endl;

        cout << "a - b = " << StaticMath::sub(a, b) << endl;

        cout << "a * b = " << StaticMath::mul(a, b) << endl;

        cout << "a / b = " << StaticMath::div(a, b) << endl;

     

        StaticMath sm;

        sm.print();

     

        system("pause");

        return 0;

    }

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

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

     

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

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

     

    Windows下创建与使用静态库

    创建静态库(.lib

    如果是使用VS命令行生成静态库,也是分两个步骤来生成程序:

    l  首先,通过使用带编译器选项 /c  Cl.exe 编译代码 (cl /c StaticMath.cpp),创建名为“StaticMath.obj”的目标文件。

    l  然后,使用库管理器 Lib.exe 链接代码 (lib StaticMath.obj),创建静态库StaticMath.lib

    当然,我们一般不这么用,使用VS工程设置更方便。创建win32控制台程序时,勾选静态库类型;打开工程属性面板è配置属性è常规,配置类型选择静态库。

     

    图:vs静态库项目属性设置

    Build项目即可生成静态库。

    使用静态库

    测试代码Linux下面的一样。有3种使用方法:

    方法一:

    VS中使用静态库方法:

    l  工程属性面板è通用属性è “框架和引用è添加引用,将显示添加引用对话框。 “项目选项卡列出了当前解决方案中的各个项目以及可以引用的所有库。 项目选项卡中,选择 StaticLibrary 单击确定

     

    l  添加StaticMath.h 头文件目录,必须修改包含目录路径。打开工程属性面板è配置属性è “C/C++”è” 常规,在附加包含目录属性值中,键入StaticMath.h 头文件所在目录的路径或浏览至该目录。

     

    编译运行OK

     

    图:静态库测试结果(vs

    如果引用的静态库不是在同一解决方案下的子工程,而是使用第三方提供的静态库lib和头文件,上面的方法设置不了。还有2中方法设置都可行。

    方法二:

    打开工程属性面板è配置属性è “链接器è命令行,输入静态库的完整路径即可。

     

    方法三:

    l  属性面板è配置属性è “链接器è常规,附加依赖库目录中输入,静态库所在目录;

    l  属性面板è配置属性è “链接器è输入,附加依赖库中输入静态库名StaticLibrary.lib

     

    动态库

    通过上面的介绍发现静态库,容易使用和理解,也达到了代码复用的目的,那为什么还需要动态库呢?

    为什么还需要动态库?

    为什么需要动态库,其实也是静态库的特点导致。

    l  空间浪费是静态库的一个问题。

     

    l  另一个问题是静态库对程序的更新、部署和发布页会带来麻烦。如果静态库liba.lib更新了,所以使用它的应用程序都需要重新编译、发布给用户(对于玩家来说,可能是一个很小的改动,却导致整个程序重新下载,全量更新)。

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

     

    动态库特点总结:

    l  动态库把对一些库函数的链接载入推迟到程序运行的时期。

    l  可以实现进程之间的资源共享。(因此动态库也称为共享库)

    l  将一些程序升级变得简单。

    l  甚至可以真正做到链接载入完全由程序员在程序代码中控制(显示调用)。

    WindowLinux执行文件格式不同,在创建动态库的时候有一些差异。

    l  Windows系统下的执行文件格式是PE格式,动态库需要一个DllMain函数做出初始化的入口,通常在导出函数的声明时需要有_declspec(dllexport)关键字

    l  Linuxgcc编译的执行文件默认是ELF格式,不需要初始化入口,亦不需要函数做特别的声明,编写比较方便。

    与创建静态库不同的是,不需要打包工具(arlib.exe),直接使用编译器即可创建动态库。

    Linux下创建与使用动态库

     

    linux动态库的命名规则

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

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

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

    创建动态库(.so

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

    DynamicMath.h头文件

    #pragma once

    class DynamicMath

    {

    public:

            DynamicMath(void);

            ~DynamicMath(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();

    };

     

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

    g++ -fPIC -c DynamicMath.cpp

    -fPIC 创建与地址无关的编译程序(picposition independent code),是为了能够在多个应用程序间共享。

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

    g++ -shared -o libdynmath.so DynamicMath.o

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

     

    其实上面两个步骤可以合并为一个命令:

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

     

    使用动态库

    编写使用动态库的测试代码:

    测试代码:

    #include "../DynamicLibrary/DynamicMath.h"

     

    #include <iostream>

    using namespace std;

     

    int main(int argc, char* argv[])

    {

        double a = 10;

        double b = 2;

     

        cout << "a + b = " << DynamicMath::add(a, b) << endl;

        cout << "a - b = " << DynamicMath::sub(a, b) << endl;

        cout << "a * b = " << DynamicMath::mul(a, b) << endl;

        cout << "a / b = " << DynamicMath::div(a, b) << endl;

     

        DynamicMath dyn;

        dyn.print();

        return 0;

    }

    引用动态库编译成可执行文件(跟静态库方式一样):

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

    然后运行:./a.out,发现竟然报错了!!!

     

    可能大家会猜测,是因为动态库跟测试程序不是一个目录,那我们验证下是否如此:

     

    发现还是报错!!!那么,在执行的时候是如何定位共享库文件的呢?

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

    2)        对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH段—环境变量LD_LIBRARY_PATH/etc/ld.so.cache文件列表—/lib/,/usr/lib 目录找到库文件后将其载入内存。

    如何让系统能够找到它:

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

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

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

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

    我们将创建的动态库复制到/usr/lib下面,然后运行测试程序。

     

    Windows下创建与使用动态库

    创建动态库(.dll

    Linux相比,在Windows系统下创建动态库要稍微麻烦一些。首先,需要一个DllMain函数做出初始化的入口(创建win32控制台程序时,勾选DLL类型会自动生成这个文件):

    dllmain.cpp入口文件

    // dllmain.cpp : Defines the entry point for the DLL application.

    #include "stdafx.h"

     

    BOOL APIENTRY DllMain( HMODULE hModule,

                           DWORD  ul_reason_for_call,

                           LPVOID lpReserved

                         )

    {

        switch (ul_reason_for_call)

        {

        case DLL_PROCESS_ATTACH:

        case DLL_THREAD_ATTACH:

        case DLL_THREAD_DETACH:

        case DLL_PROCESS_DETACH:

            break;

        }

        return TRUE;

    }

    通常在导出函数的声明时需要有_declspec(dllexport)关键字:

    DynamicMath.h头文件

    #pragma once

    class DynamicMath

    {

    public:

        __declspec(dllexport) DynamicMath(void);

        __declspec(dllexport) ~DynamicMath(void);

     

        static __declspec(dllexportdouble add(double a, double b);//加法

        static __declspec(dllexportdouble sub(double a, double b);//减法

        static __declspec(dllexportdouble mul(double a, double b);//乘法

        static __declspec(dllexportdouble div(double a, double b);//除法

     

        __declspec(dllexportvoid print();

    };

    生成动态库需要设置工程属性,打开工程属性面板è配置属性è常规,配置类型选择动态库。

     

    图:v动态库项目属性设置

    Build项目即可生成动态库。

    使用动态库

    创建win32控制台测试程序:

    TestDynamicLibrary.cpp测试程序

    #include "stdafx.h"

    #include "DynamicMath.h"

     

    #include <iostream>

    using namespace std;

     

    int _tmain(int argc_TCHARargv[])

    {

        double a = 10;

        double b = 2;

     

        cout << "a + b = " << DynamicMath::add(a, b) << endl;

        cout << "a - b = " << DynamicMath::sub(a, b) << endl;

        cout << "a * b = " << DynamicMath::mul(a, b) << endl;

        cout << "a / b = " << DynamicMath::div(a, b) << endl;

     

        DynamicMath dyn;

        dyn.print();

     

        system("pause");

        return 0;

    }

    方法一:

    l  工程属性面板è通用属性è “框架和引用è添加引用,将显示添加引用对话框。项目选项卡列出了当前解决方案中的各个项目以及可以引用的所有库。 项目选项卡中,选择 DynamicLibrary 单击确定

     

    l  添加DynamicMath.h 头文件目录,必须修改包含目录路径。打开工程属性面板è配置属性è “C/C++”è” 常规,在附加包含目录属性值中,键入DynamicMath.h 头文件所在目录的路径或浏览至该目录。

     

    编译运行OK

     

    图:动态库测试结果(vs

    方法二:

    l  属性面板è配置属性è “链接器è常规,附加依赖库目录中输入,动态库所在目录;

     

    l  属性面板è配置属性è “链接器è输入,附加依赖库中输入动态库编译出来的DynamicLibrary.lib

     

    这里可能大家有个疑问,动态库怎么还有一个DynamicLibrary.lib文件?即无论是静态链接库还是动态链接库,最后都有lib文件,那么两者区别是什么呢?其实,两个是完全不一样的东西。

     

    StaticLibrary.lib的大小为190KBDynamicLibrary.lib的大小为3KB,静态库对应的lib文件叫静态库,动态库对应的lib文件叫【导入库】。实际上静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息

    动态库的显式调用

    上面介绍的动态库使用方法和静态库类似属于隐式调用,编译的时候指定相应的库和查找路径。其实,动态库还可以显式调用。【在C语言中】,显示调用一个动态库轻而易举!

    Linux下显式调用动态库

    #include <dlfcn.h>,提供了下面几个接口:

    l  void * dlopen( const char * pathname, int mode ):函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。

    l  void* dlsym(void* handle,const char* symbol)dlsym根据动态链接库操作句柄(pHandle)与符号(symbol),返回符号对应的地址。使用这个函数不但可以获取函数地址,也可以获取变量地址。

    l  int dlclose (void *handle)dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0,才会真正被系统卸载。

    l  const char *dlerror(void):当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。

    Windows下显式调用动态库

    应用程序必须进行函数调用以在运行时显式加载 DLL。为显式链接到 DLL,应用程序必须:

    l  调用 LoadLibrary(或相似的函数)以加载 DLL 和获取模块句柄。

    l  调用 GetProcAddress,以获取指向应用程序要调用的每个导出函数的函数指针。由于应用程序是通过指针调用 DLL 的函数,编译器不生成外部引用,故无需与导入库链接。

    l  使用完 DLL 后调用 FreeLibrary

    显式调用C++动态库注意点

    C++来说,情况稍微复杂。显式加载一个C++动态库的困难一部分是因为C++name mangling另一部分是因为没有提供一个合适的API来装载类,在C++中,您可能要用到库中的一个类,而这需要创建该类的一个实例,这不容易做到。

    name mangling可以通过extern "C"解决。C++有个特定的关键字用来声明采用C binding的函数:extern "C" 。用 extern "C"声明的函数将使用函数名作符号名,就像C函数一样。因此,只有非成员函数才能被声明为extern "C",并且不能被重载。尽管限制多多,extern "C"函数还是非常有用,因为它们可以象C函数一样被dlopen动态加载。冠以extern "C"限定符后,并不意味着函数中无法使用C++代码了,相反,它仍然是一个完全的C++函数,可以使用任何C++特性和各种类型的参数。

    另外如何从C++动态库中获取类,附上几篇相关文章,但我并不建议这么做:

    l  LoadLibrary调用DLL中的Class》:http://www.cppblog.com/codejie/archive/2009/09/24/97141.html

    l  C++ dlopen mini HOWTO》:http://blog.csdn.net/denny_233/article/details/7255673

    “显式”使用C++动态库中的Class是非常繁琐和危险的事情,因此能用“隐式”就不要用“显式”,能静态就不要用动态。

    附件:Linux下库相关命令

    g++(gcc)编译选项

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

    l  -static :指定生成静态链接库。

    l  -fPIC :表示编译为位置独立的代码,用于编译共享库。目标文件需要创建成位置无关码, 念上就是在可执行程序装载它们的时候,它们可以放在可执行程序的内存里的任何地方。

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

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

    l  -Wall :生成所有警告信息。

    l  -ggdb :此选项将尽可能的生成gdb 的可以使用的调试信息。

    l  -g :编译器在编译的时候产生调试信息。

    l  -c :只激活预处理、编译和汇编,也就是把程序做成目标文件(.o文件

    l  -Wl,options :把参数(options)传递给链接器ld 。如果options 中间有逗号,就将options分成多个选项,然后传递给链接程序。

    nm命令

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

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

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

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

    $nm libhello.h

    ldd命令

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

     

    总结

    二者的不同点在于代码被载入的时刻不同

    l  静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库,因此体积较大

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

    动态库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。带来好处的同时,也会有问题!如经典的DLL Hell问题,关于如何规避动态库管理问题,可以自行查找相关资料。

     

    展开全文
  • 动态链接在企业级开发中无处不在,本课程包含Windows动态链接相关知识点,通过浅显易懂的代码与讲解,让你熟悉掌握动态链接技术!
  • C++动态库封装及调用

    万次阅读 多人点赞 2017-05-10 11:40:33
    一直对动态库的封装理解不是很透彻,虽然之前写过一个Demo,不过并没有真正的理解。所以写下来,帮助自己理解下。 1、一个程序从源文件编译生成可执行文件的步骤: 预编译 --> 编译 --> 汇编 --> 链接 (1)预编译...

    一直对动态库的封装理解不是很透彻,虽然之前写过一个Demo,不过并没有真正的理解。所以写下来,帮助自己理解下。

    1、一个程序从源文件编译生成可执行文件的步骤:

    预编译 -->  编译 -->  汇编 --> 链接

    (1)预编译,即预处理,主要处理在源代码文件中以“#”开始的预编译指令,如宏展开、处理条件编译指令、处理#include指令等。

    (2)编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析以及优化后生成相应的汇编代码文件。

    (3)汇编是将汇编代码转变成二进制文件。

    (4)链接将二进制文件链接成一个可执行的命令,主要是把分散的数据和代码收集并合成一个单一的可加载并可执行的的文件。链接可以发生在代码静态编译、程序被加载时以及程序执行时。链接过程的主要工作是符号解析和重定位。

    2、库 

    库是一组目标文件的包,就是一些最常用的代码编译成目标文件后打包存放。而最常见的库就是运行时库(Runtime Library),如C运行库CRT.

    库一般分为两种:静态库(.a 、.lib)动态库(.so 、.dll )所谓静态、动态是指链接过程。 

    3、静态库与动态库

    区别:

    (1)lib是编译时用到的,dll是运行时用到的。如果要完成源代码的编译,只需要lib;如果要使动态链接的程序运行起来,只需要dll。
    (2)如果有dll文件,那么lib一般是一些索引信息,记录了dll中函数的入口和位置,dll中是函数的具体内容;如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。使用静态编译的lib文件,在运行程序时不需要再挂动态库,缺点是导致应用程序比较大,而且失去了动态库的灵活性,发布新版本时要发布新的应用程序才行。
    (3)动态链接的情况下,有两个文件:一个是LIB文件,一个是DLL文件。LIB包含被DLL导出的函数名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到DLL文件。在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中相应函数代码的地址,从而节省了内存资源。DLL和LIB文件必须随应用程序一起发行,否则应用程序会产生错误。如果不想用lib文件或者没有lib文件,可以用WIN32 API函数LoadLibrary、GetProcAddress装载。

    ------这里主要讲动态库的优点特性。--------

    静态库:函数和数据被编译进一个二进制文件(通常扩展名为.LIB)。在使用静态库的情况下,在编译链接可执行文件时,链接器从库中复制这些函数和数据并把它们和应用程序的其它模块组合起来创建最终的可执行文件(.EXE文件)。
    在使用动态库的时候,往往提供两个文件:一个引入库和一个DLL。引入库包含被DLL导出的函数和变量的符号名,DLL包含实际的函数和数据。在编译链接可执行文件时,只需要链接引入库,DLL中的函数代码和数据并不复制到可执行文件中,在运行的时候,再去加载DLL,访问DLL中导出的函数。

    静态库有两个重大缺点:

    1)空间浪费

    2)静态链接对程序的更新、部署和发布会带来很多麻烦。一旦程序中有任何模块更新,整个程序就要重新链接,发布给用户。

    动态链接的基本思想:把程序按照模块拆分成各个相对独立的部分,在程序运行时才将它们链接在一起形成一个完整的程序,而不是想静态链接一样把所有的程序模块都链接成一个单独的可执行文件。

    特点:

    1)代码共享,所有引用该动态库的可执行目标文件共享一份相同的代码与数据。

    2)程序升级方便,应用程序不需要重新链接新版本的动态库来升级,理论上只要简单地将旧的目标文件覆盖掉。

    3)在运行时可以动态地选择加载各种应用程序模块

    下面重点介绍Windows下动态链接库DLL.

    DLL即动态链接库(Dynamic-Link Libaray)的缩写,相当于Linux下的共享对象。Windows系统中大量采用了DLL机制,甚至内核的结构很大程度依赖与DLL机制。Windows下的DLL文件和EXE文件实际上是一个概念,都是PE格式的二进制文件。一般的动态库程序有lib文件和dll文件,lib文件是编译时期连接到应用程序中的,而dll文件是运行时才会被调用的。

    为了更好的理解DLL,首先介绍一下导出和导入的概念。

    (1)导出与导入

    在ELF(Linux下动态库的格式),共享库中所有的全局函数和变量在默认情况下都可以被其他模块使用,即ELF默认导出所有的全局符号。DLL不同,需要显式地“告诉”编译器需要导出某个符号,否则编译器默认所有的符号都不导出。

    程序使用DLL的过程其实是引用DLL中导出函数和符号的过程,即导入过程。对于从其他DLL导入的符号,需要使用“__declspec(dllimport)”显式声明某个符号为导入符号。在ELF中,使用外部符号时,不需要额外声明该符号是从其他共享对象导入的。

    指定符号的导入导出一般有如下两种方法:

    1)MSVC编译器提供了一系列C/C++的扩展来指定符号的导入导出,即__declspec属性关键字

    __declspec(dllexport) 表示该符号是从本DLL导出的符号

    __declspec(dllimport) 表示该符号是从别的DLL中导入的

    2)使用“.def”文件来声明导入到导出符号,详细参考《程序员的自我修养--链接、装载与库》。

    应用程序使用DLL可以采用两种方式:一种是隐式链接(调用),另一种是显式链接。在使用DLL之前首先要知道DLL中函数的结构信息
    4、DLL创建



    下面是头文件内容:创建工程时有默认的导出函数,这里将其删除掉重新写的。

    // 下列 ifdef 块是创建使从 DLL 导出更简单的
    // 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 MYDLL_EXPORTS
    // 符号编译的。在使用此 DLL 的
    // 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
    // MYDLL_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
    // 符号视为是被导出的。
    #ifdef MYDLL_EXPORTS
    #define MYDLL_API __declspec(dllexport)
    #else
    #define MYDLL_API __declspec(dllimport)
    #endif
    
    extern "C" MYDLL_API double seekArea(int r, int h);
    

    这里将seek函数声明为导出函数;

    当定义了符号MYDLL_EXPORTS,MYDLL_API被设置为 __declspec(dllexport)修饰符,This modifier enables the function to be exported by the DLL so that it can be used by other applications。若未定义则TMYDLL_API被设置为__declspec(dllimport)This modifier enables the compiler to optimize the importing of the function from the DLL for use in other applications。当DLL项目生成时,MYDLL_EXPORTS默认是定义的,所以默认设置的是__declspec(dllexport) 修饰符。 

    对应源文件的内容:

    // myDLL.cpp : 定义 DLL 应用程序的导出函数。
    //封装圆柱体的体积
    
    #include "stdafx.h"
    #include "stdio.h"
    #include "myDLL.h"
    
    void show(){
    	printf("Call the library function.\n");
    	printf("***************************\n");
    }
    double area(int r){
    	return 3.14*r*r;
    }
    
    MYDLL_API double seekArea(int r, int h){
    	show();
    	double under = 3.14*r*r;
    	double v = under*h;
    	return v;
    }
    

    然后编译就会生成对应的dll文件,同时也会生成对应的lib文件。 
    注意:a.DLL中导出函数的声明有两种方式:在函数声明中加上__declspec(dllexport);采用模块定义(.def)文件声明。详见:http://www.cnblogs.com/enterBeijingThreetimes/archive/2010/08/04/1792099.html 
      b.对于C文件创建dll时或者想使用C编译器创建dll时,建议使用 extern “C” 标志,参见extern "C"的简单解析


    5.DLL的隐式调用

    隐式链接采用静态加载的方式,比较简单,需要.h、.lib、.dll三件套。新建“控制台应用程序”或“空项目”。配置如下: 
    项目->属性->配置属性->VC++ 目录-> 在“包含目录”里添加头文件testdll.h所在的目录 
    项目->属性->配置属性->VC++ 目录-> 在“库目录”里添加头文件testdll.lib所在的目录 
    项目->属性->配置属性->链接器->输入-> 在“附加依赖项”里添加“testdll.lib”(若有多个 lib 则以空格隔开) 。 //你也可以在项目属性中设置库的链接,#pragma comment(lib, "DLLSample.lib")


    库文件头文件等目录设置,本文将库文件及头文件拷贝到工程目录下DLL文件夹下

    添加LIB依赖项


    #调用的源程序#

    // callmyDLL.cpp : 定义控制台应用程序的入口点。
    //包含头头文件,函数声明
    
    
    #include "stdafx.h"
    #include "stdlib.h"
    #include "myDLL.h"
    extern "C" _declspec(dllimport)  double seekArea(int r, int h);
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	int r = 1, h = 5;
    	double area = seekArea(r, h);
    	printf("Area is:%f\n", area);
    	system("pause");
    	return 0;
    }
    


    运行时最后一步:将动态库文件拷贝到可执行文件目录下,否则会出现如下错误。


    6、DLL显示调用

    对于显示连接,即动态加载我们需要调用LoadLibrary
    在MSDN中:HMODULE WINAPI LoadLibrary(
      __in  LPCTSTR lpFileName
    );
    它的功能是映射一个可执行模块到调用进程的地址空间。由此我们知道显示调用就是函数指针来调用函数。

    Steps:
    1、声明头文件<windows.h>,说明我想用windows32方法来加载和卸载DLL
    2、然后用typedef定义一个指针函数类型.typedef  void(*fun) //这个指针类型,要和你调用的函数类型和参数保持一致
    3、定一个句柄实例,用来取DLL的实例地址。HINSTANCE hdll;
    格式为hdll=LoadLibrary(“DLL地址”);这里字符串类型是LPSTR,当是unicode字符集的时候会不行,
    因此要在配置-属性-常规里面把默认字符集“unicode”改成支持多字符扩展即可。
    4、取的地址要判断,返回的句柄是否为空,如果为无效句柄,那么要释放加载DLL所占用的内存。
    5、定义一个函数指针,用来获取你要用的函数地址。
      然后通过GetProcAdress来获取函数的地址,参数是DLL的句柄和你要调用的函数名:比如:FUN=(fun)GetProcAdress(hdll,"sum");
      这里也要判断要函数指针是否为空,如果没取到要求的函数,那么要释放句柄。
    6、然后通过函数指针来调用函数。
    7、调用结束后,就释放句柄FreeLibrary(hdll);

    直接上代码,一一一一一目了然

    // callDLLSee.cpp : 定义控制台应用程序的入口点。
    //通过调用windowsAPI 来加载和卸载DLL
    #include "stdafx.h"
    #include "Windows.h"
    typedef double(*Dllfun)(int , int);
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	Dllfun funName;
    	HINSTANCE hdll;
    	//put DLL under the Debug path 
    	//use   _T 设置为宽字符
    	hdll = LoadLibrary( _T("myDLL.dll"));
    	if (hdll == NULL)
    	{
    		FreeLibrary(hdll);
    	}
    	funName = (Dllfun)GetProcAddress(hdll, "seekArea");
    	if (funName == NULL)
    	{
    		FreeLibrary(hdll);
    	}
    	int r = 1, h = 10;
    	double area = funName(r, h);
    	printf("area = %f\n", area);
    
    	FreeLibrary(hdll);
    	return 0;
    }
    


    展开全文
  • 动态库(共享库)的制作和使用

    千次阅读 2019-03-14 01:10:51
    Linux下的动态库为lib*.so格式的二进制文件(目标文件),对应于Windows下的.dll格式的文件。 (1)命名规则 lib+库名+.so (2)动态库的制作 1)生成与位置无关的代码(.o) 2)将.o文件打包成动态库(共享库)...

     Linux下的动态库为lib*.so格式的二进制文件(目标文件),对应于Windows下的.dll格式的文件。

    1)命名规则

    lib+库名+.so

    2)动态库的制作

    1)生成与位置无关的代码(.o)  2)将.o文件打包成动态库(共享库)

            仍然以上篇文章的代码为例。

    [root@localhost src]# gcc -fPIC -c *.c 
    [root@localhost src]# ls
    add.c  add.o  div.c  div.o  mul.c  mul.o  sub.c  sub.o      //这几个.o文件已经是库函数了,它们是与位置无关的代码。PIC可以小写也可以大写,表示生成与位置无关的代码。

    [root@localhost src]# gcc -shared *.o -o libMytest.so
    [root@localhost src]# ls
    add.c  add.o  div.c  div.o  libMytest.so  mul.c  mul.o  sub.c  sub.o   // 将所有.o文件打包到动态库libMytest.so中

    3)发布和使用动态库(共享库)

    ldd命令用来显示二进制代码文件动态库的链接情况,如:ldd foo。将生成的libMytest.so库文件和头文件head.h发送给客服,客服就可以根据头文件中的接口情况,来知道库文件的功能 (具体怎么实现的他也不知道),从而客服就可以使用库文件来完成自己的工作了(main.c):

    [root@localhost Calc]# gcc -pedantic -Wall -pipe main.c -I include/ -L src/ -lMytest -o zsx   //等价于: gcc -pedantic -Wall -pipe main.c -I include/ src/libMytest.so -o zsx
    [root@localhost Calc]# ls
    include  lib  main.c  src  zsx
    [root@localhost Calc]# ldd zsx
        linux-vdso.so.1 =>  (0x00007ffffa7e8000)
        libMytest.so => not found
        libc.so.6 => /lib64/libc.so.6 (0x00007f591dc98000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f591e078000)    //  ld-linux-x86-64.so.2为动态链接器库文件(二进制文件),程序在执行时,动态库的调用需要动态链接器(一个程序,二进制代码文件)来进行调用。动态链接器是按照一定的规则去查找动态库文件的,即按照动态库的环境变量中的每个路径依次进行查找。Linux系统的/lib中就存放了系统在启动时候就需要用到的一些动态库。由ldd zsx可以看出,动态链接器无法找到代码所需要的动态库文件,即该动态库文件不在动态链接器的搜索路径中,下面给出几种解决方法:

    1.将库文件libMytest.so放在/lib中就可以了,这样链接器就可以找到该库文件。但是,不建议这样做,因为是系统的库文件目录,如果名字冲突就会发生故障。

    2.设置环境变量LD_LIBRARY_PATH的值。

    [root@localhost Calc]# echo $LD_LIBRARY_PATH

    [root@localhost Calc]# export LD_LIBRARY_PATH=/mnt/hgfs/share/gcc/Calc/src/libMytest.so
    [root@localhost Calc]# echo $LD_LIBRARY_PATH
    /mnt/hgfs/share/gcc/Calc/src/libMytest.so

    此时链接器会首先在环境变量LD_LIBRARY_PATH中查找库文件,没有在去其余环境变量中查找。该方法也只是临时有效,当关闭终端后,环境变量LD_LIBRARY_PATH的值又恢复了空值,因此又需要再次设置!这种方法仅适用于:在开发测试动态库过程中使用,因为仅仅临时有效。在测试开发完成后,就需要一种稳定的方法。

    3.修改当前用户的bash配置文件:~/.bashrc  修改完成后,需要关闭终端然后再次启用终端,该配置才会生效。

    [root@localhost ~]# vim ~/.bashrc

    export LD_LIBRARY_PATH=/mnt/hgfs/share/gcc/Calc/src

    重启终端:

    [root@localhost ~]# echo $LD_LIBRARY_PATH
    /mnt/hgfs/share/gcc/Calc/src
    即:  该路径永久生效

    4.修改动态链接器的配置文件:/etc/ld.so.conf。将动态库的路径写到配置文件中,将libMytest.so所在绝对路径追加入到/etc/ld.so.conf文件;使用ldconfig -v 更新,使配置生效。

    [root@localhost ~]# vim /etc/ld.so.conf
    /mnt/hgfs/share/gcc/Calc/src

    [root@localhost ~]# ldconfig -v

    总结:

    1).放到系统的库目录中 -- 不允许使用

    2).临时测试

    环境变量: LD_LIBRARY_PATH=将动态库的路径设置给该变量

    将设置的值, 导入到系统环境变量中: export LD_LIBRARY_PATH

    当终端关闭, 设置会失效

    3).不常用的方法(永久设置):

    在家目录的 .bashrc文件 中添加一句话: export LD_LIBRARY_PATH=动态库目录的绝对路径

    .bashrc修改完成, 需要重启终端

    4).常用的方法(永久设置)

    1. 需要找动态连接器的配置文件 --  /etc/ld.so.conf

    2. 动态库的路径写到配置文件中

    3. 更新 ldconfig –v  v参数表示显示更新过程的详细信息

    (4)动态库的优缺点

    优点:执行程序体积小;动态库更新了,在接口不变的情况下,不需要重新编译程序,只需要保证新库跟旧库名称一样,接口一样,且新库能够被链接器找的到;

    缺点:在发布最终版本的应用程序时,需要将动态库提供给客服;

    展开全文
  • 动态库

    2020-02-26 16:54:48
    总结一:动态库 前言  我们知道程序编译链接经常使用动态,同时我们可能还知道,动态库时程序运行时加载的。但是动态库到底有什么作用,如何生成、如何加载等,我们却很少关注。接下来,我给大家做一个简单的介绍。...
  • vs2019创建动态库

    2020-04-21 11:02:23
    1.记住生成的动态库是x64还是x86,必须与使用它的平台相对应 2. extern "C" __declspec(dllexport) void function(); 其中extern "C"的作用是告诉编译器将被它修饰的代码按C语言的方式进行编译。 __declspec(dll...
  • 动态库的初始化

    2019-03-05 15:35:49
    【linux】linux下动态库so文件的一些认识 来源:http://mypyg.iteye.com/blog/845915 so其实就是shared object的意思。今天看了上面的博客,感觉好吃力。赶紧做个笔记记录一下。下面的内容大多都是连接中的,穿插...
  • linux动态库动态库的版本管理

    千次阅读 2019-03-14 12:31:09
    Linux下动态库有三个名字:real name、so name、link name。 real name:共享库本身的名字,命名格式为libname.so.x.y.z,lib是前缀,name是共享库的名字,so是后缀,x是主版本,y是次版本号,z是发布版本号。 主...
  • C++静态库与动态库的区别?

    万次阅读 多人点赞 2018-08-17 20:29:59
    C++静态库与动态库 这次分享的宗旨是——让大家学会创建与使用静态库、动态库,知道静态库与动态库的区别,知道使用的时候如何选择。这里不深入介绍静态库、动态库的底层格式,内存布局等,有兴趣的同学,推荐一本...
  • Linux中的动态库和静态库(.a.la.so.o)

    万次阅读 2018-04-21 23:58:33
    Linux中的动态库和静态库(.a/.la/.so/.o) 原文地址:https://www.cnblogs.com/findumars/p/5421910.html 在windows下,一般可以通过文件的后缀名来识别文件的类型。在Linux下大致上也是可以的。但是要明确的一点是...
  • 通俗理解动态库与静态库区别

    万次阅读 多人点赞 2019-06-21 15:27:46
    引:最近做了算法产品化相关的一些工作,其中涉及到算法库封装的相关工作,封装为动态库。总结动态库和静态库区别和对应使用原则。 区别:静态库和动态库最本质的区别就是:该库是否被编译进目标(程序)内部。 ...
  • linux中的动态链接

    千次阅读 2019-04-03 12:38:41
    在使用动态链接库的时候并不会把动态库的代码全部copy到生成的程序中,而是在程序运行的时候再去加载对应的代码,所以使用同一个动态库的程序可以共用一份代码,而且当你对动态库进行升级的时候,也不用去修改使用它...
  • Linux静态库和动态库区别

    万次阅读 多人点赞 2011-04-14 10:40:00
       函数库分为静态库和动态库两种。    静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。    动态库在程序编译时并不会被连接到目标代码中,而是在...
  • 库是共享程序代码的方式,一般分为静态库和动态库。库实现了某些特定的功能模块化。方便分享使用! 异同点: 2.静态库和动态库有什么特点? - 不同点: 静态库:链接时完整地拷贝至可执行文件中,被多次...
  • 一般代码流的程序员很多会订制...库是共享程序代码的方式,一般分为静态库和动态库。 二、静态库动态库区别静态库:链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝。 动态库:链接时不复制,程
  •                 &nbs...
  • C++静态库和动态库用法

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

    万次阅读 2018-06-29 15:34:21
    静态链接文件 目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”)。静态库是一个或者多...
  • 本文的目的是测试各种类型库的编译后的使用效果,包括库又链接其他库的...②静态库libbb.a依赖动态库libaa.so的测试; ③动态库libbb.so依赖静态库libaa.a的测试; ④动态库libbb.so依赖动态库libaa.so的测试; ...
  • 而库又分为两种,静态库(lib)和动态库(dll), 那么这两种库有什么区别静态库是我们的程序在链接时会把用到的静态库全部都链接进去,形成一个exe,这也导致我们的exe很大(程序是先编译,再链接库,最后形成exe) ...
  • xcode 创建静态库和动态库

    千次阅读 2014-11-24 11:51:35
    1、linux中静态库和动态库区别: 库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。库分静态库和动态库两种。 静态库:这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个...
  • 基本概念 程序编译一般需经预处理、编译、 汇编链接几个步骤。在我们的应用中,有一些公共代码是需要反复使用,就把这些代码编译为“库”文件...**动态库:**DLL 是一个包含可由多个程序同时使用的代码数据的库...
  • iOS中的动态库和静态库区别

    千次阅读 2018-11-29 15:25:00
    2019独角兽企业重金招聘Python工程师标准>>> ...
  • 什么是库库是写好的现有的,成熟的,...库有两种:静态库(.a、.lib)和动态库(.so、.dll)。 所谓静态、动态是指链接。回顾一下,将一个程序编译成可执行程序的步骤: 静态库之所以成为【静态库】,是因为在链接阶
  • 静态库和动态库区别(面试题)

    千次阅读 2019-08-01 14:59:32
    静态库 静态函数库的扩展名一般为(.a或.lib),这类的函数库通常扩展名为libxxx.a或xxx.lib 。 这类库在编译的时候会直接整合到目标程序中,所以利用静态函数库编译成的文件体积会比较大,这类函数库最大的优点就是...
  • 1.静态库和动态库的存在形式上的区别 静态库 .a .framework 动态库 .dylib (在Xcode 8里面,看到后缀为.tbd的库,它的本质都是.dylib文件) .framework 2.静态库和动态库在使用上的区别 ...
  • 创建MFC项目时,选择动态库和静态库区别动态库在VS2017版本中,选择的时候是叫“在共享DLL中使用MFC”。这样创建的时候生成的*.exe文件一般较小,原因有几点1. 此*.exe程序内部,一般不会包含文件所需要的库,其...
  • linux下生成静态库和动态库

    千次阅读 2018-05-14 16:29:37
    转自:https://blog.csdn.net/ddreaming/article/details/53096411一、动态库静态库简介库是写好的现有的,成熟的,可以复用的代码。现实中每个程序都要依赖很多基础...库有两种:静态库.a(win 系统下是lib)动态...
  • 关于静态库和动态库区别网上已经写了很多了,我就不再赘述,大家可以自行搜索。 这里我主要介绍静态库和动态库在运行时间上的区别。 我看书上写的是静态库比动态库在运行速度上快1%~5%。 然后我写了一段程序...

空空如也

1 2 3 4 5 ... 20
收藏数 823,534
精华内容 329,413
关键字:

动态库