Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use Boost.Log across DLL boundaries?

Tags:

c++

dll

boost-log

I am trying to integrate Boost.Log in a fairly large application that is composed of a main application that dynamically loads plugins from DLLs. The initial idea was to pass a logging source to plugins so that they can add log messages. However, as soon as code from a DLL tries to log a message to the provided source, the application crashes with an access violation.

Approach 1

The following minimal example illustrates the problem:

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

Where logFromDll is defined in a separate (DLL) project:

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

As stated above, this crashes with an access violation in logFromDll (compiled with visual studio 2010).

Approach 2

Boost.Log provides a mechanism for "global storage" of logging sources:

Having declared a global logger, one can be sure to have a thread-safe access to this logger instance from any place of the application code. The library also guarantees that a global logger instance will be unique even across module boundaries.

Sounds exactly like what I need. So I set up the following example:

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

This does not crash, but yields the following output:

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

That is, the custom formatting that I set up in main.cpp is only applied when I log from the main project. Any logging from the DLL project is formatted using the default format.

So, how can I perform logging across DLL boundaries in a way that all (formatting) options I set up in the main project are applied correctly?

like image 571
TC. Avatar asked Jun 19 '14 08:06

TC.


1 Answers

I've figured out what the problem was. The documentation for Boost.Log states that:

If your application consists of more than one module (e.g. an exe and one or several dll's) that use Boost.Log, the library must be built as a shared object. If you have a single executable or a single module that works with Boost.Log, you may build the library as a static library.

I was using Boost.Log as a static library. Building boost with shared linkage and using that in my project resolved the problem.

like image 169
TC. Avatar answered Oct 03 '22 20:10

TC.