【问题标题】:Logging from library with spdlog使用 spdlog 从库中记录
【发布时间】:2015-08-04 16:31:06
【问题描述】:

我正在尝试在涉及 windows 下的库的项目中使用spdlog。 我创建了两个记录器。一个用于使用库的应用程序,一个用于库本身。 库的记录器是从应用程序创建的,但是当库要添加消息时,它会崩溃。

以下是一个简化的示例。

图书馆

libclass.h

#ifndef LIBCLASS_H
#define LIBCLASS_H

#include <spdlog/spdlog.h>

#ifdef WIN32
#  ifdef BUILD_APPLIB_SHARED
#    define APPLIB_EXPORT __declspec(dllexport)
#  else
#    define APPLIB_EXPORT
#  endif //BUILD_APPLIB_SHARED
#else
#  define APPLIB_EXPORT
#endif // WIN32

class APPLIB_EXPORT LibClass
{
public:
    LibClass();
    ~LibClass();

    static std::string loggerName();

    void testLog();

private:
    std::shared_ptr<spdlog::logger> m_logger;
};

#endif //LIBCLASS_H

libclass.cpp

#include "libclass.h"

const std::string myLoggerName = "lib_logger";

LibClass::LibClass()
{
    m_logger = spdlog::get(myLoggerName);
}

LibClass::~LibClass()
{ }

std::string LibClass::loggerName()
{
    return myLoggerName;
}

void LibClass::testLog()
{
    m_logger->info("Log from library");
}

应用程序

main.cpp

#include <spdlog/spdlog.h>
#include <applib/libclass.h>

void logtest()
{
    auto logger = spdlog::get("app_logger");
    logger->info("Log from application");
}

int main(int argc, char *argv[])
{
    // create loggers
    auto appLogger = spdlog::stdout_logger_mt("app_logger");
    auto libLogger = spdlog::stdout_logger_mt(LibClass::loggerName());

    // log from app
    logtest();

    // log from lib
    LibClass lc;
    lc.testLog();

    return 0;
}

【问题讨论】:

    标签: c++ spdlog


    【解决方案1】:

    Spdlog 使用单例注册表来跟踪可用的记录器。不过,每个 dll 和 exe 都会获得该注册表的 one instance

    当您在 exe 中创建记录器时,它会添加到 exe 的注册表中,但不会添加到 dll 中。当您在 dll 中使用 spdlog::get(myLoggerName) 时,您正在查询不包含“lib_logger”的 dll 的注册表,因此您得到一个空的 shared_ptr。

    可能的解决方案是:如果您只在 dll 中使用它,则在 lib 中创建 lib_logger 而不是 exe,或者将记录器从 exe 传递到 dll 并在调用之前在 dll 中调用spdlog::register_logger spdlog::get(myLoggerName)。然后,您可以使用来自 exe 和 dll 的相同记录器。

    可以在https://github.com/gabime/spdlog/wiki/How-to-use-spdlog-in-DLLs找到如何跨 dll 边界注册记录器的示例

    或使用您的代码的示例:

    图书馆

    libclass.h

    #ifndef LIBCLASS_H
    #define LIBCLASS_H
    
    #include <spdlog/spdlog.h>
    
    #ifdef WIN32
    #  ifdef BUILD_APPLIB_SHARED
    #    define APPLIB_EXPORT __declspec(dllexport)
    #  else
    #    define APPLIB_EXPORT
    #  endif //BUILD_APPLIB_SHARED
    #else
    #  define APPLIB_EXPORT
    #endif // WIN32
    
    class APPLIB_EXPORT LibClass
    {
    public:
      LibClass();
      ~LibClass();
    
      static std::string loggerName();
    
      void testLog();
    
    private:
      std::shared_ptr<spdlog::logger> m_logger;
    };
    
    APPLIB_EXPORT void registerLogger(std::shared_ptr<spdlog::logger> logger);
    
    #endif //LIBCLASS_H
    

    libclass.cpp

    #include "libclass.h"
    
    const std::string myLoggerName = "lib_logger";
    
    LibClass::LibClass()
    {
      m_logger = spdlog::get(myLoggerName);
    }
    
    LibClass::~LibClass()
    { }
    
    std::string LibClass::loggerName()
    {
      return myLoggerName;
    }
    
    void LibClass::testLog()
    {
      m_logger->info("Log from library");
    }
    
    APPLIB_EXPORT void registerLogger(std::shared_ptr<spdlog::logger> logger)
    {
      spdlog::register_logger(logger);
    }
    

    应用程序 main.cpp

    #include <spdlog/spdlog.h>
    #include <spdlog/sinks/stdout_sinks.h>
    
    #include <applib/libclass.h>
    
    void logtest()
    {
      auto logger = spdlog::get("app_logger");
      logger->info("Log from application");
    }
    
    int main(int argc, char* argv[])
    {
      // create loggers
      auto appLogger = spdlog::stdout_logger_mt("app_logger");
      auto libLogger = spdlog::stdout_logger_mt(LibClass::loggerName());
    
      registerLogger(libLogger);
    
      // log from app
      logtest();
    
      // log from lib
      LibClass lc;
      lc.testLog();
    
      return 0;
    }
    

    【讨论】:

      【解决方案2】:

      您的示例在 spdlog 的 current version 上运行良好:

      $ g++ -std=c++11 main.cpp libclass.cpp  -I .
      $ ./a.out 
      [2015-08-24 07:29:04.502] [app_logger] [info] Log from application
      [2015-08-24 07:29:04.502] [lib_logger] [info] Log from library
      

      使用共享库时也一样:

      # CMake config:
      project(TEST)
      include_directories(.)
      add_library(class SHARED libclass.cpp)
      target_compile_options(class PUBLIC -std=c++11)
      add_executable(main main.cpp)
      target_link_libraries(main class)
      

      结果:

      $ cmake .
      $ make 
      $ ldd main
          ...
          libclass.so => ...
      $ ./main 
      [2015-08-25 08:57:51.864] [app_logger] [info] Log from application
      [2015-08-25 08:57:51.864] [lib_logger] [info] Log from library
      

      确保链接到 Windows 上的 DLL 运行时。

      【讨论】:

      • 您的示例正在运行,因为所有内容都在同一个二进制文件下。如果您在共享库中构建 libclass 并与共享库链接,则它不起作用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-16
      • 2011-07-12
      相关资源
      最近更新 更多