许久不写C++的已经快忘光了,最近刚好有用到,乘机整理一下C++中如何封装Dll以及如何调试,如何调用的知识。
关于动态链接库有什么好处,我就不多废口舌了,直接开干吧。
1、创建dll项目
2、创建头文件(.h)和源文件(.cpp)
2.1头文件编写
2.2源文件编写
3 调试dll
1、创建dll项目
打开VS(个人用的VS2019)→新建项目→在C++语言+库下选择动态连接库
输入项目名称:CppDllDemo
点击【创建】
2、创建头文件(.h)和源文件(.cpp)
在【解决方案资源管理器】中的【头文件】和【源文件】目录下,分别创建头文件:“CppDllDemo.h”和源文件:“CppDllDemo.cpp”。
2.1、头文件编写
这个头文件是指要声明对外暴露的函数的头文件,dll项目中不对外暴露的组件可以新建其他头文件按照C++普通方式写就好了。
假设这次dll封装两个简单函数:两个double数的求和函数、打印“hello world”的函数。
这个主头文件 个人习惯是按照如下格式来写:
1、声明导出/导入宏
2、头文件标识 #ifndef HEAD_H #define HEAD_H
|
| 3、不得不包含的头文件
|
| 4、一些要用的结构体、类等
|
| extern "C"
| {
| | 5、要导出的函数声明
| |
| |
| |
| }
|
┕结束头文件标识 #endif
参考以上格式,查看如下代码(至少看起来不是很费劲了)
#pragma once
//定义导出、导入宏
#ifdef CPPDLLDEMO_EXPORTS
#define CPPDLLDEMO_API __declspec(dllexport)
#else
#define CPPDLLDEMO_API __declspec(dllimport)
#endif // CPPDLLDEMO_EXPORTS
//头文件标识
#ifndef CPPDLLDEMO_H
#define CPPDLLDEMO_H
/*----------------------{
包含一些不得不包含的头文件
}----------------------*/
/*----------------------{
这里写一些结构体、类等
}----------------------*/
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
CPPDLLDEMO_API double Add(double a, double b);
CPPDLLDEMO_API void SayHello();
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !CPPDLLDEMO_H
以上有几点要说明
1、关于“#ifdef CPPDLLDEMO_EXPORTS”
在创建好dll项目后,这个宏就已经被VS自动声明了,它的命名就是项目名全大写加“EXPORTS”。
你可以在子项目属性中的预编译中看到:
右键项目名,点击属性→【C/C++】→【预处理器】→【预处理器定义】
2、宏CPPDLLDEMO_API :__declspec(dllexport)和__declspec(dllimport)
在dll开发时,使用export,就是说带有这个的函数都是要输出供外部调用的
import是给外部的,其他程序导入这个dll时,带有宏标记的函数就会被导入。
3、extern "C"
如果是C++(#ifdef __cplusplus),就强制按照C标准进行编译,因为C++编译会对函数名及进行修改,导致调用时的很多麻烦。
2.2、源文件编写
在头文件中只做了函数声明,函数的定义要在源文件中编写,在“CppDllDemo.cpp”中,完成函数的定义:
#include "pch.h"; //新版本的预编译头
#include "CppDllDemo.h" //包含创建的头文件
#include <iostream>
using namespace std;
//函数定义
double Add(double a, double b)
{
double c = a + b;
return c;
}
void SayHello()
{
cout << "Hello World!" << endl;
}
以上,就编写完成了,选择合适的解决方案平台(Debug/Release?,x86/x64?)后生成项目即可。
如果有编译失败的,还请留言,我们一起研究研究。
编译成功后,在生成的目录下就能找到生成“DebugCppDll.dll”文件,当让还有一并生成的其他文件,诸如“xxx.lib”文件。
一般用动态方式加载dll的时候,直接拿“xxx.dll”文件去用就好了。
3 调试dll
dll项目不能像控制台程序一样的去运行,所以应该怎么调试呢,一般在dll项目的下,新建一个控制台程序(不嫌麻烦你也可以搞个mfc程序)来调试dll项目。
在VS的【解决方案资源管理器】中,dll项目名的上方,即“解决方案‘xxxxx’”处右键,点击【添加】→【新建项目】
选择C++控制台项目,取名“DebugCppDll”。
创建好后,在【解决方案资源管理器】中该项目名右键→【设为启动项目】。
再次右键 →【添加】→【引用】,在项目标签下选择刚才的dll项目
点击确定添加完成后,在“DebugCppDll”项目下新建源文件,写main函数入口(正常情况下VS已经帮你写好“hello world”的程序了)。在文件头添加dll中的“.h”文件,如下:
// DebugCppDll.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
#include <iostream>
#include "..\CppDllDemo\CppDllDemo.h" //dll的头文件
using namespace std;
int main()
{
double result = Add(4.5, 11.2); //调用 Add函数
cout << "result = " << result << endl; //答应计算结果
SayHello(); //调用SayHello函数
cin.get();
}
运行可看到调用成功:
接着当我们需要调试时呢,转到dll项目中,比如在“CppDllDemo.cpp”中打上断点;
这样再次启动“DebugCppDll”项目(是启动项,所以之间点VS上面的运行按钮就好),就会命中该断点,方便我们的调试。
---------------
尾巴:关于如何通过动态调用dll,下一篇文章进行详述