对 boost::serialization 的未定义引用

Posted

技术标签:

【中文标题】对 boost::serialization 的未定义引用【英文标题】:Undefined reference to boost::serialization 【发布时间】:2021-02-21 10:49:54 【问题描述】:

我正在尝试使用 boost::asio 创建一些具有序列化结构的简单服务器。但是,在我的项目中尝试使用 boost::archives 时,我遇到了一些链接器错误。我得到很多未定义的引用。你能帮我找出错误吗?

src/libserver.a(session.cpp.o): In function `boost::archive::text_iarchive::text_iarchive(std::istream&, unsigned int)':
session.cpp:(.text._ZN5boost7archive13text_iarchiveC2ERSij[_ZN5boost7archive13text_iarchiveC5ERSij]+0x25): undefined reference to `boost::archive::text_iarchive_impl<boost::archive::text_iarchive>::text_iarchive_impl(std::istream&, unsigned int)'

我的项目结构如下:

.
├── CMakeLists.txt
├── main.cpp
└── src
    ├── CMakeLists.txt
    ├── server.cpp
    ├── server.hpp
    ├── session.cpp
    └── session.hpp

我的根 CMakeLists.txt

cmake_minimum_required(VERSION 3.5)
project(mainServer)

set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)

add_subdirectory(src)

find_package(Boost 1.65.1.0 REQUIRED system)

if(Boost_FOUND)
    include_directories($Boost_INCLUDE_DIRS)
    add_executable(mainServer main.cpp)
    target_link_libraries(mainServer $Boost_LIBRARIES)
    target_link_libraries(mainServer server)
endif()

还有我的 src CMakeLists.txt

add_library(
    server
    server.cpp
    session.cpp
)

set_target_properties(server PROPERTIES LINKER_LANGUAGE CXX)
target_include_directories(server PUBLIC "$CMAKE_CURRENT_SOURCE_DIR")

以及在 session.hpp 中产生链接错误的代码

#pragma once

#include <boost/asio.hpp>
#include <string>
#include <deque>
#include <memory>
#include <message/message.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/bind/bind.hpp>

class Session : public std::enable_shared_from_this<Session>

public:
    Session(boost::asio::ip::tcp::socket socket) : socket(std::move(socket))
    
    

    void run();
    void printMessage(const boost::system::error_code &e);
    boost::asio::streambuf stream_buf;

private:
    boost::asio::ip::tcp::socket socket;
    common::message::Message msg;

    template <typename Handler>
    void readMsg(Handler handler)
    
        void (Session::*f)(
            const boost::system::error_code &,
            common::message::Message &, boost::tuple<Handler>) = &Session::handle_read_header<common::message::Message, Handler>;
        boost::asio::async_read(socket, boost::asio::buffer(inboundHeader),
                                boost::bind(f,
                                            this, boost::asio::placeholders::error, boost::ref(msg),
                                            boost::make_tuple(handler)));
    

    template <typename T, typename Handler>
    void handle_read_header(const boost::system::error_code &e,
                            T &t, boost::tuple<Handler> handler)
    
        if (e)
        
            boost::get<0>(handler)(e);
        
        else
        
            std::istringstream is(std::string(inboundHeader, headerLength));
            std::size_t inbound_data_size = 0;
            if (!(is >> std::hex >> inbound_data_size))
            
                boost::system::error_code error(boost::asio::error::invalid_argument);
                boost::get<0>(handler)(error);
                return;
            

            inboundData.resize(inbound_data_size);
            void (Session::*f)(
                const boost::system::error_code &,
                T &, boost::tuple<Handler>) = &Session::handle_read_data<T, Handler>;
            boost::asio::async_read(socket, boost::asio::buffer(inboundData),
                                    boost::bind(f, this,
                                                boost::asio::placeholders::error, boost::ref(t), handler));
        
    

    template <typename T, typename Handler>
    void handle_read_data(const boost::system::error_code &e,
                          T &t, boost::tuple<Handler> handler)
    
        if (e)
        
            boost::get<0>(handler)(e);
        
        else
        
            try
            
                std::string archive_data(&inboundData[0], inboundData.size());
                std::istringstream archive_stream(archive_data);
                boost::archive::text_iarchive archive(archive_stream);
                archive >> t;
            
            catch (std::exception &e)
            
                boost::system::error_code error(boost::asio::error::invalid_argument);
                boost::get<0>(handler)(error);
                return;
            
            boost::get<0>(handler)(e);
        
    

    static const size_t headerLength8;
    std::string outboundHeader;
    std::string outboundData;
    char inboundHeader[headerLength];
    std::vector<char> inboundData;
;

【问题讨论】:

如果你用-lboost_serialization手动构建,可以吗? 你需要将你的 add_subdirectory(src) 移到 Boost 之后。否则未知。 我尝试了以下 g++ main.cpp src/server.cpp src/session.cpp -lboost_serialization 和同样的问题。 如果您在使用-lboost_serialization 手动构建时遇到同样的问题,我会说您的安装已损坏。 我根据 boost 文档重新安装了 boost,得到了最新的 cmake,现在手动构建工作正常,所以我认为现在 CMake 有问题。 【参考方案1】:

序列化是一个预编译库,因此您必须将它包含在您的 find 命令中: find_package(Boost 1.65.1.0 REQUIRED system serialization)

只搜索 Boost 和 Boost::system 只会包含 boost 和系统库的头文件,而不包含序列化库的二进制文件。 它编译的原因是,序列化标头包含在 Boost::boost 中,但它无法链接,因为您没有链接到实现。

【讨论】:

我将它添加到我的根 CMakeLists,按照@vre 的建议将 add_subdirectory(src) 移到 find_package 之后,但仍然是同样的问题:/ 您正在使用 boost 的共享库,您能否测试将 Boost_USE_STATIC_LIBS 更改为 ON 或确保您的 boost 二进制文件 (.dll / .so) 位于您的全局路径中.

以上是关于对 boost::serialization 的未定义引用的主要内容,如果未能解决你的问题,请参考以下文章

我可以告诉 Boost.MPI 哪个类版本与 Boost.Serialization 一起使用吗?

如何为 boost::serialization 指定一个 nvp 包装器?

来自boost / serialization / vector #include的链接器错误

如何让 boost::serialization 工作?

boost::serialization::traits 的具体例子?

为什么我不能编译Boost.Serialization演示?