打印 table,编译级别打印
Lua
-- 编译级别打印 table:输出元表、元方法、函数原型、Upvalue、元素类型等底层信息
function debug_print_table(t, depth_limit, processed)
-- 初始化参数:默认最大递归深度 5,避免死循环;processed 记录已处理对象(防循环引用)
depth_limit = depth_limit or 5
processed = processed or setmetatable({}, {__mode = "k"}) -- 弱引用表,不影响垃圾回收
-- 1. 基础校验:如果不是 table/function/userdata,直接打印原始值
if type(t) ~= "table" and type(t) ~= "function" and type(t) ~= "userdata" then
print(string.format("[%s] %s", type(t), tostring(t)))
return
end
-- 2. 防循环引用:如果已处理过该对象,直接打印引用标识
if processed[t] then
print(string.format("[%s] <循环引用: %s>", type(t), tostring(t)))
return
end
processed[t] = true -- 标记为已处理
-- 3. 打印对象基本信息(内存地址、类型)
local obj_info = string.format("[%s] 内存地址: %p", type(t), t)
print(obj_info)
-- 4. 递归打印时的缩进(按深度生成)
local function get_indent(depth)
return string.rep(" ", depth)
end
-- 5. 核心逻辑:解析编译级信息(按类型处理)
local function parse_object(obj, depth)
if depth > depth_limit then
print(get_indent(depth) .. "<递归深度超限>")
return
end
local obj_type = type(obj)
-- 5.1 处理 table 类型(核心:元表、元方法、元素详情)
if obj_type == "table" then
-- 打印元表(编译级核心信息:table 的行为由元表控制)
local mt = debug.getmetatable(obj)
if mt then
print(get_indent(depth) .. "元表 (metatable):")
parse_object(mt, depth + 1, processed) -- 递归解析元表(元表也是 table)
else
print(get_indent(depth) .. "元表 (metatable): nil")
end
-- 打印 table 元素(非普通遍历:标注元素类型+编译级信息)
print(get_indent(depth) .. "元素 (键: 类型=值):")
for k, v in pairs(obj) do
local k_type = type(k)
local v_type = type(v)
local key_str = string.format("[%s] %s", k_type, tostring(k))
local val_str = ""
-- 对值的编译级信息特殊处理(函数、userdata 等)
if v_type == "function" then
-- 函数:打印参数数量、Upvalue、定义位置(编译级原型信息)
local func_info = debug.getinfo(v, "Slnu")
local param_num = func_info.nparams or 0
local is_vararg = func_info.isvararg and "是" or "否"
local upvalues = {}
local up_idx = 1
while true do
local up_name, up_val = debug.getupvalue(v, up_idx)
if not up_name then break end
table.insert(upvalues, string.format("%s = [%s] %s", up_name, type(up_val), tostring(up_val)))
up_idx = up_idx + 1
end
val_str = string.format(
"[function] 名称: %s | 参数数: %d | 可变参数: %s | 定义行: %d-%d | Upvalue: {%s}",
func_info.name or "匿名", param_num, is_vararg,
func_info.linedefined or -1, func_info.lastlinedefined or -1,
table.concat(upvalues, ", ")
)
elseif v_type == "userdata" then
-- Userdata:打印元表(C 扩展对象的编译级关联信息)
local v_mt = debug.getmetatable(v)
val_str = string.format("[userdata] 元表: %s", v_mt and tostring(v_mt) or "nil")
elseif v_type == "table" then
val_str = string.format("[table] 内存地址: %p", v)
else
val_str = string.format("[%s] %s", v_type, tostring(v))
end
print(get_indent(depth + 1) .. key_str .. " → " .. val_str)
end
-- 5.2 处理 function 类型(单独传入函数时解析)
elseif obj_type == "function" then
local func_info = debug.getinfo(obj, "Slnu")
print(get_indent(depth) .. "函数原型信息:")
print(get_indent(depth + 1) .. "名称: " .. (func_info.name or "匿名函数"))
print(get_indent(depth + 1) .. "定义文件: " .. (func_info.source or "未知"))
print(get_indent(depth + 1) .. "定义行号: " .. (func_info.linedefined or -1) .. "-" .. (func_info.lastlinedefined or -1))
print(get_indent(depth + 1) .. "参数数量: " .. (func_info.nparams or 0))
print(get_indent(depth + 1) .. "支持可变参数: " .. (func_info.isvararg and "是" or "否"))
-- 打印 Upvalue(闭包捕获的变量,编译级关键信息)
local up_idx = 1
print(get_indent(depth + 1) .. "Upvalue (闭包变量):")
while true do
local up_name, up_val = debug.getupvalue(obj, up_idx)
if not up_name then break end
print(get_indent(depth + 2) .. up_name .. ": [" .. type(up_val) .. "] " .. tostring(up_val))
up_idx = up_idx + 1
end
-- 5.3 处理 userdata 类型(C 扩展对象,编译级关联元表)
elseif obj_type == "userdata" then
local ud_mt = debug.getmetatable(obj)
print(get_indent(depth) .. "Userdata 元表:")
parse_object(ud_mt, depth + 1, processed)
end
end
-- 开始解析当前对象(初始深度 1)
parse_object(t, 1, processed)
print("----------------------------------------") -- 分隔线
end
function add_button()
print('add a Button')
debug_print_table(__Nova)
end
LuaRuntime(可能是ToLua)
Lua
LuaRuntime.Instance.BindObject("gameViewController", this);//需要绑定了,才能在 .lua 调用 __Nova.gameViewController.
打印堆栈
???
