以前总是不知道怎么使用第三方库,每次想学习一个库进行开发,总是遇到各种各样的问题,由于自己能力不够,不知怎么解决,网上也没有找到适合自己的解决方法,最后都放弃。比如之前想学vlc视频程序,想学duilib界面库,因为总感觉mfc的界面太丑,想学boost库等,可是之前对一些知识理解不到位,总是挫败告终,此时特意记录下来,以免以后忘记。
本文主要讲使用第三方库或自己编写的库的常规流程,从引入到最后成功调用。当然你使用第三方库的时候,还会遇到其他的问题导致编译不过,或者使用时候出错,这个会在另一篇博客中介绍。
本文主要以自己编写一个库作为例子,介绍每一个过程的细节,其实第三方库也是这么一个过程,作为程序员,举一反三的能力,相信还是没问题的。
一、编写库所生成的文件(核心文件)
库工程生成的三个核心文件是:xxx.h、xxx.lib、和xxx.dll。注意:并不是一定要同时存在三个文件,具体用哪个或哪两个文件,要根据你使用的情况而定,显式动态调用只需xxx.dll即可,隐式动态调用则必须要xxx.h和xxx.lib。
本文以生成一个math的库工程为例,注意仅仅是演示作用,自己实际开发时候尽量避免与现有的库同名,否则命名冲突。
1.1、新建win32项目,名称:math,点确定,选择dll,完成。
1.2、在mian.cpp(或者添加一个xxx.h的头文件和xxx.cpp的源文件,道理一样)添加以下代码。然后编译,生成文件即可。
1.3、看看生成了什么,去到debug目录下,生成了math.dll,和math.lib。头文件在哪?其实此时的main.cpp 就是所谓的头文件,只是懒得改罢了,所以此时的三个核心文件是:main.cpp,math.lib和main.dll。
二、两种使用库的方式。此时添加一个Pro工程调用这个库。
有了以上三个文件,有了新建的pro工程,要什么调用Add函数呢?这就是接下来要讲的,两种使用库的方式:隐式动态调用和显式动态调用。
2.1、隐式动态调用:
隐式动态调用:简单讲,就是告诉编译器,函数声明在头文件,函数定义在lib中。
隐式动态调用所需文件:xxx.h,和xxx.lib,两者缺一不可。隐式动态调用,有两种导入方式:
第一种导入方式:
1、包含头文件路径;注意,此时是main.cpp的路径,你的应该是xxx.h路径,即函数声明的文件路径
2、包含库文件路径;注意,刚才生成的lib的路径
3、添加库文件名称;(声明所在)
4、在调用的位置添加头文件;(定义所在)
5、将math.dll丢到Pro.exe所在目录下。
包含头文件和库路径
添加链接库的名称
在Pro工程中使用Add函数吧!看,调用成功!
第二种导入方式
1、包含头文件路径;
2、添加头文件名称;
3、使用#pragma comment(lib,“库名称”);
4、将math.dll丢到Pro.exe所在目录下。
先删除上面的配置文件,然后添加头文件路径。
引入头文件,添加#pragma comment(lib,“库名称”)。并查看结果,注意库的路径名称。实际中一般处理方法是,库路径包含到math.lib的路径,#pragma comment(lib,“math.lib”),此处故意为之,目的是让新手能看懂。
2.2、显式动态调用:
显式动态调用:简单讲,当exe执行,需要调用dll的时候,加载这个dll,并找到对应函数的地址,然后调用方法。
导入方式:很粗暴,只需要dll即可,并不需要.h和.lib,这两个是在编译的时候告诉exe,dll中函数的地址,而显式调用,直接在运行时找函数地址,所以不需要提前告诉exe,函数在哪。
1、include <windows.h> ;此头文件中定义导入库的函数:LoadLibrary()
2、HMODULE hMod = LoadLibrary(“math.dll”);//dll路径
3、FUNA addfun = (FUNA)GetProcAddress(hMod, TEXT(“Add”));//直接写调用的函数名:Add,返回函数地址
4、addfun(a, b);直接调用。
三、库导出函数时候的细节情况
1、在隐式动态调用的时候,_declspec(dllexport) int Add(int a,int b),就可以调用动态库
2、在显式动态调用的时候,必须添加extern “C”,如extern “C”_declspec(dllexport) int Add(int a,int b),否则在寻找函数指针时失败。原因为C++有函数重载,编译器会改编函数名称,当extern "C"之后,就用C的方式命名,就能找到函数地址,其中还涉及到函数调用约定等知识,在后续再研究,再记录下来。在隐式动态调用中没有出现这个问题,是编译器帮忙做了一些工作,会绑定改名后的地址,所以不会失败。
四、新建工程使用这个库
具体过程在第二部演示,不再展示,放在第二部分讲,是让新手更清楚显式和隐式调用之间的区别,怎么找到函数声明,怎么找到函数定义,或者怎么找到程序运行时的函数地址。
源码请看https://download.csdn.net/download/littlelittlefish_xyg/10716835