You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决C++项目引用动态库时的LNK2001未解析外部符号错误

动态库LNK2001未解析外部符号问题解决

问题描述

我有两个项目,第一个是名为Log的动态库项目,包含Log.h和Log.cpp文件。在Log项目内部调用Log::Init()可正常运行,但在另一个引用Log项目的Sandbox项目中调用时,出现LNK2001未解析外部符号错误,怀疑是Visual Studio 2022中遗漏了相关设置,希望实现外部项目对Log的正常引用。

相关代码

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

Log.cpp

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

错误信息

级别    代码    描述    项目    文件    行    抑制状态
错误    LNK2001    未解析的外部符号 "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   

解决步骤

1. 修复头文件的导出导入宏

直接使用__declspec(dllexport)会导致外部项目无法正确导入符号,需要定义条件宏区分动态库编译时的导出逻辑和外部项目编译时的导入逻辑:

修改Log.h为:

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

#include <memory>

// 定义导出导入宏,动态库项目编译时导出符号,外部项目编译时导入符号
#ifdef PRUNUS_LOG_EXPORTS
#define PRUNUS_API __declspec(dllexport)
#else
#define PRUNUS_API __declspec(dllimport)
#endif

namespace Prunus{
    class PRUNUS_API 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;
    };
}

然后在Log项目的属性 -> C/C++ -> 预处理器 -> 预处理器定义中添加PRUNUS_LOG_EXPORTS,确保动态库编译时正确导出符号。

2. 配置外部项目(Sandbox)的引用设置

  • 添加项目引用:右键Sandbox项目 -> 添加 -> 项目引用,勾选Log项目,确保构建顺序正确。
  • 添加头文件路径:Sandbox项目属性 -> C/C++ -> 常规 -> 附加包含目录,添加Log项目头文件所在的目录。
  • 配置链接器:
    • 确保Sandbox项目的编译模式(Debug/Release)和Log项目完全一致;
    • 链接器 -> 常规 -> 附加库目录,添加Log项目生成的.lib文件所在目录(比如x64/Debug);
    • 链接器 -> 输入 -> 附加依赖项,添加Log项目生成的.lib文件名(比如Log.lib)。

3. 验证静态成员的符号导出

修改后的宏会自动处理类的静态成员s_CoreLogger和s_ClientLogger的导出/导入逻辑,无需额外修改cpp文件。

内容的提问来源于stack exchange,提问作者YaoFew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 01:02:46