C++ 调用dll的方法小结

 更新时间:2026年05月08日 09:55:45   作者:Sakuya__  
本文主要介绍了C++ 调用dll的方法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

动态链接库

动态链接库也被叫做为dll,是Dynamic Link Library的缩写。dll是一个被其他应用程序调用的程序模块,其中封装了可以被调用的资源或函数。dll不能够单独运行,它是依附于exe文件创建的进程来执行的。每个程序都可以通过链接dll使用其中包含的接口函数,这有助于避免代码重用和促进内存的有效使用,使程序实现模块化,只在相应的功能被请求时才加载相应模块。

另外,调用者只需要根据自己要实现的功能调用dll中对应的接口,而不需要知道每个接口函数具体的实现。dll的开发者可以通过dll隐藏接口的代码实现,比如你只想让其他人使用你的算法,但不想让其他人知道你的算法和逻辑代码,就可以把它们封装到dll中。这样,调用人的程序中不会包含算法实际的实现代码,而只有调用dll的接口代码。

建立一个DLL

打开Visual Studio,新建 -> 项目 -> Visual C++ -> 动态链接库

使用__declspec(dllexport)关键字导出dll

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

#ifdef __cplusplus         // 一般用于将C++代码以标准C形式输出(即以C的形式被调用)
extern"C"{                 // 告诉编译器下面大括号括起来的函数是c语言函数(因为c++和c语言对函数的编译转换不一样,主要是c++中存在重载)
#endif
__declspec(dllexport) int __stdcall  add(int a, int b);      // __declspec(dllexport)声明导出该函数供外部调用
__declspec(dllexport) int __stdcall  subtruct(int a, int b); // __stdcall是Windows API默认的函数调用协议,函数采用从右到左的压栈方式,自己在退出时清空堆栈,也可以不使用
#ifdef __cplusplus
}
#endif

__cplusplus是c++中的自定义宏,这个宏表示这是一段C++的代码。 在C++中,为了支持重载机制,在编译生成的汇编码中,要对函数的名字进行一些处理,加入比如函数的返回类型等等.而在C中,只是简单的函数名字而已,不会加入其他的信息.也就是说:C++和C对产生的函数名字的处理是不一样的。这里使用extern "C"就是告诉编译器,以C的方式来链接它括起来的函数。上面的函数的含义就是:如果这是一段C++代码,那么加入extern "C"处理大括号中的代码。

再添加arithmetic.cpp文件实现函数:

#include "Arithmetic.h"

int __stdcall  add(int a, int b)
{
	return a + b;
}

int __stdcall  subtruct(int a, int b)
{
	return a - b;
}

编写好之后,我们直接右键项目名,点生成就可以项目路径下的debug文件夹里找到我们生成的dll和lib文件

查看DLL中的函数

有时候,我们需要调用已经写好的dll,但是我们不知道这个dll中有什么函数。我们可以在Visual Studio的安装目录\Common7\Tools\Bin下,找到微软提供的查看已有dll中函数名的工具Dependency Walker

我们只需要把刚才生成的dll文件拖进Dependency中,就可以看到这个dll中所包含的函数名以及它所依赖的dll

调用DLL

一、静态调用

1. 我们测试一下调用这个刚才创建的DLLTest的dll,首先创建一个工程,添加如下代码:

#include <iostream>

#pragma comment(lib, "DllTest.lib")                                     // 告诉程序lib文件的路径,这里就表示当前目录
extern "C" __declspec(dllimport) int __stdcall add(int a, int b);       // 这里使用__declspec(dllimport),正好和生成dll时的__declspec(dllexport)对应
extern "C" __declspec(dllimport) int __stdcall subtruct(int a, int b);  // 生成dll时没有加__stdcall的话,这里也不用加

int main()
{
	int a = 3;
	int b = 2;
	std::cout << "add result is: " << add(a, b) << std::endl;
	std::cout << "subtruct result is: " << subtruct(a, b) << std::endl;
}

 要把生成的lib文件放到和工程代码的统一路径下,在然后将dll文件放到和程序要生成的EXE文件同一路径下:

运行程序,可以看到调用成功:

2 . 当我们要导入好几个dll,且这些dll中有很多函数时,可以为每个dll新建一个头文件来声明导入的函数,如我们新建一个Arithmetic.h的头文件,把DllTest.dll中所有的函数声明都写在这里:

#ifdef __cplusplus
extern "C" {
#endif

	__declspec(dllimport) int __stdcall add(int a, int b);
	__declspec(dllimport) int __stdcall subtruct(int a, int b);

#ifdef __cplusplus
}
#endif

然后在所有用到这个dll中函数的cpp文件中包含这个头文件,就可以使用dll中的函数了

#include <iostream>
#include "Arithmetic.h"

int main()
{
	int a = 3;
	int b = 2;
	std::cout << "add result is: " << add(a, b) << std::endl;
	std::cout << "subtruct result is: " << subtruct(a, b) << std::endl;
}

然后我们还需要添加lib库,可以新建一个名为Lib的文件夹,把所有的dll的lib文都放在里面。然后直接右键项目,选择属性,在属性配置→链接器→常规→附加库目录里添加这个Lib文件夹的路径

然后在链接器→输入→附加依赖项中添加lib文件的名字,最后一样要把dll文件放在程序要生成的EXE文件同一路径下

运行程序,可以得到和上面一样的结果。 

二、动态调用

动态调用不是链接时完成的,而是在运行时完成的,动态调用不会在可执行文件中写入DLL相关的信息,而是直接调用dll中的函数。

// 动态调用DLL库
void DynamicUse()
{
    // 运行时加载DLL库
    HMODULE module = LoadLibraryA("DLLTest1.dll");     // 根据DLL文件名,加载DLL,返回一个模块句柄
    if (module == NULL)
    {
        printf("加载DLLTest1.dll动态库失败\n");
        return;
    }
    typedef int(*AddFunc)(int, int);                  // 定义函数指针类型
    AddFunc add;
    // 导出函数地址
    add = (AddFunc)GetProcAddress(module, "add");     // GetProcAddress返回指向的函数名的函数地址
 
    int sum  = add(100, 200);
    printf("动态调用,sum = %d\n",sum);
}

 一般使用动态调用,都是调用一些系统dll中的几个函数函数时使用这种方法,因为调用我们自己写的dll时,很多函数都会经常用到,动态调用就太麻烦了。

到此这篇关于C++ 调用dll的方法小结的文章就介绍到这了,更多相关C++ 调用dll内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++实现线程同步的四种方式总结

    C++实现线程同步的四种方式总结

    这篇文章主要为大家详细介绍了C++实现线程同步的四种方式,文中的示例代码讲解详细,对我们学习C++有一定的帮助,需要的可以参考一下
    2022-11-11
  • Linux系统下C语言gets函数出现警告问题的解决方法

    Linux系统下C语言gets函数出现警告问题的解决方法

    这篇文章主要给大家介绍了关于在Linux系统下C语言gets函数出现警告问题的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-12-12
  • C++实现指针空值的示例代码

    C++实现指针空值的示例代码

    本文主要介绍了C++实现指针空值的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • C++使用ZLIB库实现目录压缩与解压功能

    C++使用ZLIB库实现目录压缩与解压功能

    在软件开发和数据处理中,对数据进行高效的压缩和解压缩是一项重要的任务,这不仅有助于减小数据在网络传输和存储中的占用空间,还能提高系统的性能和响应速度,本文将介绍如何使用 zlib 库进行数据的压缩和解压缩,以及如何保存和读取压缩后的文件
    2025-02-02
  • C标准库<assert.h>的实现详解

    C标准库<assert.h>的实现详解

    这篇文章主要介绍了C标准库<assert.h>的实现,主要包括了<assert.h>的基本概念、实现及用法等,需要的朋友可以参考下
    2014-09-09
  • 基于C++实现一个日期计算器

    基于C++实现一个日期计算器

    这篇文章主要为大家详细介绍了如何利用C++实现一个简单的日期计算器,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以参考一下
    2022-10-10
  • C++实现LeetCode(81.在旋转有序数组中搜索之二)

    C++实现LeetCode(81.在旋转有序数组中搜索之二)

    这篇文章主要介绍了C++实现LeetCode(81.在旋转有序数组中搜索之二),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • c++实现扫雷小游戏代码分享

    c++实现扫雷小游戏代码分享

    这篇文章主要介绍了c++实现扫雷小游戏并附上代码分享,代码不能够实现当所查坐标周围雷的数量为0时,直接展开周围坐标,但有一点的知识性参考价值,需要的小伙伴可以参考一下
    2022-02-02
  • vc++ 监控指定路径下文件变化实现代码

    vc++ 监控指定路径下文件变化实现代码

    这篇文章主要介绍了vc++ 监控指定路径下文件变化实现代码,需要的朋友可以参考下
    2019-04-04
  • C++多字节字符与宽字节字符相互转换

    C++多字节字符与宽字节字符相互转换

    最近在C++编程中经常遇到需要多字节字符与宽字节字符相互转换的问题,自己写了一个类来封装wchar_t与char类型间的转换
    2012-11-11

最新评论