Forráskód Böngészése

#消息总线跨dll调用

zxs 2 hete
szülő
commit
47ecaacdaf

+ 5 - 4
CMakeLists.txt

@@ -21,7 +21,8 @@ elseif(UNIX)
     add_definitions(-DLINUX_BUILD)
 endif()
 # 包含子项目。
-add_subdirectory ("robot")
-add_subdirectory ("logger")
-add_subdirectory ("drivers")
-add_subdirectory ("generator")
+# add_subdirectory ("robot")
+# add_subdirectory ("logger")
+# add_subdirectory ("drivers")
+# add_subdirectory ("generator")
+add_subdirectory ("message_bus")

BIN
lib/windows/message_bus/message_bus.dll


BIN
lib/windows/message_bus/message_bus.lib


+ 27 - 0
message_bus/CMakeLists.txt

@@ -0,0 +1,27 @@
+# CMakeList.txt: robot 的 CMake 项目,在此处包括源代码并定义
+# 项目特定的逻辑。
+#
+
+# 将源代码添加到此项目的可执行文件。
+#add_executable (message_bus "message_bus_impl.h" "message_bus_impl.cpp" )
+add_library(message_bus SHARED "message_bus_impl.h" "message_bus_impl.cpp")
+
+if (CMAKE_VERSION VERSION_GREATER 3.12)
+  set_property(TARGET message_bus PROPERTY CXX_STANDARD 20)
+endif()
+
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include)
+
+# 添加 /bigobj 选项
+if (MSVC)
+    target_compile_options(message_bus PRIVATE /bigobj)
+endif()
+
+if (WIN32)
+    target_link_libraries(message_bus)
+elseif(IOS)
+elseif(UNIX)
+    target_link_libraries(message_bus pthread)
+endif()
+# TODO: 如有需要,请添加测试并安装目标。

+ 41 - 0
message_bus/message_bus_impl.cpp

@@ -0,0 +1,41 @@
+#include "message_bus_impl.h"
+
+namespace robotics::v3 {
+	message_bus_impl::message_bus_impl() {
+	}
+
+	message_bus_impl::~message_bus_impl() {
+		map_.clear();
+	}
+
+	message_bus_impl* message_bus_impl::instance() {
+		static message_bus_impl g_message_bus_impl;
+		return &g_message_bus_impl;
+	}
+
+	bool message_bus_impl::bind(std::string const& str_topic, std::any const& fn) {
+		auto range = map_.equal_range(str_topic);
+		if (range.first != range.second)
+			return false;
+		map_.emplace(str_topic, std::pair(false, fn));
+		return true;
+	}
+
+	void message_bus_impl::bind_multiple(std::string const& str_topic, std::any const& fn) {
+		map_.emplace(str_topic, std::make_pair(true, fn));
+	}
+
+	std::vector<std::any> message_bus_impl::find(const std::string& str_topic) {
+		std::vector<std::any> result;
+		auto range = map_.equal_range(str_topic);
+		for (Iterater it = range.first; it != range.second; ++it) {
+			result.push_back(it->second.second);
+		}
+		return result;
+	}
+
+	void message_bus_impl::remove(const std::string& str_topic) {
+		auto range = map_.equal_range(str_topic);
+		map_.erase(range.first, range.second);
+	}
+}

+ 58 - 0
message_bus/message_bus_impl.h

@@ -0,0 +1,58 @@
+#pragma once
+#ifdef WINDOWS_BUILD
+#ifdef MESSAGE_BUS_EXPORTS
+#define MESSAGE_BUS_IMPL _declspec(dllexport)
+#else
+#define MESSAGE_BUS_IMPL _declspec(dllimport)
+#endif
+#endif
+//stl
+#include <map>
+#include <any>
+#include <string>
+#include <functional>
+
+namespace robotics::v3 {
+#ifdef WINDOWS_BUILD
+	class MESSAGE_BUS_IMPL message_bus_impl {
+#elif LINUX_BUILD
+	class message_bus_impl {
+#endif
+	public:
+		/**
+		 * @brief 单例
+		 * @return
+		 */
+		static message_bus_impl* instance();
+		~message_bus_impl();
+		/**
+		 * @brief 绑定单个函数
+		 * @param str_topic
+		 * @param fn
+		 * @return
+		 */
+		bool bind(std::string const& str_topic, std::any const& fn);
+		/**
+		 * @brief 绑定多个函数
+		 * @param str_topic
+		 * @param fn
+		 */
+		void bind_multiple(std::string const& str_topic, std::any const& fn);
+		/**
+		 * @brief 查找
+		 * @param str_topic 
+		 * @return 
+		 */
+		std::vector<std::any> find(const std::string& str_topic);
+		/**
+		 * @brief 删除
+		 * @param str_topic 
+		 */
+		void remove(const std::string& str_topic);
+	private:
+		message_bus_impl();
+	private:
+		std::multimap<std::string, std::pair<bool, std::any>> map_;
+		typedef std::multimap<std::string, std::pair<bool, std::any>>::iterator Iterater;
+	};
+}

+ 88 - 26
robot/robotics/message_bus.hpp

@@ -17,13 +17,22 @@
 #include <boost/noncopyable.hpp>
 //robotics
 #include "function_traits.hpp"
+#include "message_bus_impl.h"
 
 namespace robotics {
 	namespace v3 {
 		class message_bus :boost::noncopyable {
 		public:
+			/**
+			 * @brief 构造
+			 */
+			message_bus() {
+				message_bus_impl_ = message_bus_impl::instance();
+			}
+			/**
+			 * @brief 析构
+			 */
 			~message_bus() {
-				map_.clear();
 			}
 			/**
 			 * @brief 注册消息
@@ -32,9 +41,9 @@ namespace robotics {
 			 * @param f
 			 */
 			template<typename _Fn>
-			void bind(const std::string& str_topic, _Fn&& f) {
+			void bind_multiple(const std::string& str_topic, _Fn&& f) {
 				auto func = v3::to_function(std::forward<_Fn>(f));
-				add(str_topic, std::move(func));
+				add_multiple(str_topic, std::move(func));
 			}
 			/**
 			 * @brief 注册消息
@@ -45,20 +54,55 @@ namespace robotics {
 			 * @param obj
 			 */
 			template<typename _Fn, typename _Obj>
-			void bind(const std::string& str_topic, _Fn&& f, _Obj&& obj) {
+			void bind_multiple(const std::string& str_topic, _Fn&& f, _Obj&& obj) {
 				auto func = v3::to_function((v3::function_traits<_Fn>::stl_function_type)(std::bind_front(std::forward<_Fn>(f), std::forward<_Obj>(obj))));
-				add(str_topic, std::move(func));
+				add_multiple(str_topic, std::move(func));
+			}
+			/**
+			 * @brief 注册消息
+			 * @tparam _Fn
+			 * @param str_topic
+			 * @param f
+			 */
+			template<typename _Fn>
+			bool bind(const std::string& str_topic, _Fn&& f) {
+				auto func = v3::to_function(std::forward<_Fn>(f));
+				return add(str_topic, std::move(func));
+			}
+			/**
+			 * @brief 注册消息
+			 * @tparam _Fn
+			 * @tparam _Obj
+			 * @param str_topic
+			 * @param f
+			 * @param obj
+			 */
+			template<typename _Fn, typename _Obj>
+			bool bind(const std::string& str_topic, _Fn&& f, _Obj&& obj) {
+				auto func = v3::to_function((v3::function_traits<_Fn>::stl_function_type)(std::bind_front(std::forward<_Fn>(f), std::forward<_Obj>(obj))));
+				return add(str_topic, std::move(func));
 			}
 			/**
 			 * @brief 发送消息
 			 * @param str_topic
 			 */
-			void call(const std::string& str_topic) {
-				using function_type = std::function<void()>;
+			template<typename _Ret>
+			_Ret invoke(const std::string& str_topic) {
+				using function_type = std::function<_Ret()>;
 				std::string str_msg_type = str_topic + typeid(function_type).name();
-				auto range = map_.equal_range(str_msg_type);
-				for (Iterater it = range.first; it != range.second; ++it) {
-					std::any_cast<function_type>(it->second)();
+				auto funcs = message_bus_impl_->find(str_msg_type);
+				if constexpr(std::is_same<_Ret, void>::value) {
+					for(auto &fn : funcs) {
+						std::any_cast<function_type>(fn)();
+					}
+				} else {
+					if (funcs.empty())
+						throw std::runtime_error("no function binded to topic " + str_topic);
+					_Ret result = _Ret{};
+					for(auto &fn : funcs) {
+						result = std::any_cast<function_type>(fn)();
+					}
+					return result;
 				}
 			}
 			/**
@@ -67,13 +111,24 @@ namespace robotics {
 			 * @param str_topic
 			 * @param ...args
 			 */
-			template<typename... _Args>
-			void call(const std::string& str_topic, _Args ...args) {
-				using function_type = std::function<void(_Args...)>;
+			template<typename _Ret,typename... _Args>
+			_Ret invoke(const std::string& str_topic, _Args ...args) {
+				using function_type = std::function<_Ret(_Args...)>;
 				std::string str_msg_type = str_topic + typeid(function_type).name();
-				auto range = map_.equal_range(str_msg_type);
-				for (Iterater it = range.first; it != range.second; ++it) {
-					std::any_cast<function_type>(it->second)(args...);
+				auto funcs = message_bus_impl_->find(str_msg_type);
+				if constexpr(std::is_same<_Ret, void>::value) {
+					for(auto &fn : funcs) {
+						std::any_cast<function_type>(fn)(args...);
+					}
+				}
+				else {
+					if(funcs.empty())
+						throw std::runtime_error("no function binded to topic " + str_topic);
+					_Ret result = _Ret{};
+					for (auto& fn : funcs) {
+						result = std::any_cast<function_type>(fn)(args...);
+					}
+					return result;
 				}
 			}
 			/**
@@ -85,27 +140,34 @@ namespace robotics {
 			void remove(const std::string& str_topic) {
 				using function_type = std::function<void(_Args...)>;
 				std::string str_msg_type = str_topic + typeid(function_type).name();
-				auto range = map_.equal_range(str_msg_type);
-				while (range.first != range.second) {
-					range.first = map_.erase(range.first);
-					++range.first;
-				}
+				message_bus_impl_->remove(str_msg_type);
 			}
 		private:
 			/**
-			 * @brief 添加
+			 * @brief 多个添加
 			 * @tparam _Fn
 			 * @param str_topic
 			 * @param f
 			 */
 			template<typename _Fn>
-			void add(const std::string& str_topic, _Fn&& f) {
+			void add_multiple(const std::string& str_topic, _Fn&& f) {
+				std::string str_msg_type = str_topic + typeid(f).name();
+				message_bus_impl_->bind_multiple(str_msg_type, std::forward<_Fn>(f));
+			}
+			/**
+			 * @brief 单个添加
+			 * @tparam _Fn 
+			 * @param str_topic 
+			 * @param f 
+			 * @return 
+			 */
+			template<typename _Fn>
+			bool add(const std::string& str_topic, _Fn&& f) {
 				std::string str_msg_type = str_topic + typeid(f).name();
-				map_.emplace(std::move(str_msg_type), std::forward<_Fn>(f));
+				return message_bus_impl_->bind(str_msg_type, std::forward<_Fn>(f));
 			}
 		private:
-			std::multimap<std::string, std::any> map_;
-			typedef std::multimap<std::string, std::any>::iterator Iterater;
+			message_bus_impl* message_bus_impl_ = nullptr;
 		};
 	}
 }

+ 58 - 0
robot/robotics/message_bus_impl.h

@@ -0,0 +1,58 @@
+#pragma once
+#ifdef WINDOWS_BUILD
+#ifdef MESSAGE_BUS_EXPORTS
+#define MESSAGE_BUS_IMPL _declspec(dllexport)
+#else
+#define MESSAGE_BUS_IMPL _declspec(dllimport)
+#endif
+#endif
+//stl
+#include <map>
+#include <any>
+#include <string>
+#include <functional>
+
+namespace robotics::v3 {
+#ifdef WINDOWS_BUILD
+	class MESSAGE_BUS_IMPL message_bus_impl {
+#elif LINUX_BUILD
+	class message_bus_impl {
+#endif
+	public:
+		/**
+		 * @brief 单例
+		 * @return
+		 */
+		static message_bus_impl* instance();
+		~message_bus_impl();
+		/**
+		 * @brief 绑定单个函数
+		 * @param str_topic
+		 * @param fn
+		 * @return
+		 */
+		bool bind(std::string const& str_topic, std::any const& fn);
+		/**
+		 * @brief 绑定多个函数
+		 * @param str_topic
+		 * @param fn
+		 */
+		void bind_multiple(std::string const& str_topic, std::any const& fn);
+		/**
+		 * @brief 查找
+		 * @param str_topic
+		 * @return
+		 */
+		std::vector<std::any> find(const std::string& str_topic);
+		/**
+		 * @brief 删除
+		 * @param str_topic
+		 */
+		void remove(const std::string& str_topic);
+	private:
+		message_bus_impl();
+	private:
+		std::multimap<std::string, std::pair<bool, std::any>> map_;
+		typedef std::multimap<std::string, std::pair<bool, std::any>>::iterator Iterater;
+	};
+	}