跳到主要内容

客户端升级到 Visual Studio 2022 指南

目标读者:熟悉服务器开发,不熟悉 DirectX 的开发者 预计工作量:2-3周 风险等级:中等


📋 目录

  1. 环境准备
  2. 项目结构分析
  3. 核心改动点
  4. 分步实施指南
  5. 常见问题
  6. 测试清单

环境准备

1.1 安装 Visual Studio 2022

安装组件:
✅ 使用 C++ 的桌面开发
✅ Windows 10 SDK (10.0.19041.0 或更高)
✅ Windows 8.1 SDK (兼容老项目)
❌ 不需要 Linux 开发工具

1.2 获取依赖库

需要准备的库:

库名原版本目标版本下载地址
Boost1.34.11.81.0https://www.boost.org/users/download/
Lua5.0.35.4.4https://www.lua.org/download.html
luabind旧版本0.9.1https://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.hClient/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.hClient/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

步骤

  1. 删除 Client/execryptor.h
  2. 删除 Client/execryptor.cpp
  3. 修改 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 是"不安全函数"警告(如 strcpysprintf
  • 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年)

升级步骤

  1. 下载 Boost 1.81.0:https://www.boost.org/users/download/
  2. 解压到 client-code/boost_1_81_0/
  3. 编译 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::bindboost::functionboost::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

升级步骤

  1. 下载 Lua 5.4.4:https://www.lua.org/ftp/lua-5.4.4.tar.gz
  2. 解压到 client-code/lua-5.4.4/
  3. 替换 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(或最新版)

升级步骤

  1. 从 GitHub 下载:https://github.com/luabind/luabind
  2. 替换 client-code/luabind/ 目录
  3. 修改 luabind/public.h 以适配 Boost 1.81

注意事项

  • luabind 依赖 Boost,必须先升级 Boost
  • 可能需要修改 luabind 的代码以适配新 Boost

3.3 项目配置迁移(P2 - 中优先级)

🟢 3.3.1 VS2003 → VS2022 项目文件

步骤

  1. 使用 VS2022 自动升级

    右键 Client.vcproj → 打开方式 → Visual Studio 2022

    VS2022 会自动将 .vcproj 转换为 .vcxproj

  2. 检查编译配置

    项目属性 → 配置属性 → 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
  3. 调整包含目录

    项目属性 → 配置属性 → C/C++ → 常规 → 附加包含目录
    - ../
    - ../engine/include
    - ../gui/include
    - ../RenderD3D/include
    - ../boost_1_81_0
    - ../lua-5.4.4/src
    - ../luabind
  4. 调整库目录

    项目属性 → 配置属性 → 链接器 → 常规 → 附加库目录
    - ../boost_1_81_0/stage/lib
  5. 添加链接依赖

    项目属性 → 配置属性 → 链接器 → 输入 → 附加依赖项
    - 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.hClient/public.cpp__declspec(thread)thread_local
  • 删除 execryptor.hexecryptor.cpp 相关代码
  • 修改 Client/public.h 第170-184行

Day 5-7:hash_map 替换

  • 替换 engine/include/Ini.h 中的 stdext::hash_mapstd::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: 运行时崩溃

可能原因

  1. thread_local 使用不当
  2. Boost 升级导致的 ABI 不兼容
  3. 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 是一个中等复杂度的任务,主要难点在于:

  1. ✅ 依赖库升级(Boost、Lua、luabind)
  2. ✅ 旧式 C++ 代码适配(__declspec(thread)stdext::hash_map
  3. ✅ DirectX 兼容性(需要 Windows 10 SDK)

好消息

  • EXECryptor 未启用,无需处理内联汇编
  • DirectX 代码封装良好,无需深入了解
  • 项目结构清晰,修改范围可控

预计成果

  • 使用现代 C++ 编译器(C++11/14/17)
  • 更好的调试体验
  • 更高的代码安全性
  • 更方便维护

祝升级顺利!