文章为转载,原文出处https://blog.csdn.net/qq_29542611/article/details/86618902

前言
先简单介绍下DLL。DLL:Dynamic Link Library 动态链接库 是一个被其他应用程序调用的程序模块,其中封装了可以被调用的资源或函数。DLL 文件属于可执行文件,它符合Windows系统的PE文件格式,不过它是依附于EXE文件创建的的进程来执行的,不能单独运行。为了演示调用DLL程序的2种方法,我们先建一个简单的DLL程序。

建一个简单的DLL程序
IDE 使用vs2015,新建工程DLLTest1,选择空项目,创建完毕 右击项目 -> 属性 -> 常规 -> 配置类型 选择 动态库.dll。还是上一张图吧。

添加头文件Calc.h 在头文件中添加导出函数add函数

  1. #pragma once
  2.  
  3. extern "C" __declspec(dllexport) int add(int a, int b);

cpp文件中进行实现  

  1. #include "Calc.h"
  2.  
  3. int add(int a, int b)
  4. {
  5. return a + b;
  6. }

生成解决方案,在Debug下生成 DLLTest1.dll和DLLTest1.lib  

对DLL程序调用方式一

同样是新建空项目,添加main.cpp文件,将 DLLTest1.dll和DLLTest1.lib 拷贝到工程代码目录,然后项目添加添加现有项。项目目录如下
在这里插入图片描述

使用代码如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <Windows.h>
  4.  
  5. #pragma comment(lib,"DLLTest1.lib")
  6.  
  7. extern "C" int add(int a, int b);
  8.  
  9. // 静态调用DLL库
  10. void StaticUse()
  11. {
  12. int sum = add(10, 20);
  13. printf("静态调用,sum = %d\n", sum);
  14. }

方式一 是静态调用,在连接阶段 将DLL库信息编写到EXE文件中,当调用DLL库中的函数是会加重DLL库。#pragma comment(lib,“DLLTest1”)告诉连机器需要在FirstDll.lib文件中找到DLL中导出函数的信息。  

对DLL程序调用方式二

方法一属于静态调用,其方式是通过链接器将DLL函数的导出函数写进可执行文件。现在使用第二种方式,相对前一种 是动态调用。动态调用不是链接时完成的,而是在运行时完成的。动态调用不会在可执行文件中写入DLL相关的信息。代码如下:

  1. // 动态调用DLL库
  2. void DynamicUse()
  3. {
  4. // 运行时加载DLL库
  5. HMODULE module = LoadLibrary("DLLTest1.dll");
  6. if (module == NULL)
  7. {
  8. printf("加载DLLTest1.dll动态库失败\n");
  9. return;
  10. }
  11. typedef int(*AddFunc)(int, int); // 定义函数指针类型
  12. AddFunc add;
  13. // 导出函数地址
  14. add = (AddFunc)GetProcAddress(module, "add");
  15.  
  16. int sum = add(100, 200);
  17. printf("动态调用,sum = %d\n",sum);
  18. }

用到了以下2个函数:  

  1. // 根据DLL文件名 加载DLL
  2. // suc,返回一个模块句柄
  3. HMODULE WINAPI LoadLibrary(
  4. _In_ LPCTSTR lpFileName
  5. );
  6. // suc,返回lpProcName指向的函数名的函数地址。
  7. FARPROC GetProcAddress(
  8. HMODULE hModule,
  9. LPCSTR lpProcName
  10. );

测试

测试代码如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <Windows.h>
  4.  
  5. #pragma comment(lib,"DLLTest1.lib")
  6.  
  7. extern "C" int add(int a, int b);
  8.  
  9. // 静态调用DLL库
  10. void StaticUse()
  11. {
  12. int sum = add(10, 20);
  13. printf("静态调用,sum = %d\n", sum);
  14. }
  15.  
  16. // 动态调用DLL库
  17. void DynamicUse()
  18. {
  19. HMODULE module = LoadLibrary("DLLTest1.dll");
  20. if (module == NULL)
  21. {
  22. printf("加载DLLTest1.dll动态库失败\n");
  23. return;
  24. }
  25. typedef int(*AddFunc)(int, int); // 定义函数指针类型
  26. AddFunc add;
  27. add = (AddFunc)GetProcAddress(module, "add");
  28.  
  29. int sum = add(100, 200);
  30. printf("动态调用,sum = %d\n", sum);
  31. }
  32.  
  33. int main(char argc, char* argv[])
  34. {
  35. StaticUse();
  36. DynamicUse();
  37. system("pause");
  38. return 0;
  39. }

验证结果,和我们想象的一样。  

  

C/C++:Windows编程—调用DLL程序的2种方法(转载)的更多相关文章

  1. [Windows][VC]开机自动启动程序的几种方法

    原文:[Windows][VC]开机自动启动程序的几种方法 很多监控软件要求软件能够在系统重新启动后不用用户去点击图标启动项目,而是直接能够启动运行,方法是写注册表Software\\Microsof ...

  2. java中调用dll文件的两种方法

    一中是用JNA方法,另外是用JNative方法,两种都是转载来的, JNA地址:http://blog.csdn.net/shendl/article/details/3589676   JNativ ...

  3. VC++开机自动启动程序的几种方法 (转载)

    转载:http://blog.csdn.net/zhazhiqiang/article/details/51909703 很多监控软件要求软件能够在系统重新启动后不用用户去点击图标启动项目,而是直接能 ...

  4. windows下获取IP地址的两种方法

    windows下获取IP地址的两种方法: 一种可以获取IPv4和IPv6,但是需要WSAStartup: 一种只能取到IPv4,但是不需要WSAStartup: 如下: 方法一:(可以获取IPv4和I ...

  5. 请阐述调用Activity有哪几种方法,并写出相关的Java代码

    请阐述调用Activity有哪几种方法,并写出相关的Java代码. 答案:可以采用两种方式调用Activity:显示调用和隐式调用.显示调用直接指定了Activity,代码如下: Intent int ...

  6. android中退出当前应用程序的四种方法

    android中退出当前应用程序的四种方法 [IT168 技术]Android程序有很多Activity,比如说主窗口A,调用了子窗口B,如果在B中直接finish(), 接下里显示的是A.在B中如何 ...

  7. android 安全退出应用程序的几种方法

    android 安全退出应用程序的几种方法 正常关闭应用程序: 当应用不再使用时,通常需要关闭应用,可以使用以下三种方法关闭android应用: 第一种方法:首先获取当前进程的id,然后杀死该进程.a ...

  8. Tomcat部署发布JSP应用程序的三种方法 (转)

    Tomcat部署发布JSP应用程序的三种方法     1.直接放到Webapps目录下      Tomcat的Webapps目录是Tomcat默认的应用目录,当服务器启动时,会加载所有这个目录下的应 ...

  9. ASP.NET,C#后台调用前台javascript的五种方法

    C#后台调用前台javascript的五种方法 由于项目需要,用到其他项目组用VC开发的组件,在web后台代码无法访问这个组件,所以只好通过后台调用前台的javascript,从而操作这个组件.在网上 ...

随机推荐

  1. 61. File类

    IO技术主要作用是解决设备与设备之间的数据传输问题.比如:硬盘---->内存     内存的数据---->硬盘上    把硬盘的数据------>内存中 IO技术的应用场景:     ...

  2. JMeter生成性能报表-Windows环境和Linux环境

    转载自https://www.cnblogs.com/imyalost/p/10239317.html

  3. Linux环境下安装PHP的gd库

    当前使用的安装包版本: freetype-2.4.0.tar.bz2 jpegsrc.v9.tar.gz libpng-1.6.28.tar.gz 1.安装freetype tar jxvf free ...

  4. 转载-NX11.0二次开发新增Spreadsheet相关类的用法!

    这几天搜NX对EXCAL读取写入相关的开发内容,发现唐工写了一篇关于NX11对EXCAL操作的文章.让我知道NX11新增了对EXCAL操作相关的类,以前NX里是没有的.我以前都是用OLE方式去做,没用 ...

  5. 树莓派安装raspbian

    需要准备 Win32DiskImager-v0.6 2016-09-23-raspbian-jessie.img 右键管理员打开Win32DiskImager 选择上面的img文件,选择存储卡盘符,点 ...

  6. PostgreSQL——服务器基本设置与操作

    一.编译安装: 环境准备: GNU make 版本 >=3.8 (make --version) ISO/ANSI C 编译器,至少須兼容 C89 标准,GCC 或 intel 編译器等均可 g ...

  7. 剑指offer——74求1+2+3+n

    题目描述 求1+2+3+...+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B:C).   题解: 利用类的构造和析构 //利用类的构 ...

  8. BigDecimal.divide方法

    java.math.BigDecimal.divide(BigDecimal divisor, int roundingMode) 返回一个BigDecimal,其值为(this/除数),其标度是th ...

  9. HTML5篇

    [HTML5十大新特性] (1) 语义化标签 (2) 增强型表单 (3) 视频和音频 (4) canvas绘图 (5) SVG绘图 (6) 地理定位 (7) 拖放API (8) Web Worker ...

  10. 2019年Pandas官方用户调研

    import pandas as pd import seaborn as sns import matplotlib.pyplot as plt %matplotlib inline plt.rcP ...