精华内容
下载资源
问答
  • 2018-09-06 15:40:13

    ##windows平台:

    .dll : 动态链接库,作为共享函数库的可执行文件.
    .obj : 目标文件,相当于源代码对应的二进制文件,未经过重定义.
    .lib : 可理解为多个 obj 的集合,本质与 .obj 相同.
    

    ##linux平台:

    .so:(share object)动态链接库,和windows 的 dll 类似
    .o : 目标文件,相当于源代码对应的二进制文件 类似 windows 下 obj.
    .a : 与 .o 类似,多个 .o 的集合 类似 windows 下 lib.
    
    	98年菜鸡一枚,请大佬们多多关照!
    
    更多相关内容
  • Linux的.a、.so和.o文件

    千次阅读 2021-05-10 17:30:12
    在说明Linux的.a、.so和.o文件关系之前,先来看看windows下obj,lib,dll,exe的关系windows下obj,lib,dll,exe的关系lib是和dll对应的。lib是静态链接库的库文件,dll是动态链接库的库文件。所谓静态就是link的时候把...

    在说明Linux的.a、.so和.o文件关系之前,先来看看windows下obj,lib,dll,exe的关系

    windows下obj,lib,dll,exe的关系

    lib是和dll对应的。lib是静态链接库的库文件,dll是动态链接库的库文件。

    所谓静态就是link的时候把里面需要的东西抽取出来安排到你的exe文件中,以后运行你的exe的时候不再需要lib。

    所谓动态就是exe运行的时候依赖于dll里面提供的功能,没有这个dll,你的exe无法运行。

    lib,dll,exe都算是最终的目标文件,是最终产物。而c/c++属于源代码。源代码和最终目标文件中过渡的就是中间代码obj,实际上之所以需要中间代码,是你不可能一次得到目标文件。比如说一个exe需要很多的cpp文件生成。而编译器一次只能编译一个cpp文件。这样编译器编译好一个cpp以后会将其编译成obj,当所有必须要的cpp都编译成obj以后,再统一link成所需要的exe,应该说缺少任意一个obj都会导致exe的链接失败。

    1.obj里存的是编译后的代码跟数据,并且有名称,所以在连接时有时会出现未解决的外部符号的问题。当连成exe后便不存在名称的概念了,只有地址。lib就是一堆obj的组合。

    2.理论上可以连接obj文件来引用其他工程(可以认为一个obj文件等价于编译生成它的cpp文件,可以引用obj来替换cpp,也可以添加cpp来替换obj ),但实际中通常用lib来实现工程间相互引用。

    3.编译器会默认链接一些常用的库,其它的需要你自己指定。

    lib和DLL的区别

    (1)lib是编译时需要的,dll是运行时需要的。如果要完成源代码的编译,有lib就够了。如果也使动态连接的程序运行起来,有dll就够了。在开发和调试阶段,当然最好都有。

    (2) 一般的动态库程序有lib文件和dll文件。lib文件是必须在编译期就连接到应用程序中的,而dll文件是运行期才会被调用的。如果有dll文件,那么对应的lib文件一般是一些索引信息,具体的实现在dll文件中。如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。 静态编译的lib文件有好处:给用户安装时就不需要再挂动态库了。但也有缺点,就是导致应用程序比较大,而且失去了动态库的灵活性,在版本升级时,同时要发布新的应用程序才行。

    (3)在动态库的情况下,有两个文件,一个是引入库(.LIB)文件(实际上也算是一个静态库,只是在链接时只能把函数在DLL的入口链接到exe中,而不像真正静态链接库那样将函数体真正链接到exe中 ,通过lib进行的动态链接实际上也使用了静态链接来实现 ),一个是DLL文件,引入库文件包含被DLL导出的函数的名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到所需要使用的DLL文件,库中的函数和数据并不复制到可执行文件中,因此在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址,这样当一个或多个应用程序运行是再把程序代码和被调用的函数代码链接起来,从而节省了内存资源。从上面的说明可以看出,DLL和.LIB文件必须随应用程序一起发行,否则应用程序将会产生错误。

    DLL内的函数分为两种:

    (1)DLL导出函数,可供应用程序调用;

    (2)DLL内部函数,只能在DLL程序使用,应用程序无法调用它们

    创建静态链接库和创建动态链接库

    VC6中创建[Win32 Dynamic-Link Library]工程便可以创建出一个空的DLL工程.

    VC6中创建[Win32 Static Library]工程便可以创建出一个空的LIB工程(静态链接库工程,仅生成一个lib文件).

    添加lib文件的常用办法有二个:

    1、把*.lib放在VC的Lib目录中

    2、修改project setting的Link->Input中的Addtional library path,加入你的目录dll:是可实际运行的二进制代码,有定位代码的!

    3、也可以在object/library中直接写上lib文件路径.(这里实际上是可以写上任意obj文件或者lib文件的).

    linux .o,.a,.so

    .o,是目标文件,相当于windows中的.obj文件

    .so 为共享库,是shared object,用于动态连接的,相当于windows下的dll

    .a为静态库,是好多个.o合在一起,用于静态连接

    静态函数库

    特点:实际上是简单的普通目标文件的集合,在程序执行前就加入到目标程序中。

    优点:可以用以前某些程序兼容;描述简单;允许程序员把程序link起来而不用重新编译代码,节省了重新编译代码的时间(该优势目前已不明显);开发者可以对源代码保密;理论上使用ELF格式的静态库函数生成的代码可以比使用共享或动态函数库的程序运行速度快(大概1%-5%)

    生成:使用ar程序(archiver的缩写)。ar rcs my_lib.a f1.o f2.o是把目标代码f1.o和f2.o加入到my_lib.a这个函数库文件中(如果my_lib.a不存在则创建)

    使用:用gcc生成可执行代码时,使用-l参数指定要加入的库函数。也可以用ld命令的-l和-L参数。

    共享函数库

    共享函数库在可执行程序启动的时候加载,所有程序重新运行时都可自动加载共享函数库中的函数。.so文件感觉很复杂,光是命名规则就已经看得我很晕了~整理一下,共享库需要:soname、real name,另外编译的时候名字也有说法。依次解释下:

    soname:必须的格式:lib+函数库名+.so+版本号信息(但是记住,非常底层的C库函数都不是以lib开头命名的)。例子:/usr/lib/libreadline.so.3

    real name:顾名思义是真正的名字啦,有主版本号和发行版本号。但是没找到实例……

    编译器编译的时候需要的函数库的名字就是不包含版本号信息的soname,例如上面的例子把最后的.3去掉就可以了。

    位置:共享函数库文件必须放在特定目录,对于开放源码来说,GNU标准建议所有的函数库文件都放在/usr/local/lib目录下,而且建议命令、可执行程序都放在/usr/local/bin目录下。不过这个只是习惯啦,可以改变,具体的位置信息可以看/etc/ld.so.conf里面的配置信息。当然,也可以修改这个文件,加入自己的一些特殊的路径要求。

    创建:在网上找到了gcc方式和easyeclipse环境下两种创建方式。

    gcc方式:

    首先创建object文件,这个文件将加入通过gcc –fPIC 参数命令加入到共享函数库里面,标准格式:gcc -shared -Wl,-soname,your_soname -o library_name file_list library_list(说实话这个标准格式看起来好复杂,我找了个实例,但是好像和那个标准格式稍有不同:gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so)

    在easyeclipse环境下生成.so文件:

    1.选择新建工程,建立一个c++工程

    2.在工程类型选项里选择 Shared Library,然后填入工程名字PXXX点击完成即可。

    3.编写程序,然后编译就会在debug或者release里生成一个libPXXX.so文件,如果不要lib的起头标记点击project菜单的Properties选项,然后在弹出的界面的右边点击Build artifact页面,将Output prefix选项的内容清空即可。

    4.如果是C++程序,注意在接口函数的前面加上extern "C"标记,在头文件加上如下标记:

    #ifdef __cplusplus

    #extern "C"{

    #endif

    头文件主体

    #ifdef cplusplus

    }

    #endif

    如果不加以上标记,经过编译后,so里的函数名并非你编写程序时设定的函数名,在开发环境左侧的工程文件列表中点开debug项里的PXXX.o可以看到so文件里的函数名都是在你设定的函数名后面加了一个Fi标记,比如你用的设定的函数名称是Func(), 而so里的函数名则为Func__Fi()或者其他的名称。

    安装:拷贝共享库文件到指定的标准的目录,然后运行ldconfig。如果没有权限这样做,那么就只好通过修改环境变量来实现这些函数库的使用了。方法不再说了,很复杂。

    查看:可以通过运行ldd来看某个程序使用的共享函数库。例如ldd /bin/ls。查看.so文件使用nm命令,如nm libXXX.so。(注意,nm对于静态的函数库和共享的函数库都起作用)

    关于覆盖:如果想用自己的函数覆盖某个库中的一些函数,同时保留该库中其他的函数的话,可以在/etc/ld.so.preload中加入要替换的库(.o结尾的文件),这些preloading的库函数将有优先加载的权利。

    关于更新:每次新增加动态加载的函数库、删除某个函数库或者修改某个函数库的路径时,都要重新运行ldconfig来更新缓存文件/etc/ld.so.cache,此文件保存已排好序的动态链接库名字列表

    (在Linux下,共享库的加载是由/lib/ld.so完成的,ld.so加载共享库时,会从ld.so.cache查找)

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

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

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

    行时还需要动态库存在。本文主要通过举例来说明在Linux中如何创建静态库和动态库,以

    及使用它们。

    在创建函数库前,我们先来准备举例用的源程序,并将函数库的源程序编译成.o文件。

    第1步:编辑得到举例的程序--hello.h、hello.c和main.c;

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

    Hello XXX!"。hello.h(见程序1)为该函数库的头文件。main.c(见程序3)为测试库文件的

    主程序,在主程序中调用了公用函数hello。

    程序1: hello.h

    #ifndef HELLO_H

    #define HELLO_H

    void hello(const char *name);

    #endif //HELLO_H

    程序2: hello.c

    #include

    void hello(const char *name)

    {

    printf("Hello %s!\n", name);

    }

    程序3: main.c

    #include "hello.h"

    int main()

    {

    hello("everyone");

    return 0;

    }

    第2步:将hello.c编译成.o文件;

    无论静态库,还是动态库,都是由.o文件创建的。因此,我们必须将源程序hello.c通过g

    cc先编译成.o文件。

    在系统提示符下键入以下命令得到hello.o文件。

    gcc -c hello.c

    #

    我们运行ls命令看看是否生存了hello.o文件。

    ls

    hello.c hello.h hello.o main.c

    #

    在ls命令结果中,我们看到了hello.o文件,本步操作完成。

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

    第3步:由.o文件创建静态库;

    静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将

    创建的静态库名为myhello,则静态库文件名就是libmyhello.a。在创建和使用静态库时,

    需要注意这点。创建静态库用ar命令。

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

    ar -cr libmyhello.a hello.o

    #

    我们同样运行ls命令查看结果:

    ls

    hello.c hello.h hello.o libmyhello.a main.c

    #

    ls命令结果中有libmyhello.a。

    第4步:在程序中使用静态库;

    静态库制作完了,如何使用它内部的函数呢?只需要在使用到这些公用函数的源程序中包

    含这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明静态库名,gcc将会从

    静态库中将公用函数连接到目标文件中。注意,gcc会在静态库名前加上前缀lib,然后追

    加扩展名.a得到的静态库文件名来查找静态库文件。

    在程序3:main.c中,我们包含了静态库的头文件hello.h,然后在主程序main中直接调用公

    用函数hello。下面先生成目标程序hello,然后运行hello程序看看结果如何。

    法一 # gcc -o hello main.c -L. –lmyhello,或gcc main.c -L. –lmyhello -o hello自定义的库时,main.c还可放在-L.和 –lmyhello之间,但是不能放在它俩之后,否则会提示myhello没定义,但是是系统的库时,如g++ -o main(-L/usr/lib) -lpthread main.cpp就不出错。

    法二 #gcc main.c libmyhello.a -o hello或gcc -o hello main.c libmyhello.a

    法三:先生成main.o:gcc -c main.c ,再生成可执行文件:gcc -o hello main.o libmyhello.a或gccmain.o libmyhello.a -o hello ,动态库连接时也可以这样做。

    ./hello

    Hello everyone!

    #

    我们删除静态库文件试试公用函数hello是否真的连接到目标文件 hello中了。

    rm libmyhello.a

    rm: remove regular file `libmyhello.a'? y

    ./hello

    Hello everyone!

    #

    程序照常运行,静态库中的公用函数已经连接到目标文件中了。

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

    第5步:由.o文件创建动态库文件;

    动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀lib,但其

    文件扩展名为.so。例如:我们将创建的动态库名为myhello,则动态库文件名就是libmyh

    ello.so。用gcc来创建动态库。

    在系统提示符下键入以下命令得到动态库文件libmyhello.so。

    gcc -shared -fPIC -o libmyhello.so hello.o (-o不可少)

    #

    我们照样使用ls命令看看动态库文件是否生成。

    ls

    hello.c hello.h hello.o libmyhello.so main.c

    #

    第6步:在程序中使用动态库;

    在程序中使用动态库和使用静态库完全一样,也是在使用到这些公用函数的源程序中包含

    这些公用函数的原型声明,然后在用gcc命令生成目标文件时指明动态库名进行编译。我们

    先运行gcc命令生成目标文件,再运行它看看结果。

    gcc -o hello main.c -L. -lmyhello

    (或 #gcc main.c libmyhello.so -o hello 不会出错(没有libmyhello.so的话,会出错),但是接下来./hello 会提示出错,因为虽然连接时用的是当前目录的动态库,但是运行时,是到/usr/lib中找库文件的,将文件libmyhello.so复制到目录/usr/lib中就OK了)

    ./hello

    ./hello: error while loading shared libraries: libmyhello.so: cannot open shar

    ed object file: No such file or directory

    #

    哦!出错了。快看看错误提示,原来是找不到动态库文件libmyhello.so。程序在运行时,

    会在/usr/lib和/lib等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提

    示类似上述错误而终止程序运行。我们将文件libmyhello.so复制到目录/usr/lib中,再试

    试。

    mv libmyhello.so /usr/lib

    ./hello

    Hello everyone!

    #

    成功了。这也进一步说明了动态库在程序运行时是需要的。

    我们回过头看看,发现使用静态库和使用动态库编译成目标程序使用的gcc命令完全一样,

    那当静态库和动态库同名时,gcc命令会使用哪个库文件呢?抱着对问题必究到底的心情,

    来试试看。

    先删除除.c和.h外的所有文件,恢复成我们刚刚编辑完举例程序状态。

    rm -f hello hello.o /usr/lib/libmyhello.so

    ls

    hello.c hello.h main.c

    #

    在来创建静态库文件libmyhello.a和动态库文件libmyhello.so。

    在生成动态库时,需要使用-fPIC,这样才能生成位置无关的代码,达到代码段和数据段共享的目的

    gcc -c -fpic hello.c //编译hello.c时也需要加上-fpic选项,否则rodata' can not be used when making a shared object; recompile with -fPIC

    ar -cr libmyhello.a hello.o (或-cvr )

    gcc -shared -fPIC -o libmyhello.so hello.o

    ls

    hello.c hello.h hello.o libmyhello.a libmyhello.so main.c

    #

    通过上述最后一条ls命令,可以发现静态库文件libmyhello.a和动态库文件libmyhello.s

    o都已经生成,并都在当前目录中。然后,我们运行gcc命令来使用函数库myhello生成目标

    文件hello,并运行程序 hello。

    gcc -o hello main.c -L. –lmyhello (动态库和静态库同时存在时,优先使用动态库, 当然,直接#gcc main.c libmyhello.a -o hello的话,就是指定为静态库了)

    ./hello

    ./hello: error while loading shared libraries: libmyhello.so: cannot open shar

    ed object file: No such file or directory

    #

    从程序hello运行的结果中很容易知道,当静态库和动态库同名时,gcc命令将优先使用动态库,默认去连/usr/lib和/lib等目录中的动态库,将文件libmyhello.so复制到目录/usr/lib中即可。

    Note:

    编译参数解析

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

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

    -fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code)。那么在产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

    如果不加fPIC,则编译出来的代码在加载时需要根据加载到的位置进行重定位(因为它里面的代码并不是位置无关代码),如果被多个应用程序共同使用,那么它们必须每个程序维护一份so的代码副本了.(因为so被每个程序加载的位置都不同,显然这些重定位后的代码也不同,当然不能共享)。

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

    -L. 表示要连接的库在当前目录中;(多个库:在编译命令行中,将使用的静态库文件放在源文件后面就可以了。比如:gcc -L/usr/lib myprop.c libtest.a libX11.a libpthread.a -o myprop

    其中-L/usr/lib指定库文件的查找路径。编译器默认在当前目录下先查找指定的库文件,如前面的“法二 #gccmain.c libmyhello.a-o hello”)

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

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

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

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

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

    ld(GNU linker)会去找GCC命令中的参数-L

    编译过程是分为四个阶段:预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编 (Assembly)和连接(link) 【链接】

    再找gcc的环境变量LIBRARY_PATH

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

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

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

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

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

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

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

    有关环境变量:

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

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

    另:

    从上述可知,如何找到生成的动态库有3种方式:

    (1)把库拷贝到/usr/lib和/lib目录下。

    (2)在LD_LIBRARY_PATH环境变量中加上库所在路径。

    例如动态库libhello.so在/home/example/lib目录下:

    export LD_LIBRARY_PATH=LD_LIBRARY_PATH:/home/example/lib

    (3) 修改/etc/ld.so.conf文件,把库所在的路径加到文件末尾(直接写在文件末尾,不要在路径前加include),并执行ldconfig刷新(ldconfig 命令的用途,主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如前介绍,lib.so),进而创建出动态装入程序(ld.so)所需的连接和缓存文件.缓存文件默认为/etc/ld.so.cache,此文件保存已排好序的动态链接库名字列表.)。这样,加入的目录下的所有库文件都可见。

    附:像下面这样指定路径去连接系统的静态库,会报错说要连接的库找不到:

    g++ -o main main.cpp -L/usr/lib libpthread.a

    必须这样g++ -o main main.cpp -L/usr/lib -lpthread才正确 。

    自定义的库考到/usr/lib 下时,

    g++ -o main main.cpp -L/usr/lib libpthread.a libthread.a libclass.a会出错,但是这样g++ -o main main.cpp -L/usr/lib -lpthread -lthread -lclass就正确了。

    展开全文
  • 在 windows 系统平台上,dll 动态库没有提供 .lib 文件,又不想动态获取函数地址怎么办? 使用 lib.exe 工具可以根据 .def 定义文件生成 .lib 文件。 例如,我这里有一个 test.dll 动态库文件,我想要生成 lib 链接...

    在 windows 系统平台上,dll 动态库没有提供 .lib 文件,又不想动态获取函数地址怎么办?

    使用 lib.exe 工具可以根据 .def 定义文件生成 .lib 文件。

    例如,我这里有一个 test.dll 动态库文件,我想要生成 lib 链接库文件可以这样操作。

    1. 打开 Developer Command Prompt for VS 2022 开发工具命令行,用来设置运行变量。
    2. 使用 dumpbin.exe /EXPORTS test.dll > test.txt ,此时会把输出重定向到 test.txt 文件
    3. 使用 golang 写的工具(完整代码在下面)执行命令 libhelper.exe test.txt,此时会生成 test.def 文件。
    4. 使用 lib /def:test.def /machine:x64 /out:test.lib 命令,会生成 test.lib 链接库文件 。
    # 1
    dumpbin /exports test.dll > test.def
    
    # 2
    修改 test.def 文件
    
    类似这样
    
    LIBRARY
    EXPORTS
    	MyFunction
    	_cgo_dummy_export
    
    #  3
    lib /def:test.def /machine:x64 /out:test.lib
    
    package main
    
    import "C"
    
    import (
    	"bufio"
    	"flag"
    	"fmt"
    	"log"
    	"os"
    	"strings"
    )
    
    //export HelloWorld
    func HelloWorld() {
    	println("HelloWorld!")
    }
    
    var (
    	InputFilename string
    )
    
    func init(){
    	flag.StringVar(&InputFilename,"input filename","","eg. input filename exports.txt | output filename exports.def")
    }
    
    func main() {
    	flag.Parse()
    	if !flag.Parsed() {
    		println("please input *.txt -h get help.")
    		os.Exit(0)
    	}
    
    	//
    	//var filename string = "exports.txt"
    	var filename string = InputFilename
    	file, err := os.OpenFile(filename, os.O_RDONLY, os.ModePerm)
    	if err != nil {
    		log.Fatalln(err)
    	}
    
    	var (
    		dllName string
    		isStart = false
    		functionName []string
    	)
    
    	scanner := bufio.NewScanner(file)
    	for scanner.Scan() {
    		s := scanner.Text()
    		// 获取 dll 名字
    		if strings.Contains(s,"Section contains the following exports for") {
    			fields := strings.Fields(s)
    			name := fields[len(fields) - 1]
    			dllName = strings.Split(name,".")[0]
    		}
    		if strings.Contains(s, "Summary") {
    			isStart = false
    		}
    		// 获取 dll 导出函数名称
    		if isStart {
    			if len(s) > 0 {
    				s = strings.TrimSpace(s)
    				fields := strings.Fields(s)
    				functionName = append(functionName,fields[len(fields) - 1])
    			}
    		}
    		if strings.Contains(s, "ordinal hint RVA") {
    			isStart = true
    		}
    		//fmt.Println(scanner.Text())
    	}
    	if err := scanner.Err(); err != nil {
    		fmt.Fprintln(os.Stderr, "reading standard input:", err)
    	}
    
    	// 输出 def 文件
    	out,err := os.Create(strings.Split(filename,".")[0] + ".def")
    	if err != nil {
    		panic(err)
    	}
    	out.WriteString(fmt.Sprintf("LIBRARY %s\n",dllName))
    	out.WriteString("EXPORTS\n")
    	for _, s := range functionName {
    		out.WriteString(fmt.Sprintf("   %s\n",s))
    	}
    }
    
    
    展开全文
  • 在链接步骤中,连接器将从库文件取得所需的代码,复制到生成的可执行文件中。这种库称为静态库,其特点是可执行文件中包含了库代码的一份完整拷贝;缺点就是被多次使用就会有多份冗余拷贝。 动态库 动态库又称动态...

    静态库

    程序编译一般需经预处理、编译、汇编和链接几个步骤。在应用中,有一些公共代码是需要反复使用,就把这些代码编译为“库”文件;在链接步骤中,连接器将从库文件取得所需的代码,复制到生成的可执行文件中。这种库称为静态库,其特点是可执行文件中包含了库代码的一份完整拷贝;缺点就是被多次使用就会有多份冗余拷贝。

    动态库

    动态库又称动态链接库英文为DLL,是Dynamic Link Library 的缩写形式,DLL是一个包含可由多个程序同时使用的代码和数据的库,DLL不是可执行文件。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个 DLL 中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。DLL 还有助于共享数据和资源。多个应用程序可同时访问内存中单个DLL 副本的内容。DLL 是一个包含可由多个程序同时使用的代码和数据的库。Windows下动态库为.dll后缀,在linux在为.so后缀。

    俩者区别

    静态库是编写的时候加载进源代码进行编译的,如各种头文件。动态库是在程序运行的时候映射进程序的内存空间进行动态加载的,如DLL文件。静态库和动态库是两种共享程序代码的方式,它们的区别是:静态库在程序的链接阶段被复制到了程序中,和程序运行的时候没有关系;动态库在链接阶段没有被复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用。使用动态库的优点是系统只需载入一次动态库,不同的程序可以得到内存中相同的动态库的副本,因此节省了很多内存。

    静态链接库生成方法

    1、新建一个项目,选择Win32项目

    2、选择静态库,预编译头可以加也可以不加,这里我不加

    如果没有选静态库,可以在项目/工程属性/配置属性/常规/项目默认值配置类型中修改

    3、添加.cpp文件和.h文件

    (1)demo.cpp文件

    #include<iostream>
    #include<vector>
    #include"BinarySearchLib.h"
    using namespace std;
     
    //递归方法
    int Binary_Search_Recursion(vector<int> v, int begin, int end, int key)
    {
    	if (begin > end)
    		return -1;
    	int mid = (begin + end) >> 1;
    	if (v[mid] > key)
    		return Binary_Search_Recursion(v, begin, mid - 1, key);
    	else if (v[mid] < key)
    		return Binary_Search_Recursion(v, mid + 1, end, key);
    	else
    		return mid;
    }
     
    //非递归方法
    int Binary_Search(vector<int> v, int begin, int end, int key)
    {
    	if (begin > end)
    		return -1;
    	int mid = 0;
    	while (begin <= end)
    	{
    		mid = (begin + end) >> 1;
    		if (v[mid] > key)
    			end = mid - 1;
    		else if (v[mid] < key)
    			begin = mid + 1;
    		else
    			return mid;
    	}
    	return -1;
    }
    

    (2)BinarySearchLib.h文件

    #ifndef  _BinarySearchLib_H
    #define  _BinarySearchLib_H
     
    #include<vector>
    using namespace std;
     
    int Binary_Search_Recursion(vector<int> v, int begin, int end, int key);
    int Binary_Search(vector<int> v, int begin, int end, int key);
     
    #endif
     
    

    4、生成解决方案


     

    这时候可以看到下方显示成功

    5、把项目所在文件夹Debug文件夹下找到.lib文件

    在这里我新建了一个控制台程序

    (1)复制.lib和.h文件到需要使用项目的文件夹下

    (2)把.h文件添加到工程中,并在工程中添加库#pragma comment(lib,"BinarySearchLib.lib")

    如果不写#pragma comment(lib,"BinarySearchLib.lib")可以在项目/工程属性/链接器/输入/附加依赖项中添加BinarySearchLib.lib。  

    动态链接库生成方法

    1、新建一个项目,选择Win32项目

    2、选择DLL

    如果没有选DLL,可以在项目/工程属性/配置属性/常规/项目默认值配置类型中修改

    3、添加BinarySearchDll.h文件和BinarySearch.cpp文件

    代码如下:(在静态库我用的是vector,但是显示调用的时候,得到的函数地址一直是0,不清楚原因,待究)

    BinarySearchDll.h

    #ifndef _MYCODE_H_
    #define _MYCODE_H_
     
    #ifdef DLLDEMO1_EXPORTS
    #define EXPORTS_DEMO _declspec( dllexport )
    #else
    #define EXPORTS_DEMO _declspec(dllimport)
    #endif
     
    extern  "C" EXPORTS_DEMO int Binary_Search(int v[], int begin, int end, int key);
     
    #endif
    

    BinarySearchDll.cpp

    #include "stdafx.h"
    #include "MyCode.h"
     
    int Binary_Search(int v[], int begin, int end, int key)
    {
    	if (begin > end)
    		return -1;
    	int mid = 0;
    	while (begin <= end)
    	{
    		mid = (begin + end) >> 1;
    		if (v[mid] > key)
    			end = mid - 1;
    		else if (v[mid] < key)
    			begin = mid + 1;
    		else
    			return mid;
    	}
    	return -1;
    }
    

    4、生成->生成解决方案

    Debug目录下有BinarySearch.lib文件和BinarySearch.dll文件



    5、调用动态链接库

    有两种调用方式,静态(隐式)调用和动态(显式调用)

    (1)静态(隐式)调用,和静态链接库方式一样

    把.h文件和.lib文件放在需要调用的项目目录下,把.h文件添加到工程中,并在工程中添加库#pragma comment(lib,"BinarySearchLib.lib")如果不写可以在项目/工程属性/链接器/输入/附加依赖项中添加BinarySearchLib.lib。并把生成的.dll.要放到,使用该库的工程的 debug()目录下。

    (2)动态(显式)调用

    显式调用只需把dll文件放在被调用的项目Debug目录下

    需要包含windows.h,动态调用法要用Windows API中的LoadLibrary()和GetProcAddress()来调入dll库,指出库中函数位置。

    代码如下:

    #include <windows.h>
    #include <iostream>
    using namespace std;
     
    typedef int(*AddFunc)(int[], int, int, int);
     
    int main(int argc, char *argv[])
    {
    	int data[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
    	HMODULE hDll = LoadLibrary("DLLDemo1.dll");
    	if (hDll != NULL)
    	{
    		AddFunc add = (AddFunc)GetProcAddress(hDll, "Binary_Search");
    		if (add != NULL)
    		{
    			cout << add(data, 0, 7, 3) << endl;
    		}
    		FreeLibrary(hDll);
    	}
    }
    

    可能会遇到的问题

    1、上面已经说明,用vector不能调用,为什么?我还没解决

    2、error C2664: “HMODULE LoadLibraryW(LPCWSTR)”: 无法将参数 1 从“const char [13]”转换为“LPCWSTR”

    解决办法:项目->项目属性->配置属性->常规->字符集:选择使用多字节字符集

    理论

    (基本摘抄自博客)

    1、.h .lib .dll文件关系

    摘自:http://www.cnblogs.com/zcshan/archive/2010/12/03/1895605.html

    .h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的。

    附加依赖项的是.lib不是.dll,若生成了DLL,则肯定也生成 LIB文件。如果要完成源代码的编译和链接,有头文件和lib就够了。如果也使动态连接的程序运行起来,有dll就够了。在开发和调试阶段,当然最好都有。

    .h .lib .dll三者的关系是:

    H文件作用是:声明函数接口

    DLL文件作用是: 函数可执行代码

    当我们在自己的程序中引用了一个H文件里的函数,编链器怎么知道该调用哪个DLL文件呢?这就是LIB文件的作用: 告诉链接器 调用的函数在哪个DLL中,函数执行代码在DLL中的什么位置,这也就是为什么需要附加依赖项 .LIB文件,它起到桥梁的作用。如果生成静态库文件,则没有DLL ,只有lib,这时函数可执行代码部分也在lib文件中

    目前以lib后缀的库有两种,一种为静态链接库(Static Libary,以下简称“静态库”),另一种为动态连接库(DLL,以下简称“动态库”)的导入库(Import Libary,以下简称“导入库”)。静态库是一个或者多个obj文件的打包,所以有人干脆把从obj文件生成lib的过程称为Archive,即合并到一起。比如你链接一个静态库,如果其中有错,它会准确的找到是哪个obj有错,即静态lib只是壳子。动态库一般会有对应的导入库,方便程序静态载入动态链接库,否则你可能就需要自己LoadLibary调入DLL文件,然后再手工GetProcAddress获得对应函数了。有了导入库,你只需要链接导入库后按照头文件函数接口的声明调用函数就可以了。导入库和静态库的区别很大,他们实质是不一样的东西。静态库本身就包含了实际执行代码、符号表等等,而对于导入库而言,其实际的执行代码位于动态库中,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。

    一般的动态库程序有lib文件和dll文件。lib文件是必须在编译期就连接到应用程序中的,而dll文件是运行期才会被调用的。如果有dll文件,那么对应的lib文件一般是一些索引信息,具体的实现在dll文件中。如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。静态编译的lib文件有好处:给用户安装时就不需要再挂动态库了。但也有缺点,就是导致应用程序比较大,而且失去了动态库的灵活性,在版本升级时,同时要发布新的应用程序才行。在动态库的情况下,有两个文件,而一个是引入库(.LIB)文件,一个是DLL文件,引入库文件包含被DLL导出的函数的名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到所需要使用的DLL文件,库中的函数和数据并不复制到可执行文件中,因此在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址,这样当一个或多个应用程序运行是再把程序代码和被调用的函数代码链接起来,从而节省了内存资源。从上面的说明可以看出,DLL和.LIB文件必须随应用程序一起发行,否则应用程序将会产生错误。

    2、C++静态链接库与动态链接库

    摘自:http://www.cnblogs.com/skynet/p/3372855.html

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

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

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

    图:编译过程

    (1)静态库

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

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

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

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

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

    (2)动态库

    通过上面的介绍发现静态库,容易使用和理解,也达到了代码复用的目的,那为什么还需要动态库呢?
    为什么还需要动态库?
    为什么需要动态库,其实也是静态库的特点导致。
    1)空间浪费是静态库的一个问题。

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

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

    动态库特点总结:

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

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

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

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

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

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

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

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

    其他文章:在自己的项目中调用别人的库的方法(static lib库,dynamic lib库以及dll动态库)_邓无邪的博客-CSDN博客

    展开全文
  • dll导出def和lib文件

    千次阅读 2018-08-16 15:46:11
    却很少知道在命令行下,由两个更好用的命令,分别是dumpbin和lib,这是VS安装目录下的两个程序。 dumpbin 用法: DUMPBIN [选项] [文件] 选项: /ALL /ARCHIVEMEMBERS /CLRHEADER /DEPENDENTS ....
  • keil5如何将代码打包为lib文件

    千次阅读 2019-10-09 08:42:20
    对于某些需要加密的.c代码,keil软件提供了打包为lib文件的方法,便于移植和调用。 1.新建GROUP 将所有需要打包的.c文件copy到该group中,需要确保这些.c文件的相对独立性,即包含.h文件即可调用。其他如中断类的....
  • 在项目上有时需要提供程序给客户自己修改一些参数调节效果,但自己又不想提供源码公开时,这时就可以使用keil自带的打包Lib文件功能,操作如下: 1、先打开一个工程项目,如果DRIVER文件下的lcd.c、key.c、24c02.c...
  • 目录 ...1.nasm -f elf -o lib/kernel/print.o lib/kernel/print.asm  2.gcc -I ./lib/ -c -o kernel/main.o kernel/main.c  3.ld -Ttext 0xc0001500 -e main -o kernel/kernel.bin ke...
  • C语言文件生成静态库lib

    千次阅读 2021-03-12 14:53:25
    最近看到一个模块的程序,在阅读的时候发现一个函数有引用,有声明,却找不到在哪里定义,模块只有头文件没有对应的.c文件,顿生疑惑,想着这程序怎么能运行呢。后来发现文件夹中有个后缀为.a的文件...
  • .a文件和.lib文件的区别

    万次阅读 2017-07-06 10:50:42
    .a文件和.lib文件的区别  2013-08-01 10:42:37| 分类: 编程知识|举报|字号 订阅    下载LOFTER我的照片书 | (转载) 最近开始...
  • 一、现象:QT中调用VS生成的DLL动态库成功,但调用静态lib库失败,通常提示xxx.a文件未找到 二、原因:首先dll动态库与lib静态库区别在于,调用前者时只是跳转到dll中函数入口地址,函数的具体内容在编译时并不加载...
  • C51FPS.LIB

    2013-04-09 21:31:01
    如果你在单片机编程的时候出现下面的错误,是因为缺少c51fps.lib文件,把此文件下载后放到D:\KEIL\C51\LIB\C51FPS.LIB即可 *** FATAL ERROR L210: I/O ERROR ON INPUT EXCEPTION 0021H: PATH OR FILE NOT FOUND D...
  • Linux的库文件是.a、.so、.o。 Windows的库文件是.lib
  • 首先我找了我的库,里面并没有这个lib,网上也试了很多方法,最后都不行,下载也下载不到这个库,我干脆就删了~ 方法是: 使用vs2013右键点击解决方案属性,找到里面的链接器->输入项,看一下项目的附加依赖项...
  • 使用的库是 Poco\JSON,在使用此库之前使用的是JsonCpp,使用起来只需要包含json.cpp文件即可,且使用简单,地址:mirrors / open-source-parsers / jsoncpp · CODE CHINA (csdn.net),但是发现没办法使用中文字符...
  • 错误:无法打开输入文件"xxx.lib"文件 解决方式: 链接器中,附加目录错了;或者附加依赖库的问题
  • “.dll .obj .lib”和“ .so .o .a”文件 (1) .dll .obj .lib使用在windows平台下。 .dll:动态链接库,作为共享函数库的可执行文件。 .obj:目标文件,相当于源代码对应的二进制文件,未经重定位。 .lib:可...
  • 理解Linux的.a、.so和.o文件

    千次阅读 多人点赞 2019-07-29 21:47:55
    在说明Linux的.a、.so和.o文件关系之前,先来看看windows下obj,lib,dll,exe的关系 windows下obj,lib,dll,exe的关系 lib是和dll对应的。lib是静态链接库的库文件,dll是动态链接库的库文件。 所...
  • 作者:joy ... 配置:win7 64位 QT 5.2.1 采用VS2010编译器 进来开始打算继续用QT编程,荒废许多之后再来做事情,好多内容都有点忘记了。以至于自己博客中写到的解决问题的...问题描述:手欠,想要打开试着打开lib
  • 将C语言文件生成静态库lib

    千次阅读 2017-04-19 14:30:32
    1,创建三个文件Test.c , Test.h,main.c 内容分别如下: Test.h 1 #ifndef _TEST_H_ 2 #define _TEST_H_ 3 4 int get_result(int firstNum,int secondNum); 5 6 #endif //test.h Test.c 1 #include "Test.h" 2 ...
  • .o 就相当于Windows里的obj文件  .a 是好多个.o合在一起,用于静态连接 ....o文件是链接文件,.a是静态库文件,靠.o文件生成,作为一个库为外部程序提供函数,接口。 生成.o文件: gcc ...
  • 我们利用OpenCV编程的时候一般需要关联多个lib文件,如果发布程序,不仅需要发布我们自己生成的lib,还需要将这些lib一起带过去。那么有没有一种可以将这么多lib文件一起打包在一起的方法呢? 比如我的程序用到了这...
  • openssl 静态 链接库 libeay32.lib ssleay32.lib

    千次下载 热门讨论 2012-01-12 13:27:50
    openssl 1.0.0b 的静态链接库 libeay32.lib ssleay32.lib,用他编译无需dll就可以运行。 网上找不到,自己动手弄的,需要的同学你懂的。 编译参数: /MT /Ox /O2 /Ob2 -O -DOPENSSL_NO_RC5 -DOPENSSL_NO_MD2 -...
  • 就相当于windows里的obj文件 ,一个.c或.cpp文件对应一个.o文件.a文件::: 是好多个.o合在一起的静态库文件,相当于windows下的.lib文件。给外部程序提供接口,用于静态连接 ,即STATIC mode。多个.a可以链接生成...
  • 目录 问题原因: ...或者使用docker挂载该文件时,挂载的文件权限不是400(所有者读)/600(所有者读写)/700(所有者读写执)会报错 解决办法: 在挂载的主机上运行 chmod 600 /mydata/rabbitmq/d..
  • .lib文件详解

    千次阅读 2013-06-19 14:26:38
    lib文件通过编译才可以使用编译分静态动态之分。 静态编译 静态lib将导出声明和实现都放在lib中。编译后所有代码都嵌入到宿主程序 动态编译 动态lib相当于一个h文件,是对实现部分(.d
  • Linux 目录结构:/lib 分析

    千次阅读 2021-05-09 01:03:57
    8种机械键盘轴体对比本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?我们在之前的文章中已经分析了其他重要.../lib 文件夹是 库文件目录 ,包含了所有对系统有用的库文件。简单来说,它是应用程序、命...
  • 此时编译会提示:fatal error LNK1104: 无法打开文件“×××.lib”,原因是编译器找不到lib文件。 给项目添加库文件路径 在VS中右击项目点属性: 配置属性-->链接器-->常规-->附加目录 。在里面填上库文件所在的...
  • 关于库生成的问题  我们通常把一些公用函数制作成函数库,供其它程序使用。函数库分为静态库和动态库两种。... 简单地说,静态库是一个目标文件的简单集合。因此,首先要解决目标文件。  第一
  • 此功能可以帮助查看lib文件是静调库还是dll的导入库Microsoft 库管理器 (LIB.exe) 创建和管理通用对象文件格式 (COFF) 对象文件库。...LIB 创建标准库、导入库和导出文件,在生成程序时可将它们 LI...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 339,699
精华内容 135,879
关键字:

lib o 与 文件