使用visual studio2019创建dll导出自定义类

系列文章目录

文章目录

前言

程序对动态链接库dll、静态链接库lib想必都很熟悉了,网上也有很多的相关介绍。但网上介绍的一般都是C语言函数介绍,很少看到有自定义类导出dll。下面我就和大家一起讨论一下如何使用visual studio2019开发工具把自定义的类导出dll。

一、具体操作步骤

1.创建动态链接库工程(DLL)


2.头文件声明

cpp 复制代码
#ifdef ConfigJsonDataDll_Exports
#define ConfigJsonDataDll_API __declspec(dllexport) 
#else
#define ConfigJsonDataDll_API __declspec(dllimport)
#endif

#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
#include "nlohmann/json.hpp"

using namespace std;
using nlohmann::json;

namespace ConfigJsonData {
	
	class ConfigJsonDataDll_API ConfigData
	{
	public:
		ConfigData();
		~ConfigData();
		
	public:
		void loadJsonFile(const string& fileName);
		void loadJsonString(const string& jsonString);
		json toJson();
		void fromJson();
		void saveToJsonFile(const string& fileName);
	public:
		// Getter 和 Setter 方法  
		const json& getJsonData() const { return _jsonData; }
		void setJsonData(const json& jsonData) { _jsonData = jsonData; }

		const string& getFileName() const { return _fileName; }
		void setFileName(const string& fileName) { _fileName = fileName; }

		const string& getAdcType() const { return _adcType; }
		void setAdcType(const string& adcType) { _adcType = adcType; }

		 map<string, int>& getFpgaMap()  { return _FpgaMap; }
		void setFpgaMap(const map<string, int>& fpgaMap) { _FpgaMap = fpgaMap; }

		const map<string, string>& getCameraInfoMap() const { return _cameraInfoMap; }
		void setCameraInfoMap(const map<string, string>& cameraInfoMap) { _cameraInfoMap = cameraInfoMap; }

		const map<string, vector<int>>& getGainMap() const { return _gainMap; }
		void setGainMap(const map<string, vector<int>>& gainMap) { _gainMap = gainMap; }

		const map<string, vector<int>>& getOffsetMap() const { return _offsetMap; }
		void setOffsetMap(const map<string, vector<int>>& offsetMap) { _offsetMap = offsetMap; }

		const map<string, map<string, map<string, int>>>& getIndexBankRegMap() const { return _indexBankRegMap; }
		void setIndexBankRegMap(const map<string, map<string, map<string, int>>>& indexBankRegMap) { _indexBankRegMap = indexBankRegMap; }
	
	private:
		string _fileName;
		string _adcType;
		map<string, int> _FpgaMap;
		map<string, string> _cameraInfoMap;
		map<string, vector<int>> _gainMap;
		map<string, vector<int>> _offsetMap;
		map<string, map<string, map<string, int>>> _indexBankRegMap;

		json _jsonData;
	};
}

3.实现文件定义

cpp 复制代码
#include "ConfigData.h"


using namespace ConfigJsonData;

ConfigData::ConfigData()
{
	//_jsonData = std::make_shared<json>();
}


ConfigData::~ConfigData()
{
	_FpgaMap.clear();
	_cameraInfoMap.clear();
	_gainMap.clear();
	_offsetMap.clear();
}


void ConfigData::loadJsonString(const string& jsonString)
{
	_jsonData = json::parse(jsonString);
}

void ConfigData::fromJson()
{
	try {
		//取出CameraInfor数据
		if (_jsonData.find("CameraInfor") != _jsonData.end())
		{
			nlohmann::json cameraJson = _jsonData.at("CameraInfor");
			for (auto& elem : cameraJson.items())
			{
				cout << "cameraInfo.key=" << elem.key() << ", cameraInfo.value=" << elem.value().get<std::string>() << endl;
				_cameraInfoMap[elem.key()] = elem.value().get<std::string>();
				string adcTypeKey = elem.value().get<string>();
				_adcType = adcTypeKey;
			}
		}
		
		std::cout << "ADC Type = " << _jsonData["CameraInfor"]["ADC_TPYE"] << std::endl;
		for (auto& i : _jsonData["FPGA"].items()) {
			std::cout << i.key() << " : " << i.value() << std::endl;
			_FpgaMap[i.key()] = i.value();
		}
		auto adc_type = json::string_t(_jsonData["CameraInfor"]["ADC_TPYE"]);
		
		for (auto& i : _jsonData["ADC_" + adc_type].items()) {
			string indexKey = i.key();
			for (auto& j : i.value().items()) {
				string bankKey = j.key();
				for (auto& k : j.value().items()) {
					string registKey = k.key();
					auto Index = json::string_t(i.key());
					auto Bank = json::string_t(j.key());
					auto Register = json::string_t(k.key());
					auto Value = json::number_integer_t(k.value());
					printf("[ADC Index] = %s, [ADC Bank] = %s, ADC Register %s = %zd\n", Index.c_str(), Bank.c_str(), Register.c_str(), Value);
					_indexBankRegMap[indexKey][bankKey][registKey] = Value;		
				}			
			}
		}

		cout << "*************验证三层嵌套的map否已正确存储**************" << endl;
		//验证_indexBankRegMap中的数据是否已正确存储 
		for (const auto& index_pair : _indexBankRegMap) {
			cout << "[ADC Index]=" << index_pair.first << endl;
			for (const auto& bank_pair : index_pair.second) {
				cout << "  [ADC Bank]=" << bank_pair.first << endl;
				for (const auto& reg_pair : bank_pair.second) {
					cout << "    ADC Register:" << reg_pair.first << " = " << reg_pair.second << endl;
				}
			}
		}

		//取出Gaim
		string adcGainKey = "GAIN_" + _adcType;
		if (_jsonData.contains(adcGainKey))
		{
			string gainKey;
			vector<int> gainValueVec;
			for (auto &elem : _jsonData[adcGainKey].items())
			{
				gainKey = json::string_t(elem.key());
				nlohmann::json gainValue = elem.value();
				if (gainValue.is_array())
				{
					for (auto &elem : gainValue)
					{
						if (elem.is_number())
						{
							auto gainTemp = json::number_integer_t(elem);
							cout << "gain temp valuel=" << gainTemp << endl;
							gainValueVec.push_back(gainTemp);
						}
					}
				}
			}
			_gainMap[gainKey] = gainValueVec;
		}

		//取出offset
		string adcOffsetKey = "OFFSET_" + adc_type;
		if (_jsonData.contains(adcOffsetKey))
		{
			string offsetKey;
			vector<int> offsetValueVec;
			for (auto &elem : _jsonData[adcOffsetKey].items())
			{
				offsetKey = nlohmann::json::string_t(elem.key());
				nlohmann::json offsetValue = elem.value();
				if (offsetValue.is_array())
				{
					for (auto &elem : offsetValue)
					{
						if (elem.is_number())
						{
							auto offsetTemp = json::number_integer_t(elem);
							cout << "offset Temp value=" << offsetTemp << endl;
							offsetValueVec.push_back(offsetTemp);
						}
					}
				}
			}
			_offsetMap[offsetKey] = offsetValueVec;
		}
	}
	catch (const json::exception& e) {
		std::cerr << "Error parsing JSON: " << e.what() << std::endl;
		return ;
	}
	return ;
}

void ConfigData::loadJsonFile(const string& fileName)
{
	std::ifstream file(fileName);
	if (!file.is_open())
	{
		//throw runtime_error("Failed to open file: " + fileName);
		std::cerr << "Failed to open the file." << std::endl;
		return ;
	}
	file >> _jsonData;
	file.close();
}

void ConfigData::saveToJsonFile(const string& fileName)
{
	ofstream file(fileName);
	if (!file.is_open())
	{
		std::cerr << "open file failed!" << endl;
		return;
	}
	
	file << _jsonData.dump(4) << endl;
	file.close();
}

json ConfigData::toJson()
{
	nlohmann::json j;
	j["ADC_TPYE"] = _adcType;
	j["FPGA"] = _FpgaMap;
	j["CameraInfor"] = _cameraInfoMap;
	j["GAIN_AK8446"] = _gainMap;
	j["OFFSET_AK8446"] = _offsetMap;
	j["ADC_AK8446"] = _indexBankRegMap;

	_jsonData = j;
	return j;
}

说明,动态链接库dll定义头文件,与普通的exe工程中的头文件唯一区别,就是文件头

需要加入导出dll的宏定义,以及要在类名前加上ConfigJsonDataDll_API:

cpp 复制代码
#ifdef ConfigJsonDataDll_Exports
#define ConfigJsonDataDll_API __declspec(dllexport) 
#else
#define ConfigJsonDataDll_API __declspec(dllimport)
#endif

#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
#include "nlohmann/json.hpp"

using namespace std;
using nlohmann::json;

namespace ConfigJsonData {
	
	class ConfigJsonDataDll_API ConfigData

4.生成dll工程

这是在visual studio2019配置项中会自动生成预处理器宏,一般情况下都能正常生成dll和lib文件的,如果在生成的debug和release中发现只用dll而没有lib,一般都是忘记2点:

1.导出宏忘记在头文件中声明了

cpp 复制代码
#ifdef ConfigJsonDataDll_Exports
#define ConfigJsonDataDll_API __declspec(dllexport) 
#else
#define ConfigJsonDataDll_API __declspec(dllimport)
#endif

2.类名前忘记加宏定义了关键字ConfigJsonDataDll_API

cpp 复制代码
class ConfigJsonDataDll_API ConfigData


5 使用dll

1.生成ConfigJsonDataDllTest测试工程,配置类型是exe

2.这里为了能调试dll中的源码我使用静态库方式使用

(1)把在dll工程中的头文件ConfigData.h拷贝到ConfigJsonDataDllTest测试工程下。

注意:如果你的dll工程中依赖其他第三方的头文件和lib和dll库的话,也要把这些依赖库的头文件和lib以及dll库拷贝到你的exe工程中

(2)把dll工程中的dll文件拷贝到你的exe工程中,把dll文件拷贝到exe同级目录

(3)如果需要调试dll源码,需要把ConfigJsonDataDll.pdb文件连同ConfigJsonDataDll.dll一起拷贝到exe同级目录下

3.测试dll代码

cpp 复制代码
// ConfigJsonDataDllTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <map>
#include "ConfigData.h"

using namespace ConfigJsonData;
using namespace std;

#pragma comment(lib, "ConfigJsonDataDll.lib")

int main()
{
	ConfigData config;

	config.loadJsonFile("config.json");
	config.fromJson();
	map<string,int>fpgaMap = config.getFpgaMap();
	for (const auto& item : fpgaMap)
	{
		cout << "item.key=" << item.first << ", item.value=" << item.second << endl;
	}
}

注意:如果在你的exe工程中配置编译器设置使用预编译宏时,需要把预编译宏加入到你的配置选项中。

在预处理其中加入宏:ConfigJsonDataDll_API

总结

在使用dll中遇到的坑基本上都踩了一遍,把上文中提到的注意点处理好,基本上就能正常使用了。

相关推荐
程序猿多布3 小时前
使用Visual Studio将C#程序发布为.exe文件
c#·visual studio
半青年1 天前
华为鸿蒙电脑能否作为开发机?开发非鸿蒙应用?
ide·华为·编辑器·电脑·idea·harmonyos·visual studio
battlestar2 天前
Visual studio 打包方法
ide·visual studio
算法歌者2 天前
Visual Studio 项目 .gitignore 文件指南
git·visual studio
伐尘2 天前
【Qt】编译 Qt 5.15.x For Windows 基础教程 Visual Studio 2019 MSVC142 x64
windows·qt·visual studio
jiunian_cn2 天前
【c++】异常详解
java·开发语言·数据结构·c++·算法·visual studio
五花肉村长3 天前
Linux-Ext系列文件系统
linux·运维·服务器·c++·笔记·visual studio
吾门4 天前
机器视觉开发教程——C#如何封装海康工业相机SDK调用OpenCV/YOLO/VisionPro/Halcon算法
图像处理·opencv·计算机视觉·c#·.net·.netcore·visual studio
航Hang*4 天前
C PRIMER PLUS——第6-2节:二维数组与多维数组
c语言·开发语言·经验分享·程序人生·算法·学习方法·visual studio
珊瑚里的鱼4 天前
第八讲 | stack和queue的使用及其模拟实现
开发语言·c++·笔记·visualstudio·stl·学习方法·visual studio