12

Windows のライブラリを含むプロジェクトでspdlogを使用しようとしています。2 つのロガーを作成します。ライブラリを使用するアプリ用に 1 つ、ライブラリ自体用に 1 つ。ライブラリのロガーはアプリから作成されますが、ライブラリがメッセージを追加しようとするとクラッシュします。

以下は簡単な例です。

図書館

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

2 に答える 2

5

Spdlog は、使用可能なロガーを追跡するためにシングルトン レジストリを使用します。ただし、dll および exe ごとにそのレジストリのインスタンスを 1 つ取得します。

exe でロガーを作成すると、exe のレジストリに追加されますが、dll には追加されません。dll で使用するspdlog::get(myLoggerName)と、「lib_logger」を含まない dll のレジストリを照会しているため、null の shared_ptr が取得されます。

可能な解決策は次のとおりです。とにかくdllでのみ使用している場合は、exeの代わりにlibにlib_loggerを作成するか、exeからdllにロガーを渡して、を呼び出すspdlog::register_logger 前にdll内で呼び出しspdlog::get(myLoggerName)ます。その後、exe と dll の両方から同じロガーを使用できます。

dll の境界を越えてロガーを登録する方法の例は、https://github.com/gabime/spdlog/wiki/How-to-use-spdlog-in-DLLsにあります。

または、コードを使用した例:

図書館

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;
}
于 2019-10-18T18:16:59.600 に答える