0

I have two projects, the first one is a dynamic library project, lets say Log project, and there is a file: Log.h

#pragma once
#include "Core.h"
#include "spdlog/spdlog.h"

#include <memory>

namespace Prunus{
    class __declspec(dllexport) Log
    {
    public:
        static void Init();

        inline static std::shared_ptr<spdlog::logger>& GetCoreLogger() { return s_CoreLogger; }
        inline static std::shared_ptr<spdlog::logger>& GetClientLogger() { return s_ClientLogger; }
        static std::shared_ptr<spdlog::logger> s_CoreLogger;
        static std::shared_ptr<spdlog::logger> s_ClientLogger;
    };
}

while in Log.cpp, it is:

#include "Log.h"
#include "spdlog/sinks/stdout_color_sinks.h"

namespace Prunus {
    std::shared_ptr<spdlog::logger> Log::s_CoreLogger;
    std::shared_ptr<spdlog::logger> Log::s_ClientLogger;

    void Log::Init() {
        spdlog::set_pattern("%^[%T] %n: %v%$");
        s_CoreLogger = spdlog::stdout_color_mt("PRUNUS");
        s_CoreLogger->set_level(spdlog::level::trace);
        s_ClientLogger = spdlog::stdout_color_mt("APP");
        s_ClientLogger->set_level(spdlog::level::trace);
    }
}

And I tried to invoke the Log::Init() in Log project it self, it can work. But when I reference it in another project which references on Log project, it throws error like:

Severity    Code    Description Project File    Line    Suppression State
Error   LNK2001 unresolved external symbol "public: static class std::shared_ptr<class spdlog::logger> Prunus::Log::s_CoreLogger" (?s_CoreLogger@Log@Prunus@@2V?$shared_ptr@Vlogger@spdlog@@@std@@A)    Sandbox F:\code\Prunus\Prunus\Sandbox\SandboxApplication.obj    1   

Not sure whether there are additional settings I missed in visual studio 2022

I tried to use the Log::Init() inside the Log project, it can work, but it can not while referencing outside the project. What I want is to reference it outside the Log project.

YaoFew
  • 3
  • 1
  • Have you included the right lib file in the project settings? From the project you are importing the other library to, you need to make sure in its settings (the LINKER section), that the folder and library are included so the compiler has those as well as the header files – Sam P Mar 20 '23 at 16:27
  • Sorry, I'm new to C++ projects, can you please guide me where to check? – YaoFew Mar 20 '23 at 16:31
  • 1
    You'll need to check a couple places. One is where the output of your Log library (likely the project folder, release, x64, or something along those lines). Then from Visual Studio, right click your main project, click properties, then select the linker tab. From the input section there you can enter your log library under `Additional Dependences` (something like log.lib), and then you'll have to make sure from the Linker>General tab to make sure the directory that library is located in is included as well under `Additional Library Directories`. – Sam P Mar 20 '23 at 16:35
  • Side note: As currently written this question will likely fall victim to being closed as a duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) The answer to your question will almost certainly be in there, but that sucker's an omnibus of dozens of answers so it'll take you a while to find it. – user4581301 Mar 20 '23 at 17:03
  • Make sure the settings @SamP mentions have been set, and if they are make sure you state that in the question so that we can help point you at which answer is relevant to you. – user4581301 Mar 20 '23 at 17:03
  • thanks for your guidance, the additional dependencies in my main project is: $(CoreLibraryDependencies);%(AdditionalDependencies), and I have added the Log project as a reference in my main project – YaoFew Mar 21 '23 at 02:15
  • And I tried to make the Log project a static library project instead of a dynamic library, then it can works, but what I need is it as a dynamic library... – YaoFew Mar 21 '23 at 02:16
  • Are there any other errors besides lnk2001? Such as lnk2019? – Minxin Yu - MSFT Mar 21 '23 at 03:05
  • only lnk2001 and lnk1120 – YaoFew Mar 21 '23 at 05:14

1 Answers1

0

Do not export an entire class, especially if it contains static variables.

Separate function declaration from definition.

namespace Prunus {
    class   Log
    {
    public:
        __declspec(dllexport) static void Init();
        __declspec(dllexport)   inline static std::shared_ptr<spdlog::logger>& GetCoreLogger();
        __declspec(dllexport)   inline static std::shared_ptr<spdlog::logger>& GetClientLogger();

    private:
        static std::shared_ptr<spdlog::logger> s_CoreLogger;
        static std::shared_ptr<spdlog::logger> s_ClientLogger;
    };
}

.cpp

namespace Prunus {
    std::shared_ptr<spdlog::logger> Log::s_CoreLogger;
    std::shared_ptr<spdlog::logger> Log::s_ClientLogger;

    
        void Log::Init() {
          
           ...
           ...
        }

        inline   std::shared_ptr<spdlog::logger>& Log::GetCoreLogger() { return Log::s_CoreLogger; }
        inline   std::shared_ptr<spdlog::logger>& Log::GetClientLogger() { return Log::s_CoreLogger; }
   
}
Minxin Yu - MSFT
  • 2,234
  • 1
  • 3
  • 14
  • Awesome! it works! can you please tell me the reason why previous does not work but moving the __declspec ahead of the function make it works? – YaoFew Mar 21 '23 at 12:33
  • The problem is that In DLL, the exported function definition needs to be placed in the cpp file. Putting __declspec before function instead of the class is just a suggestion. There should be warning that a static variable is being exported. – Minxin Yu - MSFT Mar 22 '23 at 01:27