Boost(MSVC编译),使用信号槽。
天天看QT的信号槽,突然发现boost中也有信号槽,所以想试试boost的信号槽,尝试一下。需要先对boost进行编译,之后我会使用信号槽作为演示代码。
1 .打开msvc编译工具链
2.执行命令 cd 到你的boost 文件夹下 再执行bootstrap.bat msvc
3.编译安装boost
b2 install --build-type=complete threading=multi link=shared address-model=64 toolset=msvc-14.2
link 是动态库 如果你想编译静态库的话把link=shared 修改为link=static。
msvc版本号在C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC文件夹下的文件夹名称找。
4.到C:\Boost 内找到编译完成的库和头文件
Boost库的使用-信号槽
1.新建一个项目,用来测试boost
CMakeLists.txt 我的cmake里面有个预编译头,你不需要的话可以删除相关部分。不然可能会报错
cmake_minimum_required(VERSION 3.19) project(BoostTest) #指定C++标准 set(CMAKE_CXX_STANDARD 17) #指定输出目录 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/output) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/output) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/output) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/output) #自动编译QT文件 set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) #开启包含当前编译目录 set(CMAKE_INCLUDE_CURRENT_DIR ON) #指定QT版本和对应的库 set(QT_VERSION 5) set(REQUIRED_LIBS Core Gui Widgets) set(REQUIRED_LIBS_QUALIFIED Qt5::Core Qt5::Gui Qt5::Widgets) #寻找QT库 find_package(Qt${QT_VERSION} COMPONENTS ${REQUIRED_LIBS} REQUIRED) #自动查找头文件路径函数 macro(FIND_INCLUDE_DIR result curdir) #定义函数,2个参数:存放结果result;指定路径curdir; file(GLOB_RECURSE children "${curdir}/*.hpp" "${curdir}/*.h" ) #遍历获取{curdir}中*.hpp和*.h文件列表 file(GLOB SOURCE_INCLUDE ${children} ) #将文件放入 SOURCE_INCLUDE 中 set(dirlist "") #定义dirlist中间变量,并初始化 foreach(child ${children}) #for循环 string(REGEX REPLACE "(.*)/.*" "\\1" LIB_NAME ${child}) #字符串替换,用/前的字符替换/*h if(IS_DIRECTORY ${LIB_NAME}) #判断是否为路径 list (FIND dirlist ${LIB_NAME} list_index) #判断dirlist是否含有${LIB_NAME} if(${list_index} LESS 0) LIST(APPEND dirlist ${LIB_NAME}) #将合法的路径加入dirlist变量中 else() endif() #结束判断 endif() endforeach() #结束for循环 set(${result} ${dirlist}) #dirlist结果放入result变量中 endmacro() #自动查找源文件路径函数 macro(FIND_SRC_DIR result curdir) file(GLOB_RECURSE children "${curdir}/*.cpp" "${curdir}/*.cc") file(GLOB SOURCE_SRC ${children} ) set(dirlist "") foreach(child ${children}) string(REGEX REPLACE "(.*)/.*" "\\1" LIB_NAME ${child}) if(IS_DIRECTORY ${LIB_NAME}) list (FIND dirlist ${LIB_NAME} list_index) if(${list_index} LESS 0) LIST(APPEND dirlist ${LIB_NAME}) else() endif() endif() endforeach() set(${result} ${dirlist}) endmacro() #调用函数,指定参数 #自动查找头文件路径函数 macro(FIND_UI_DIR result curdir) #定义函数,2个参数:存放结果result;指定路径curdir; file(GLOB_RECURSE children "${curdir}/*.ui") #遍历获取{curdir}中*.hpp和*.h文件列表 file(GLOB SOURCE_UI ${children} ) #将文件放入 SOURCE_INCLUDE 中 set(dirlist "") #定义dirlist中间变量,并初始化 foreach(child ${children}) #for循环 string(REGEX REPLACE "(.*)/.*" "\\1" LIB_NAME ${child}) #字符串替换,用/前的字符替换/*h if(IS_DIRECTORY ${LIB_NAME}) #判断是否为路径 list (FIND dirlist ${LIB_NAME} list_index) #判断dirlist是否含有${LIB_NAME} if(${list_index} LESS 0) LIST(APPEND dirlist ${LIB_NAME}) #将合法的路径加入dirlist变量中 else() endif() #结束判断 endif() endforeach() #结束for循环 set(${result} ${dirlist}) #dirlist结果放入result变量中 endmacro() FIND_SRC_DIR(SRC_DIR_LIST ${PROJECT_SOURCE_DIR}/src) FIND_INCLUDE_DIR(INCLUDE_DIR_LIST ${PROJECT_SOURCE_DIR}/src) FIND_UI_DIR(UI_DIR_LIST ${PROJECT_SOURCE_DIR}/src) #将INCLUDE_DIR_LIST中路径列表加入工程,包括第三方库的头文件路径 include_directories( ${INCLUDE_DIR_LIST} #INCLUDE_DIR_LIST路径列表加入工程 ${PROJECT_SOURCE_DIR}/third_party/Boost/include/boost-1_81 ) #指定链接动态库文件夹 #增减windows库文件 if(WIN32) set(PLAT_FROM_DEP ws2_32.lib ) endif() #增加第三方连接库文件 file(GLOB LIB_Boost ${PROJECT_SOURCE_DIR}/third_party/Boost/lib/*.lib) link_directories(${PROJECT_SOURCE_DIR}/third_party/Boost/lib) # 指定格式为utf-8 add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>") add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>") #使用指定的源文件来生成目标可执行文件 add_executable(${PROJECT_NAME} main.cpp ${SOURCE_INCLUDE} ${SOURCE_SRC} ${SOURCE_UI} ${STDAFX_PCH_C}) target_link_libraries(${PROJECT_NAME} ${REQUIRED_LIBS_QUALIFIED}) target_link_libraries(${PROJECT_NAME} ${LIB_Boost}) if(WIN32) target_link_libraries(${PROJECT_NAME} ${PLAT_FROM_DEP}) endif() target_precompile_headers(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/protocol/stdafx.h)
main.cpp
#include <iostream> #include <boost/signals2.hpp> using namespace boost::signals2; typedef signal<void(int, int)> vi_sig; vi_sig sig2; void slots1() { std::cout << "slot 1 called" << std::endl; } void slots2(int a, int b, int c, int mm) { std::cout << "slot 2 get a " << a << " get b " << b << " get c " << c << " get mm " << mm << std::endl; } void SetEventDataReceived(slot<void(int, int)> func) { sig2.connect(func); } int main() { signal<void()>sig1; sig1.connect(slots1); sig1(); SetEventDataReceived( std::bind(slots2 , std::placeholders::_1, std::placeholders::_2, 3, 4) ); sig2(1, 2); return 0; }
上面的是一个不在类内的信号槽,因此我需要使用一个在类内的信号槽,把上面的代码稍作修改。
#include <iostream> #include <boost/signals2.hpp> using namespace boost::signals2; typedef signal<void(int, int)> vi_sig; vi_sig sig2; class SlotTest { public: static void slots2(int a, int b, int c, int mm) { std::cout << "slot 2 get a " << a << " get b " << b << " get c " << c << " get mm " << mm << std::endl; } }; class SignalTest { public: void Connect() { sig2(1, 2); } }; class SignalTest2 { public: void Connect() { sig2(1, 2); } }; int main() { // 只要在此处绑定了函数那么其他类只要执行该信号则会触发SLOT类的对应函数,则不需要关注调用者是谁 SlotTest aa; sig2.connect(std::bind(aa.slots2 , std::placeholders::_1, std::placeholders::_2, 3, 4) ); SignalTest bb; bb.Connect(); SignalTest2 cc; cc.Connect(); return 0; }
示例代码写的比较简单。如果需要写成项目的话还需要考虑更多的复杂情况,但是已经做到了解耦。