Boost (compiled with MSVC) + using signal slots

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

  1. Execute the command cd to your boost folder and then execute bootstrap.bat msvc

  2. 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.

  1. Go to C:\Boost to find the compiled library and header files

Use of Boost library – signal slot

  1. 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.