Boost(MSVC编译)+使用信号槽

本文介绍了如何使用MSVC编译Boost库,特别是关注信号槽的使用。通过CMake配置项目,连接Boost库,并展示了不在类内的简单信号槽使用示例,以及如何将信号槽功能应用于类内部的方法。

Boost(MSVC编译),使用信号槽。

天天看QT的信号槽,突然发现boost中也有信号槽,所以想试试boost的信号槽,尝试一下。需要先对boost进行编译,之后我会使用信号槽作为演示代码。

1 .打开msvc编译工具链

在这里插入图片描述

  1. 执行命令 cd 到你的boost 文件夹下 再执行bootstrap.bat msvc
    在这里插入图片描述

  2. 编译安装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文件夹下的文件夹名称找。
在这里插入图片描述

  1. 到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;
}

示例代码写的比较简单。如果需要写成项目的话还需要考虑更多的复杂情况,但是已经做到了解耦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

turbolove

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值