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;
}
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.
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):
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With