接着《动态链接库(DLL)总结---简单使用(1)》我们来完善dll项目。为什么说是要完善DLL项目呢?在实际开发中,一个DLL实现后,通常会交给客户程序,以便后者能够调用。客户程序需要知道DLL导出了那些函数和函数原型,有人说我们在上篇文章是知道的啊,之所以知道是因为程序都是我们自己写的。如果我们自己使用别人编写的dll呢?那么我们可以使用一些工具来知道导出了那些函数和函数的原型,但是这样就不是很方便。通常在编写动态链接库的时候,会提供一个头文件,此文件中提供了导出了那些函数,以及函数的相关注释。
我们将上例中的 MyDllOne.h 文件改写如下:
#ifdef DLL1_API_IMP
#else
#define DLL1_API_IMP __declspec(dllimport)
#endif
DLL1_API_IMP int add(int a, int b);
DLL1_API_IMP int sub(int a, int b);
这里使用的是条件编译选项判断是否定义了DLL1_API_IMP符合,如果定义了该符合,则不做任何的操作;否则,将其定义为 __declspec(dllimport),然后用定义的__declspec(dllimport)去替换函数add 和 sub前面的DLL1_API_IMP。
MyDllOne.cpp文件改写如下:
#include "stdafx.h"
#define DLL1_API_IMP __declspec(dllexport)
#include "MyDllOne.h"
int add(int a, int b)
{
return (a + b);
}
int sub(int a, int b)
{
return (a - b);
}
我们在 MyDllOne.cpp文件中,首先定义DLL1_API_IMP宏,然后在导入MyDllOne.h文件。为什么要这么做呢?在程序编辑的时候,头文件不参与编译,源文件单独编译。因此,在编译MyDllOne.cpp文件的时候,首先定义了DLL1_API_IMP宏,将其定义为__declspec(dllexport)。然后在导入MyDllOne.h文件,展开头文件后,先判断是否定义了DLL1_API_IMP宏,发现定义了就不会再定义DLL1_API_IMP宏了,而是直接编译cpp后面的内容。
当我们生成dll文件后,交给其他程序使用的时候,只要后者没有定义DLL1_API_IMP宏,就会将DLL1_API_IMP宏定义为 __declspec(dllimport)。
这样我们就可以实现,.h头文件既可以由dll编写程序使用,也可以供调用该dll的程序使用。
我们将重新生成的 MyDllOne.h、MyDllOne.dll 和 MyDllOne.lib文件拷贝到window控制台测试项目目录下,代码如下:
#include "stdafx.h"
#include <Windows.h>
#pragma comment(lib,"DLL1.lib")
#include "DLL1.h"
int _tmain(int argc, _TCHAR* argv[])
{
printf("4+3 = %d \n", add(4, 3));
printf("4-3 = %d \n", sub(4, 3));
system("pause");
return 0;
}