客户端升级到 Visual Studio 2022 指南
目标读者:熟悉服务器开发,不熟悉 DirectX 的开发者 预计工作量:2-3周 风险等级:中等
📋 目录
环境准备
1.1 安装 Visual Studio 2022
安装组件:
✅ 使用 C++ 的桌面开发
✅ Windows 10 SDK (10.0.19041.0 或更高)
✅ Windows 8.1 SDK (兼容老项目)
❌ 不需要 Linux 开发工具
1.2 获取依赖库
需要准备的库:
| 库名 | 原版本 | 目标版本 | 下载地址 |
|---|---|---|---|
| Boost | 1.34.1 | 1.81.0 | https://www.boost.org/users/download/ |
| Lua | 5.0.3 | 5.4.4 | https://www.lua.org/download.html |
| luabind | 旧版本 | 0.9.1 | https://github.com/luabind/luabind |
| DirectX SDK | 旧版 | Windows 10 SDK | 已集成在 VS2022 |
1.3 目录布局
client-code/
├── Client/ # 主客户端代码
├── engine/ # 游戏引擎(渲染、网络等)
├── gui/ # GUI 框架
├── RenderD3D/ # DirectX 渲染层
├── Media/ # 音频管理
├── Magic/ # 魔法/技能系统
├── boost_1_34_1/ # 旧版 Boost(需要替换)
├── lua-5.0.3/ # 旧版 Lua(需要替换)
├── luabind/ # Lua 绑定库
└── greta/ # 正则表达式库
项目结构分析
2.1 项目文件
客户端使用 VS2003 项目文件格式(.vcproj):
Client/Client.vcproj # 主客户端项目(需要升级)
engine/engine.vcproj # 引擎项目(需要升级)
gui/gui.vcproj # GUI 项目(需要升级)
RenderD3D/RenderD3D.vcproj # 渲染项目(需要升级)
2.2 编译配置
原始配置(VS2003):
- 预编译头:public.h
- 字符集:多字节
- 运行库:单线程 (/ML)
目标配置(VS2022):
- 预编译头:public.h
- 字符集:多字节(保持不变)
- 运行库:多线程 DLL (/MD)
- C++ 标准:C++17 或 C++20
核心改动点
3.1 必须修改的问题(P0 - 最高优先级)
🔴 3.1.1 线程局部存储
问题文件:Client/public.h、Client/public.cpp
问题代码:
// Client/public.h:57-58
extern __declspec(thread) stCallStackInfo g_callStack[256];
extern __declspec(thread) int g_callStackIndex = -1;
// Client/public.cpp:4-5
__declspec(thread) stCallStackInfo g_callStack[256];
__declspec(thread) int g_callStackIndex = -1;
修改方案:
// 改为 C++11 标准的 thread_local
extern thread_local stCallStackInfo g_callStack[256];
extern thread_local int g_callStackIndex = -1;
影响范围:
- 这两个文件需要修改
- 修改后需要重新编译所有依赖
public.h的文件
🔴 3.1.2 移除 EXECryptor 保护代码
问题文件:Client/execryptor.h、Client/execryptor.cpp
问题代码:
// Client/public.h:170-184
#define USE_EXECRYPT_API
#ifdef USE_EXECRYPT_API
#include "./execryptor.h"
#define FUNCTION_BEGIN_NEW CRYPT_START FUNCTION_BEGIN
#define FUNCTION_END_NEW FUNCTION_END CRYPT_END
#else
#define FUNCTION_BEGIN_NEW FUNCTION_BEGIN
#define FUNCTION_END_NEW FUNCTION_END
#endif
修改方案:
// 直接删除 USE_EXECRYPT_API 相关代码
// public.h 改为:
#define FUNCTION_BEGIN_NEW FUNCTION_BEGIN
#define FUNCTION_END_NEW FUNCTION_END
// 可以删除或注释掉:
// #include "./execryptor.h"
// #define USE_EXECRYPT_API
步骤:
- 删除
Client/execryptor.h - 删除
Client/execryptor.cpp - 修改
Client/public.h第170-184行
🔴 3.1.3 hash_map → unordered_map
问题文件:
engine/include/Ini.h
engine/include/engine.h
engine/source/Ini.cpp
engine/source/PhraseFilter.cpp
engine/source/FilePackHelper.cpp
RenderD3D/include/D3DMBitmap.h
RenderD3D/include/D3DDevice.h
Property/cTableManager.h
Magic/cAnimation.cpp
Magic/HashMapStrToNum.h
Client/CountryInfo.h
问题代码:
// engine/include/Ini.h:27
stdext::hash_map<std::string,unsigned int> mapKey;
stdext::hash_map<std::string,unsigned int> m_mapGroups;
修改方案:
// 改为 C++11 标准容器
#include <unordered_map>
std::unordered_map<std::string,unsigned int> mapKey;
std::unordered_map<std::string,unsigned int> m_mapGroups;
注意事项:
stdext::hash_map是 MSVC 扩展,C++11 已废弃std::unordered_map是标准容器,API 兼容- 需要同时修改
.h和.cpp文件
🔴 3.1.4 删除警告抑制
问题文件:engine/include/Ini.h
问题代码:
// engine/include/Ini.h:3-4, 78
#pragma warning( push )
#pragma warning( disable : 4996 )
// ...
#pragma warning( pop )
原因:
4996是"不安全函数"警告(如strcpy、sprintf)- VS2022 中这些函数仍然存在,但会产生警告
修改方案:
// 方案1:直接删除警告抑制(推荐)
// 将所有 strcpy/strncpy 改为 strcpy_s/strncpy_s
// 将所有 sprintf 改为 sprintf_s
// 方案2:保留警告抑制(快速方案)
// 在项目设置中添加:_CRT_SECURE_NO_WARNINGS
推荐方案:使用方案2(在项目属性中设置)
项目属性 → C/C++ → 预处理器 → 预处理器定义
添加:_CRT_SECURE_NO_WARNINGS
3.2 依赖库升级(P1 - 高优先级)
🟡 3.2.1 Boost 升级
原版本:Boost 1.34.1(2007年) 目标版本:Boost 1.81.0(2023年)
升级步骤:
- 下载 Boost 1.81.0:https://www.boost.org/users/download/
- 解压到
client-code/boost_1_81_0/ - 编译 Boost(仅编译需要的库):
cd boost_1_81_0
bootstrap.bat
b2 --toolset=msvc-14.3 --with-system --with-thread --with-filesystem --with-date_time
注意事项:
- 不需要编译所有 Boost 库
luabind依赖boost::bind、boost::function、boost::shared_ptr- 建议先编译测试,只编译必要的库
代码改动:
// 可能需要修改的 boost::bind 用法
// 旧代码(Boost 1.34):
boost::bind(&Class::Method, this, _1, _2)
// 新代码(C++11,可以不依赖 boost):
std::bind(&Class::Method, this, std::placeholders::_1, std::placeholders::_2)
🟡 3.2.2 Lua 升级
原版本:Lua 5.0.3 目标版本:Lua 5.4.4
升级步骤:
- 下载 Lua 5.4.4:https://www.lua.org/ftp/lua-5.4.4.tar.gz
- 解压到
client-code/lua-5.4.4/ - 替换
lua-5.0.3/目录
注意事项:
- Lua API 有变化(如
lua_open()→luaL_newstate()) luabind可能需要重新编译或升级
常见 API 变化:
// Lua 5.0.3
lua_State *L = lua_open();
lua_register(L, "myfunc", my_func);
// Lua 5.4.4
lua_State *L = luaL_newstate();
lua_register(L, "myfunc", my_func); // 仍然支持
🟡 3.2.3 luabind 升级
原版本:旧版(依赖 Boost 1.34) 目标版本:luabind 0.9.1(或最新版)
升级步骤:
- 从 GitHub 下载:https://github.com/luabind/luabind
- 替换
client-code/luabind/目录 - 修改
luabind/public.h以适配 Boost 1.81
注意事项:
- luabind 依赖 Boost,必须先升级 Boost
- 可能需要修改
luabind的代码以适配新 Boost
3.3 项目配置迁移(P2 - 中优先级)
🟢 3.3.1 VS2003 → VS2022 项目文件
步骤:
-
使用 VS2022 自动升级
右键 Client.vcproj → 打开方式 → Visual Studio 2022VS2022 会自动将
.vcproj转换为.vcxproj -
检查编译配置
项目属性 → 配置属性 → C/C++ → 语言
- C++ 语言标准:ISO C++17 标准 (/std:c++17)
- 启用运行时类型信息:是 (/GR)
项目属性 → 配置属性 → C/C++ → 代码生成
- 运行时库:多线程 DLL (/MD)(Debug用/MDd)
- 启用字符串池:是 (/GF)
项目属性 → 配置属性 → C/C++ → 预处理器
- 预处理器定义:添加 _CRT_SECURE_NO_WARNINGS
项目属性 → 配置属性 → C/C++ → 预编译头
- 预编译头:使用 (/Yu)
- 预编译头文件:public.h -
调整包含目录
项目属性 → 配置属性 → C/C++ → 常规 → 附加包含目录
- ../
- ../engine/include
- ../gui/include
- ../RenderD3D/include
- ../boost_1_81_0
- ../lua-5.4.4/src
- ../luabind -
调整库目录
项目属性 → 配置属性 → 链接器 → 常规 → 附加库目录
- ../boost_1_81_0/stage/lib -
添加链接依赖
项目属性 → 配置属性 → 链接器 → 输入 → 附加依赖项
- d3d9.lib
- d3dx9.lib
- dsound.lib
- winmm.lib
- comctl32.lib
- (Boost库根据需要添加)
分步实施指南
第1周:准备工作和基础修改
Day 1-2:环境搭建
- 安装 VS2022 和必要的 SDK
- 下载依赖库(Boost、Lua、luabind)
- 编译 Boost(仅必要的库)
- 备份原项目
Day 3-4:核心代码修改
- 修改
Client/public.h和Client/public.cpp(__declspec(thread)→thread_local) - 删除
execryptor.h、execryptor.cpp相关代码 - 修改
Client/public.h第170-184行
Day 5-7:hash_map 替换
- 替换
engine/include/Ini.h中的stdext::hash_map→std::unordered_map - 替换其他文件中的
stdext::hash_map - 编译 engine 项目测试
第2周:依赖库升级和编译测试
Day 8-10:Boost 和 Lua 升级
- 替换 Boost 1.34 → 1.81
- 替换 Lua 5.0.3 → 5.4.4
- 升级 luabind
- 修改包含路径
Day 11-14:项目迁移和编译
- 迁移 Client.vcproj → Client.vcxproj
- 迁移 engine.vcproj → engine.vcxproj
- 迁移 gui.vcproj → gui.vcxproj
- 迁移 RenderD3D.vcproj → RenderD3D.vcxproj
- 配置项目属性
- 尝试编译所有项目
第3周:修复编译错误和测试
Day 15-17:修复编译错误
- 解决 Boost 相关的编译错误
- 解决 Lua API 变化的问题
- 解决 DirectX 相关的问题
- 解决链接错误
Day 18-19:运行时测试
- 客户端启动测试
- 登录功能测试
- 场景渲染测试
- UI 功能测试
Day 20-21:网络协议测试
- 与服务器通信测试
- 验证协议兼容性
- 性能测试
常见问题
Q1: Boost 升级后 boost::bind 不工作
原因:Boost 1.81 的 API 有变化
解决方案:
// 旧代码
boost::bind(&Class::Method, this, _1, _2)
// 新代码(使用 std::bind)
std::bind(&Class::Method, this, std::placeholders::_1, std::placeholders::_2)
Q2: Lua 升级后 lua_open() 不存在
原因:Lua 5.1+ 改变了 API
解决方案:
// 旧代码
lua_State *L = lua_open();
// 新代码
lua_State *L = luaL_newstate();
Q3: DirectX 头文件找不到
原因:VS2022 不包含 DirectX SDK
解决方案:
1. 安装 Windows 10 SDK
2. 项目属性 → VC++ 目录 → 包含目录
添加:$(WindowsSdkDir)Include\$(WindowsSDKVersion)um
Q4: 预编译头编译失败
原因:VS2022 的预编译头机制有变化
解决方案:
项目属性 → C/C++ → 预编译头
- 预编译头:使用 (/Yu)
- 预编译头文件:public.h
确保 public.h 在所有 .cpp 文件的第一行(除了 stdafx.cpp)
Q5: 链接错误 "unresolved external symbol"
原因:缺少必要的库文件
常见解决方案:
# DirectX 相关
添加:d3d9.lib d3dx9.lib dsound.lib
# Boost 相关
添加:libboost_system-vc143-mt.lib libboost_thread-vc143-mt.lib
# Windows 相关
添加:winmm.lib comctl32.lib
Q6: 字符编码问题
原因:VS2022 默认使用 Unicode
解决方案:
项目属性 → 配置属性 → 常规 → 字符集
设置为:多字节字符集
Q7: 运行时崩溃
可能原因:
thread_local使用不当- Boost 升级导致的 ABI 不兼容
- Lua API 变化
调试方法:
// 使用调试器逐步调试
// 检查线程局部变量的初始化顺序
// 检查 Boost 智能指针的使用
测试清单
编译测试
- Release 编译通过(0 错误,0 警告)
- Debug 编译通过(0 错误,允许少量警告)
- 所有 4 个项目都能独立编译
功能测试
- 客户端启动正常
- 登录界面正常显示
- 角色创建正常
- 角色选择正常
- 进入游戏场景正常
- 角色移动正常
- 技能释放正常
- 物品使用正常
- 聊天功能正常
- UI 交互正常
网络测试
- 连接服务器成功
- 登录认证成功
- 数据同步正常
- 排行榜数据正常显示(SortListInfo 相关)
- 断线重连正常
性能测试
- 帧率稳定(≥ 30 FPS)
- 内存占用正常(无明显泄漏)
- CPU 占用正常
- 加载速度可接受
附录
A. 推荐工具
- Visual Studio 2022:编译和调试
- Boost.Config:快速配置 Boost 编译选项
- Process Explorer:监控 DLL 加载和内存
- DebugView:查看日志输出
B. 参考文档
C. 联系方式
如有问题,请联系:
- 技术负责人:[你的联系方式]
- 原始开发者:[如果能联系到的话]
总结
升级到 VS2022 是一个中等复杂度的任务,主要难点在于:
- ✅ 依赖库升级(Boost、Lua、luabind)
- ✅ 旧式 C++ 代码适配(
__declspec(thread)、stdext::hash_map) - ✅ DirectX 兼容性(需要 Windows 10 SDK)
好消息:
- EXECryptor 未启用,无需处理内联汇编
- DirectX 代码封装良好,无需深入了解
- 项目结构清晰,修改范围可控
预计成果:
- 使用现代 C++ 编译器(C++11/14/17)
- 更好的调试体验
- 更高的代码安全性
- 更方便维护
祝升级顺利!