当前位置: 首页 > news >正文

Dll的编写与Dll的显示调用和隐式调用

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

Dll的编写:

    现在新建的Dll工程中创建一个新的类,我在这个类中简单定义了Add, Substract, Mutiply, Divide这4个方法

    具体代码如下:(MathFuncs.h)

#pragma once

#ifndef _MathFuncs_H
#define _MathFuncs_H

//定义函数导出
#ifdef __cplusplus
#define MyDll extern "C" __declspec(dllexport)  
#else
#define  MyDll __declspec(dllexport)
#endif // __cplusplus

//若不使用extern "C"关键字,则C++编译器会打乱函数的名称,使利用函数名的显式调用这种调用方式失败
//加上这个关键字是为了保持函数名的完整性
//#define MyDll  __declspec(dllexport)  

MyDll double Add(double a, double b);
MyDll double Substract(double a, double b);
MyDll double Mutiply(double a, double b);
MyDll double Divide(double a, double b);

class MathFuncs
{
public:
    MathFuncs(void);
    ~MathFuncs(void);

    double Add(double a, double b);

    double Substract(double a, double b);

    double Mutiply(double a, double b);

    double Divide(double a, double b);
};

#endif // !_MathFuncs_H

    注意要在类地外部将所要使用的方法用前面定义的关键字进行导出。

    然后再cpp文件中实现他们,代码如下:

#include "stdafx.h"
#include "MathFuncs.h"
#include <stdexcept>

using namespace std;

MathFuncs::MathFuncs(void)
{
}

MathFuncs::~MathFuncs(void)
{
}

double MathFuncs::Add(double a, double b)
{
    return a + b;
}

double MathFuncs::Substract(double a, double b)
{
    return a - b;
}

double MathFuncs::Mutiply(double a, double b)
{
    return a * b;
}

double MathFuncs::Divide(double a, double b)
{
    if (0 == b)
    {
	  throw new invalid_argument("b can not be zero!");
    } 
    else
    {
	  return a / b;
    }
}

//输出的方法都要将包含方法的类实例化
//输出的方法的实体不能含有类名
double Add(double a, double b)
{
    MathFuncs clsMF;
    return clsMF.Add(a, b);
}

double Substract(double a, double b)
{
    MathFuncs clsMF;
    return clsMF.Substract(a, b);
}

double Mutiply(double a, double b)
{
    MathFuncs clsMF;
    return clsMF.Mutiply(a, b);
}

double Divide(double a, double b)
{
    MathFuncs clsMF;
    return clsMF.Divide(a, b);
}

    完成后,将工程编译一下可以得到dll、lib等文件。现在我们来使用这个dll文件。

    显示调用,又称动态调用,具体思路为:

    定义相应的函数指针 -> 使用LoadLibrary加载需要使用的dll -> 利用GetProcAddress方法根据dll中的方法名称调用相应的方法 -> 使用FreeLibrary释放调用的dll文件

    代码如下:

//在显式调用中,c++和c调用动态库的写法是一样的

//显示调用(动态调用)
//1. 定义相应的函数指针
//2.使用LoadLibrary加载需要使用到的Dll
//3. 利用Dll中方法的名称调用里面的方法
//4. 使用FreeLibrary释放加载的Dll文件

#include <stdio.h>
#include <windows.h>
#include <iostream>
#include <conio.h>  //控制台输出、输入,其中包含了通过控制台进行数据输入和数据输出的函数
#include <string>

//动态调用函数所使用的函数指针一定要与所调用Dll中方法的返回值和参数完全一致
typedef double (*Calculate)(double a, double b);

using namespace std;

int main(void)
{
    HINSTANCE hDll;  //新建一个用于储存所调用Dll的句柄

    //注意宽字符版要用TEXT()去更改输入字符
    hDll = LoadLibrary(TEXT("../UsingDll/MathFuncsDll.dll"));  //“..”表示当前程序的“exe”文件所在路径的父路径(上一级路径)

    if (NULL != hDll)
    {
	  double a, b, dblResult;
	  string strSign;

	  cout << "请输入所要使用的计算方法(Add, Substract, Mutiply, Divide):";
	  getline(cin, strSign);
	  LPCSTR lpcStr = strSign.c_str();  //string转LPCSTR

	  cout << "请输入元素a:";
	  cin >> a;
	  cout << endl << "请输入元素b:";
	  cin >> b;
	 
	  Calculate pCalculate = NULL;  //定义一个函数指针

	  pCalculate = (Calculate)GetProcAddress(hDll, lpcStr);  //获取Dll中名为“lpcStr”的方法

	  if (NULL != pCalculate)
	  {
		dblResult = (*pCalculate)(a, b);
		cout << "调用Dll中方法计算后的结果为:" << dblResult << endl;

		FreeLibrary(hDll);  //在动态调用完Dll后必须使用该方法将其释放
	  }
	  else
	  {
		cout << "调用Dll中方法失败!" << endl;
	  }
    }

    system("pause");
    return 0;
}

    接下来是隐式调用:

    先要把dll工程中生成的lib文件导入到本工程,然后把dll文件放在程序运行的根目录下(.exe)或者system32文件夹中,跟着利用代码把要使用到的方法用关键字__declspec(dllimport)将他们导入。

    代码如下:

#include <iostream>

//隐式调用
//在导入Dll中方法时要在extern后使用"C"来防止C++编译器改变方法的名称
//1. 要先导入要用到的Dll中的方法(名称、参数等完全一致)
//2. 然后将对应的lib文件添加进工程
//3. 所使用的Dll文件一定要和exe文件处于同一路径之下,或者system32文件夹中
extern "C" __declspec(dllimport)double Add(double a, double b);
extern "C" __declspec(dllimport)double Substract(double a, double b);
extern "C" __declspec(dllimport)double Mutiply(double a, double b);
extern "C" __declspec(dllimport)double Divide(double a, double b);

using namespace std;

int main(_In_ int _Argc, char* argv[] )
{
    double a, b;
    double dblAddResult, dblSubstractResult, dblMutiplyResult, dblDivideResult;

    cout << "请输入a:";
    cin >> a;
    cout << endl << "请输入b:";
    cin >> b;

    dblAddResult = Add(a, b);

    dblSubstractResult = Substract(a, b);

    dblMutiplyResult = Mutiply(a, b);

    dblDivideResult = Divide(a, b);

    cout << "利用Dll中Add方法得到的结果为:" << dblAddResult << endl;
    cout << "利用Dll中Substract方法得到的结果为:" << dblSubstractResult << endl;
    cout << "利用Dll中Mutiply方法得到的结果为:" << dblMutiplyResult << endl;
    cout << "利用Dll中Divide方法得到的结果为:" << dblDivideResult << endl;

    system("pause");

    return 0;
}


转载于:https://my.oschina.net/u/2314763/blog/404074

相关文章:

  • JFinal 中使用 Dubbo —— 1 改造JFinal Demo
  • Memcached命令解析
  • 音乐社交APP源码ios版
  • linux下查看机器的cpu信息
  • Ext JS 6 驾临
  • ssh整合easyui的权限设计
  • ConcurrentDictionaryTKey, TValue的AddOrUpdate方法
  • 程序开发心理学阅读笔记——第II篇
  • Swift基础
  • Android学习笔记之AlarmManager有关的定时器和闹钟的实现
  • oozie 安装过程总结
  • Ossim中查看网络流量历史数据
  • linux下安装FFmpeg
  • XML处理类
  • Prototype属性
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • 【面试系列】之二:关于js原型
  • Angular2开发踩坑系列-生产环境编译
  • JavaScript新鲜事·第5期
  • KMP算法及优化
  • PHP变量
  • Python进阶细节
  • vue数据传递--我有特殊的实现技巧
  • 初识MongoDB分片
  • 将 Measurements 和 Units 应用到物理学
  • 模仿 Go Sort 排序接口实现的自定义排序
  • 前端_面试
  • 思考 CSS 架构
  • 无服务器化是企业 IT 架构的未来吗?
  • 2017年360最后一道编程题
  • 阿里云重庆大学大数据训练营落地分享
  • ​LeetCode解法汇总2696. 删除子串后的字符串最小长度
  • ​MySQL主从复制一致性检测
  • #stm32驱动外设模块总结w5500模块
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • (2)STL算法之元素计数
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (LeetCode C++)盛最多水的容器
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (二)fiber的基本认识
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • .a文件和.so文件
  • .Mobi域名介绍
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .NET 设计模式初探
  • .net 托管代码与非托管代码
  • .NET(C#) Internals: as a developer, .net framework in my eyes
  • .net与java建立WebService再互相调用
  • ::before和::after 常见的用法
  • @RestControllerAdvice异常统一处理类失效原因
  • @Tag和@Operation标签失效问题。SpringDoc 2.2.0(OpenApi 3)和Spring Boot 3.1.1集成
  • [2544]最短路 (两种算法)(HDU)
  • [BJDCTF2020]The mystery of ip