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

C++中DLL声明函数由客户端实现,遇未解析外部符号错误求解

解决DLL调用客户端实现函数的链接错误问题

问题根源

你现在的写法是在引擎DLL项目里定义了main函数,还声明了外部的CreateApplication函数,但DLL编译时链接器要求所有符号都要有实现,而这个函数只在客户端项目里,所以必然会报未解析外部符号。The Cherno的教程里其实是把引擎做成静态库而非动态库(DLL)来使用的,或者说调整了项目的启动与链接逻辑,不是让DLL自身携带main函数。

正确实现方案

方案1:改成静态库(和教程完全对齐)

  1. 修改引擎项目类型:
    • 在VS中右键引擎项目→属性→配置属性→常规→项目默认值→配置类型,选择“静态库(.lib)”。
  2. 配置客户端项目依赖:
    • 右键客户端项目→项目依赖,勾选引擎项目;或者在客户端项目的链接器→输入→附加依赖项中,添加上引擎生成的.lib文件。
  3. 保留现有代码结构:
    • 引擎的Entrypoint.h维持原有内容不变,保留extern Hazel::Application* Hazel::CreateApplication();和main函数。
    • 客户端项目继续实现CreateApplication函数。
      编译客户端项目时,链接器会将引擎静态库的代码与客户端代码合并,main函数里调用的CreateApplication就能正常找到实现。

方案2:必须使用DLL的情况

如果坚持要用动态库,不能直接在DLL中调用客户端的函数,需要通过函数指针回调实现:

  1. 引擎DLL中定义函数指针与设置接口:
    // 引擎的Entrypoint.h
    namespace Hazel {
        typedef Application* (*CreateAppFunc)();
        extern CreateAppFunc g_CreateApplication;
    
        // 导出供客户端调用的设置函数
        __declspec(dllexport) void SetCreateApplication(CreateAppFunc func);
    }
    
    // 引擎的Entrypoint.cpp
    namespace Hazel {
        CreateAppFunc g_CreateApplication = nullptr;
    
        __declspec(dllexport) void SetCreateApplication(CreateAppFunc func) {
            g_CreateApplication = func;
        }
    
        int main(int argc, char** argv) {
            if (!g_CreateApplication) {
                // 可添加错误处理逻辑,如日志提示
                return -1;
            }
            Application* app = g_CreateApplication();
            app->Run();
            delete app;
            return 0;
        }
    }
    
  2. 客户端项目中设置回调并调用引擎main:
    // 客户端代码
    #include "Hazel/Entrypoint.h"
    
    Hazel::Application* Hazel::CreateApplication() {
        return new Sandbox();
    }
    
    int main(int argc, char** argv) {
        // 将自身实现传给引擎
        Hazel::SetCreateApplication(&Hazel::CreateApplication);
        // 调用引擎的main函数
        return Hazel::main(argc, argv);
    }
    
  3. 确保客户端项目链接引擎DLL的导入库(.lib),且运行时能找到DLL文件。

核心提醒

  • The Cherno的教程采用静态库模式,这种模式下引擎代码会直接被打包进客户端可执行文件,因此引擎中的main能直接找到客户端实现的函数。
  • DLL是独立的二进制文件,编译时无法依赖外部项目的符号,必须通过回调、动态加载这类手段实现跨模块调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 23:06:34