Boost (compiled by MSVC), using signal slots.
I look at the signal slots of QT every day, and suddenly find that there are signal slots in boost, so I want to try the signal slots of boost, try it out. Boost needs to be compiled first, and then I will use signal slots as demo code.
1. Open the msvc compilation toolchain
-
Execute the command cd to your boost folder and then execute bootstrap.bat msvc
-
Compile and install boost
b2 install --build-type=complete threading=multi link=shared address-model=64 toolset=msvc-14.2
link is a dynamic library. If you want to compile a static library, change link=shared to link=static.
The msvc version number can be found in the folder name under the C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC folder.
- Go to C:\Boost to find the compiled library and header files
Use of Boost library – signal slot
- Create a new project to test boost
CMakeLists.txt There is a precompiled header in my cmake, you can delete the relevant part if you don’t need it. Otherwise, an error may be reported
cmake_minimum_required(VERSION 3.19) project(BoostTest) # specify the C++ standard set(CMAKE_CXX_STANDARD 17) # Specify the output directory 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) #Automatically compile QT files set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) #Open contains the current compilation directory set(CMAKE_INCLUDE_CURRENT_DIR ON) #Specify the QT version and the corresponding library set(QT_VERSION 5) set(REQUIRED_LIBS Core Gui Widgets) set(REQUIRED_LIBS_QUALIFIED Qt5::Core Qt5::Gui Qt5::Widgets) #Look for the QT library find_package(Qt${QT_VERSION} COMPONENTS ${REQUIRED_LIBS} REQUIRED) #Automatically find the header file path function macro(FIND_INCLUDE_DIR result curdir) #Define the function, 2 parameters: store the result result; specify the path curdir; file(GLOB_RECURSE children "${curdir}/*.hpp" "${curdir}/*.h" ) #Traverse to obtain the list of *.hpp and *.h files in {curdir} file(GLOB SOURCE_INCLUDE ${children} ) #put the file into SOURCE_INCLUDE set(dirlist "") #Define the dirlist intermediate variable and initialize it foreach(child ${children}) #for loop string(REGEX REPLACE "(.*)/.*" "\1" LIB_NAME ${child}) #string replacement, replace /*h with characters before / if(IS_DIRECTORY ${LIB_NAME}) #Judge whether it is a path list (FIND dirlist ${LIB_NAME} list_index) #Judge whether dirlist contains ${LIB_NAME} if(${list_index} LESS 0) LIST(APPEND dirlist ${LIB_NAME}) #Add the legal path to the dirlist variable else() endif() #end judgment endif() endforeach() #end for loop set(${result} ${dirlist}) #dirlist results into the result variable endmacro() #Automatically find the source file path function 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() # call the function, specify the parameters #Automatically find the header file path function macro(FIND_UI_DIR result curdir) #Define the function, 2 parameters: store the result result; specify the path curdir; file(GLOB_RECURSE children "${curdir}/*.ui") #Traverse to obtain the list of *.hpp and *.h files in {curdir} file(GLOB SOURCE_UI ${children} ) #put the file into SOURCE_INCLUDE set(dirlist "") #Define the dirlist intermediate variable and initialize it foreach(child ${children}) #for loop string(REGEX REPLACE "(.*)/.*" "\1" LIB_NAME ${child}) #string replacement, replace /*h with characters before / if(IS_DIRECTORY ${LIB_NAME}) #Judge whether it is a path list (FIND dirlist ${LIB_NAME} list_index) #Judge whether dirlist contains ${LIB_NAME} if(${list_index} LESS 0) LIST(APPEND dirlist ${LIB_NAME}) #Add the legal path to the dirlist variable else() endif() #end judgment endif() endforeach() #end for loop set(${result} ${dirlist}) #dirlist results into the result variable 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) #Add the path list in INCLUDE_DIR_LIST to the project, including the header file path of the third-party library include_directories( ${INCLUDE_DIR_LIST} #INCLUDE_DIR_LIST path list to join the project ${PROJECT_SOURCE_DIR}/third_party/Boost/include/boost-1_81 ) #Specify link dynamic library folder #Increase or decrease windows library files if(WIN32) set(PLAT_FROM_DEP ws2_32.lib ) endif() #Add third-party link library file file(GLOB LIB_Boost ${PROJECT_SOURCE_DIR}/third_party/Boost/lib/*.lib) link_directories (${PROJECT_SOURCE_DIR}/third_party/Boost/lib) # The specified format is utf-8 add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>") add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>") #Use the specified source file to generate the target executable file 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; }
The above is a signal slot that is not in the class, so I need to use a signal slot in the class and modify the above code slightly.
#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() {<!-- --> // As long as the function is bound here, other classes will trigger the corresponding function of the SLOT class as long as the signal is executed, and there is no need to pay attention to who the caller is 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; }
The sample code is relatively simple to write. If it needs to be written as a project, more complex situations need to be considered, but decoupling has been achieved.