Как я могу использовать Boost.Log через границы DLL?

Я пытаюсь интегрировать 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;
}

Где 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).

Подход 2

Boost.Log предоставляет механизм для «глобальное хранилище» источников журналов:

Объявив глобальный регистратор, можно быть уверенным, что он имеет поточно-безопасный доступ к этому экземпляру регистратора из любого места кода приложения. Библиотека также гарантирует, что экземпляр глобального регистратора будет уникальным даже вне границ модуля.

Звучит в точности как то, что мне нужно. Итак, я создал следующий пример:

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, чтобы все параметры (форматирования), которые я установил в основном проекте, применялись правильно?


person TC.    schedule 19.06.2014    source источник


Ответы (3)


Я понял, в чем проблема. Документация для Boost.Log заявляет, что:

Если ваше приложение состоит из более чем одного модуля (например, exe и одной или нескольких dll), использующих Boost.Log, библиотека должна быть создана как общий объект. Если у вас есть один исполняемый файл или один модуль, который работает с Boost.Log, вы можете построить библиотеку как статическую.

Я использовал Boost.Log как статическую библиотеку. Создание ускорения с общей связью и использование этого в моем проекте решило проблему.

person TC.    schedule 20.06.2014

Не совсем ответ на ваш вопрос

Лично я считаю, что вы слишком много требуете от DLL. В общем, мой подход к ведению журнала из библиотек DLL заключался в том, чтобы устранить особенности ведения журнала в приложении путем предоставления простой функции обратного вызова для библиотеки DLL.

Обычно образуют несколько вариантов:

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

Приложение должно предоставить правильный перевод своей собственной службе.

person Dennis    schedule 19.06.2014

Чтобы получить законченное решение, просто добавьте #define BOOST_LOG_DYN_LINK в описанный logger.h перед BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT и включите logger.h в исходные файлы приложения / dll.

person IronMouse    schedule 06.08.2018