C++ 调用DLL的方法总结

qi.wei

发布于 2018.02.04 21:12 阅读 5896 评论 2

C++ 调用DLL的方法总结

文章分为以下几个部分:

1DLL是什么?

2.为什么要加载DLL

3.加载DLL的方法

4.什么时候用显式调用?什么时候用隐式调用?

5lib文件是什么?

6.怎么通过显式调用加载DLL

7.怎么通过隐式调用加载DLL

8.总结


DLL是什么?

      DLL又叫做动态链接库。DLL文件中存放的是各类程序的函数(子过程)实现过程,当程序需要调用函数时需要先载入DLL,然后取得函数的地址,最后进行调用。拿超级狗来说,他们提供的DLL文件里面所存放的内容就是超级狗的接口函数。

为什么要加载DLL

如果想要使用超级狗API就必须加载超级狗提供的DLL。使用DLL文件的好处是程序不需要在运行之初加载所有代码,只有在程序需要某个函数的时候才从DLL中取出。另外,使用DLL文件还可以减小程序的体积。

加载DLL的方法

      加载DLL有两种方法:(1)显式调用    2)隐式调用

什么时候用显式调用?什么时候用隐式调用?

      首先说一下,这两种方式都需要.h文件和DLL文件。隐式调用和显示调用最大的一个区别就是隐式调用还要用到lib文件。其次显示调用比较复杂,隐式调用比较简单。

      如果说,只有.h文件和DLL文件,那么只可以通过显示调用的方式,如果有lib文件的情况下,一般都会选择比较简单的隐式调用,当然特殊情况下也可以选择显示调用的方法。

lib文件是什么?

      上面刚提到,隐式调用还需要用到lib文件,那么问题来了,什么是lib文件?

      lib有两种,一种是静态库另一种就是隐式调用时配合DLL文件使用的,起链接的作用。

怎么通过显式调用加载DLL

1.        显示调用必备两样东西:头文件、DLL文件

2.        将头文件和DLL文件放在项目目录下

3.        LoadLibrary() 函数用来载入指定的dll文件,加载到调用程序的内存中(DLL没有自己的内存!)GetProcAddress() 函数检索指定的动态链接库(DLL)中的输出库函数地址,以备调用。FreeLibrary() 释放dll所占空间。

4.        QT中通过QLibrary 类来加载DLL

VS示例代码:

#include <windows.h>  
#include <stdio.h>  
void main(void)  
{  
typedef int(*pMax)(int a,int b);  
typedef int(*pMin)(int a,int b);  
HINSTANCE hDLL;  
PMax Max  
HDLL=LoadLibrary("MyDll.dll");//加载动态链接库MyDll.dll文件;  
Max=(pMax)GetProcAddress(hDLL,"Max");  
A=Max(5,8);  
printf("比较的结果为%d\n",a);  
FreeLibrary(hDLL);//卸载MyDll.dll文件;  
} 


怎么通过隐式调用加载DLL

1.        隐式调用必备三样东西:头文件、DLL文件、lib文件

2.        VS中将三者都放在项目目录下;QT中将头文件、lib文件放入项目目录下,将DLL文件放入输出目录下。

3.        添加lib文件。VS中右击项目à属性à链接器à附加依赖项à添加lib文件。QT中右击项目à添加库à选择库文件(lib文件)à完成,这样会自动在.pro文件中添加配置代码,也可以自己在.pro文件中添加代码,格式为:LIBS += -L位置 -l文件名。

4.        使用接口函数

VS示例代码(QT类似):

#include <iostream>

#include "dog_api_cpp.h"
#include "vendor_code.h"

using namespace std;

int main()
{
	dog_status_t   status;
	dog_handle_t   handle;
	dog_size_t     fsize;

	unsigned char membuffer[128];

	//登录
	status = dog_login(0,
		(dog_vendor_code_t *)vendor_code,
		&handle);
	cout << status<<endl;

	//获取文件大小
	status = dog_get_size(handle,
		1,			/*文件ID*/
		&fsize);
	cout << status << endl;
	cout << fsize << endl;

	//读取数据
	status = dog_read(handle,
		1,     /* file ID */
		0,                 /* 字节偏移量 */
		fsize,             /* length */
		&membuffer);    /* file data */
	cout << status << endl;
	cout << membuffer << endl;

	return 0;
}



总结

      这次学习超级狗API的使用,主要问题有如下几个:

1.        使用超级狗API到底该用哪个dll哪个lib

2.        怎么加载dlllib

3.        函数该怎么调?

对于第一个问题,为什么会有这么一个问题?因为超级狗他们给了很多dlllib,其中有64位的有32位的,有demo的有正式的,64位和32位主要是根据编译器来选择,VSQT都是默认为32位的。Demo和正式的那我们肯定是要选择正式的。所以最终确定下来的应该是一个dll和一个lib

对于第二个问题,怎么加载,在上面已经说得很清楚了。之所以花这么多篇幅介绍怎么加载dll就是因为,超级狗API的使用,最关键的地方就是dll的调用。

对于第三个问题,函数该怎么调用?首先要确定函数的返回类型,在超级狗API当中,所有的函数返回类型都是dog_status_t类型,这是返回的状态信息,是一个整数,不同的数字代表不同的状态,可以通过判断这个数字来确定下一步的操作。然后再通过对照API文档,理解要传递的参数是什么,哪几个参数是传递进去供函数使用的,哪个参数是函数执行完之后改变了的。

解决掉上述三个主要问题,超级狗API使用的问题也就解决了。