日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

lua userdata

發布時間:2025/5/22 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 lua userdata 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

????userdata類型是為了方便C/C++對Lua進行擴展,因為在用C/C++擴展時,我們經常會自定義數據類型,如:

typedef?struct?epoll_fd {?int?epfd;size_t?size;struct?epoll_event?*events; }epoll_fd_t;

????我們要想在Lua中使用此類型的對象,就必須使用userdata類型來表示。

? ? 對于Lua而言,所有C/C++自定義的類型都是userdata類型,無法區分,那么在實際的應用中userdata都會設置metatable,通過metattable來區分不同的userdata類型。

????metatable其實也是table,metatable中的方法則稱為“元方法”。對于userdata的metatable,當我們訪問userdata對象的成員時,lua會調用metatable中的__index()元方法,如果__index也是table,則從__index table中查找對應的成員。當lua要回收userdata對象時,會調用metatable中的__gc()元方法。還有很多元方法,可以查看文檔說明。

  • userdata常用的Lua C API

  • ????1) 創建userdata for lua

    void?*lua_newuserdata?(lua_State?*L,?size_t?size);This?function?allocates?a?new?block?of?memory?with?the?given?size,?pushes?onto?the?stack?a?new?full?userdata?with?the?block?address,?and?returns?this?address.Userdata?represent?C?values?in?Lua.?A?full?userdata?represents?a?block?of?memory.?It?is?an?object?(like?a?table):?you?must?create?it,?it?can?have?its?own?metatable,?and?you?can?detect?when?it?is?being?collected.?A?full?userdata?is?only?equal?to?itself?(under?raw?equality).When?Lua?collects?a?full?userdata?with?a?gc?metamethod,?Lua?calls?the?metamethod?and?marks?the?userdata?as?finalized.?When?this?userdata?is?collected?again?then?Lua?frees?its?corresponding?memory.

    ????從上面的說明,可以知道返回的就是內存地址,我們只需要強制轉換為我們的自定義類型即可使用。

    ? ?2) 創建metatable: ?

    int?luaL_newmetatable?(lua_State?*L,?const?char?*tname);If?the?registry?already?has?the?key?tname,?returns?0.?Otherwise,?creates?a?new?table?to?be?used?as?a?metatable?for?userdata,?adds?it?to?the?registry?with?key?tname,?and?returns?1. In?both?cases?pushes?onto?the?stack?the?final?value?associated?with?tname?in?the?registry.

    ? ? 新創建的metatable會存放于registry中,其實registry也是一個table.

    ????要從registry中獲取指定的metatable:

    void?luaL_getmetatable?(lua_State?*L,?const?char?*tname); Pushes?onto?the?stack?the?metatable?associated?with?name?tname?in?the?registry

    ????3) 設置metatable:?

    int?lua_setmetatable?(lua_State?*L,?int?index);Pops?a?table?from?the?stack?and?sets?it?as?the?new?metatable?for?the?value?at?the?given?acceptable?index.

    ????metatable其實也是table,所以所有對table操作的方法,均可用在metatable上,包括為metatable設置元方法等。

    ????4) 從棧中獲取userdata:

    void?*luaL_checkudata?(lua_State?*L,?int?narg,?const?char?*tname); Checks?whether?the?function?argument?narg?is?a?userdata?of?the?type?tname. It?will?throws?an?error?when?the?given?value?is?not?a?userdata?of?the?expected?type.

    2. 對lua-epoll模塊進行簡單的修改,

    ????在上一篇博文的基礎上,對其源碼進行修改如下:

    //?lua_f_epoll.c #include?"lua_f_base.h" #include?"epoll_fd.h"#define?EPOLL_METATABLE_NAME?"Epoll.MT"#define?check_epoll_fd(L)?luaL_checkudata(L,?1,?EPOLL_METATABLE_NAME);static?int?lua_f_epoll_close(lua_State?*L) {epoll_fd_t?*self?=?(epoll_fd_t?*)check_epoll_fd(L);epoll_fd_release(self);return?0; }static?int?lua_f_epoll_register(lua_State?*L) {if(lua_gettop(L)?<?3){RETERR("invalid?args");}epoll_fd_t?*self?=?(epoll_fd_t?*)check_epoll_fd(L);int?fd?=?luaL_checkint(L,?2);int?event?=?luaL_checkint(L,?3);if(fd?<?0){RETERR("invalid?fd");}if(epoll_fd_add(self,?fd,?event)?<?0){RETERR("epoll_fd_add?fail");}lua_pushboolean(L,?1);return?1; }static?int?lua_f_epoll_modify(lua_State?*L) {if(lua_gettop(L)?<?3){RETERR("invalid?args");}epoll_fd_t?*self?=?(epoll_fd_t?*)check_epoll_fd(L);int?fd?=?luaL_checkint(L,?2);int?event?=?luaL_checkint(L,?3);if(fd?<?0){RETERR("invalid?fd");}if(epoll_fd_mod(self,?fd,?event)?<?0){RETERR("epoll_fd_mod?fail");}lua_pushboolean(L,?1);return?1; }static?int?lua_f_epoll_unregister(lua_State?*L) {if(lua_gettop(L)?<?2){RETERR("invalid?args");}epoll_fd_t?*self?=?(epoll_fd_t?*)check_epoll_fd(L);int?fd?=?luaL_checkint(L,?2);if(fd?<?0){RETERR("invalid?fd");}if(epoll_fd_del(self,?fd)?<?0){RETERR("epoll_fd_del?fail");}lua_pushboolean(L,?1);return?1; }static?int?lua_f_epoll_wait(lua_State?*L) {epoll_fd_t?*self?=?(epoll_fd_t?*)check_epoll_fd(L);int?timeout?=?luaL_optint(L,?2,?-1);int?n?=?epoll_fd_wait(self,?timeout);if(n?<?0){RETERR("epoll_fd_wait?fail");}lua_newtable(L);int?i;for(i?=?0;?i?<?n;?++i){lua_pushinteger(L,?self->events[i].events);lua_rawseti(L,?-2,?self->events[i].data.fd);}return?1; }static?const?struct?luaL_Reg?lua_f_epoll_func[]?=?{{"close",?lua_f_epoll_close},{"register",?lua_f_epoll_register},{"modify",?lua_f_epoll_modify},{"unregister",?lua_f_epoll_unregister},{"wait",?lua_f_epoll_wait},{NULL,?NULL}, };static?int?lua_f_epoll_create(lua_State?*L) {size_t?size?=?luaL_optint(L,?1,?EPOLL_DEFAULT_SIZE);int?epfd?=?epoll_create(size);if(epfd?<?0){RETERR("epoll_create?fail");}epoll_fd_t?*self?=?(epoll_fd_t*)lua_newuserdata(L,?sizeof(epoll_fd_t));if(epoll_fd_init(self,?epfd,?size)?<?0){RETERR("epoll_fd_init?fail");}luaL_getmetatable(L,?EPOLL_METATABLE_NAME);lua_setmetatable(L,?-2);return?1; }static?int?lua_f_epoll_version(lua_State?*L) {const?char?*ver?=?"Lua-Epoll?V0.0.1?by?wenhao.ye";lua_pushstring(L,?ver);return?1; }static?const?struct?luaL_Reg?lua_f_epoll_mod[]?=?{{"create",?lua_f_epoll_create},{"version",?lua_f_epoll_version},{NULL,?NULL}, };/*mt?=?{__gc?=?lua_f_epoll_close,__index?=?{close?=?lua_f_epoll_close,register?=?lua_f_epoll_register,modify?=?lua_f_epoll_modify,unregister?=?lua_f_epoll_unregister,wait?=?lua_f_epoll_wait,},};epoll?=?{create?=?lua_f_epoll_create,version?=?lua_f_epoll_version,EPOLLIN?=?EPOLLIN,EPOLLPRI?=?EPOLLPRI,EPOLLOUT?=?EPOLLOUT,EPOLLRDNORM?=?EPOLLRDNORM,EPOLLRDBAND?=?EPOLLRDBAND,EPOLLWRNORM?=?EPOLLWRNORM,EPOLLWRBAND?=?EPOLLWRBAND,EPOLLMSG?=?EPOLLMSG,EPOLLERR?=?EPOLLERR,EPOLLHUP?=?EPOLLHUP,EPOLLRDHUP?=?EPOLLRDHUP,EPOLLONESHOT?=?EPOLLONESHOT,EPOLLET?=?EPOLLET,};*/ int?luaopen_epoll(lua_State?*L) {luaL_newmetatable(L,?EPOLL_METATABLE_NAME);LTABLE_ADD_CFUNC(L,?-1,?"__gc",?lua_f_epoll_close);lua_newtable(L);luaL_register(L,?NULL,?lua_f_epoll_func);lua_setfield(L,?-2,?"__index");lua_pop(L,?1);luaL_register(L,?"epoll",?lua_f_epoll_mod);#define?SETCONST(EVENT)?\lua_pushnumber(L,?EVENT);?\lua_setfield(L,?-2,?#EVENT)//?push?const?values?into?epoll?table.SETCONST(EPOLLIN);SETCONST(EPOLLPRI);SETCONST(EPOLLOUT);SETCONST(EPOLLRDNORM);SETCONST(EPOLLRDBAND);SETCONST(EPOLLWRNORM);SETCONST(EPOLLWRBAND);SETCONST(EPOLLMSG);SETCONST(EPOLLERR);SETCONST(EPOLLHUP);SETCONST(EPOLLRDHUP);SETCONST(EPOLLONESHOT);SETCONST(EPOLLET);return?1; }

    ????上述代碼用到的關于epoll的操作,我封裝在epoll_fd,h文件中:

    //?epoll_fd.h #ifndef?_EPOLL_FD_H_ #define?_EPOLL_FD_H_#ifdef?__cplusplus extern?"C"{ #endif#include?"def.h" #include?"io_tools.h"?//?for?fd_set_nonblock() #include?<fcntl.h> #include?<sys/epoll.h> #include?<string.h> #include?<errno.h> #include?<unistd.h>#define?EPOLL_DEFAULT_SIZE?1024?typedef?struct?epoll_fd {?int?epfd;size_t?size;struct?epoll_event?*events; }epoll_fd_t;inline?int?epoll_fd_init(epoll_fd_t?*self,?int?epfd,?size_t?size) {self->epfd?=?epfd;self->size?=?size;self->events?=?(struct?epoll_event?*)MALLOC(sizeof(struct?epoll_event)?*?size);if(self->events?==?NULL)return?-1;return?0; }inline?int?epoll_fd_release(epoll_fd_t?*self) {safe_close(self->epfd);safe_free(self->events);return?0; }inline?int?epoll_fd_add(epoll_fd_t?*self,?int?fd,?int?event) {if(fd_set_nonblock(fd)?<?0){ERR("fd_set_nonblock?fail");return?-1;}struct?epoll_event?ev;ev.data.fd?=?fd;ev.events?=?event;if(epoll_ctl(self->epfd,?EPOLL_CTL_ADD,?fd,?&ev)?<?0){ERR("epoll_ctl_add?fail");return?-1;}return?0; }inline?int?epoll_fd_mod(epoll_fd_t?*self,?int?fd,?int?event) {struct?epoll_event?ev;ev.data.fd?=?fd;ev.events?=?event;if(epoll_ctl(self->epfd,?EPOLL_CTL_MOD,?fd,?&ev)?<?0){ERR("epoll_ctl_mod?fail");return?-1;}return?0; }inline?int?epoll_fd_del(epoll_fd_t?*self,?int?fd) {if(epoll_ctl(self->epfd,?EPOLL_CTL_DEL,?fd,?NULL)?<?0){ERR("epoll_ctl_del?fail");return?-1;}return?0; }inline?int?epoll_fd_wait(epoll_fd_t?*self,?int?timeout) {return?epoll_wait(self->epfd,?self->events,?self->size,?timeout); }#ifdef?__cplusplus } #endif#endif

    ????代碼很簡單,也就不過多說明了,上述代碼如果直接拿來用會編譯不過,因為這些代碼是在我的整個工程中,會用到其他的一些宏或者函數,工程代碼地址:?https://git.oschina.net/yewenhao/libutils

    ????如果不想拿整個工程,只需要把DBG(), ERR(), 換成簡單的打印函數printf即可,其他的函數如下:

    #define?RETERR(_e)?\DBG("err:?%s",?(_e));\lua_pushnil(L);?\lua_pushfstring(L,?"%s:?%s",?strerror(errno),?(_e));?\return?2#define?LTABLE_ADD_CFUNC(L,?index,?name,?func)?\lua_pushcfunction(L,?(func));\lua_setfield(L,?(index)-1,?(name));int?fd_set_nonblock(int?fd) {int?val;if((val?=?fcntl(fd,?F_GETFL,?0))?==?-1){perror("fcntl?get");return?-1;}val?|=?O_NONBLOCK;if(fcntl(fd,?F_SETFL,?val)?==?-1){perror("fcntl?set");return?-1;}return?0; }

    ????修改后的epoll模塊的使用參考:

    local?epoll?=?require('epoll') print(epoll.version())local?epfd?=?epoll.create() epfd:register(fd,?epoll.EPOLLIN)while?true?dolocal?events,?err=?epfd:wait()if?not?err?then--?handle?eventsend--?... endepfd:unregister(fd) epfd:close() print('done')


    轉載于:https://my.oschina.net/kaedehao/blog/513222

    總結

    以上是生活随笔為你收集整理的lua userdata的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 男女av在线| 天天摸天天做天天爽 | 貂蝉被到爽流白浆在线观看 | 国产一区二区内射 | 日韩av在线网址 | 日本成人不卡 | 综合网伊人| 性折磨bdsm欧美激情另类 | 国产精品二区一区二区aⅴ 一卡二卡三卡在线观看 | 91美女高潮出水 | 日本高清黄色电影 | 一区二区三区四区五区av | 成年人视屏 | 日日艹| 天天曰夜夜操 | 午夜啪啪网 | 亚洲精品.www | 亚洲草逼视频 | 欧美精品一区二区三区久久久 | 奇米视频在线观看 | www欧美视频 | 婷婷99| 中文字幕精品久久久久人妻红杏1 | 久久永久视频 | 国产日韩一区二区 | 欧美怡红院视频 | 国内av网站 | 伊人成人动漫 | 午夜精品久久久久久久久久久久久蜜桃 | 免费在线观看的黄色网址 | 好看的中文字幕av | 欧美一区二区视频在线 | 日韩三级小视频 | 黄色小说在线看 | 亚洲一区二区视频网站 | 精品一区二区三区中文字幕 | 欧美成a| 亚洲在线影院 | 中文字幕一区不卡 | 永久免费国产 | 日本视频免费看 | 麻豆视频一区二区 | 欧美亚洲 | 久久韩国| 久久免费国产 | 色视频网址| 亚洲砖区免费 | 大片av| 亚洲综合视频在线观看 | 国模一区二区 | 男人的网站在线观看 | 草久久久| 手机在线视频一区 | 亚洲视频在线播放免费 | 97色吧| 亚洲成年人av | 欧美色影院| 欧美性猛交乱大交 | 91九色国产 | 69网址| 夜夜精品一区二区无码 | 催眠美妇肉奴系统 | 封神榜二在线高清免费观看 | 伊人影院久久 | videos亚洲| 黄色激情毛片 | 色吧av | 国产大片一区 | 欧洲自拍偷拍 | 夜夜狠 | 久久久久久久久影院 | eeuss一区二区三区 | 婷婷精品在线 | 天天插视频 | 国产精品一区二区三区高潮 | 亚洲av电影一区二区 | 老色驴综合网 | 亚洲高潮无码久久 | 国产一区免费在线 | 亚洲另类欧美日韩 | 狠狠干,狠狠操 | 亚洲成人av在线 | 欧美网站在线 | 久久婷婷国产 | 久久九九国产视频 | 淫语对白 | 国产网站在线免费观看 | 久久一区av | 四级毛片 | 亚洲卡一| 欧美乱妇一区二区三区 | 欧美视频在线观看免费 | 强迫凌虐淫辱の牝奴在线观看 | 91视频在线观看网站 | 二级黄色片 | 天天射天天干天天 | 久久久久久黄色片 | 手机看片福利在线 | 黑人满足娇妻6699xx |