我正在尝试将Boost.Log集成到一个相当大的应用程序中,该应用程序由一个动态加载DLL插件的主应用程序组成。最初的想法是将logging source传递给插件,以便他们可以添加日志消息。但是,只要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;
}
在单独的(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编译)中发生访问冲突而崩溃。
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边界执行日志记录?
答案 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源文件中。