從lua調(diào)用C++函數(shù)和對(duì)象利用LuaPlus可以方便的從C++中調(diào)用lua腳本,翻過(guò)也一樣。通過(guò)注冊(cè)函數(shù)或類對(duì)象,lua便可以訪問(wèn)C++。一、C風(fēng)格函數(shù)注冊(cè)Lua提供了C風(fēng)格的回調(diào)函數(shù)注冊(cè),該函數(shù)原型如下:intCallback(LuaState*state);無(wú)論是全局函數(shù)、類非虛函數(shù)、類虛函數(shù),只要符合上面的原型,都可以向Lua注冊(cè)。我們以全局函數(shù)為例,下面是我們提供的一個(gè)回調(diào)函數(shù)CStyleAddF" />

欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

LuaPlus學(xué)習(xí)(三)

系統(tǒng) 1697 0

<--!版權(quán)所有foruok,轉(zhuǎn)載注明出處!-->

從lua調(diào)用C++函數(shù)和對(duì)象

利用LuaPlus可以方便的從C++中調(diào)用lua腳本,翻過(guò)也一樣。通過(guò)注冊(cè)函數(shù)或類對(duì)象,lua便可以訪問(wèn)C++。

一、C風(fēng)格函數(shù)注冊(cè)

Lua提供了C風(fēng)格的回調(diào)函數(shù)注冊(cè),該函數(shù)原型如下:
int Callback(LuaState * state);
無(wú)論是全局函數(shù)、類非虛函數(shù)、類虛函數(shù),只要符合上面的原型,都可以向Lua注冊(cè)。我們以全局函數(shù)為例,下面是我們提供的一個(gè)回調(diào)函數(shù)CStyleAddFunc:
int CStyleAddFunc(LuaState * state) ... { LuaStackargs(state); if (args[ 1 ].IsNumber() && args[ 2 ].IsNumber()) ... { state -> PushNumber(args[ 1 ].GetInteger() + args[ 2 ].GetInteger()); return 1 ; } return 0 ; }
在回調(diào)函數(shù)中,我們通過(guò)棧來(lái)訪問(wèn)參數(shù),棧中可以存貯多個(gè)參數(shù), LuaStackargs(state);語(yǔ)句獲取棧對(duì)象供后續(xù)訪問(wèn)。 接下來(lái)判斷參數(shù)是否是數(shù)字,如果兩個(gè)參數(shù)都是數(shù)字,那么進(jìn)行加操作,將結(jié)果壓入棧中,將壓入棧中的數(shù)據(jù)的個(gè)數(shù)返回。注意,返回值代表壓入棧中的元素的個(gè)數(shù),而不是某種計(jì)算結(jié)果或其它意義的返回值。通過(guò)改變返回值來(lái)查看程序的輸出,這樣可以對(duì)返回值的含義有個(gè)感性的了解。 要注冊(cè)回到只需調(diào)用Register函數(shù)即可,這在第一篇中已經(jīng)用到。下面是測(cè)試函數(shù):
void TestCFunctionCallBack() ... { LuaStateOwnerstate; // "print"needthis state -> OpenLibs(); // registermyfunctionCStyleAddFunctoAdd state -> GetGlobals().Register( " Add " ,CStyleAddFunc); // callmyfunctionandprinttheresult state -> DoString( " ret=Add(1,5);print(ret) " ); }
state -> DoString( " ret=Add(1,5);print(ret) " );該句用來(lái)從執(zhí)行Lua命令串。我們先調(diào)用Add并將結(jié)果賦值給ret變量,然后打印ret的值。 main函數(shù)如下:
int _tmain( int argc,_TCHAR * argv[]) ... { TestCFunctionCallBack(); return 0 ; }
編譯運(yùn)行,一切OK。 我們也可以從Lua腳本文件中調(diào)用注冊(cè)的回調(diào)函數(shù), 第一篇 中有演示。 要注冊(cè)類的成員函數(shù),則需要調(diào)用Register的另一種形式
Register( const char* funcName, const Callee& callee, int (Callee::*func)(LuaState*), int nupvalues = 0 ); ,提供類實(shí)例指針和函數(shù)即可完成注冊(cè)。下面是示例代碼:
class CTestCallBack ... { public : int NonVirtualFunc(LuaState * state) ... { LuaStackargs(state); printf( " Innon-virtualmemberfunction.nomsg. " ); return 0 ; } int virtual VirtualFunc(LuaState * state) ... { LuaStackargs(state); printf( " Invirtualmemberfunction.msg=%s " ,args[ 1 ].GetString()); return 0 ; } } ; void TestClassMemberFuncReg() ... { LuaStateOwnerstate; // "print"needthis state -> OpenLibs(); LuaObjectglobalobj = state -> GetGlobals(); CTestCallBacktcb; globalobj.Register( " MemberFunc " ,tcb, & CTestCallBack::NonVirtualFunc); state -> DoString( " MemberFunc() " ); globalobj.Register( " VirMemberFunc " ,tcb, & CTestCallBack::VirtualFunc); state -> DoString( " VirMemberFunc('Hi,myboy') " ); }
修改一下main函數(shù),將
TestClassMemberFuncReg()加進(jìn)去就可以看效果了。

二、任意形式C++函數(shù)注冊(cè)

LuaPlus提供了 RegisterDirect() 來(lái)直接注冊(cè)任意形式的函數(shù),這樣更為直接,不必受限于上述的函數(shù)原型,使用起來(lái)很方便。同樣此函數(shù)像Register一樣,可以注冊(cè)類的成員函數(shù)(也需要顯示指定this指針)。下面是代碼:
float Add( float num1, float num2) ... { return num1 + num2; } class CForRegDirect ... { public : int Sum( int a, int b, int c) ... { return a + b + c; } // constisnecessary virtual void SeeMessage( const char * msg) ... { printf( " msg=%s " ,msg); } } ; void TestRegisterDirect() ... { LuaStateOwnerstate; state -> OpenLibs(); LuaObjectgobj = state -> GetGlobals(); // registerglobalfunctiondirectly gobj.RegisterDirect( " Add " ,Add); state -> DoString( " print(Add(1.5,2.3)) " ); // registermemberfunction CForRegDirectforobj; gobj.RegisterDirect( " MemberSum " ,forobj,CForRegDirect::Sum); state -> DoString( " print(MemberSum(1,2,7)) " ); gobj.RegisterDirect( " VirCMsg " ,forobj,CForRegDirect::SeeMessage); state -> DoString( " print(VirCMsg('haha,Doyouseeme?')) " ); }

三、注冊(cè)函子對(duì)象

上面兩節(jié)的方式可以實(shí)現(xiàn)簡(jiǎn)單的回調(diào)注冊(cè),注冊(cè)類的成員函數(shù)時(shí)需要顯式提供類指針,不適合用于映射C++中的類結(jié)構(gòu)。 RegisterObjectFunctor()和元表(metatable)結(jié)合,提供了一種新的方法 。我們不需要在注冊(cè)函數(shù)時(shí)顯式的提供this指針,作為替代,this指針可以從調(diào)用者的userdata或__object成員獲取。 元表(metatable)是一個(gè)普通的表對(duì)象,它定義了一些可以被重寫(xiě)的操作,如add,sub,mul,index,call等,這些操作以"__"開(kāi)頭,如__add,__index等。加入你重寫(xiě)了__add,那么在執(zhí)行add操作時(shí)就會(huì)調(diào)用你自己定義的__add操作。這種特性可以用來(lái)模擬C++中的類對(duì)象,注冊(cè)函子對(duì)象正是利用了這種特性來(lái)實(shí)現(xiàn)的。 下面我們將一個(gè)C++類映射到Lua中。類代碼如下:
class CMultiObject ... { public : CMultiObject( int num):m_num(num) ... { } int Print(LuaState * state) ... { printf( " %d " ,m_num); return 0 ; } protected : int m_num; } ; void TestRegObjectDispatchFunctor() ... { LuaStateOwnerstate; state -> OpenLibs(); // createmetaTable LuaObjectmetaTableObj = state -> GetGlobals().CreateTable( " MultiObjectMetaTable " ); metaTableObj.SetObject( " __index " ,metaTableObj); // registerfunctorformultiobject metaTableObj.RegisterObjectFunctor( " Print " ,CMultiObject::Print); // getainstancesofCMultiObject CMultiObjectobj1( 10 ); // "clone"aobjectinlua,theluaobject(hereistable)hasobj1'sdata LuaObjectobj1Obj = state -> BoxPointer( & obj1); // setluaobject'smetatabletoMetaTableObj obj1Obj.SetMetaTable(metaTableObj); // putluaobjecttoGlobalscope,thusitcanbeaccessedlater. state -> GetGlobals().SetObject( " obj1 " ,obj1Obj); CMultiObjectobj2( 20 ); LuaObjectobj2Obj = state -> BoxPointer( & obj2); obj2Obj.SetMetaTable(metaTableObj); state -> GetGlobals().SetObject( " obj2 " ,obj2Obj); // nowcallPrintandPrint2 state -> DoString( " obj1:Print(); " ); state -> DoString( " obj2:Print(); " ); }
首先我們需要生成一個(gè)元表(metatable),將C++類的成員函數(shù)注冊(cè)到該元表中。然后依據(jù)CMultiObject的實(shí)例生成lua中與其對(duì)應(yīng)的對(duì)象(也是表),將該對(duì)象的metatable(也即該表的__object成員)設(shè)置為之前產(chǎn)生的元表。最后將新生成的lua對(duì)象放置到全局作用域中,這樣后面就可以直接引用這些對(duì)象。 我們可以做這樣的近似理解:每個(gè)實(shí)例的數(shù)據(jù)元素存放在與已對(duì)應(yīng)的lua table中,而類的成員函數(shù)則存放在metatable中(函子對(duì)象)。當(dāng)調(diào)用obj1obj:Print()時(shí),會(huì)先找到其metatable,然后在metatable中找Print()函數(shù)。 這樣便實(shí)現(xiàn)了類似C++中的類結(jié)構(gòu)。每個(gè)實(shí)例有自己的數(shù)據(jù),而所有實(shí)例共享一份方法列表。 另外一種方式是利用表的userdata來(lái)實(shí)現(xiàn),需要先創(chuàng)建一個(gè)lua表對(duì)象,然后將C++對(duì)象obj1設(shè)置為該表的userdata(也是設(shè)置其__object成員),再將該表對(duì)象的metatable設(shè)置為我們之前創(chuàng)建的元表。最后就可以用表明來(lái)調(diào)用Print函數(shù)。代碼如下:
LuaObjecttable1Obj = state -> GetGlobals().CreateTable( " table1 " ); table1Obj.SetLightUserData( " __object " , & obj1); table1Obj.SetMetaTable(metaTableObj); LuaObjecttable2Obj = state -> GetGlobals().CreateTable( " table2 " ); table2Obj.SetLightUserData( " __object " , & obj2); table2Obj.SetMetaTable(metaTableObj); state -> DoString( " table1:Print() " ); state -> DoString( " table2:Print() " );
注冊(cè)函子對(duì)象(RegisterObjectFunctor)這種方式的限制在于:要注冊(cè)的函數(shù)必須符合原型( int Callback(LuaState * state); )。為了打破這種限制,LuaPlus提供了另外一種方式。

四、直接注冊(cè)函子對(duì)象

直接注冊(cè)函子對(duì)象(RegisterObjectDirect)和 RegisterDirect類似,不考慮函數(shù)原型,可以直接向元表注冊(cè)任意形式的函數(shù) 。 為CMultiObject添加新的成員函數(shù):
void Print2( int num) ... { printf( " %d%d /n" ,m_num,num); }
調(diào)用RegisterObjectDirect方法:
metaTableObj.RegisterObjectDirect( " Print2 " ,(CMultiObject * ) 0 , & CMultiObject::Print2);
第二個(gè)參數(shù) (CMultiObject * ) 0有點(diǎn)奇怪,這是模板參數(shù)的需要。 最后:
state -> DoString( " obj1:Print2(5) " ); state -> DoString( " obj2:Print2(15) " ); state -> DoString( " table1:Print2(5) " ); state -> DoString( " table2:Print2(15) " );

五、注銷回調(diào)

注銷回調(diào)是件簡(jiǎn)單的事情,調(diào)用SetNil("yourCallBack")即可,如:
gobj.SetNil( " Add " ); metaTableObj.SetNil( " Print2 " );
好了,迄今為止最長(zhǎng)的一篇,看著像是LuaPlus文檔的翻譯(?),不過(guò)還是加入了一些自己的理解。文檔我看了下,琢磨了半天才明白。希望能快點(diǎn)將LuaPlus用起來(lái)。 資料: (1) Lua5.1參考手冊(cè) (2) Lua入門(mén)wiki (3)LuaPlus.html,源碼包中帶的。 <--!版權(quán)所有foruok,轉(zhuǎn)載注明出處!-->

LuaPlus學(xué)習(xí)(三)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 成人网免费视频 | 2018天天干夜夜操 | 日韩在线免费视频 | 日本a v在线播放 | 久久中文字幕网 | 日韩中文字幕网 | 91久久国产| 欧美性xxxxx极品老少 | japanesemature乱子在线 | 日韩欧美一区二区三区 | 久久久99国产精品免费 | 人人人人澡| 国产福利视频一区二区 | 国内精品小视频福利网址 | 亚洲成人福利在线观看 | 一区二区三区中文字幕 | 视频精品一区 | 97在线碰碰观看免费高清 | 91p在线观看 | 国产精品色综合 | 大陆黄色网| 日本理论片好看理论片 | 夜夜夜操操操 | 午夜性色一区二区三区不卡视频 | 日韩专区中文字幕 | 啪啪激情综合 | 欧美午夜影院 | 亚洲一区国产 | 欧美一区二区免费 | 一级美女大片 | 欧美三级成人理伦 | 四虎在线观看一区二区 | 亚洲天堂在线电影 | 欧美日韩中文字幕一区二区高清 | 一级观看免费完整版视频 | jizz性欧美2 日本不卡在线 | 欧美三级视频在线观看 | 欧美日韩综合视频 | 国产精品99爱免费视频 | 国产精品极品美女在线观看免费 | 色婷婷精品视频 |