Unreal Engine 4 问题:使用asio后编译打包报错:unresolved external symbol

当项目中使用asio作为通讯库时,编译打包时总是报如下错误:

error LNK2019: unresolved external symbol "__declspec(dllimport) public: __cdecl std::bad_cast::bad_cast(char const *)" (__imp_??0bad_cast@std@@QEAA@PEBD@Z) referenced in function "public: __cdecl asio::ip::bad_address_cast::bad_address_cast(void)" (??0bad_address_cast@ip@asio@@QEAA@XZ)
error LNK2001: unresolved external symbol "__declspec(dllimport) public: __cdecl std::bad_cast::bad_cast(char const *)" (__imp_??0bad_cast@std@@QEAA@PEBD@Z)
error LNK2001: unresolved external symbol "protected: virtual void __cdecl std::bad_cast::_Doraise(void)const " (?_Doraise@bad_cast@std@@MEBAXXZ)
error LNK2001: unresolved external symbol "protected: virtual void __cdecl std::bad_cast::_Doraise(void)const " (?_Doraise@bad_cast@std@@MEBAXXZ)

查看asio::ip::bad_address_cast的源代码,发现bad_address_cast继承了<typeinfo>中定义的std::bad_cast,代码如下:

//
// ip/bad_address_cast.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef ASIO_IP_BAD_ADDRESS_CAST_HPP
#define ASIO_IP_BAD_ADDRESS_CAST_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include "asio/detail/config.hpp"
#include <typeinfo>

#include "asio/detail/push_options.hpp"

namespace asio {
namespace ip {

/// Thrown to indicate a failed address conversion.
class bad_address_cast : public std::bad_cast
{
public:
  /// Default constructor.
  bad_address_cast() {}

  /// Destructor.
  virtual ~bad_address_cast() ASIO_NOEXCEPT_OR_NOTHROW {}

  /// Get the message associated with the exception.
  virtual const char* what() const ASIO_NOEXCEPT_OR_NOTHROW
  {
    return "bad address cast";
  }
};

} // namespace ip
} // namespace asio

#include "asio/detail/pop_options.hpp"

#endif // ASIO_IP_ADDRESS_HPP


从代码中看到#include <typeinfo>,应该没有理由找不到std::bad_cast。再查看VC++中提供的typeinfo的源代码:

// typeinfo standard header

/***
*typeinfo - Defines the type_info structure and exceptions used for RTTI
*
*    Copyright (c) Microsoft Corporation. All rights reserved.
*    Modified January 1996 by P.J. Plauger
*
*Purpose:
*       Defines the type_info structure and exceptions used for
*       Runtime Type Identification.
*
*       [Public]
*
****/

#pragma once

#ifndef _TYPEINFO_
#define _TYPEINFO_
#ifndef RC_INVOKED
#include <exception>

#pragma pack(push,_CRT_PACKING)
#pragma warning(push,_STL_WARNING_LEVEL)
#pragma warning(disable: _STL_DISABLED_WARNINGS)
_STL_DISABLE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new

#pragma warning(disable: 4275)    // non dll-interface class 'X' used as base for dll-interface class 'Y'

#include <vcruntime_typeinfo.h>

 _STD_BEGIN

// size in pointers of std::function and std::any (roughly 3 pointers larger than std::string when building debug)
constexpr int _Small_object_num_ptrs = 6 + 16 / sizeof (void *);

 #if !(_HAS_EXCEPTIONS)

        // CLASS bad_cast
class _CRTIMP2_IMPORT bad_cast
    : public exception
    {    // base of all bad cast exceptions
public:
    bad_cast(const char *_Message = "bad cast") noexcept
        : exception(_Message)
        {    // construct from message string
        }

    virtual ~bad_cast() noexcept
        {    // destroy the object
        }

protected:
    virtual void _Doraise() const
        {    // perform class-specific exception handling
        _RAISE(*this);
        }
    };

        // CLASS bad_typeid
class _CRTIMP2_IMPORT bad_typeid
    : public exception
    {    // base of all bad typeid exceptions
public:
    bad_typeid(const char *_Message = "bad typeid") noexcept
        : exception(_Message)
        {    // construct from message string
        }

    virtual ~bad_typeid() noexcept
        {    // destroy the object
        }

protected:
    virtual void _Doraise() const
        {    // perform class-specific exception handling
        _RAISE(*this);
        }
    };

class _CRTIMP2_IMPORT __non_rtti_object
    : public bad_typeid
    {    // report a non RTTI object
public:
    __non_rtti_object(const char *_Message)
        : bad_typeid(_Message)
        {    // construct from message string
        }
    };
 #endif /* _HAS_EXCEPTIONS */

 _STD_END

#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
#pragma pack(pop)
#pragma warning(pop)
#endif /* RC_INVOKED */
#endif // _TYPEINFO_

/*
 * Copyright (c) Microsoft Corporation.  ALL RIGHTS RESERVED.
 * Modified January 1996 by P.J. Plauger
 * Modified November 1998 by P.J. Plauger
 * Consult your license regarding permissions and restrictions.
V6.50:0009 */

是class bad_cast定义前有这么一行:  #if !(_HAS_EXCEPTIONS)
当在.Build.cs中添加bEnableExceptions = true后,编译时会添加参数:/EHsc,这将导致_HAS_EXCEPTIONS=1,#if !(_HAS_EXCEPTIONS)为false,从而最终class bad_cast不被包含。于是就导致unresolved external symbol。

修改方法也很简单,修改asio::ip::bad_address_cast的源代码,将std::bad_cast替换成std::exception即可:

//
// ip/bad_address_cast.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef ASIO_IP_BAD_ADDRESS_CAST_HPP
#define ASIO_IP_BAD_ADDRESS_CAST_HPP

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include "asio/detail/config.hpp"
#include <exception>

#include "asio/detail/push_options.hpp"

namespace asio {
namespace ip {

/// Thrown to indicate a failed address conversion.
class bad_address_cast : public std::exception
{
public:
  /// Default constructor.
  bad_address_cast() {}

  /// Destructor.
  virtual ~bad_address_cast() ASIO_NOEXCEPT_OR_NOTHROW {}

  /// Get the message associated with the exception.
  virtual const char* what() const ASIO_NOEXCEPT_OR_NOTHROW
  {
    return "bad address cast";
  }
};

} // namespace ip
} // namespace asio

#include "asio/detail/pop_options.hpp"

#endif // ASIO_IP_ADDRESS_HPP

猜你喜欢

转载自blog.csdn.net/netyeaxi/article/details/82499698