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

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;
}
时间: 2024-07-30 19:14:42

Dll的编写与Dll的显示调用和隐式调用的相关文章

Dll的显式和隐式调用

隐式调用: 需要把生成动态链接库时生成的.lib文件加入到工程中去,在使用DLL时,只需说明一下就可以直接调用DLL中的函数,像调用程序内部的函数一样 显示调用: 需要使用LoadLibrary方式将自己生成的DLL文件先加载进来,在通过LoadLibrary返回的HINSTANCE,调用GetProcAddress获取想要的函数,然后就可以正常调用DLL中的函数 注意:在应用程序退出前,应该FreeLibrary来释放动态链接库 VC++中有两种方式来导出函数: 1. 通过_declspec

隐式调用 Intent 大全

//调用浏览器 Uri uri = Uri.parse(""); Intent it = new Intent(Intent.ACTION_VIEW,uri); startActivity(it); //显示某个坐标在地图上 Uri uri = Uri.parse("geo:38.899533,-77.036476"); Intent it = new Intent(Intent.Action_VIEW,uri); startActivity(it); //显示路径

Intent(二)隐式调用intent

在上一节我们一起学习了显示调用Intent,这一节我们来学习如何隐式调用Ingtent.有了这个我们就可以调用其他的线程,或者程序,可以让我们的应用程序变得多彩,如打开网页,拨打电话等. 接下来让我们来做两个例子:第一个调用浏览器,第二个调用拨号盘. 1.调用浏览器:接着上次的例子,在MainActivity中的按钮添加以下代码: Intent intent=new Intent(Intent.ACTION_VIEW) ;//这个是系统的一个内置动做. intent.setData(Uri.pa

显示接口和隐式接口的区别:

一.新建一个接口类 using System; using System.Collections.Generic; using System.Linq; using System.Web; /// <summary> /// InterF 的摘要说明 /// </summary> public class InterF { public interface hide { string show(); } public interface display { string show(

JavaScript中valueOf、toString的隐式调用

今天在群上有人问这样一个问题: 函数add可以实现连续的加法运算函数add语法如下add(num1)(num2)(num3)...;//注意这里是省略号哟,无限使用举例如下:add(10)(10)=20;add(10)(20)(50)=80;add(10)(20)(50)(100)=180;请用js代码实现函数add. 自个琢磨了一会只能Google之,代码如下: function add(num){ var sum=num, tmp=function(v){ sum+=v; return tm

Intent 的显示意图和隐式意图

Intent是意图,四大组件之间的通讯通过Intent来完成分为显示意图与隐式意图. Intent的显示意图很好理解就是指定好要跳转的界面: 可以通过putExtra传递不同类型的信息,以上只是一些例子.然后在SecondActivity接收这些信息就可以了: int类型与boolean类型接收时要写默认收到的信息即未收到时显示的,要注意与传递的信息区分开. Intent的隐式意图与显示意图相反,它不指定跳转的界面,是根据设置action的值来跳转,只要与设置的action值匹配就行: 然后在清

selenium 的显示等待和隐式等待的区别(记录加强版)

什么是显示等待和隐式等待? 显示等待就是有条件的等待隐式等待就是无条件的等待 隐式等待 当使用了隐式等待执行测试的时候,如果 WebDriver 没有在 DOM 中找到元素,将继续等待,超出设定时间后则抛出找不到元素的异常,换句话说,当查找元素或元素并没有立即出现的时候,隐式等待将等待一段时间再查找 DOM,默认的时间是 0 from selenium import webdriver browser = webdriver.Chrome() browser.implicitly_wait(10

Windows提供了两种将DLL映像到进程地址空间的方法(隐式和显式)

调用DLL,首先需要将DLL文件映像到用户进程的地址空间中,然后才能进行函数调用,这个函数和进程内部一般函数的调用方法相同.Windows提供了两种将DLL映像到进程地址空间的方法: 1. 隐式的加载时链接 这种方法需要DLL工程经编译产生的LIB文件,此文件中包含了DLL允许应用程序调用的所有函数的列表,当链接器发现应用程序调用了LIB文件列出的某个函数,就会在应用程序的可执行文件的文件映像中加入一些信息,这些信息指出了包含这个函数的DLL文件的名字.当这个应用程序运行时,也就是它的可执行文件

在Android中Intent的概念及应用(一)——显示Intent和隐式Intent

Intent寻找目标组件的两种方式: 显式Intent:通过指定Intent组件名称来实现的,它一般用在知道目标组件名称的前提下,一般是在相同的应用程序内部实现的. 隐式Intent:通过Intent Filter来实现的,它一般用在没有明确指出目标组件名称的前提下,一般是用于在不同应用程序之间. 一.显示Intent: 创建一个Activity的完整过程: 1.手动创建一个类,让其继承自Activity: public class MyAty extends Activity 2.让其绑定一个