selph
selph
Published on 2020-11-05 / 559 Visits
0
0

DLL 导出接口类

前言

之前在用Windows API 实现添加任务计划的时候,用到了COM组件,COM组件的使用和Windows API截然不同,COM组件的使用是通过接口得到对象,来使用对象的各种方法,这种面向对象的方式我感觉很方便,一个接口,实现一个功能。

经过搜索资料了解到,COM思想是定义一个抽象类(都是纯虚函数),然后调用者和dll共用同一个抽象类的头文件(dll根据这个抽象类来实现派生类)以及这种方式写出来的dll接口通用性很强

两个月前学了C++都没咋用过,我觉得是时候来实践实践了哈哈哈

这样简单描述对新人(比如我)来说肯定不会很明白的,接下来举例子来讲解

代码示例

这里制作一个简易计算器功能来讲解:通过封装一个接口来实现计算器的加减乘除基本功能:

export_Test.h: 共用的头文件

#ifdef EXPORTTEST_EXPORTS
#define EXPORTTEST_API __declspec(dllexport)
#else
#define EXPORTTEST_API __declspec(dllimport)
#endif

//要作为接口方法导出的函数写成虚函数,写在抽象类里
//其他内部实现在类内定义进行即可
//一个接口一个功能
class Calu1 {
public:
	virtual int add(int n1, int n2) = 0;
	virtual int sub(int n1, int n2) = 0;
	virtual void delObject() = 0;
};

//通过工厂函数获得这个类,不同抽象类的工厂函数名称不能相同
//使用抽象基类作为函数类型,是因为这样一来,只有基类的函数被导出了
//其余功能函数对外不可见,仅用于内部调用
//从而实现接口与实现分离
extern "C" EXPORTTEST_API Calu1 * GetObj1();

class Calu2 {
public:
	virtual int mul(int n1, int n2) = 0;
	virtual int div(int n1, int n2) = 0;
	virtual void delObject() = 0;
};
//导出函数是一个 返回值为Calu2指针类型的函数,也就是对象指针
extern "C" EXPORTTEST_API Calu2 * GetObj2();

这里把计算器拆成两半了,主要是想尝试一下多个接口要如何并存。

从入门体验上来说,一个接口类对应一个工厂函数(创建对应派生类的函数),一个接口用来实现一个功能,一个派生类可以继承多个类,其中一个是接口类就行

export_Test.cpp: 功能实现

#include "export_Test.h"

#include <iostream>
using namespace std;

//公共用的类就单独定义基类,让接口派生类来继承
class ShowRes {
public:
	void PrintRes(int x) {
		cout << x << endl;
	}


};

class TwoNum :public Calu1 {
public:
	TwoNum() {
		cout << "Object is Created!"<< endl;
	}
	~TwoNum() {
		cout << "Object is Deleted!" << endl;
	}
	virtual int add(int n1, int n2) {
		int res = n1 + n2;
		cout <<n1<<" + "<<n2<< " = " << res << endl;
		return res;
	}
	virtual int sub(int n1, int n2) {
		int res = n1 - n2;
		cout << n1 << " - " << n2 << " = " << res << endl;
		return res;
	}
	virtual void delObject() {
		delete this;
	}

};


extern "C" EXPORTTEST_API Calu1 * GetObj1() {
	return new TwoNum;
}

/// ///////////////////////////////////////////////////

class TwoNummd :public Calu2 ,public ShowRes{
public:
	TwoNummd() {
		cout << "Object is Created!" << endl;
	}
	~TwoNummd() {
		cout << "Object is Deleted!" << endl;
	}
	virtual int mul(int n1, int n2) {
		int res = tmpmul(n1, n2);
		cout << n1 << " * " << n2 << " = " << res << endl;
		return res;
	}
	virtual int div(int n1, int n2) {
		int res = n1 / n2;
		cout << n1 << " - " << n2 << " = ";
		PrintRes(res);
		return res;
	}
	virtual void delObject() {
		delete this;
	}
	int tmpmul(int n1, int n2) {
		return n1 * n2;
	}

};

Calu2* GetObj2()
{
	return new TwoNummd;
}

就是接口类的纯虚函数的简单实现,没啥说的

Test.cpp: 调用测试

#include <iostream>
using namespace std;
#include "export_Test.h"
#pragma comment(lib,"exportTest.lib")


int main()
{
    
    Calu1* p = GetObj1();
    p->add(66,5);
    p->sub(72,60);

    Calu2* n = GetObj2();
    n->mul(5, 9);
    n->div(1024, 222);

    system("pause");
    std::cout << "Hello World!\n";
}

新建一个控制台项目来调用刚刚写的接口类,从调用者的角度来看,这个计算器的类提供了计算的功能,直接调用就行,很方便的感觉


Comment