当前位置: 首页 > news >正文

【cmake实战十一】com组件方法的简单实现

【cmake实战十一】com组件的简单实现

  • 一、com组件(com方法)
  • 二、类图
  • 三、代码目录
  • 四、构建、编译、运行
  • 五、相关知识讲解

  • 本文主要是dll使用的深入介绍,文中介绍的也基本和cmake知识没有太多关系,用到的cmake知识之前也都有介绍。
  • 本文用到的demo和类图下载地址为:https://download.csdn.net/download/junxuezheng/86733649

一、com组件(com方法)

  • com组件相关知识网上介绍的比较多,后来做了一些了解,发现com也是开发软件的一种方法,网上资料我就不搬砖了,简单来说,COM也是一种组织软件的方法。
  • 1.组件必须动态连接;
  • 2.组件必须隐藏(或封装)其内部实现细节。

这样理解COM组件

二、类图

  • 本人水平有限,画的类图若有问题,欢迎大家指正。
  • 比如,addClass和subClass两个在注册到进程中时,是调用了ibaseMangaer.h中导出的函数的,这点本人暂时不清楚怎么在类图中体现,后续清楚了再回来补上。
    在这里插入图片描述

三、代码目录

在这里插入图片描述

1.main.cpp

//main.cpp
#include<iostream>
#include<windows.h>
#include "base/ibaseManger.h"
#include "add/i_add.h"
#include"sub/i_sub.h"
using namespace std;

int main()
{
	// 第0:失败。addPtr0应该是空指针,因为LoadLibrary时才注册到baseMap中。
	ibaseManger* ibaseMng = getbaseManager();
	std::shared_ptr<IaddClass> addPtr0 = getBase<IaddClass>();
	if (nullptr == addPtr0)
	{
		cout << "addPtr0 is nullptr" << endl;
	}

	// 第一.加载dll,在加载dll的过程中把addClass注册到baseManger的map中
	HMODULE handle_add = (HMODULE)::LoadLibrary("C:\\Users\\Administrator\\Desktop\\test11\\lib\\Debug\\add.dll");
	HMODULE handle_sub = (HMODULE)::LoadLibrary("C:\\Users\\Administrator\\Desktop\\test11\\lib\\Debug\\sub.dll");
	if (NULL == handle_add || NULL == handle_sub)
	{
		cout << "load dll faile" << endl;
	}


	//int id = 123;
	//std::shared_ptr<IaddClass> addPtr = getBase<IaddClass>(id);//第一版是按照通过id获取的,但是后面发现没有必要再传id进去

	//第二:成功获取addClass
	std::shared_ptr<IaddClass> addPtr = getBase<IaddClass>();
	if (nullptr == addPtr)
	{
		cout << "addPtr is nullptr" << endl;
	}
	int sum = addPtr->add(1, 9);
	cout << "1+9="<<sum<<endl;

	//第三:成功获取subClass
	std::shared_ptr<IsubClass> subPtr = getBase<IsubClass>();
	if (nullptr == subPtr)
	{
		cout << "addPtr is nullptr" << endl;
	}
	int sub = subPtr->sub(1,9);
	cout << "1-9="<<sub<<endl;

	return 0;
}

2.CmakeList.txt

CMAKE_MINIMUM_REQUIRED(VERSION 3.8.0)

PROJECT(COMPUTER)

set_property(GLOBAL PROPERTY USE_FOLDERS ON)

ADD_EXECUTABLE(computer main.cpp)

ADD_SUBDIRECTORY(base)
ADD_SUBDIRECTORY(add)
ADD_SUBDIRECTORY(sub)

INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/base") #要到haha目录,否则找不到
TARGET_LINK_LIBRARIES(computer base)

SET(EXECUTABLE_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib")

3.base

//ibaseManger.h
#pragma once
#include<iostream>
#include"base.h"
#include<map>
#include<Windows.h>
using namespace std;

#ifndef DLL_EXPORT
	#define API __declspec(dllexport)
#else 
	#define API __declspec(dllimport)
#endif

class API ibaseManger
{
public:
	ibaseManger() {};
	virtual ~ibaseManger() {};

	virtual int registerBase(const int id, std::shared_ptr<base> basePtr) = 0;
	virtual int getBase(const int& id, std::shared_ptr<base>& basePtr) =0;
	//void init();
	
};

API ibaseManger* getbaseManager();

//template<typename T>
API int registers(std::shared_ptr<base> basePtr)
{
	int id = basePtr->getGUID();
	ibaseManger* baseMg = getbaseManager();
	int ret = baseMg->registerBase(id, basePtr);
	return 0;
}

template<typename T>
std::shared_ptr<T> getBase()
{
	ibaseManger* baseMg = getbaseManager();
    std::shared_ptr<base> basePtr;
	int id = T::getID();
	int ret = baseMg->getBase(id, basePtr);
	if (0 != ret)
	{
		return nullptr;
	}
	
	std::shared_ptr<T> svr = std::dynamic_pointer_cast<T>(basePtr);

	return svr;
}
//baseManger.h
#pragma once
#include<iostream>
#include"ibaseManger.h"
#include<map>
#include<Windows.h>
using namespace std;

class baseManger : public ibaseManger
{
public:
	baseManger();
	~baseManger();
	int registerBase(const int id, std::shared_ptr<base> basePtr) ;
	int getBase(const int& id, std::shared_ptr<base>& basePtr);
	void init();
private:
	map<int, std::shared_ptr<base>>  baseMap;
};

int API createBaseManger(baseManger* baseMng)
{
	//baseMng = new baseManger();
	//baseMng->init();
	return 0;
}

//base.h
#pragma once
#include<iostream>
#include<Windows.h>

class base
{
public:
	virtual int getGUID() = 0;
	static const int getID() 
	{
		return 000;
	}
};


//baseManger.cpp
#include "baseManger.h"
using namespace std;

API ibaseManger* getbaseManager()
{
	static baseManger m_baseManager;
	return &m_baseManager;
}

baseManger::baseManger()
{

}
baseManger::~baseManger()
{

}
int baseManger::registerBase(const int id, std::shared_ptr<base> basePtr)
{
	baseMap.insert(pair<int, std::shared_ptr<base>>(id, basePtr));

	return 0;
}

int baseManger::getBase(const int& id, std::shared_ptr<base>& basePtr)
{
	auto iter = baseMap.find(id);
	if (iter == baseMap.end())
	{
		return -1;
	}
	basePtr = iter->second;
	return 0;
}

void baseManger::init()
{
	//LoadLibrary("C:\\Users\\jx\\Desktop\\test10\\lib\\Debug\\baseManager.dll");
}
CMAKE_MINIMUM_REQUIRED(VERSION 3.8.0)

SET(TARGET "base")


ADD_LIBRARY(base SHARED baseManger.cpp  baseManger.h base.h ibaseManger.h)

set_target_properties(${TARGET} PROPERTIES FOLDER "base")

SET(LIBRARY_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib")

4.add

//i_add.h
#pragma once
#include<iostream>
#include"../base/base.h"
#ifndef DLL_EXPORT
	#define API __declspec(dllexport)
#else 
	#define API __declspec(dllimport)
#endif
//register(123, IaddClass);

class IaddClass :public base
{
public:
	IaddClass() {};
	virtual ~IaddClass() {};
	virtual int add(int a, int b) =0;
	virtual int getGUID() =0;
	static int getID()
	{
		return 123;
	}
};
//add.h
#pragma once
#include<iostream>
#include"i_add.h"

class addClass :public IaddClass
{
public:
	addClass();
	~addClass();
	virtual int add(int a, int b) override;
	virtual int getGUID() override;
};
//add.cpp
#include "add.h"
#include <memory>
#include"../base/ibaseManger.h"
using namespace std;

//REGISTERBASE(addClass);

//addClass* g_addClass = new addClass;
//std::shared_ptr<addClass> g_addClass = make_shared(new addClass());

std::shared_ptr<addClass> g_addClass(new addClass());
int ret = registers(g_addClass);

addClass::addClass()
{
}
addClass::~addClass()
{
}
int addClass::add(int a,int b)
{
	return a+b;
}

int addClass::getGUID()
{
	return 123;
}
CMAKE_MINIMUM_REQUIRED(VERSION 3.8.0)

SET(TARGET "add")


ADD_LIBRARY(add SHARED add.cpp i_add.h add.h)

INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/base") 
TARGET_LINK_LIBRARIES(add base)
set_target_properties(${TARGET} PROPERTIES FOLDER "com")

SET(LIBRARY_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib")

5.sub
同add只有方法不一样,其他一致。

四、构建、编译、运行

  • 1、构建
cmake -B build

在这里插入图片描述

  • 2、编译
cmake --build build
  • 3、运行
    在这里插入图片描述

五、相关知识讲解

  • 正常情况应该使用guid,本文为了方便理解,id使用了int类型的数据。(guid使用visual studio就可以生成)
  • add.dll和sub.dlll内部都是可以通过main.cpp中的方法调用彼此的,本文没有写相应的例子。(在dll加载到内存中后)
  • 注册dll:
    LoadLibrary时,add.dll的add.cpp调用ibaseManager的方法注册到了进程中,存储到了baseMap中
  • iaddClass和isubClass两个类只有接口的定义,而接口的实现封装起来了,实现了接口的定义和实现的分离。
  • baseMap中存放的是智能指针。
  • 基类智能指针转换为派生类的智能指针使用dynamic_pointer_cast
std::shared_ptr<T> svr = std::dynamic_pointer_cast<T>(basePtr);
  • 智能指针赋值
std::shared_ptr<addClass> g_addClass(new addClass());
  • 获取注册的dll,采用了模板函数
template<typename T>
std::shared_ptr<T> getBase()

相关文章:

  • RDP直线圆弧分割算法
  • 为什么有的python内置函数怎么就一个pass?
  • 主从复制 读写分离
  • flink-taskmanager内存计算
  • 大数据复习(day03)
  • C++ 优先队列 priority_queue 使用篇
  • 同事嫌我改Bug慢,原来是没掌握这些代码Debug技巧
  • 图文讲解带你拿捏MyBatis(一)——MyBatis入门
  • [Python]Django类视图
  • 重识Nginx - 12 SSL/TLS 浅析
  • 神经网络做多元线性回归,神经网络是线性模型吗
  • 如何查看Debian/Ubuntu和RHEL/AlmaLinux/Rocky软件包的更新日志
  • Java—多线程
  • 【第九篇】商城系统-商城首页功能
  • 【SpringBoot+MyBatisPlus】系统全局异常处理器的使用以及添加员工功能的实现
  • 【347天】每日项目总结系列085(2018.01.18)
  • 【技术性】Search知识
  • android图片蒙层
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • ECS应用管理最佳实践
  • Java|序列化异常StreamCorruptedException的解决方法
  • LintCode 31. partitionArray 数组划分
  • Sequelize 中文文档 v4 - Getting started - 入门
  • 复习Javascript专题(四):js中的深浅拷贝
  • 近期前端发展计划
  • 蓝海存储开关机注意事项总结
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 网络应用优化——时延与带宽
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 线性表及其算法(java实现)
  • 正则学习笔记
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • (1/2)敏捷实践指南 Agile Practice Guide ([美] Project Management institute 著)
  • (超详细)语音信号处理之特征提取
  • (转)程序员技术练级攻略
  • (转载)从 Java 代码到 Java 堆
  • ***利用Ms05002溢出找“肉鸡
  • .NET CF命令行调试器MDbg入门(三) 进程控制
  • .net 怎么循环得到数组里的值_关于js数组
  • .NET 中什么样的类是可使用 await 异步等待的?
  • .NET/C# 使用 ConditionalWeakTable 附加字段(CLR 版本的附加属性,也可用用来当作弱引用字典 WeakDictionary)
  • .NET国产化改造探索(三)、银河麒麟安装.NET 8环境
  • .NET开发不可不知、不可不用的辅助类(一)
  • .NET开发人员必知的八个网站
  • .NET下ASPX编程的几个小问题
  • @Autowired 与@Resource的区别
  • @CacheInvalidate(name = “xxx“, key = “#results.![a+b]“,multi = true)是什么意思
  • @Repository 注解
  • @transactional 方法执行完再commit_当@Transactional遇到@CacheEvict,你的代码是不是有bug!...
  • [23] 4K4D: Real-Time 4D View Synthesis at 4K Resolution
  • [8481302]博弈论 斯坦福game theory stanford week 1
  • [C#]使用DlibDotNet人脸检测人脸68特征点识别人脸5特征点识别人脸对齐人脸比对FaceMesh
  • [C/C++]数据结构 堆的详解
  • [C/C++]数据结构 深入挖掘环形链表问题
  • [C++]C++入门--引用