本文描述的方法基于Visual Studio,因而只能于用Windows。这调试法一大优点:可同时察看lua变量、C变量。
一、安装Visual Studio和LuaDkmDebugger
安装Visual Studio时,只须安装和C/C++相关的基本模块。至于版本,低的可能还不支持,应该是越新越好。至少能用版本:Visual Studio 2019(Version 16.10.2)。
LuaDkmDebugger是个开源Visual Studio插件。
This Visual Studio extension enables debugging of Lua scripts running inside C++ applications with Lua library.
使用Visual Studio要求的方法安装该插件:“Extensions”——“Manage Extensions”。安装成功,便可进入调试了,以下是截图。

在变量区,还可查看两个特殊变量:注册表“[registry]”、环境“_ENV”。
二、LuaDkmDebugger存在的缺陷
2.1 无法在*.lua内灵活设置断点
官网有写,使用lua_dkm_debug.json可实现在*.lua内设置断点。但试了几次,偶尔有过成功,更多是失败。
后来放弃了,改用专门写一个能被*.lua调用的C函数,在该C函数内设断点。想查看*.lua中何时的变量了,调用该函数。
图1中rose.cpp_breakpoint()就是自写C函数,断点其实设置在那里。是用“Call Stack”改为查看*.lua。至于C函数怎么写,能放置断点就行,这时intf_breakpoint。
static int intf_breakpoint(lua_State* L) { SDL_Log("for debug. app can insert breakpoint at this line"); return 0; }
2.2 启用LuaDkmDebugger后,会使lua库的一些函数没法进入断点
举个例子,在lvm.c内的luaV_execute(lua_State *L, CallInfo *ci)内设置断点,执行时,断点会不停在你设的语句,而是停在了*.lua的某个地方。
以我经验,越靠近执行*.lua的C代码处,越可能设置失败。因为这原因,如果想用断点深入理解luaV_execute执行逻辑,建议先Disable LuaDkmDebugger。
LuaDkmDebugger解决了实时查看lua脚本变量,对lua的语法错误问题,LuaDkmDebugger就无能为力了。
三、定位*.lua脚本语法错误
编写lua脚本,谁都没法避免不犯语法错,需要一种方法,能以最快速度定位出错误在哪行,是什么错。lua内部有一套向上报错机制,但这须要调用lua的框架做配合。
3.1 lua_kernel_base::protected_call
Rose实现了一套基于lua的报错机制,这个还有完善中。目前版本,为快速定位语法错,至少须在lua_kernel_base::protected_call内设置断点,此时msg变量指示了错在哪行,及什么错。

3.2 luaB_assert:查看assert(诊断)时的变量值
-- assert(诊断) assert(minor == this.WHEELTEC_MINOR_BOX);
在lua代码,经常会出现类似上面assert语句。当assert出false时,会触发“3.1 lua_kernel_base::protected_call”处断点,此时变量“msg”是类似下面的值。
lua/home.lua:208: assertion failed! stack traceback: [C]: in function '.assert' lua/home.lua:208: in field 'pre_base_wheeltec' lua/home.lua:171: in field 'pre_driver' lua/home.lua:71: in function <lua/home.lua:55>
通过msg,可定位出哪条assert出错,但无法第一时间知道assert语句内中变量是何值,像上面的“minor”。有些assert要出false,可能较难重复,这时第一时间知道变量值,就变得重要了。这时,可在luaB_assert设断点。

这个断点会先于“3.1 lua_kernel_base::protected_call”触发,通过“Call Stack”转到图中“lua_vm!@lua/home.lua ...”处,就可知道变量“minor”是何值。