zoukankan      html  css  js  c++  java
  • DLL模块例1:使用.def模块导出函数,规范修饰名称,显示连接调用dll中函数

    以下内容,我看了多篇文章,整合在一起,写的一个例子,关于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还有“侯凯”的博客。。

    ——现在的努力是为了小时候吹过的牛B!!
  • 相关阅读:
    Spring RedisTemplate操作-注解缓存操作(11)
    Spring RedisTemplate操作-通道操作(10)
    Spring RedisTemplate操作-事务操作(9)
    Spring RedisTemplate操作-发布订阅操作(8)
    Spring RedisTemplate操作-HyperLogLog操作(7)
    Spring RedisTemplate操作-Set操作(5)
    Spring RedisTemplate操作-ZSet操作(6)
    Spring RedisTemplate操作-List操作(4)
    Spring RedisTemplate操作-哈希操作(3)
    Spring RedisTemplate操作-String操作(2)
  • 原文地址:https://www.cnblogs.com/pingge/p/3155666.html
Copyright © 2011-2022 走看看