• <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>

            loop_in_codes

            低調(diào)做技術(shù)__歡迎移步我的獨(dú)立博客 codemaro.com 微博 kevinlynx

            tolua的tolua_toxxx系列API設(shè)計(jì)

            原文鏈接:http://codemacro.com/2012/05/10/tolua-api/

            我們使用tolua++手工綁定c/c++接口到lua中,在綁定的接口實(shí)現(xiàn)里,就需要取出傳入的參數(shù)。tolua++中提供了一系列tolua_toxxx函數(shù),例如:

            lua_Number tolua_tonumber(lua_State *L, int narg, lua_Number def)
            const char *tolua_tostring(lua_State *L, int narg, const char *def)
            

            這些函數(shù)都有一個(gè)def參數(shù)。乍一看,這些函數(shù)使用起來(lái)很簡(jiǎn)單。傳入lua_State,傳入?yún)?shù)在棧中的位置,然后再傳一個(gè)失敗后返回的默認(rèn)值。

            我重點(diǎn)要說(shuō)的是這里這個(gè)失敗,按正常程序員的理解,針對(duì)lua而言,什么情況下算失敗呢?lua語(yǔ)言里函數(shù)參數(shù)支持不傳,此時(shí)實(shí)參為nil,將nil轉(zhuǎn)換為一個(gè)c類型必然失敗;參數(shù)類型不正確算不算失敗?你傳一個(gè)user data,c里按數(shù)字來(lái)取,這也算失敗。

            這么簡(jiǎn)單的API還需要多糾結(jié)什么呢?然后我們浩浩蕩蕩地寫(xiě)了上百個(gè)接口,什么tolua_tostring/tolua_tonumber的使用少說(shuō)也有500了吧?

            然后有一天,服務(wù)器宕機(jī)了,空指針:

            /* 失敗返回"",還能省空指針的判斷 */
            const char *name = tolua_tostring(L, 1, "");
            if (name[0] == '\0') { /* 空串總得判斷吧 */
             ...
            }
            

            跟蹤后發(fā)現(xiàn),腳本里傳入的是nil,這里的name取出來(lái)是NULL,而不是”“(的地址)。然后吐槽了一下這個(gè)API,辛苦地修改了所有類似代碼,增加對(duì)空指針的判斷。我沒(méi)有多想。

            故事繼續(xù),有一天服務(wù)器雖然沒(méi)宕機(jī),但功能不正常了:

            float angle = (float) tolua_tonumber(L, 1, 2 * PI);
            ...
            

            這個(gè)意思是,這個(gè)函數(shù)的參數(shù)1默認(rèn)是2*PI,什么是默認(rèn)?lua里某函數(shù)參數(shù)不傳,或傳nil就是使用默認(rèn)。因?yàn)椴粋鞯脑挘@個(gè)實(shí)參本身就是nil。但,tolua_tonumber的行為不是這樣的,它的實(shí)現(xiàn)真是偷懶:

            TOLUA_API lua_Number tolua_tonumber (lua_State* L, int narg, lua_Number def)
            {
             return lua_gettop(L)<abs(narg) ? def : lua_tonumber(L,narg);
            }
            TOLUA_API const char* tolua_tostring (lua_State* L, int narg, const char* def)
            {
             return lua_gettop(L)<abs(narg) ? def : lua_tostring(L,narg);
            }
            

            意思是,只有當(dāng)你不傳的時(shí)候,它才返回默認(rèn)值,否則就交給lua的API來(lái)管,而lua這些API是不支持應(yīng)用層的默認(rèn)參數(shù)的,對(duì)于lua_tonumber錯(cuò)誤時(shí)就返回0,lua_tostring錯(cuò)誤時(shí)就返回NULL。

            這種其行為和其帶來(lái)的common sense不一致的API設(shè)計(jì),實(shí)在讓人蛋疼。什么是common sense呢?就像一個(gè)UI庫(kù)里的按鈕,我們都知道有click事件,hover事件,UI庫(kù)的文檔甚至都不需要解釋什么是click什么是hover,因?yàn)榇蠹铱吹竭@個(gè)東西,就有了共識(shí),無(wú)需廢話,這就是common sense。就像tolua的這些API,非常普通,大家一看都期待在意外情況下你能返回def值。但它竟然不是。實(shí)在不行,你可以模仿lua的check系列函數(shù)的實(shí)現(xiàn)嘛:

            LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
             lua_Number d = lua_tonumber(L, narg);
             if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
             tag_error(L, narg, LUA_TNUMBER);
             return d;
            }
            

            即,根本不用去檢查棧問(wèn)題,直接在lua_tonumber之后再做包裝檢查。何況,lua需要你去檢查棧嗎?當(dāng)你訪問(wèn)了棧外的元素時(shí),lua會(huì)自動(dòng)返回一個(gè)全局常量luaO_nilobject:

            static TValue *index2adr(lua_State *L, int idx) {
             ...
             if (o >= L->top) return cast(TValue*, luaO_nilobject);
            }
            

            另,程序悲劇也來(lái)源于臆想。

            posted on 2012-05-10 15:38 Kevin Lynx 閱讀(5277) 評(píng)論(0)  編輯 收藏 引用 所屬分類: c/c++lua

            精品国产乱码久久久久软件| 国产午夜免费高清久久影院 | 国产精品久久久久久吹潮| 99久久精品国产综合一区| 久久精品国产亚洲AV香蕉| 三级三级久久三级久久 | 久久香蕉国产线看观看乱码| a级成人毛片久久| 东方aⅴ免费观看久久av| 狠狠精品干练久久久无码中文字幕 | 99久久久久| 思思久久好好热精品国产| 伊人久久大香线蕉综合网站| 久久99精品久久久久久齐齐| 2022年国产精品久久久久| 久久精品国产亚洲AV蜜臀色欲 | 国产免费福利体检区久久| 久久婷婷五月综合97色 | 93精91精品国产综合久久香蕉| 99久久精品国产一区二区| 亚洲国产成人精品女人久久久 | 国产毛片欧美毛片久久久| 久久久久无码专区亚洲av| 国产情侣久久久久aⅴ免费| 国产精品18久久久久久vr| 久久精品麻豆日日躁夜夜躁| 午夜精品久久久久久久久| 久久久精品久久久久久 | 综合久久国产九一剧情麻豆| 久久精品国产99国产精品澳门| 久久九九久精品国产| 一本大道加勒比久久综合| 97久久天天综合色天天综合色hd| 亚洲AV无码久久精品成人| 久久人人爽人人爽人人片av高请| 91精品国产91久久久久久青草| 国产精品成人精品久久久| 伊人久久大香线焦AV综合影院| 久久久久久夜精品精品免费啦| 久久精品国产亚洲av麻豆色欲| 国产精品久久久久久福利69堂|