打印lua中不同类型的数据
类型 | 打印 | 输出 |
nil |
print(nil)
|
nil |
布尔 |
print(true)
|
true |
number |
print(5)
|
5 |
number |
print(3.14)
|
3.14 |
字符串 |
print("Hello World!")
|
Hello World! |
light c function |
print(print)
|
function: 00007FF66598EAC0 注1:该值为value_.f的16进制 注2:print映射对应c++中的luaB_print函数 |
c fuction |
c++代码: static int CClosureStrLen(lua_State* L) lua_pushnumber(L, (int)strlen(upval)); /* push result */ lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); // 获取G表并压栈 // 创建有1个upvalue的c函数闭包(upvalue为栈顶元素),成功后将栈顶1个upvalue出栈,并将自己入栈 // 设置索引为-2处的G表的key为Lua_CClosureStrLen对应的value为c闭包CClosureStrLen(在栈顶处) 设置成功后,将栈顶的c闭包出栈
lua代码: print(Lua_CClosureStrLen) |
function: 000002348D50EA70 注:该值为value_.gc的16进制 |
lua fuction |
function Func1()
end
print(Func1)
|
function: 000001C75623DBE0 注:该值为value_.gc的16进制 |
table lua实现 |
print({1,2,a=10,b=20})
|
table: 000001C75623B5A0 注:该值为value_.gc的16进制 |
table 有元表及__tostring元方法 |
local mt = {}
mt.__tostring = function (t)
return "Hello " .. t.tag
end
local t = setmetatable({x=10,tag="this is t1 table."}, mt)
print(t) --输出Hello this is t1 table.
|
Hello this is t1 table. 注:t的元表实现了__tostring元方法,打印t时会调用该方法的返回值来输出 |
table c++实现 |
print(io)
|
table: 000001C75622B550 注:该值为value_.gc的16进制 |
light userdata |
c++代码: lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);// 获取G表并压栈
lua代码: print(Lua_lightuserdata)
|
userdata: 000001B033F52B18 注:该值为value_.p的16进制 |
full userdata 有元表及__tostring元方法 |
print(io.stdin)
|
file (00007FF96340FC00) 注1:由于为io.stdin实现了元方法__tostring,映射对应liolib.c的f_tostring函数 在lua中打印io.stdin,最后会调用f_tostring函数来打印 注2:该值为((luaL_Stream*)((char*)(value_.gc) + sizeof(Udata)))->f的FILE*指针 注3:sizeof(Udata)为40 |
full userdata |
c++代码:
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);// 获取G表并压栈
lua代码: print(Lua_fulluserdata) -- 注:该full userdata无元表和元方法
|
userdata: 000001D5CAA03EE8 注1:该值为(char*)(value_.gc) + sizeof(Udata)的16进制 注2:sizeof(Udata)为40 |
lua state |
print(coroutine.create(function() end))
|
thread: 000001C7562428C8 注:该值为value_.gc的16进制 |
去掉元表对__tostring元方法的重写,使用lua api中的tostring进行原始输出
function tostringraw( t ) if not t then return "" end local mt = getmetatable(t) if not mt then return tostring(t) end local fts = rawget(mt, "__tostring") if not fts then return tostring(t) end rawset(mt, "__tostring", nil) local output = tostring(t) rawset(mt, "__tostring", fts) return output end
使用lua输出
使用原生的print打印G表中的内容
for i,v in pairs(_G) do print("["..i.."] => "..tostring(v)) end
输出结果如下:
[rawlen] => function: 00007FF9A6038CB0 // luaB_rawlen [utf8] => table: 000001C73CD1FD90 [next] => function: 00007FF9A60391B0 // luaB_next [require] => function: 000001C73CD1F8D0 [select] => function: 00007FF9A603A100 // luaB_select [debug] => table: 000001C73CD1FA10 [tonumber] => function: 00007FF9A6038690 // luaB_tonumber [pcall] => function: 00007FF9A603A2B0 // luaB_pcall [_VERSION] => Lua 5.3 [dofile] => function: 00007FF9A6039E70 // luaB_dofile [table] => table: 000001C73CD1FB90 [collectgarbage] => function: 00007FF9A6038EE0 // luaB_collectgarbage [coroutine] => table: 000001C73CD1FC10 [rawequal] => function: 00007FF9A6038C00 // luaB_rawequal [string] => table: 000001C73CD1FCD0 [ipairs] => function: 00007FF9A60394A0 // luaB_ipairs [error] => function: 00007FF9A60389D0 // luaB_error [type] => function: 00007FF9A6039110 // luaB_type [getmetatable] => function: 00007FF9A6038A40 // luaB_getmetatable [tostring] => function: 00007FF9A603A5E0 // luaB_tostring [_G] => table: 000001C73CD1F750 [arg] => table: 000001C73CD1FE10 [setmetatable] => function: 00007FF9A6038B00 // luaB_getmetatable [math] => table: 000001C73CD1FD50 [load] => function: 00007FF9A6039AA0 // luaB_load [rawget] => function: 00007FF9A6038D60 // luaB_rawget [os] => table: 000001C73CD1FA90 [io] => table: 000001C73CD1FBD0 [print] => function: 000001C73CE093A0 // luaB_print [pairs] => function: 00007FF9A6039290 // luaB_pairs [assert] => function: 00007FF9A603A060 // luaB_assert [package] => table: 000001C73CD1F910 [xpcall] => function: 00007FF9A603A410 // luaB_xpcall [rawset] => function: 00007FF9A6038E20 // luaB_rawset [loadfile] => function: 00007FF9A6039700 // luaB_loadfile
使用实现的printx来递归打印G表中的内容(带元表输出)
test3.lua代码如下:
local test3 = {} test3.var1 = 100 function test3:func1() end return test3
main.lua代码如下:
function printx ( t ) local printx_cache={} -- 防止打印过的table被重复展开打印,造成死循环 local function sub_printx(t,indent) -- indent为分隔字符串 当前为2个空格 if (printx_cache[tostring(t)]) then print(indent.."*** has print ***") else printx_cache[tostring(t)]=true if (type(t)=="table") then local mt = getmetatable(t) if (mt~=nil) then -- 打印当前表的元表 print(indent.."table's meta"..tostring(mt).." {") sub_printx(mt,indent..string.rep(" ",2)) print(indent.."}") end for pos,val in pairs(t) do local spos = tostring(pos) if (type(val)=="table" or type(val)=="userdata") then print(indent.."["..spos.."] => "..tostring(val).." {") sub_printx(val,indent..string.rep(" ",string.len(spos)+8)) print(indent..string.rep(" ",string.len(spos)+6).."}") elseif (type(val)=="string") then print(indent.."["..spos..'] => "'..val..'"') else print(indent.."["..spos.."] => "..tostring(val)) end end elseif type(t)=="userdata" then local mt = getmetatable(t) if (mt~=nil) then -- 打印当前userdata的元表 print(indent.."userdata's meta"..tostring(mt).." {") sub_printx(mt,indent..string.rep(" ",2)) print(indent.."}") end else print(indent..tostring(t)) end end end if (type(t)=="table" or type(t)=="userdata") then print(tostring(t).." {") sub_printx(t," ") print("}") else sub_printx(t," ") end end gt = {120,key1="Hello"} require("test3") printx(_G) -- 打印G表中的内容
输出结果如下:
table: 00000226C79D02D0 { [utf8] => table: 00000226C79CFE50 { [codepoint] => function: 00007FF9A6066A60 // codepoint [codes] => function: 00007FF9A6067370 // iter_codes [len] => function: 00007FF9A6066770 // utflen [charpattern] => "[-�-�][�-�]*" [char] => function: 00007FF9A6066D60 // utfchar [offset] => function: 00007FF9A6066ED0 // byteoffset } [_VERSION] => "Lua 5.3" [package] => table: 00000226C79D0410 { [cpath] => "I:\pubcode\LuaTest\LuaCode/?.dll" [loaded] => table: 00000226C79D03D0 { [utf8] => table: 00000226C79CFE50 { *** has print *** } [package] => table: 00000226C79D0410 { *** has print *** } [table] => table: 00000226C79D0210 { [remove] => function: 00007FF9A6063C80 // tremove [move] => function: 00007FF9A6063E20 // tmove [concat] => function: 00007FF9A6064110 // tconcat [pack] => function: 00007FF9A6064560 // pack [unpack] => function: 00007FF9A60646A0 // unpack [sort] => function: 00007FF9A6064D50 // sort [insert] => function: 00007FF9A6063AE0 // tinsert } [io] => table: 00000226C79D01D0 { [close] => function: 00007FF9A6046660 // io_close [stderr] => file (00007FF9B1A3A510) { userdata's metatable: 0000026A4EADF7D0 { [__name] => "FILE*" [lines] => function: 00007FF992497050 [seek] => function: 00007FF992498C00 [flush] => function: 00007FF992499160 [write] => function: 0000026A50891090 [read] => function: 00007FF992497E40 [__tostring] => function: 00007FF992496320 [__index] => table: 0000026A4EADF7D0 { *** has print *** } [__gc] => function: 00007FF992496720 [close] => function: 00007FF9924965D0 [setvbuf] => function: 00007FF992498EB0 } } [stdout] => file (00007FF9B1A3A4B8) { userdata's metatable: 0000026A4EADF7D0 { *** has print *** } } [stdin] => file (00007FF9B1A3A460) { userdata's metatable: 0000026A4EADF7D0 { *** has print *** } } [output] => function: 00007FF9A6046F00 // io_output [popen] => function: 00007FF9A6046B00 // io_popen [type] => function: 00007FF9A6046110 // io_type [read] => function: 00007FF9A6047DC0 // io_read [input] => function: 00007FF9A6046EE0 // io_input [lines] => function: 00007FF9A60470B0 // io_lines [open] => function: 00007FF9A6046870 // io_open [tmpfile] => function: 00007FF9A6046CF0 // io_tmpfile [write] => function: 00000226C7AA8F40 // io_write [flush] => function: 00007FF9A60490D0 // io_flush } [coroutine] => table: 00000226C79D0250 { [create] => function: 00007FF9A603CDA0 // luaB_cocreate [status] => function: 00007FF9A603D060 // luaB_costatus [resume] => function: 00007FF9A603CBE0 // luaB_coresume [wrap] => function: 00007FF9A603CE50 // luaB_cowrap [isyieldable] => function: 00007FF9A603D470 // luaB_yieldable [yield] => function: 00007FF9A603CFC0 // luaB_yield [running] => function: 00007FF9A603D4A0 // luaB_corunning } [test3] => table: 000001CB6C2BC9F0 { [func1] => function: 000001CB6C291540 [var1] => 100 } [debug] => table: 00000226C79CFE90 { [sethook] => function: 00007FF9A603EFD0 // db_sethook [setlocal] => function: 00007FF9A603E440 // db_setlocal [getregistry] => function: 00007FF9A603D650 // db_getregistry [traceback] => function: 00007FF9A603FD90 // db_traceback [upvalueid] => function: 00007FF9A603E960 // db_upvalueid [getlocal] => function: 00007FF9A603E0F0 // db_getlocal [debug] => function: 00007FF9A603F9A0 // db_debug [getupvalue] => function: 00007FF9A603E910 // db_getupvalue [getuservalue] => function: 00007FF9A603D7A0 // db_getuservalue [setuservalue] => function: 00007FF9A603D800 // db_setuservalue [setmetatable] => function: 00007FF9A603D720 // db_setmetatable [setupvalue] => function: 00007FF9A603E920 // db_setupvalue [gethook] => function: 00007FF9A603F690 // db_gethook [upvaluejoin] => function: 00007FF9A603EB20 // db_upvaluejoin [getmetatable] => function: 00007FF9A603D670 // db_getmetatable [getinfo] => function: 00007FF9A603D9D0 // db_getinfo } [math] => table: 00000226C79D0050 { [tointeger] => function: 00007FF9A604BDF0 // math_toint [log] => function: 00007FF9A604C720 // math_log [ceil] => function: 00007FF9A604C000 // math_ceil [huge] => inf [abs] => function: 00007FF9A604B700 // math_abs [modf] => function: 00007FF9A604C3D0 // math_modf [maxinteger] => 9223372036854775807 [acos] => function: 00007FF9A604BB80 // math_acos [mininteger] => -9223372036854775808 [atan] => function: 00007FF9A604BC50 // math_atan [pi] => 3.1415926535898 [random] => function: 00007FF9A604CCA0 // math_random [type] => function: 00007FF9A604CF60 // math_type [cos] => function: 00007FF9A604B910 // math_cos [sqrt] => function: 00007FF9A604C560 // math_sqrt [tan] => function: 00007FF9A604B9E0 // math_tan [randomseed] => function: 00007FF9A604CEA0 // math_randomseed [fmod] => function: 00007FF9A604C150 // math_fmod [asin] => function: 00007FF9A604BAB0 // math_asin [deg] => function: 00007FF9A604C9C0 // math_deg [rad] => function: 00007FF9A604CA90 // math_rad [min] => function: 00007FF9A604CB60 // math_min [max] => function: 00007FF9A604CC00 // math_max [ult] => function: 00007FF9A604C640 // math_ult [floor] => function: 00007FF9A604BEB0 // math_floor [exp] => function: 00007FF9A604C8F0 // math_exp [sin] => function: 00007FF9A604B840 // math_sin } [string] => table: 00000226C79CFDD0 { [gmatch] => function: 00007FF9A605EB90 // gmatch [len] => function: 00007FF9A605C6D0 // str_len [packsize] => function: 00007FF9A60619A0 // str_packsize [dump] => function: 00007FF9A605D6B0 // str_dump [match] => function: 00007FF9A605EA50 // str_match [rep] => function: 00007FF9A605CEF0 // str_rep [unpack] => function: 00007FF9A6061CB0 // str_unpack [format] => function: 00007FF9A605FB10 // str_format [reverse] => function: 00007FF9A605CA00 // str_reverse [lower] => function: 00007FF9A605CBB0 // str_lower [pack] => function: 00007FF9A60608E0 // str_pack [upper] => function: 00007FF9A605CD50 // str_upper [sub] => function: 00007FF9A605C790 // str_sub [find] => function: 00007FF9A605EA40 // str_find [gsub] => function: 00007FF9A605F2F0 // str_gsub [byte] => function: 00007FF9A605D2D0 // str_byte [char] => function: 00007FF9A605D520 // str_char } [os] => table: 00000226C79CFF90 { [clock] => function: 00007FF9A6050FA0 // os_clock [time] => function: 00007FF9A60516C0 // os_time [date] => function: 00007FF9A60511B0 // os_date [difftime] => function: 00007FF9A6051BE0 // os_difftime [execute] => function: 00007FF9A6050AE0 // os_execute [setlocale] => function: 00007FF9A6051CC0 // os_setlocale [getenv] => function: 00007FF9A6050EB0 // os_getenv [rename] => function: 00007FF9A6050CE0 // os_rename [remove] => function: 00007FF9A6050BC0 // os_remove [tmpname] => function: 00007FF9A6050E20 // os_tmpname [exit] => function: 00007FF9A6051EE0 // os_exit } [_G] => table: 00000226C79D02D0 { *** has print *** } } [searchpath] => function: 00007FF9A604E150 // ll_searchpath [preload] => table: 00000226C79D0390 { } [config] => "\ ; ? ! - " [searchers] => table: 00000226C79CFD50 { [1] => function: 00000226C79D00D0 [2] => function: 00000226C79D0290 // LuaLoader_Callback [3] => function: 00000226C79D0110 [4] => function: 00000226C79D0350 } [loadlib] => function: 00007FF9A604DCE0 // ll_loadlib [path] => "I:\pubcode\LuaTest\LuaCode/?.lua" } [dofile] => function: 00007FF9A6039E70 [require] => function: 00000226C79CFFD0 [tostring] => function: 00007FF9A603A5E0 [rawlen] => function: 00007FF9A6038CB0 [next] => function: 00007FF9A60391B0 [assert] => function: 00007FF9A603A060 [xpcall] => function: 00007FF9A603A410 [table] => table: 00000226C79D0210 { *** has print *** } [type] => function: 00007FF9A6039110 [gt] => table: 000001CB6C2BBD30 { [1] => 120 [key1] => "Hello" } [error] => function: 00007FF9A60389D0 [pairs] => function: 00007FF9A6039290 [loadfile] => function: 00007FF9A6039700 [rawset] => function: 00007FF9A6038E20 [collectgarbage] => function: 00007FF9A6038EE0 [select] => function: 00007FF9A603A100 [pcall] => function: 00007FF9A603A2B0 [tonumber] => function: 00007FF9A6038690 [_G] => table: 00000226C79D02D0 { *** has print *** } [arg] => table: 00000226C79CFF50 { [0] => "I:\pubcode\LuaTest\LuaCode/test4.lua" [-3] => "c:/Users/chen/.vscode/extensions/actboy168.lua-debug-1.30.1/runtime/win64/lua53/lua.exe" [-2] => "-e" [-1] => "dofile[[c:/Users/chen/.vscode/extensions/actboy168.lua-debug-1.30.1/script/launch.lua]];DBG(50980,true)" } [debug] => table: 00000226C79CFE90 { *** has print *** } [math] => table: 00000226C79D0050 { *** has print *** } [os] => table: 00000226C79CFF90 { *** has print *** } [print] => function: 00000226C7AA8B80 [string] => table: 00000226C79CFDD0 { *** has print *** } [io] => table: 00000226C79D01D0 { *** has print *** } [ipairs] => function: 00007FF9A60394A0 [setmetatable] => function: 00007FF9A6038B00 [load] => function: 00007FF9A6039AA0 [rawget] => function: 00007FF9A6038D60 [rawequal] => function: 00007FF9A6038C00 [coroutine] => table: 00000226C79D0250 { *** has print *** } [getmetatable] => function: 00007FF9A6038A40 }
注1:全局变量会被添加到_G表中 // 如上示例中的gt表
注2:被require进来的表会放在_G[package]表中键为[loaded]的表中 // 如上示例中的test3表
使用实现的printx来递归打印自定义表中的内容(带元表输出)
local t1 = {1,2,3,h1="earth"} local t2= setmetatable({x=10},t1) local t3= setmetatable({r=128,g=30,b=12},t2) printx(t3)
输出内容如下:
table: 000002541BAE6600 { metatable: 000002541BAE6540 { metatable: 000002541BAE6380 { [1] => 1 [2] => 2 [3] => 3 [h1] => "earth" } [x] => 10 } [r] => 128 [b] => 12 [g] => 30 }
使用C++输出
std::vector<std::string> VSDumpTable(lua_State* L) { std::vector<std::string> Msg; char szBuffer[256] = { 0 }; memset(szBuffer, 0, 256); // 好了,现在表已经在栈顶上了,像前面操作 next 的方式一样操作 // 1. 先压入 nil 调用 next 开始迭代 lua_pushnil(L); // 现在的栈是这样的:-1 => nil, -2 => table // 2. 现在循环调用 next 来获取下一组键值 // 第1个参数待查询的键,第2个参数是表的索引 // 如果没有可迭代的元素了,lua_next 会返回 0 while (lua_next(L, -2)) { // 现在的栈是这样的:-1 => value, -2 => key, -3 => table const char* key = luaL_tolstring(L, -2, NULL); lua_pop(L, 1); const char* value = luaL_tolstring(L, -1, NULL); lua_pop(L, 1); sprintf_s(szBuffer, 255, "%s => %s", key, value); Msg.push_back(szBuffer); // 现在完后,干掉 value 保留 key,为下一次迭代作准备 lua_pop(L, 1); // 现在的栈是这样的:-1 => key, -2 => table // 已经回到开始遍历时的栈帧了,可以下一次遍历了 } // lua_next 不止会返回0,而且还会帮我们把最后一个 key 给弹出去,只保留最初那个表 // 现在的栈是这样的:-1 => table return Msg; } std::vector<std::string> VSDumpRegisterTable(lua_State* L) { // 将Registry表压入栈顶 lua_pushvalue(L, LUA_REGISTRYINDEX); std::vector<std::string> Msg = VSDumpTable(L); lua_pop(L, 1); return Msg; } std::vector<std::string> VSDumpGTable(lua_State* L) { // 将G表压入栈顶 lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); std::vector<std::string> Msg = VSDumpTable(L); lua_pop(L, 1); return Msg; }
输出结果如下:
? VSDumpRegisterTable(L) { size=8 } [capacity]: 9 [allocator]: allocator [0]: "1 => thread: 0000020FB5CB2B28" [1]: "2 => table: 0000020FB5CA55D0" [2]: "_IO_input => file (00007FF8DBE3FC00)" [3]: "userdata: 00007FF74FF3E520 => table: 0000020FB5CA3A40" [4]: "_IO_output => file (00007FF8DBE3FC58)" [5]: "FILE* => table: 0000020FB5CB69A0" [6]: "_PRELOAD => table: 0000020FB5CB67A0" [7]: "_LOADED => table: 0000020FB5CA5880" [Raw View]: {_Mypair=allocator } ? VSDumpGTable(L) { size=51 } [capacity]: 63 [allocator]: allocator [0]: "io => table: 0000020FB5CB63A0" [1]: "select => function: 00007FF74FEDFF60" [2]: "rawset => function: 00007FF74FEDF4B0" [3]: "tonumber => function: 00007FF74FEDED20" [4]: "require => function: 0000020FB5CAF570" [5]: "error => function: 00007FF74FEDEF90" [6]: "game_writetext => function: 00007FF74FF273D0" [7]: "dofile => function: 00007FF74FEDFD50" [8]: "MyArrayTest => function: 0000020FB5CC3140" [9]: "tagame_gameplayercount => 8" [10]: "pairs => function: 00007FF74FEDF880" [11]: "game_readbyte => function: 00007FF74FF27190" [12]: "tostring => function: 00007FF74FEE02E0" [13]: "table => table: 0000020FB5CB62A0" [14]: "os => table: 0000020FB5CB6720" [15]: "coroutine => table: 0000020FB5CB6CA0" [16]: "game_readtext => function: 00007FF74FF27250" [17]: "pcall => function: 00007FF74FEE00B0" [18]: "Add => function: 0000020FB5CC3680" [19]: "Add2 => function: 0000020FB5CC1370" [20]: "loadgamecheatscript => function: 0000020FB5CC2FF0" [21]: "game_writehello => function: 0000020FB5CC30D0" [22]: "game_setrominfo => function: 0000020FB5CC3370" [23]: "print => function: 00007FF74FEDEAD0" [24]: "game_cheatprocess => function: 0000020FB5CC3530" [25]: "type => function: 00007FF74FEDF700" [26]: "_G => table: 0000020FB5CA55D0" [27]: "tagame_romimpl => userdata: 0000020FB5CB2090" [28]: "unserialize => function: 0000020FB5CC2F80" [29]: "serialize => function: 0000020FB5CC34C0" [30]: "myarray => table: 0000020FB5CB64A0" [31]: "xpcall => function: 00007FF74FEE01B0" [32]: "package => table: 0000020FB5CB4880" [33]: "game_getgameframe => function: 00007FF74FF27500" [34]: "getmetatable => function: 00007FF74FEDF090" [35]: "debug => table: 0000020FB5CB66A0" [36]: "loadfile => function: 00007FF74FEDF9B0" [37]: "string => table: 0000020FB5CB6420" [38]: "collectgarbage => function: 00007FF74FEDF580" [39]: "utf8 => table: 0000020FB5CB6D20" [40]: "rawlen => function: 00007FF74FEDF320" [41]: "math => table: 0000020FB5CB68A0" [42]: "_VERSION => Lua 5.3" [43]: "rawequal => function: 00007FF74FEDF270" [44]: "assert => function: 00007FF74FEDFE50" [45]: "setmetatable => function: 00007FF74FEDF150" [46]: "rawget => function: 00007FF74FEDF3F0" [47]: "load => function: 00007FF74FEDFAF0" [48]: "next => function: 00007FF74FEDF7C0" [49]: "game_writebyte => function: 00007FF74FF27310" [50]: "ipairs => function: 00007FF74FEDF900" [Raw View]: {_Mypair=allocator }
扩展阅读