8

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

方法一

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

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

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

如上所述,这会在logFromDll(使用 Visual Studio 2010 编译)中因访问冲突而崩溃。

方法二

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

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

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

记录器.h

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

主文件

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 边界执行日志记录?

4

3 回答 3

9

我已经弄清楚问题出在哪里了。Boost.Log的文档指出:

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

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

于 2014-06-20T13:35:26.033 回答
1

不是直接回答您的问题

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

通常是以下形式的一些变体:

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

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

于 2014-06-19T09:00:13.293 回答
0

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

于 2018-08-06T12:15:24.963 回答