Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logging from library with spdlog

Tags:

c++

spdlog

I am trying to use spdlog in a project involving a library under windows. I create two loggers. One for the app using the library, one for the library itself. The library's logger is created from the app but when the library want to add a message, it crash.

Following is an simplified example.

The library

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

The application

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;
}
like image 479
AlexandreP Avatar asked May 22 '15 15:05

AlexandreP


People also ask

What is spd log?

spdlog: Super fast C++ logging library [GitHub] Very fast, header only, C++ logging library. Install: Just copy the files to your build tree and use a C++11 compiler. Features: Very fast – performance is the primary goal (see becnhmarks below) Headers only.

What is Spdlog?

spdlog is a header only library. Just copy the files under include to your build tree and use a C++11 compiler. It provides a python like formatting API using the bundled fmt lib (see the reference):


1 Answers

Spdlog uses a singleton registry for keeping track of available loggers. You get one instance of that registry per dll and exe though.

When you create the logger in the exe, it is added to the exe's registry but not the dlls. When you use spdlog::get(myLoggerName) in your dll, you are querying the registry of the dll which does not contain the "lib_logger" and thus you are getting a null shared_ptr.

Possible solutions are: create the lib_logger in the lib instead of the exe if you are only using it in the dll anyway, or pass the logger from the exe to the dll and call spdlog::register_logger with it inside the dll before calling spdlog::get(myLoggerName). Then you can use the same logger from both the exe and the dll.

An example how one can register loggers across dll boundaries can be found at https://github.com/gabime/spdlog/wiki/How-to-use-spdlog-in-DLLs

Or an example using your code:

The library

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

The application 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;
}
like image 197
Stefan v.K. Avatar answered Oct 02 '22 12:10

Stefan v.K.