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

时间:2014-06-19 08:32:24

标签: c++ dll boost-log

我正在尝试将Boost.Log集成到一个相当大的应用程序中,该应用程序由一个动态加载DLL插件的主应用程序组成。最初的想法是将logging source传递给插件,以便他们可以添加日志消息。但是,只要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;
}

在单独的(DLL)项目中定义logFromDll的地方:

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";
}

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

方法2

Boost.Log为"global storage"日志源提供了一种机制:

  

申报全局记录器后,可以确保具有线程安全性   从应用程序代码的任何位置访问此记录器实例。   该库还保证了全局记录器实例   甚至跨越模块边界也是唯一的。

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

Logger.h

BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(my_logger, boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level>)

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;
}

Dll.cpp

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

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

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

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

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

3 个答案:

答案 0 :(得分:7)

我已经弄明白问题是什么。 documentation for Boost.Log表示:

  

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

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

答案 1 :(得分:1)

并非直接回答您的问题

就我个人而言,我认为你要求DLL做得太多。一般来说,我从DLL中记录的方法是通过向DLL提供简单的回调函数来删除应用程序的日志记录特性。

通常形式有一些变体:

std::function<void (DLL::LogLevel, const char*, ...)> logFunc;

应用程序可以为自己的服务提供正确的翻译。

答案 2 :(得分:0)

要完成解决方案,只需添加#define BOOST_LOG_DYN_LINK 放在logger.h之前描述的BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT 并将logger.h包含到应用程序/ dll源文件中。