如何跨DLL边界使用Boost.Log?

TC.*_*TC. 7 c++ dll boost-log

我试图将Boost.Log集成到一个相当大的应用程序中,该应用程序由一个动态加载DLL插件的主应用程序组成.最初的想法是将日志源传递给插件,以便他们可以添加日志消息.但是,只要DLL中的代码尝试将消息记录到提供的源,应用程序就会因访问冲突而崩溃.

方法1

以下最小示例说明了此问题:

int main(int argc, char* argv[])
{
    boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level> logger;

    // This is okay
    BOOST_LOG_SEV(logger, boost::log::trivial::info) << "From main()";

    // This crashes
    logFromDll(logger);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

logFromDll单独的(DLL)项目中定义的位置:

Dll.cpp

TESTDLL_API void logFromDll(boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level> &logger)
{
    BOOST_LOG_SEV(logger, boost::log::trivial::info) << "From dll";
}
Run Code Online (Sandbox Code Playgroud)

如上所述,这会在访问冲突中崩溃logFromDll(使用visual studio 2010编译).

方法2

Boost.Log为日志源的"全局存储"提供了一种机制:

声明了全局记录器后,可以确保从应用程序代码的任何位置对此记录器实例进行线程安全访问.该库还保证全局记录器实例即使跨模块边界也是唯一的.

听起来和我需要的完全一样.所以我设置了以下示例:

Logger.h

BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(my_logger, boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level>)
Run Code Online (Sandbox Code Playgroud)

Main.cpp的

int main(int argc, char* argv[])
{
    boost::log::add_console_log
    (
        std::clog,
        boost::log::keywords::format = 
        (
            boost::log::expressions::stream << "[Custom format] " << boost::log::expressions::smessage  
        )
    );

    BOOST_LOG_SEV(my_logger::get(), boost::log::trivial::info) << "From main()";

    logFromDll();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Dll.cpp

TESTDLL_API void logFromDll()
{
    BOOST_LOG_SEV(my_logger::get(), boost::log::trivial::info) << "From dll";
}
Run Code Online (Sandbox Code Playgroud)

这不会崩溃,但会产生以下输出:

[Custom format] From main() 
[2014-06-19 10:22:28.435366] [0x00000233] [info]    From dll
Run Code Online (Sandbox Code Playgroud)

也就是说,我在main.cpp中设置的自定义格式仅在我从主项目登录时应用.来自DLL项目的任何日志记录都使用默认格式进行格式化.

那么,如何以一种我在主项目中设置的所有(格式化)选项正确应用的方式跨DLL边界执行日志记录?

TC.*_*TC. 7

我已经弄明白问题是什么了.Boost.Log文档声明:

如果您的应用程序包含多个使用Boost.Log的模块(例如exe和一个或几个dll),则必须将库构建为共享对象.如果您有一个可执行文件或一个与Boost.Log一起使用的模块,您可以将库构建为静态库.

我使用Boost.Log作为静态库.通过共享链接构建提升并在我的项目中使用它解决了问题.