在 VS 平台下创建和调用 DLL 过程并不复杂,但是里面有很多小的步骤,需要亲自实践之后才会更清晰。直接一步步上图,会更加清晰。
在选择 “应用程序类型” 的时候,注意选定 “DLL”, “附加选项” 中需勾选 “预编译头”。然后点击完成就可以生成图示的 .h 和 .cpp 文件了。
前面都是小菜菜一碟,其实最关键的是如何生成 def 文件。关于 def 文件在生成 dll 文件中如何如何的优秀,我就不详细叙述了,有兴趣的自己看。
能够找到模块定义文件的关键是右键要点对地方,右键一定要停靠在当前项目 CreateDLL上,如果停靠在“解决方案”上,无论如何也找不到这玩意儿。
现在我生成需要导出的文件四个个文件,分别是:calculate.h , calculate.cpp,print.h,print.cpp.
// calculate.h
int add(int a, int b);
int sub(int a, int b);
// calculate.cpp
#include "calculate.h"
#include "stdafx.h"
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
// print.h
void print();
// print.cpp
#include "print.h"
#include "stdafx.h"
#include "iostream"
using namespace std;
void print()
{
cout<< "print successfully!" ;
}
这里需要注意的是,在源文件中需要添加 #include "stdafx.h"
,而不是在头文件中。
DLL 的声明有两种方式:一种是使用 def 文件,另一种是在函数头前直接声明。
现在我们需要导出三个函数,分别是int add(int a, int b)
, int sub(int a, int b)
,void print()
. 其实就变得很容易了,直接在 def 文件中添加如下几行代码:
EXPORTS
add
sub
print
Ok, 创建完成,直接生成(Ctrl + shift + B), 现在打开解决方案文件夹下的 Debug 目录就可以看到生成了我们需要的 CreateDLL.dll 和 CreateDLL.lib 两个文件了。
使用 __declspec(dllexport) 直接定义函数作为 dll 导出,相比 def 而言,无需添加 def 文件,只需在头文件中声明就可以。
头文件 calculate.h
#define MYDLL __declspec(dllexport)
MYDLL int add(int a, int b);
int sub(int a, int b);
MYDLL int square_error(int a, int b);
源文件 calculate.cpp
#include "calculate.h"
#include "stdafx.h"
#include
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int square_error(int a, int b)
{
return (int)pow((float)sub(a,b), 2);
}
DLL文件的调用也是比较简单的,分为了显式调用和隐式调用,其实隐式调用更加简单。先讲隐式调用,再讲显式。实际操作中隐式调用更加方便。
首先当然是创建一个 Win32 项目或者 Win32 控制台应用程序,这里略过 N 个字,大家都知道。我们创建了一个名为 CallDLL 的 Win32 控制台应用程序。需要注意的是,预编译头一定要勾选。
(1)将 CreateDLL.dll、CreateDLL.lib 以及需要用到的头文件 calculate.h、print.h 复制到当前项目的CallDLL 文件夹中。
(2)在 CallDLL.cpp 文件的入口函数前面添加上
#include “calculate.h”
#include "print.h"
#pragma comment (lib , "CreateDLL.lib" )
这时就可以正常在主函数中使用我们 dll 中函数了。如下图所示
运行程序,看看是不是 OK了,哈哈!!!
当黑框框出现的时候就已经无比鸡冻了。说明成功!
(1) 只需要将 CreateDLL.dll 文件添加到相应的文件夹,而无需神马 lib 文件和头文件。但是代码相对来说要复杂一些。
(2) 在 CallDLL.cpp 文件的入口函数前面添加上 #include
,因为要用到 API 函数。
(3) 示例代码
#include "stdafx.h"
#include // 需要调用 Windows API
#include "iostream"
using namespace std;
typedef int (*pFun)(int a,int b); // 函数指针
typedef void (*pPrint)(); // 函数指针
int _tmain(int argc, _TCHAR* argv[])
{
HMODULE h = LoadLibrary(_T("dll_test.dll"));
if(h != NULL)
{
pFun pAdd = (pFun)GetProcAddress(h, "add");
cout <<"a + b = "<20, 30) << endl;
pFun pSub = (pFun)GetProcAddress(h, "sub");
cout <<"a - b = "<20, 30) << endl;
pPrint p = (pPrint)GetProcAddress(h,"print");
p();
cout<<"\n";
}
FreeLibrary(h);
return 0;
}
同函数生成的方法差不多,下面需要把 Calcuate 类封装
头文件 calculate.h
class Calculate
{
public:
int add(int a, int b);
int sub(int a, int b);
int square_error(int a, int b);
};
源文件 calculate.cpp
注意,在源文件中,#include "stdafx.h" 要放在
#include “calculate.h”` 的前面才能生成成功。
#include "stdafx.h"
#include "calculate.h"
#include
int Calculate::add(int a, int b)
{
return a + b;
}
int Calculate::sub(int a, int b)
{
return a - b;
}
int Calculate::square_error(int a, int b)
{
return (int)pow((float)sub(a,b), 2);
}
我们需要把 Calculate 类中的 add, square_error两个函数导出, 相应的 def 文件为
LIBRARY
EXPORTS
add
square_error
同函数 dll 调用类似,此处贴上代码
// CallDLL.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include
#include "calculate.h"
#include "print.h"
using namespace std;
#pragma comment (lib , "CreateDLL.lib" )
int _tmain(int argc, _TCHAR* argv[])
{
int a = 50;
int b = 30;
Calculate calc; // 声明类的对象
cout << "a+b="<int c = calc.square_error(a,b);
cout << "a,b平方差为:"<cout<<"\n";
return 0;
}