使用Clang时共享库入口点创建出现未定义引用链接错误
问题:共享库导出类的析构函数未解析链接错误
当前项目包含供可执行文件调用的共享库Engine,尝试将入口点移至该共享库中,仅让可执行文件包含函数和待创建的类,但编译可执行文件时出现未解析外部符号错误。
可复现项目结构
共享库Engine文件
- entry.h
- BaseGame.h
- Application.cpp
entry.h 代码
#include "BaseGame.h" extern game* create_game(); int main(int argc, char *argv[]) { auto testgame = create_game(); delete testgame; return 0; }
BaseGame.h 代码
class __declspec(dllexport) game { public: game() = default; virtual ~game(); virtual bool initialize() =0; virtual bool update(float deltaTime) =0; virtual bool render(float deltaTime) =0; virtual void on_resize() =0; };
Application.cpp 代码
#include "BaseGame.h" class __declspec(dllexport) Application { public: Application()=default; ~Application()=default; };
可执行文件文件
- entry.cpp(定义create_game)
- my_game.h(继承game类)
- my_game.cpp
entry.cpp 代码
#include <entry.h> #include "my_game.h" game* create_game() { return new myGame; }
my_game.h 代码
class myGame : public game { public: myGame(){}; ~myGame() override = default; bool initialize() override; bool update(float deltaTime) override; bool render(float deltaTime) override; void on_resize() override; };
my_game.cpp 代码
#include "my_game.h" bool myGame::initialize() { return true; } bool myGame::update(float deltaTime) { return true; } bool myGame::render(float deltaTime) { return true; } void myGame::on_resize() { }
编译命令
共享库Engine编译命令
SET assembly=Engine SET compilerFlags=-g -shared -Wvarargs -Wall -Werror SET includeFlags=-Isrc SET linkerFlags=-luser32 SET defines=-D_DEBUG_EG -DGEXPORT -D_CRT_SECURE_NO_WARNINGS ECHO "Building %assembly%%..." clang++ %cFilenames% %compilerFlags% -o ../bin/%assembly%.dll %defines% %includeFlags% %linkerFlags%
可执行文件编译命令
SET assembly=testbed SET compilerFlags=-g REM -Wall -Werror SET includeFlags=-Isrc -I../Engine/src/ SET linkerFlags=-L../bin/ -lEngine.lib SET defines=-D_DEBUG_EG -DGIMPORT clang++ %cFilenames% %compilerFlags% -o ../bin/%assembly%.exe %defines% %includeFlags% %linkerFlags%
链接错误信息
创建库..\bin\testbed.lib和对象..\bin\testbed.exp entry-3b33f2.o : error LNK2019: 未解析的外部符号"public: virtual __cdecl game::~game(void)" (??1game@@UEAA@XZ),该符号在函数"public: virtual __cdecl myGame::~myGame(void)" (??1myGame@@UEAA@XZ)中被引用 ..\bin\testbed.exe : fatal error LNK1120: 1个未解析的外部符号
问题分析与解决
核心问题1:基类game的析构函数只有声明无定义
你在BaseGame.h中声明了virtual ~game();,但未在共享库的源文件中提供实现。子类myGame的析构函数执行时会自动调用基类析构,链接器找不到该实现就会报错。
解决方法:在共享库的源文件(比如Application.cpp或新增BaseGame.cpp)中添加析构函数定义:
#include "BaseGame.h" game::~game() = default;
核心问题2:导出/导入宏未正确切换
当前直接写__declspec(dllexport),但编译可执行文件时应该用__declspec(dllimport)导入类,否则会导致符号解析异常。
优化方案:修改BaseGame.h,用宏切换导出/导入:
#ifdef GEXPORT #define GAME_API __declspec(dllexport) #else #define GAME_API __declspec(dllimport) #endif class GAME_API game { public: game() = default; virtual ~game() = default; // 也可直接在这里默认定义,无需单独写源文件 virtual bool initialize() =0; virtual bool update(float deltaTime) =0; virtual bool render(float deltaTime) =0; virtual void on_resize() =0; };
编译共享库时已定义GEXPORT,会自动导出类;编译可执行文件时定义GIMPORT,此时GEXPORT未定义,会自动用dllimport导入类,确保符号正确解析。
额外注意点
- 确保共享库编译时包含所有必要源文件(比如新增
BaseGame.cpp要加入%cFilenames%)。 - 检查可执行文件编译时的链接路径
-L../bin/是否正确,确保能找到Engine.lib。
内容的提问来源于stack exchange,提问作者miyoku
相关产品推荐
相关产品推荐

