【问题标题】:Boost Log does not work correctly when linked to a shared library链接到共享库时,Boost Log 无法正常工作
【发布时间】:2013-12-20 07:17:58
【问题描述】:

我尝试这样做:在使用 Boost::Log 的 Windows (*.dll) 上创建 1 个共享库 (我想将 Boost::Log 静态链接到这个库,因为我希望所有内容都只打包在 1 个 DLL 文件中)但不成功

我的项目有 4 个文件如下:

我的 CMakeLists.txt:(还有另一个 CMakeLists.txt 使用 find_package(Boost 1.54.0 REQUIRED thread log log_setup filesystem date_time system) 找到 Boost 库)

cmake_minimum_required(VERSION 2.6)

add_library(mylog SHARED
  mylog.cpp
  )
target_link_libraries(mylog ${Boost_LIBRARIES})

if(UNIX)
  target_link_libraries(mylog rt)
endif(UNIX)

add_executable(testlog
  main.cpp
  )
target_link_libraries(testlog mylog)

我的mylog.cpp

#include "mylog.h"

namespace logging = boost::log;
namespace expr = boost::log::expressions;
namespace keywords = boost::log::keywords;

__declspec( dllexport ) void initLog()
{
    logging::add_file_log(
    keywords::file_name = "testlog.log",    
    keywords::format = expr::format("%1% [%2%] %3% ")
        % expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d, %H:%M:%S.%f")
        % expr::attr< logging::trivial::severity_level >("Severity")
        % expr::smessage
    );

    logging::add_common_attributes();
}

还有mylog.h

#ifndef _MYLOG_H
#define _MYLOG_H

#include <boost/log/common.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/date_time/local_time/local_time.hpp>
#include <boost/log/utility/empty_deleter.hpp>

__declspec( dllexport ) void initLog();

#endif //_MYLOG_H

我的main.cpp

#include "mylog.h"

int main(int, char*[])
{
    using namespace boost::log::trivial;
    initLog();
    BOOST_LOG_TRIVIAL(trace) << "A trace severity message";
    BOOST_LOG_TRIVIAL(debug) << "A debug severity message";
    BOOST_LOG_TRIVIAL(info) << "An informational severity message";
    BOOST_LOG_TRIVIAL(warning) << "A warning severity message";
    BOOST_LOG_TRIVIAL(error) << "An error severity message";
    BOOST_LOG_TRIVIAL(fatal) << "A fatal severity message";    
    return 0;
}

当我将库 mylog 编译为 static 库(没有 SHARED 关键字)并运行程序 testlog 时,日志消息是 保存在文件 testlog.log没有任何东西打印到屏幕上 如代码所述:

2013-12-20, 15:05:36.741156 [trace] A trace severity message         
2013-12-20, 15:05:36.742156 [debug] A debug severity message         
2013-12-20, 15:05:36.743156 [info] An informational severity message 
2013-12-20, 15:05:36.743156 [warning] A warning severity message     
2013-12-20, 15:05:36.743156 [error] An error severity message        
2013-12-20, 15:05:36.743156 [fatal] A fatal severity message         

但是如果我把它编译成一个 DLL shared 库(带有 SHARED 关键字),编译是成功的,但结果却不如预期。 未创建日志文件,消息以不同的格式显示在屏幕上。看起来函数 initLog 没有运行:

[2013-12-20 15:06:17.195469] [0x00000e6c] [trace]   A trace severity message          
[2013-12-20 15:06:17.198470] [0x00000e6c] [debug]   A debug severity message          
[2013-12-20 15:06:17.198470] [0x00000e6c] [info]    An informational severity message 
[2013-12-20 15:06:17.199470] [0x00000e6c] [warning] A warning severity message        
[2013-12-20 15:06:17.199470] [0x00000e6c] [error]   An error severity message         
[2013-12-20 15:06:17.200470] [0x00000e6c] [fatal]   A fatal severity message          

请帮助我。谢谢。

P/S:我也尝试过为日志创建自定义接收器,而不是使用 Boost::Log::Trivial,但结果是一样的。 Boost 1.54.0 和 1.55.0 都经过测试。

【问题讨论】:

    标签: c++ cmake shared-libraries static-libraries boost-log


    【解决方案1】:

    看来您需要适当地配置和构建boost::log 以支持动态链接。否则,它假定一个静态链接模型。

    此处的文档:http://boost-log.sourceforge.net/libs/log/doc/html/log/installation/config.html

    相关引述:

    该库有一个单独编译的部分,应该构建为 在Getting Started guide 中描述。需要注意一件事, 尽管。如果您的应用程序包含多个模块(例如 exe 和一个或多个 dll) 使用 Boost.Log,该库必须是 构建为共享对象。如果您有一个可执行文件或一个 与 Boost.Log 一起使用的模块,您可以将库构建为 静态库。

    【讨论】:

    • 感谢您的回复。问题是,如果我添加定义 -DBOOST_LOG_DYN_LINK,它将动态构建,这意味着程序 testlog 还需要 boost_log_*.dll 才能正常运行,而我想找到一种将 Boost::Log 集成到仅 1 个 DLL 文件的方法。
    • @kevin.bui :我不太了解 Windows 开发环境,但原则上,一旦您拥有两个 DLL(一个带有您的代码,一个带有 Boost 的),似乎,您可以将它们合并为一个。 编辑:谷歌搜索表明这是一个相当艰巨的任务,显然。
    • 我搜索了您的建议,但似乎他们只是将 2 个文件连接在一起,但这种方式可能会产生命名空间冲突。此外,我仍然不明白 Boost 这样的反应方式。 Anw,谢谢你的建议。
    【解决方案2】:

    您需要在调用端的initLog() 原型上具有dllimport 属性。一种惯用的方法是使用预处理器定义来告诉 mylog.h 它是否包含在 DLL 构建中,在这种情况下它需要 dllexport,或者来自与 DLL 链接的可执行文件,在这种情况下它需要 dllimport

    mylog.h:

    #ifdef BUILD_MYLOG_DLL
    #define DLLATTRIBUTE __declspec( dllexport )
    #else
    #define DLLATTRIBUTE __declspec( dllimport )
    #endif
    
    DLLATTRIBUTE void initLog();
    

    CMakeLists.txt:

    SET_TARGET_PROPERTIES(mylog PROPERTIES COMPILE_DEFINITIONS "BUILD_MYLOG_DLL")
    

    现在 dllexport 仅在构建 mylog 库时使用,包含该文件的任何其他内容都将获取 dllimport。

    如果您还想支持静态模式,请在将 DLLATTRIBUTE 定义为空的整个 BUILD_MYLOG_DLL 子句周围添加另一个条件。

    【讨论】:

    • 我确实尝试了你的方法,但仍然没有成功。在构建 mylog.cpp 和 mylog.h 时,编译器确实使用 dllexport,而在构建 main.cpp 时,使用了 dllimport。但结果还是一样。你能帮我在你的电脑上试试吗?谢谢。
    猜你喜欢
    • 1970-01-01
    • 2013-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多