首页 > 技术文章 > DLL模块例1:使用.def模块导出函数,规范修饰名称,显示连接调用dll中函数

pingge 2013-06-25 21:38 原文

以下内容,我看了多篇文章,整合在一起,写的一个例子,关于dll工程的创建,请参考博客里另一篇文章:http://www.cnblogs.com/pingge/articles/3153571.html

有什么不对的欢迎指正!!!

1.头文件

 1 //testdll.h
 9 #ifndef _TESTDLL_H_
10 #define _TESTDLL_H_
11 
12 namespace MathFuncs  
13 {  
14     // This class is exported from the testdll.dll  
15     // Returns a + b  
16     extern double _stdcall Add(double a, double b);
17 
18     // Returns a - b  
19     extern double _stdcall Subtract(double a, double b);
20 
21     // Returns a * b  
22     extern double _stdcall Multiply(double a, double b);
23 
24     // Returns a / b  
25     // Throws const std::invalid_argument& if b is 0  
26     extern double _stdcall  Divide(double a, double b);
27 }
28 
29 #endif

 

以上是dll工程的头文件,使用命名空间,声明extern外部变量,_stdcall是WIN32API的一种函数调用约定,表示函数参数从右到左压入堆栈

 1 // testdll.cpp : 定义 DLL 应用程序的导出函数。
 2 
 3 #include "stdafx.h"
 4 #include "testdll.h"  
 5 #include <stdexcept>  
 6 using namespace std;  
 7 
 8 namespace MathFuncs  
 9 {  
10     double _stdcall Add(double a, double b)  
11     {  
12         return a + b;  
13     }  
14 
15     double _stdcall Subtract(double a, double b)  
16     {  
17         return a - b;  
18     }  
19 
20     double _stdcall Multiply(double a, double b)  
21     {  
22         return a * b;  
23     }  
24 
25     double _stdcall Divide(double a, double b)  
26     {  
27         if (b == 0)  
28         {  
29             throw invalid_argument("b cannot be zero!");  
30         }  
31         return a / b;  
32     }  
33 }

以上定义的dll工程的导出函数

1 LIBRARY testdll
2 EXPORTS
3 Add @ 1
4 Subtract @ 2
5 Multiply @ 3
6 Divide @ 4

在源文件目录里面添加.def文件,

第一行说明DEF文件对应的dll

EXPORTS后列出要导出函数的名称

可以在.def文件中的导出函数名后加@n,表示要导出函数的序号为n(在进行函数调用时,这个序号将发挥其作用);

可以用dumpbin.exe或者depends.exe来查看dll中函数的接口参数——序号,函数名等

 1 //demo.cpp
 2 #include <windows.h>
 3 #include <iostream>  
 4 using namespace std;  
 5 
 6 int main()  
 7 {  
 8     double a = 7.4;  
 9     int b = 99;
10     //如果使用.def导出dll函数一定要加_stdcall
11     typedef double (_stdcall *pAdd) (double a,double b);
12     typedef double (_stdcall *pSubtract) (double a,double b);
13     HMODULE hDLL = LoadLibrary("testdll.dll");    //加载DLL文件
14     if(hDLL != NULL)
15         {
16             //得到dll中的第一个函数
17             pAdd fp1 = pAdd(GetProcAddress(hDLL,MAKEINTRESOURCE(1)));
18 
19             if(fp1 != NULL)
20                 {
21                     cout << "a + b = " <<  
22                         fp1(a, b) << endl;
23                 }
24             else
25                 {
26                     cout << "Cannot Find Function " << "add" << endl;    
27                 }
28 
29             //得到dll中的第二个函数
30             pSubtract fp2 = pSubtract(GetProcAddress(hDLL,"Subtract"));
31             if(fp2 != NULL)
32                 {
33                     cout << "a - b = " <<  
34                         fp2(a, b) << endl;  
35                 }
36             else
37                 {
38                     cout << "Cannot Find Function " << "Subtract" << endl;
39                 }
40             FreeLibrary(hDLL);
41         }
42     else
43         {
44             cout << "Cannot Find " << "testdll" << endl;
45         }
46     return 0;  
47 }

以上为一个调用dll的demo,使用显示调用,需要用到WIN32 API函数,GetProcAddress(hDLL,MAKEINTRESOURCE(1));第一个这个函数的第二个参数的获得通过dll导出函数的序号获得,GetProcAddress(hDLL,"Subtract");第二个这个函数的第二个参数的获得通过导出函数的名字来获得,

导出函数,一定要采用.def模块 或者 extern "C"修饰符来做,传统方法做出来的导出函数的名字会被编译器修改优化,导致很麻烦的名字,例如"?Subtract@MyMathFuncs@MathFuncs@@SANNN@Z"

表达上的不足请见谅。。相关资料请参考MSDN还有“侯凯”的博客。。

推荐阅读