windows基础编程 - 静态库、动态库文件

来源:互联网 发布:teambition mac 编辑:程序博客网 时间:2024/05/21 06:20

前言

  • 库文件用于打包各种封装好的.cpp文件,简化项目流程文件并且对源码起到保护作用,静态库先于动态库产生的,它是链接过程中将库文件中的代码拷贝到目标代码中生成可执行文件,这样可执行文件可独立运行。
  • 动态库文件是现在主流的调用代码风格,它在链接过程中传入到目标代码中的只是库文件中的一个地址而已,并且在可执行文件运行前/时加载动态库文件到内存中,然后通过函数跳转执行相应动态库中的代码。
  • 二者相对比较而言,静态库牺牲了空间相对效率更高,而动态库生成的可执行文件相对较小但效率更低些。但现在制作项目的流程中,更关注的是可维护性和代码的修改性,如果静态库文件中的函数发生了修改,那么需要同时重新编译静态库文件和可执行文件。然后动态库文件中的函数如果做了修改,但是函数签名和地址都未发生变化,那么只需重新编译该动态库文件即可,这样就省去重新编译这个项目的麻烦。

静态库

  • windows下的静态库文件是.lib文件,只需在VC新建对应的static library项目即可。
  • 静态库的调用有两种方式,一种是源代码中显示指明静态库文件所在的路径,使用 #pragma comment(lib,”$PATH”) 即可指定静态库路径,或者直接在project setting->link->库模块中添加该路径。
  • 注意,由于C++语法编译函数的时候存在换名现象,所以无论是使用静态库或者动态库,在Cpp文件里使用C制作的库文件均需要在调用声明前加extern “C”关键字。

动态库

  • 新建一个dynamic-link library项目即制作.dll结尾的动态库文件。
  • 该项目在编译链接后同时会生成一个.lib文件,该文件是作为动态库函数映射使用,是给可执行文件隐式调用动态库看的,与上面的静态库不完全相同。
  • 实际动态库的使用分为隐式链接(系统加载)和显示链接(手动加载)两种使用方式,前一种依赖.lib文件,也就是我们依旧需要在使用时指定.lib文件路径(和静态库一样,两种方式),而后一种其实是在代码中指定了动态库文件路径,所以可以不依赖.lib文件,但这种方式使用相对很麻烦。
  • 使用动态库中的函数需要在函数申明前加关键字__declspec(dllimport)关键字。

导出动态库

  • 方法一,在动态库函数声明前加关键字 __declspec(dllexport),这种方式生成的.lib文件中其实保存的是换名后的函数名对应的编号,而.dll文件中保存换名后的函数名对应的相对地址,这里要指出的换名和使用显示链接方式有关。
  • 方法二,在sourcefile中添加一个.def结尾的文本文件,该文件按如下语法:

    LIBRARY DLLFUNC //库名
    EXPORTS //关键字,库导出表
    DLL_Mul @ 1 //需导出的库函数,并做编号1
    //按上面格式依次指定要到处的函数和编号

    这样我们就可以在动态库项目中的源文件.cpp里函数前不加关键字__declspec(dllexport),而在.def在写一遍函数名即可,这样的效果是生成的dll和lib文件中的函数地址是不换名的函数,也是和显示链接使用方式有关,当然这里函数前加上那个关键字就保留换名语义了。

使用动态库

隐式链接
  只需设定.lib文件的路径就可以在代码里调用动态库中的函数,这样操作系统加载器(链接时从lib文件中获取需要哪个动态库)在执行程序前加载该动态库。
显示链接
 显示链接其实就是UC中的动态加载,在程序中写代码自己去查找动态库中的函数,这种方式只会在程序运行期间加载该动态库,而且就算原动态库做过修改,函数地址发生改变,对我也没影响(如果是隐式需重新编译),使用不走如下 - 使用LoadLibrary函数加载动态库,返回该库句柄 - 自己定义函数指针,并调用GetProcAddress接收该函数地址,同时需要在参数中指明函数名称,此时如果是换名函数还需从.dll文件中查找换名后的函数名。 - 使用freeLibrary函数结束并卸载该动态库。

动态库类的使用技巧

动态库类的创建方式和动态库函数一样,但需将类写在头文件中,并且在类名前加关键字__declspec(dllexport),而用户调用时只需包含该头文件,但用户又需要将该关键字改为__declspec(dllimport)才可使用,其实,只需使用如下宏技巧就可避免这个麻烦

    #ifdef DLLCLASS_EXPORTS    #define EXT_CLASS __declspec(dllexport)    #else    #define EXT_CLASS __declspec(dllimport)    #endif    class EXT_CLASS CMath{};

而在写动态库文件时自己些定义宏DLLCLASS_EXPORTS即可,用户无需做任何改变

0 0
原创粉丝点击