• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 505  文章 - 1034  trackbacks - 0
            <2008年2月>
            272829303112
            3456789
            10111213141516
            17181920212223
            2425262728291
            2345678


            子曾經曰過:編程無他,唯手熟爾!

            常用鏈接

            留言簿(94)

            隨筆分類(649)

            隨筆檔案(505)

            相冊

            BCB

            Crytek

            • crymod
            • Crytek's Offical Modding Portal

            Game Industry

            OGRE

            other

            Programmers

            Qt

            WOW Stuff

            搜索

            •  

            積分與排名

            • 積分 - 911304
            • 排名 - 14

            最新隨筆

            最新評論

            閱讀排行榜

            評論排行榜

            現在做網絡游戲項目,很多東西策劃經常變,比如懸浮提示之類的,寫在c++代碼里的,改了每次都得編譯一下,很痛苦!
            所以現在很多游戲邏輯都放在lua腳本里面(準確的說是嵌在xml里面的lua),但是沒法單步調試了,只能靠打日志和注釋掉某行的做法來定位問題,又很痛苦了!今天搜到了一個東東,那個驚喜啊!

            Lua 簡易調試器


            云風大哥寫的,果然牛人啊!現在我沒空看,先放到這兒,有空了研究下!嘿嘿
             一個簡單的調試系統:

            ---------------------------
            --  bp.lua
            ---------------------------
             
            local type=type
            local tostring=tostring
            local print=print
            local setmetatable=setmetatable
            local getfenv=getfenv
            local ipairs=ipairs
            local pairs=pairs
            local xpcall=xpcall
            local error=error
             
            local table_insert=table.insert
            local table_concat=table.concat
            local debug=debug
             
            module "bp"
             
            local nil_value={}
             
            local function traversal_r(tbl,num)
            num = num or 64
            local ret={}
            local function insert(v)
            table_insert(ret,v)
            if #ret>num then
            error()
            end
            end
            local function traversal(e)
            if e==nil_value or e==nil then
            insert("nil,")
            elseif type(e)=="table" then
            insert("{")
            local maxn=0
            for i,v in ipairs(e) do
            traversal(v)
            maxn=i
            end
            for k,v in pairs(e) do
            if not (type(k)=="number" and k>0 and k<=maxn) then
            if type(k)=="number" then
            insert("["..k.."]=")
            else
            insert(tostring(k).."=")
            end
            traversal(v)
            end
            end
            insert("}")
            elseif type(e)=="string" then
            insert('"'..e..'",')
            else
            insert(tostring(e))
            insert(",")
            end
            end
             
            local err=xpcall(
            function() traversal(tbl) end,
            function() end
            )
            if not err then
            table_insert(ret,"...")
            end
             
            return table_concat(ret)
            end
             
            function print_r(tbl,num)
            print(traversal_r(tbl,num))
            end
             
            local function init_local(tbl,level)
            local n=1
            local index={}
            while true do
            local name,value=debug.getlocal(level,n)
            if not name then
            break
            end
             
            if name~="(*temporary)" then
            if value==nil then
            value=nil_value
            end
            tbl[name]=value
            index["."..name]=n
            end
             
            n=n+1
            end
            setmetatable(tbl,{__index=index})
            return tbl
            end
             
            local function init_upvalue(tbl,func)
            local n=1
            local index={}
            while true do
            local name,value=debug.getupvalue(func,n)
            if not name then
            break
            end
             
            if value==nil then
            value=nil_value
            end
            tbl[name]=value
            index["."..name]=n
             
            n=n+1
            end
            setmetatable(tbl,{__index=index})
            return tbl
            end
             
             
            function dbg(level)
            level=level and level+2 or 2
             
            local lv=init_local({},level+1)
            local func=debug.getinfo(level,"f").func
            local uv=init_upvalue({},func)
            local _L={}
            setmetatable(_L,{
            __index=function(_,k)
            local ret=lv[k]
            return ret~=nil_value and ret or nil
            end,
            __newindex=function(_,k,v)
            if lv[k] then
            lv[k]= v~= nil and nil_value or v
            debug.setlocal(level+3,lv["."..k],v)
            else
            print("error:invalid local name:",k)
            end
            end,
            __tostring=function(_)
            return traversal_r(lv)
            end
            })
            print("_L=",traversal_r(lv))
            local _U={}
            setmetatable(_U,{
            __index=function(_,k)
            local ret=uv[k]
            return ret~=nil_value and ret or nil
            end,
            __newindex=function(_,k,v)
            if uv[k] then
            uv[k]= v~= nil and nil_value or v
            debug.setupvalue(func,uv["."..k],v)
            else
            print("error:invalid upvalue name",k)
            end
            end,
            __tostring=function(_)
            return traversal_r(uv)
            end
            })
            print("_U=",traversal_r(uv))
             
            local _G=getfenv(level)
            _G._L,_G._U=_L,_U
            debug.debug()
            _G._L,_G._U=nil,nil
            end
             
             
            local _bp_list={}
            local _bp_desc={}
             
            local function bp_list_name(name)
            local t=type(_bp_desc[name])
            print("["..name.."]",_bp_list[name] and "on" or "off")
            if t=="table" then
            for _,v in ipairs(_bp_desc[name]) do
            print("----",v)
            end
            elseif t=="string" then
            print("---",_bp_desc[name])
            end
            end
             
            local function bp_list(name)
            if name then
            bp_list_name(name)
            else
            for k,v in pairs(_bp_list) do
            bp_list_name(k)
            end
            end
            end
             
            local _bp_unnamed={}
            local _bp_unnamed_desc={}
            local _bp_unnamed_index={}
            local _bp_index=1
            do
            local weak={__mode="kv"}
            setmetatable(_bp_unnamed,weak)
            setmetatable(_bp_unnamed_desc,{__mode="k"})
            setmetatable(_bp_unnamed_index,weak)
            end
             
            local function bp_add_index()
            local info=debug.getinfo(3,"Slf")
            local func=info.func
            if _bp_unnamed[info.func]==nil then
            local desc=info.source.."("..info.currentline..")"
            _bp_unnamed[func]=true
            _bp_unnamed_desc[func]=desc
            _bp_unnamed_index[func]=_bp_index
            _bp_unnamed_index[_bp_index]=func
            _bp_index=_bp_index+1
            end
            return _bp_unnamed[func],_bp_unnamed_index[func]
            end
             
            local _bp_named={}
            local _bp_named_desc={}
             
            local function bp_add_name(name)
            local info=debug.getinfo(3,"Sl")
            local desc=info.source.."("..info.currentline..")"
            if _bp_named[name]==nil then
            _bp_named[name]=false
            end
             
            local tbl=_bp_named_desc[name]
            if tbl then
            tbl[desc] = true
            else
            _bp_named_desc[name]={ [desc] = true }
            end
             
            return _bp_named[name],name
            end
             
            local function bp_show(n)
            if type(n)=="number" then
            local func=_bp_unnamed_index[n]
            if func==nil then
            error "invalid break point id"
            end
            print("break point:",n,
            _bp_unnamed[func] and "on" or "off",
            _bp_unnamed_desc[func]
            )
            else
            print("break point:",n,_bp_named[n] and "on" or "off")
            if _bp_named_desc[n] then
            for k,v in pairs(_bp_named_desc[n]) do
            print("",k)
            end
            else
            print("tundefined")
            end
            end
            end
             
            local function bp_show_all()
            for k,_ in pairs(_bp_unnamed) do
            bp_show(_bp_unnamed_index[k])
            end
            for k,_ in pairs(_bp_named) do
            bp_show(k)
            end
            end
             
            function bp(n)
            local trigger,name
            if n==nil then
            trigger,name=bp_add_index()
            else
            trigger,name=bp_add_name(n)
            end
             
            if trigger then
            bp_show(name)
            dbg(1)
            else
            _bp_list[name]=false
            end
            end
             
            function trigger(n,on)
            on = on~=false
            if type(n)=="number" then
            local func=_bp_unnamed_index[n]
            if func==nil then
            error "invalid break point id"
            end
            _bp_unnamed[func]=on
            else
            _bp_named[n]=on
            end
            end
             
            function list(v)
            if v then
            bp_show(v)
            else
            bp_show_all()
            end
            end
             
            function error_handle(msg)
            print(msg)
            dbg(1)
            end


            可以這樣測試一下:

            require "bp"
             
            function foo(arg)
            bp.bp()    -- 設置一個匿名斷點
            return arg+1
            end
             
            =foo(0)    -- 輸出 foo(0) 
             


            運行后會進入調試控制臺:
            可以發現斷點被編了號(1 號)并被觸發,局部變量放在 _L 這張表里可以直接操作,upvalue 放在了 _U 表中 。

            break point:    1       on      =stdin(2)
            _L=     {arg=0,}
            _U=     {}


            我們可以改一下 arg 的值,如 _L.arg=1 然后 cont 退出控制臺。可以發現 foo 函數返回了 2 。
            這種匿名斷點添加方便,而且斷點跟隨邏輯而不是和代碼行做映射。也就是說,同一個 function 的不同實例(不同的 closure )可以有不同 id 的斷點,單獨控制。

            我們也可以使用具名斷點,方法是 bp.bp "bpname"
            具名斷點缺省是 disable 狀態的。如果需要激活可以用 bp.trigger "bpname" 。
            給斷點起名字的好處是,可以給一組斷點起同一個名字,這樣可以批量開關。

            bp.trigger(name,true/false) 用于開關斷點,name 可以是字符串也可以是 id 。

            列出所有斷點可以用 bp.list()
            也可以用 bp.list(name) 來列出一個斷點的狀態,name 可以是字符串也可以是 id 。

            還有一種方式,就是把調試控制臺用在錯誤處理函數中,這樣函數一出錯就自動切入控制臺。
            方法是 xpcall(some_function,bp.error_handle)

            下一步打算做單步執行 :D
            posted on 2007-05-03 07:14 七星重劍 閱讀(2676) 評論(0)  編輯 收藏 引用 所屬分類: PL--c/c++
            久久免费视频1| 久久九色综合九色99伊人| 97久久婷婷五月综合色d啪蜜芽| 久久无码专区国产精品发布| 久久综合给合久久狠狠狠97色| 亚洲欧美精品伊人久久| 久久91精品国产91| 国产成人久久精品区一区二区| 久久久久成人精品无码 | 日日躁夜夜躁狠狠久久AV| AV无码久久久久不卡网站下载 | 久久香综合精品久久伊人| 色综合久久久久无码专区| 狠狠人妻久久久久久综合| 伊人久久大香线焦AV综合影院| 久久精品国产色蜜蜜麻豆| 精品久久久无码人妻中文字幕豆芽 | 人妻久久久一区二区三区| 国产亚洲成人久久| 久久国产色AV免费观看| 久久这里的只有是精品23| 亚洲狠狠综合久久| av国内精品久久久久影院| 中文字幕久久精品无码| 四虎久久影院| 久久亚洲欧洲国产综合| 亚洲国产成人久久综合一 | 久久九九全国免费| 国产亚洲精品美女久久久| 97精品伊人久久久大香线蕉 | 97久久精品无码一区二区天美| 99久久综合国产精品免费| 伊人久久大香线蕉精品不卡| 久久亚洲天堂| 久久夜色精品国产亚洲| 国产精品中文久久久久久久| 色狠狠久久综合网| 久久婷婷五月综合97色直播| 中文成人无码精品久久久不卡| 欧美成人免费观看久久| 亚洲狠狠婷婷综合久久蜜芽|