如何将dll、png等资源打包进SDL2 C++开发的游戏exe单文件中
SDL2 + C++ 游戏单EXE打包整合方案
第一步:静态编译消除DLL依赖
先解决外部DLL的依赖问题,不需要把DLL打包进EXE,直接静态编译所有依赖库即可:
- 下载你用到的所有SDL相关库(SDL2、SDL2_image、SDL2_mixer等)的源代码版本,不要使用预编译的动态库
- 编译库时在CMake配置中关闭
BUILD_SHARED_LIBS选项,生成对应编译器的静态库文件(.lib对应MSVC,.a对应MinGW) - 你的游戏项目链接时,替换动态库引用为静态库,同时补充静态编译必备的依赖项:
- MSVC环境:在项目链接器输入中补充SDL静态编译要求的系统依赖库,比如user32.lib、gdi32.lib、winmm.lib等,同时将C/C++运行库选项改为多线程/MT,避免依赖运行库DLL
- MinGW环境:编译参数添加
-lmingw32 -lSDL2main -lSDL2 -mwindows -static-libgcc -static-libstdc++,同时链接SDL扩展对应的底层依赖库,比如libpng、libjpeg、ogg、vorbis等
- 编译完成后先单独运行EXE测试,确认无DLL缺失报错即可进入下一步。
第二步:资源文件嵌入EXE
支持两种主流Windows编译环境的嵌入方案:
MSVC(Visual Studio)环境
- 新建后缀为
.rc的资源脚本文件,按照格式定义所有资源:// 格式:资源ID 资源类型 资源本地路径 BACKGROUND_PNG PNG "res/background.png" BGM_OGG OGG "res/bgm.ogg" FONT_TTF TTF "res/font.ttf" - 将rc文件添加到VS项目中,编译时VS会自动把所有资源写入EXE的资源段。
MinGW/GCC环境
- 和上面一样编写rc资源脚本,然后用
windres工具生成目标文件:windres res.rc -O coff -o res.o - 编译游戏代码时,把
res.o和其他cpp源文件一起加入编译参数即可,资源会自动嵌入EXE。
第三步:EXE内部资源加载
不需要将资源导出到磁盘读取,SDL原生支持从内存缓冲区加载资源:
- 先用Windows API获取嵌入资源的内存指针和大小:
// 以加载PNG图片为例 HRSRC hRes = FindResource(NULL, MAKEINTRESOURCE(BACKGROUND_PNG), L"PNG"); HGLOBAL hResData = LoadResource(NULL, hRes); DWORD resSize = SizeofResource(NULL, hRes); void* resBuf = LockResource(hResData); - 用SDL的内存IO接口封装缓冲区,直接加载资源:
// 加载图片 SDL_Surface* img = IMG_Load_RW(SDL_RWFromConstMem(resBuf, resSize), 1); // 加载音频 Mix_Music* bgm = Mix_LoadMUS_RW(SDL_RWFromConstMem(resBuf, resSize), 1); // 加载字体 TTF_Font* font = TTF_OpenFont_RW(SDL_RWFromConstMem(resBuf, resSize), 1, 24); - 资源内存属于EXE的固有段,用完后正常释放SDL对象即可,不需要手动释放资源指针。
注意:如果资源总大小超过2G,需要先将项目切换为64位编译,避免触发32位程序的内存寻址限制。
内容的提问来源于stack exchange,提问作者Abdiel
相关产品推荐
相关产品推荐

