Bluelua 支持 lua 代码调试

最近鹅厂开源了一个 LuaPanda,基于 VS Code 的 lua 代码调试器,简单易用,支持多种开发框架,特性如下

  • 支持单步调试,断点调试,协程调试
  • 支持lua5.1- 5.3, 支持 slua/xlua/slua-unreal 等框架
  • 在断点处可以监视和运行表达式,返回结果
  • 可以根据断点密集程度调整 hook 频率, 有较好高的效率
  • 支持 attach 模式,lua 运行过程中可随时建立连接
  • 使用 lua / C 双调试引擎。lua 部分可动态下发,避免打包后无法调试。C 部分效率高,适合开发期调试

正好 Bluelua 里缺少一个调试器,就花了一点时间将 LuaPanda 集成进来,这样使用 Bluelua 的时候直接就能调试了,不需要再去做额外的工作了。注意,Bluelua 里只有在非 Shipping 的版本里才开启了 LuaPanda 调试

集成过程中遇到的问题

官方集成文档见 接入指引

在集成使用的过程中也遇到了一些问题,如果有要自己集成 LuaPanda 的话可以注意一下

游戏打包后 LuaPanda chook 模块崩溃问题

LuaPanda 的 hook 模块有两种实现,一种是 lua,一种就是 C 实现,C 实现代码在 Debugger/debugger_lib 目录下。默认情况下使用的是 chook 调试库,但是 Windows 上 chook 调试库会动态地去查找 lua 库函数(如 lua_settop),在游戏打包的情况下只有一个 exe,是查不到这些函数的,所以会导致空指针崩溃,这个问题已经反馈给官方了。

解决方法有两种,一是使用 lua 版本的调试库,就是将 LuaPanda.lua 文件中这段代码注释掉,但是这种方式会影响调试效率

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
if tostring(dataTable.info.useHighSpeedModule) == "true" then
local clibExt, platform;
if OSType == "Darwin" then clibExt = "/?.so;"; platform = "mac";
else clibExt = "/?.dll;"; platform = "win"; end

local lua_ver;
if _VERSION == "Lua 5.1" then
lua_ver = "501";
else
lua_ver = "503";
end

local x86Path = clibPath.. platform .."/x86/".. lua_ver .. clibExt;
local x64Path = clibPath.. platform .."/x86_64/".. lua_ver .. clibExt;

if luapanda_chook ~= nil then
hookLib = luapanda_chook;
HOOK_LEVEL = 3;
else
if this.tryRequireClib("libpdebug", x64Path) or this.tryRequireClib("libpdebug", x86Path) then
HOOK_LEVEL = 3;
end
end
end

第二种方式是将 chook 库以源码方式集成到自己的项目里,也就是将 libpdebug.h/.cpp 这两个文件放到自己的项目里一起编译,同时要打开 USE_SOURCE_CODE 宏并且在创建 lua_State 的时候要调用一下 pdebug_init() 这个函数,这样就可以享受到 chook 库的高效率调试了。Bluelua 里用的就是这种方式,具体集成方式可以参考 Bluelua/LuaPanda 模块

游戏卡死问题

使用 LuaPanda 调试时,需要在自己的 lua 代码里调用 LuaPanda.start(ip, port) 去连接 VSCode。有一次 VSCode 没有处于调试监听状态,但是游戏运行却卡死在这里,按理说没有调试的状态下游戏会正常运行,而不是阻塞在 start 里。经过研究发现,虽然 VSCode 界面上没有在调试监听的状态下,但是后台却残留了一个进程在监听调试端口,然后 LuaPanda 正常连了上去,由于开启了 stopOnEntry,这时候游戏会等待 VSCode 调试指令,导致卡死(VSCode 的界面没有进入调试状态无法操作)。解决方法就是退干净 VSCode 进程。

lua 文件路径匹配问题

调试的时候,VSCode 会根据从 lua 虚拟机里获取到的当前 lua 文件名来判断在调试哪个 lua 文件,如果这个文件名是绝对路径,VSCode 就会直接使用这个路径,如果是相对路径,VSCode 会用当前 Workspace 目录路径和这个相对路径进行连接,然后打开这个路径的文件

所以游戏里加载 lua 文件的时候,Name 最好使用相对路径(也就是 luaL_loadbuffer 的最后一个参数),这样后面在 PC 开发机上调试手机才不会出错

Bluelua 里的最后一个参数传的是相对于 Content 目录的路径,所以 VSCode 里打开 lua 的工作目录也应该是 Content,如果不是的话要自己改下 launch.json 里的 cwd 配置

最后调试中的界面如图

LuaPanda.png