1、lib 库的作用是什么LIB 有两种,一种是静态库,比如 C-Runtime 库,这种 LIB 中有函数的实现代码,一般用在静态连编上,它是将 LIB 中的代码加入目标模块(EXE 或者 DLL)文件中,所以链接好了之后,LIB 文件就没有用了.一种 LIB 是和 DLL 配合使用的,里面没有代码,代码在 DLL 中,这种LIB 是用在静态调用 DLL 上的,所以起的作用也是链接中用,链接完成了,LIB 也没用了.至于动态调用 DLL 的话,根本用不上 LIB 文件. 目标模块(EXE 或者 DLL)文件生成之后,就用不着 LIB 文件了. 如何打开 LIB 文件用编程语言,打开 lib 文件
2、的办法有三个: 1、在 object/library modules 使用全路径名; 2、把*.lib 放在 VC 的 Lib 目录中 3、修改 project setting 的 Link-Input 中的 Addtional library path,加入你的目录。 VC 中加载 LIB 文件的方法1.LIB 文件直接加入到工程文件列表中 在 VC 中打开 File View 一页,选中工程名,单击鼠标右键,然后选中“Add Files to Project“菜单,在弹出的文件对话框中选中要加入 DLL 的 LIB 文件即可。 2.设置工程的 Project Settings 来加载 DL
3、L 的 LIB 文件 打开工程的 Project Settings 菜单,选中 Link,然后在 Object/library modules 下的文本框中输入 DLL 的 LIB 文件。 3.通过程序代码的方式 加入预编译指令#pragma comment (lib,“*.lib“),这种方法优点是可以利用条件预编译指令链接不同版本的 LIB 文件。因为,在 Debug 方式下,产生的 LIB 文件是 Debug 版本,如 Regd.lib;在 Release 方式下,产生的 LIB 文件是 Release 版本,如 Regr.lib。 当应用程序对 DLL 的 LIB 文件加载后,还需要把
4、 DLL 对应的头文件(*.h)包含到其中,在这个头文件中给出了 DLL 中定义的函数原型,然后声明。 Lib 文件中的节Lib 格式只有四种类型的节(Section ) ,即 First Sec, Second Sec,Longname Sec 和 Obj Sec;其中 Second Sec 与 Longname Sec 是可选节,很多 Lib 文件中都没有。而开头的Singature 只是一个标识,它相当于 COFF 目标文件中的魔法数字。它是一个长度为 8 的字符串,值为“!n” 。 First Sec,顾名思义,就是第一个节。它包含了库中所有的符号名以及这些符号所在的目标文件在库中的位
5、置(绝对偏移) 。 Second Sec 就是第二节。它的内容和 First Sec 是相同的。不同的是, Second Sec 是一个有序表,通过它来查找库中的符号比通过 First Sec 来查找要快很多。 Longname Sec 是长名称节。这一节是一个字符串表。它包含了所有长目标文件名。如果后面的 Obj Sec 中没有给出相应的目标文件名,我们就要到这一节中来查找。 Obj Sec 就是目标文件节。这些节中存储着不同的目标文件的原始数据。 在库文件中,每一节都有两个部分。一个部分是头,另一个部分才是该节的数据;数据紧跟在头的后面。头描述了该节数据的类型、长度等信息。这些头的格式都是
6、相同的。其结构用 C 语言描述如下: typedef struct char Name16; / 名称 char Time12; / 时间 char UserID6; / 用户 ID char GroupID6; / 组 ID char Mode8; / 模式 char Size10; / 长度 char EndOfHeader2;/ 结束符 SectionHeader; 可以看到,头中的数据全都是字符串。用字符串的好处是可以提高格式的兼容性,因为在不同的机器上,数据的排列方式是不同的。有的机器是以 Little-Endian 方式工作,还有的是以 Big-Endian 方式工作,它们互不兼容
7、(这两种方式的区别!?请看我的COFF格式一文,其中的文件头一节有说明) 。用字符串就不会有这种问题(后面我们将会遇到)。但它也有不方便的地方,就是必须把字符串转换成数值,多了一个步骤。 在这个结构中,最常用的 Name、Size 以及 EndOfHeader 三个成员。Name 就是节的名称啦!Size 也很好理解,就是该节数据的长度。现在要注意的就是这个 EndOfHeader 成员了!这个成员标志着头的结束,其内容为“n”(注意,这里没有打错,是两个字符“” 和“n”) 。怎么样?有点奇怪吧?为什么要有这个结束符?每一节的头长度一定,每节中的数据长度也知道。按顺序向下读不行吗?答案是:不
8、行!因为每一节之间存在间隙!通常是一个字节或零个字节。如果是零个字节倒好,按顺序向下读是 OK 的。可是如果不为零的话,这样读就要错位了。要知道错位没有,只好用一个结束符来定位了。如果在读头的时候发现结束符不对,那就要一个字节一个字节地向下查找,直到找到结束符,才能算是对齐了。切记!切记! 当然,通过 First Sec 或 Second Sec 中给出的偏移来读数据就不存在这个问题。不会发生错位,放心读吧! 现在让我们来看看每一节中的数据是什么样子。 First Sec第一节,通常就是 Lib 中的每一个小节。它的名称是“/”。其数据部分的结构如下: typedef struct unsig
9、ned long SymbolNum; / 库中符号的数量 unsigned long SymbolOffsetn; / 符号所在目标节的偏移 char StrTablem; / 符号名称字符串表 FirstSec; 第一个成员 SymbolNum 是符号的数量。注意!它是以 Big-Endian 方式储存的(x86 平台上的数据是以 Little-Endian 方式储存的。这里应该注意转换。后面给出的 convert 函数可以在 Little-Endian 格式与 Big-Endian 格式之间进行相互转换) 。 第二个成员 SymbolOffset 是一个数组,它的长度 n 就是符号的数量
10、,也就是SymbolNum。这个数组储存了每一个符号所在的目标节的偏移。我们可以方便地通过它来查找符号所在的目标文件。注意!它也是以 Big-Endian 格式储存的。 第三个成员 StrTable 是一个字符串表,它的长度 m 就是 SectionHeader.Size 的值减去(SymbolNum+1)*4。其结构很简单,就是一堆以 0结尾的字符串(和 COFF 文件中的字符串表结构相同) 。在有的系统中,它还可能是以“/n”这两个字符结尾的字符串的集合。 很简单的一个结构,不过有两个成员的长度是不定的。怎么才能方便地从 Lib 中读出这些数据,留给大家自己想吧!下面我只给出一个进行 Li
11、ttle-Endian 与 Big-Endian 互转的函数。 inline void convert(void * p / 要转换的数据的指针 ,size_t size = 4 / 数据的长度,long 为 4,short 为 2 ) char * buf=(char*)p; char temp; for ( size_t i=0;in LongName Sec: This_Is_Long_Name00010 This_Is_Long_Name00020 Obj Sec1: Name16: “shortname/” Obj Sec2: Name16: “/0” / 这里使用了第一个长文件名 This_Is_Long_Name0001 Obj Sec3: Name16: “/22” / 这里使用了第二个长文件名 This_Is_Long_Name0002
Copyright © 2018-2021 Wenke99.com All rights reserved
工信部备案号:浙ICP备20026746号-2
公安局备案号:浙公网安备33038302330469号
本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。