库的创建和使用1

来源:互联网 发布:全球域名交易 编辑:程序博客网 时间:2024/06/05 20:22

     库是我们经常要是用的东西。库分为两种 静态库和动态库。 两种的共同点是实现了代码的重用。但是静态库是是编译之后就别打包到exe可执行文件中去了,但是动态库不是的,他可以显示的加载,在你需要的时候。当然也可以隐式加载。这样的话,显然他不是被打包到exe中去的。

      我们先来看两种库的文件构成。  静态库是一个lib文件,但是给到使用者的时候,往往会有一个头文件。来声明库里面的函数。动态库的构成呢。也是一个lib文件,一个dll文件。通常也会有一个头文件给到使用者。但是这里两个lib文件的是根本不同的。静态库的lib文件就是库的实际代码和符号表等,而动态库的lib文件呢。其实他是一个导入库,导入库只包含了地址符号表等,确保程序找到对应函数的一些基本地址信息。

        两种库的生成方式。对于静态库来说,他是在链接时与汇编生成的obj文件链接在一起,打包到exe文件中。所以lib文件格式与obj文件格式相类似。由于lib文件时打包到exe文件中去的,所以可执行文件运行时是可以脱离静态库文件的。这样的话,移植很方便。同样也造成了浪费。    对于动态库来说,在链接的时候,并没有将dll打包到exe文件中,只是告诉了链接器导入库,这里记载函数的地址的符号表,用于定位。运行时,去加载dll。所以exe文件运行时是不能离开dll的。这样的可执行文件的移植不如静态库方便。节省了资源。  

          两种库文件的的调用方式都用两种显示和隐式。对于静态库来说 ,隐式调用就是在vs 中在项目属性中link的input 中添加依赖项。显式调用就是使用#pragma comment(lib,"..\xx.lib")。 对于动态库的话也有显式和隐式调用区分。隐式调用就是在项目属性中的link 的input添加依赖项。对于显式调用的时候,就是用LoadLibrary获得模块的句柄,然后用GetProcAddress 获取函数地址,这样去调用函数。但是我们在显示调用的时候库文件时,库文件的导出函数就必须要extern “C” 修饰。这个是由于GetProcAddress  这些函数的API 的接口是是标准c的接口的。显式的去调用的时候我们只能extern "C"修饰。所以这个是不支持重载的。对于类的导出也是很复杂的,所以不建议使用显式调用dll。如果我们dll函数是有重载的,我们在使用dependency 工具去查看的时候会发现 用extern “C”修饰的函数和没有用extern “C”修饰的函数 函数名字是不一样的。这些函数是这个dll的模块的真正的函数入口。当我们使用不同的调用约定的方式的时候,函数名也会不一样。我们会发现在显式调用的时候,我们使用GetProcAddress  填上真正函数名时时有函数入口地址返回的。这是还要dll里面导出函数的调用约定,是__cdecl 还是__stdcall 的,c,c++的调用约定方式__cdcel。不过dll调用约定方式__stdcall的话,register 会报错。

        

0 0
原创粉丝点击