C++中DLL声明函数由客户端实现,遇未解析外部符号错误求解
解决DLL调用客户端实现函数的链接错误问题
问题根源
你现在的写法是在引擎DLL项目里定义了main函数,还声明了外部的CreateApplication函数,但DLL编译时链接器要求所有符号都要有实现,而这个函数只在客户端项目里,所以必然会报未解析外部符号。The Cherno的教程里其实是把引擎做成静态库而非动态库(DLL)来使用的,或者说调整了项目的启动与链接逻辑,不是让DLL自身携带main函数。
正确实现方案
方案1:改成静态库(和教程完全对齐)
- 修改引擎项目类型:
- 在VS中右键引擎项目→属性→配置属性→常规→项目默认值→配置类型,选择“静态库(.lib)”。
- 配置客户端项目依赖:
- 右键客户端项目→项目依赖,勾选引擎项目;或者在客户端项目的链接器→输入→附加依赖项中,添加上引擎生成的.lib文件。
- 保留现有代码结构:
- 引擎的
Entrypoint.h维持原有内容不变,保留extern Hazel::Application* Hazel::CreateApplication();和main函数。 - 客户端项目继续实现
CreateApplication函数。
编译客户端项目时,链接器会将引擎静态库的代码与客户端代码合并,main函数里调用的CreateApplication就能正常找到实现。
- 引擎的
方案2:必须使用DLL的情况
如果坚持要用动态库,不能直接在DLL中调用客户端的函数,需要通过函数指针回调实现:
- 引擎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; } } - 客户端项目中设置回调并调用引擎
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); } - 确保客户端项目链接引擎DLL的导入库(.lib),且运行时能找到DLL文件。
核心提醒
- The Cherno的教程采用静态库模式,这种模式下引擎代码会直接被打包进客户端可执行文件,因此引擎中的
main能直接找到客户端实现的函数。 - DLL是独立的二进制文件,编译时无法依赖外部项目的符号,必须通过回调、动态加载这类手段实现跨模块调用。
内容的提问来源于stack exchange,提问作者danyjf
相关产品推荐
相关产品推荐

