不同平台下,库文件的编译和应用原理

可能你还在用Visual C++平台或者VS2005编译源文件, 最后生成一个.exe或者DLL或者是lib文件,这一切都发生得那么神不知鬼不觉,测试一下,你是否了解下面的概念:

1. 一个dll或者exe文件的生成经过了哪些环节?

2. dll的调用有哪些方式?在这些不同的方式中,随DLL发布的.h文件, .lib文件,.dll文件将参与新的编译连接过程,那么他们分别参与到哪些过程.

3. #include<stdio.h> 是我们常用库,这个库,是静态库,动态库,还是其它, 位置如何?

能非常肯定2和3答案的,不是本文的读者,可以离开。^-^

第一:编译的全过程, 以windows平台为例.

先看看整个编译的过程, 为了防止概念过多,去掉预处理,汇编等繁杂的概念, 因为这些我们触碰不到, 我们关注的核心就两个,编译(compile), 连接(link):

compile -> link

通过编译,能生成的东东有: .obj文件, lib文件. 注意.obj文件和lib都是源代码生成的符号,包含信息一致,在头脑里不要区分它们,就简单的认为它们都是一个东西.

编译的时候, 大家都是独立编译的, 所以只需要找到函数或者变量的声明 就可以。因此参与这个过程的, 只需要.h文件(没有.h的, 可以通过extern 声明, 也是没有任何问题的)

通过link, 把编译成成的.obj文件, lib文件的符号连接起来, 形成二进制文件(DLL 或者exe)

连接的时候, 这个过程务必要找到编译后的符号文件, 比如函数和变量的定义

对于编译生成的DLL, 这个会在运行的时候用到. DLL 包含的是二进制的地址信息, 所以, 如果我们需要用到DLL, 务必知晓其地址信息。 这个地址信息, 可以直接通过windows平台查找dll的方法(比如, 下文提到的DLL三种使用模式中的独立使用方式). 另外一种常见的方式是: 通过lib定位DLL的信息, 对应于下面的DLL + lib或者DLL + .h + lib的方式. 当然lib要参与连接生成exe或者dll, 而.h如果存在的话, 必定是参与compile. 这种方式, 正是上文提到的: 我们采用的库的方式.

第二:windows平台下的动态链接库和静态链接库
但对一个项目而言,可以切分,比如将项目分为A模块,其它模块。

如果我们先将A模块编译成二进制的DLL,然后再和其他模块合并,这个时候,就称为动态链接;
如果我们现将A模块编译成lib文件, 然后在和其他模块合并,这个时候,成为静态链接;

接下来,我们关注什么是静态链接,什么是静态链接。

对于静态连接,已经没有任何可讲的地方了, 还记得吗,lib文件相当于obj文件, 我们如何用obj文件,就如何用lib文件,也许你真的明白obj文件的使用,但这里还是要让你重温一下:
如果有三个C源文件:a.c, b.c , c.c,及其配套的.h文件:a.h, b.h,c.h, 通过编译,将产生a.obj, b.obj, c.obj三个obj文件.

这里,如果a,b,c之间不存在相互引用, 根本不需要头文件参与进来编译的, 但是,如果,a用了b的变量或者函数,在编译a的时候,必须要一个头文件来声明所引用的函数(可以不必是b.h文件,甚至是x.h文件,但里面必须有用到变量或者函数的声明)。

当这三个文件编译之后,再进行连接,则肯定可以成功。

静态链接的道理跟obj文件的编译是一个道理,假如把b看做是静态库lib,b.h则是静态库所对应的lib文件. 当a.c需要用到b.c

中的函数来编译时, 它只需要b.h文件,生成a.obj, 最后a.obj和b.lib文件连接生成我们需要的二进制文件。


动态链接库,即有dll参与的库文件使用,也就是dll的使用方式,可以有以下几种:

1. dll独立使用

2. dll + lib

3. dll + lib + .h

在DLL独立使用的情况下:windows下会有一个loadLibray的机制,将生成的DLL二进制地址信息加入,直接调用,所以DLL既不需要编译,也不需要连接, 扔给exe文件就可以调用,有人称之为动态加载

在含有lib文件的情况下, 库函数的使用,是要参与连接的, 这就是传说中的静态加载 . 其原理如下:

此时的lib文件,跟上面静态链接不同,不再是所有的源文件的函数和变量内容,而是仅仅是DLL中函数或者变量的符号,通过lib的指引,其它的函数调用DLL库中的函数,轻而易举。

至于.h文件的作用,当然是参与编译了;如果源文件中用到dll的函数, 不声明为extern或者通过dll发布的头文件生命的话,是无法编译通过的。

一般而言,发布了lib文件, 最好发布一下头文件,不然怎么知道lib中带了什么函数呢?当然如果你是lib的制作者,你了解lib里面的蛛丝马迹,当然,你用个extern搞定这些lib中的函数和变量,也未尝不可。


OK,这里一句话可以做结Windows下的库调用:

.h参与compile, lib参与link, dll 参与excute

第三: Linux平台下的动态链接库和静态链接库

在静态链接技术上,两者五区别,中间的.o文件相当与.a静态文件, 跟Windows平台类似,动态连接技术上,两者存在区别:动态链接文件叫做share object, .so文件,但理论一致,只是,这个.so文件,包含的信息不同,相当于windows下dll + lib的信息, 也就是说, so文件,要参与连接, 也参与执行,但是, 可执行程序并不依赖于参与连接的so文件,可以是其它任何时间任何地点,只要接口相同的so文件。这点跟windows下的dll完全一样。

在gcc平台可以测试上面的原理。编译器所作的工作,各个平台也是有一些区别的。如果用gcc编译,会对其中的奥秘有更多的理解,这样会让你更多的思考利用vc和windows平台时,你没有考虑过的问题。


最后开篇的第三个问题没有解决:

stdio的引用方式是哪种: 应该是动态链接库, 但是加载的方式是静态的。

stdio库包含了dll(system32目录下), stdio.h, stdio.lib.

标准库大多是采用这样的方式. 动态的加载方式, 仅限于自己自导自演的游戏。开源库,标准库,都是动态链接库的静态加载。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值