lua 用string來進行二進制buffer操作

buffer 作為一個連續(xù)的內存區(qū)域概念,在lua中就是string了。一是內容是內存連續(xù)的,二是可以存儲任何東西。在作為二進制buffer概念去使用 string 的時候,一些地方就需要注意了。

首先,buffer 和字符串的區(qū)別在于,字符串是可見字符的,c風格的字符串后面會添加一個 \0 來作為結尾,所以在 c 向 lua傳遞一個 buffer 的時候,請使用 lua_pushlstring 而非 lua_pushstring, 函數(shù)聲明見下:

LUA_API void  (lua_pushlstring) (lua_State *L, const char *s, size_t l);

LUA_API void  (lua_pushstring) (lua_State *L, const char *s);

而在 lua 向 c 傳遞buffer的時候,在c端接收的時候,請使用 lua_tolstring, 而非 lua_tostring 或 tolua_tostring(tolua中接口), 函數(shù)聲明如下:

LUA_API const char     *(lua_tolstring) (lua_State *L, int idx, size_t *len);

#define lua_tostring(L,i)   lua_tolstring(L, (i), NULL)
TOLUA_API const char* tolua_tostring (lua_State* L, int narg, const char* def);

其次,在對buffer進行操作,更改內部內容的時候,因為 lua 是不支持直接操作內存的,所以可以傳遞給c端,有c端去更改內部內容,這樣lua端的字符串內容就被改變了。

但是看過lua源碼之后,發(fā)現(xiàn)字符串有緩存。因為在lua中字符串是不會被修改的,即沒有對應的修改字符串的API。字符串的不可變性,導致lua內部基于此形成一個緩存優(yōu)化,即在構造一個字符串時候,會根據(jù)對應的哈希值尋找內部緩存,如果沒有則新建一個并扔到緩存中去。而上面用c直接修改字符串內存的問題在于,字符串的內存內容改變了,而其哈希值卻沒變,從而導致了問題,例如:

local s1 = string.rep('\0', 10)
local s2 = string.rep('\0', 10)

上述代碼中,s1 和 s2 對應的哈希值是一樣的,因此在創(chuàng)建 s2 的時候,發(fā)現(xiàn)緩存中有個一樣的,就直接返回 s1了。假如我們在 s1 新建之后,用c端硬性的修改內容區(qū)域,那么接下來獲取的s2實際上并不是全0的內容了。

誠然,可以在 c 端修改內容的時候,連帶更改對應的哈希值,但是這樣對于 buffer 頻繁修改的物件來說,未免太多余了,而且損耗性能。只好作罷。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容