VS2019封装C++接口至可执行动态链接库.dll
本文主要总结如何对已实现的C++函数、类进行封装,以便在其他平台或者语言上进行便捷使用或者二次开发!
重点参考:
1.https://blog.csdn.net/hai_fellow_Z/article/details/117290517
2.https://blog.csdn.net/weixin_38994901/article/details/106625837
备注:在进行编码是,务必将封装目录下的
pch.h
置于排列第一的头文件,如下图:
一.将函数封装成.dll+.lib具体实现步骤
- 新建DLL工程:
- 填充pch.h和pch.cpp文件
首先,在pch.h文件中,利用extern "C" __declspec(dllexport) void test();
语句对要生成Dll的函数Test进行声明。
// pch.h: 这是预编译标头文件。
// 下方列出的文件仅编译一次,提高了将来生成的生成性能。
// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。
// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。
#ifndef PCH_H
#define PCH_H
// 添加要在此处预编译的标头
#include "framework.h"
#include <iostream>
extern "C" __declspec(dllexport) void test();
#endif //PCH_H
// pch.cpp: 与预编译标头对应的源文件
#include "pch.h"
// 当使用预编译的头时,需要使用此源文件,编译才能成功。
void test()
{
std::cout << "yes! " << std::endl;
}
- 点击工程上方生成解决方案,工程目录下x64文件夹下将生成对应的
.dll
和.lib
- 主函数调用:
分别将封装好的路径放在./include
文件夹下,和./lib
文件夹下,正常配置其路径到VS属性下的外部包含目录、包含库目录,以及将.lib
对应名字添加至链接器
//修改后的代码
#pragma once
#pragma comment(lib,"Dll1.lib")
#include <iostream>
using namespace std;
extern "C" __declspec(dllimport) void test();
int main()
{
test();
return 0;
}
二.将类封装成.dll+.lib具体实现步骤
- 创建DLL项目命名为BPNet
项目自动生成了pch.cpp,pch.h,dllmain.cpp,framework.h四个文件,这个先不管它,也不要删除。 - 写好主要内容,想封装的不想让别人看见的。本文是BP.cpp和BP.h,BP.cpp主类为 class TEST,嵌套类为class BPNET,主要结构如下:
BP.h内容:
/*BP.h*/ class TEST { public: class BPNET {//嵌套类 public: BPNET(); ~BPNET(); }m_bpnet;//内嵌类名字 public: TEST(); ~TEST(); void split(); void mytrain(); void mytest(); };
/*BP.cpp*/ TEST::BPNET::BPNET(){} TEST::BPNET::~BPNET(){} TEST::TEST(){} TEST::~TEST(){} void TEST::split()//不想让用户看见这个函数 { } void TEST::mytrain() { } void TEST::mytest() { }
- 基类
因为我们封装dll是不想让用户看见我们的源码细节,只需要提供个接口给他们调用,所以我们建个虚基类,基类中的函数就是函数调用的接口。
我将基类写在pch.h文件中,不用写函数的实现,只写声明就可以了。
/*pch.h*/
class BPBase
{
public:
BPBase() {};
virtual ~BPBase() {};
public:
//只开放这两个函数接口
virtual void mytrain() = 0;
virtual void mytest() = 0;
};
再修改BP.h文件,让TEST类继承BPBase类
- 工厂类
因为基类是虚类,不能创建实例,所以用基类的指针指向子类,调用子类的功能。创建BPFactory.cpp和BPFactory.h,联系基类和子类。
/*BPFactory.h*/
#pragma once
#include"pch.h"
class CLASS_DECLSPEC BPFactory
{
public:
BPFactory();
~BPFactory();
public:
BPBase* CreateObject();
void DeleteObject(BPBase* _bp);
};
/*BPFactory.cpp*/
#include "pch.h"
#include"BPFactory.h"
#include "BP.h"
// 当使用预编译的头时,需要使用此源文件,编译才能成功。
BPFactory::BPFactory()
{}
BPFactory::~BPFactory()
{}
BPBase* BPFactory::CreateObject()
{
return new TEST;
}
void BPFactory::DeleteObject(BPBase* _bp)
{
if (_bp)
delete _bp;
}
- 导出类和函数,在基类所在头文件中加上这一句
#define CLASS_DECLSPEC __declspec(dllexport)//表示这里要把类导出再修改基类声明,所有类都要加上CLASS_DECLSPEC
文档细节
/*pch.h*/
#ifndef PCH_H
#define PCH_H
// 添加要在此处预编译的标头
#include "framework.h"
#endif //PCH_H
#define CLASS_DECLSPEC __declspec(dllexport)//表示这里要把类导出//
//基类
class CLASS_DECLSPEC BPBase
{
public:
BPBase() {};
virtual ~BPBase() {};
public:
virtual void mytrain() = 0;
virtual void mytest() = 0;
};
- 生成dll和lib文档
选择debug或release,两个都可以生成dll和lib,选择哪个就可以去项目下的哪个文件下找dll和lib,具体区别可以自己查,X86和X64都可以选择,最后点击调试,就可以了。
- DLL调用
重新创建一个项目hello,将原来DLL项目的dll和lib还有基类头文件pch.h和工厂类BPFactory.h,共四个文档复制到新项目里,如下图红圈标注的四个文件
新项目的main.cpp
#include<iostream>
#include"BPFactory.h"//工厂类调用
using namespace std;
int main()
{
BPFactory factory;
BPBase* bpDll = factory.CreateObject();
bpDll->mytrain();
bpDll->mytest();
}
添加依赖后运行:
8.运行结果: