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

tolua++初探(六)

系統 1862 0
這是學習tolua++的最后一篇了。在這一篇里完成一個稍微復雜一點的例子(^_^其實還是很簡單)。 導出三個類CBase、CDerived1、CDerived2到lua,導出兩個函數toDerived1、toDerived2。lua腳本中聲明兩個函數Derived1Test和Derived2Test,我們在C++中調用。Derived1Test和Derived2Test會調用toDerived*對其參數進行向下轉換(從CBase轉到CDerived*),然后調用派生類的方法做一些測試。 基本上和前面幾個例子類似,新增加的部分是在C++中調用Lua腳本里定義的函數。這牽涉到虛擬棧的操作,后面會解釋一下。 還是老樣子,先把實際的頭文件列出來。tlclass.h如下:
#ifndef__TOLUACLASS_h #define __TOLUACLASS_h class CBase ... { public : CBase() ... {} virtual ~ CBase() ... {} virtual void ShowMessage() ... {printf( " BaseClass " );} static char * ClassName() ... { return " CBase " ;} } ; class CDerived1: public CBase ... { public : CDerived1() ... {} ~ CDerived1() ... {} void ShowMessage() ... {printf( " Derived1Class " );} void ShowDerived1() ... {printf( " showderived11111 " );} } ; class CDerived2: public CBase ... { public : CDerived2() ... {m_nNumber = 0 ;} ~ CDerived2() ... {} void ShowMessage() ... {printf( " Derived2Class " );} void ShowDerived2() ... {printf( " showderived22222 " );} void SetNumber( int num) ... {m_nNumber = num;} int GetNumber() ... { return m_nNumber;} protected : int m_nNumber; } ; extern CDerived1 * toDerived1( void * p); extern CDerived2 * toDerived2( void * p); #endif
tlclass.pkg如下:
$#include " tlclass.h " class CBase ... { public : virtual void ShowMessage(); static char * ClassName(); } ; class CDerived1: public CBase ... { public : void ShowMessage(); void ShowDerived1(); } ; class CDerived2: public CBase ... { public : void ShowMessage(); void ShowDerived2(); void SetNumber( int num); int GetNumber(); } ; CDerived1 * toDerived1( void * p); CDerived2 * toDerived2( void * p);
這次多定義了兩個函數toDerived1和toDerived2,全局的。我們也可以把他們直接放在類中,或者一個MODULE中。module大概是類似的namespace的東西,把一堆雜七雜八的家什如變量、常量、函數、類實例等放在一起,在lua中通過"."來訪問。下面是手冊中的例子:
modulemod ... { #define N extern int var; int func(...): }
這樣我們可以在lua中用mod.N,mod.var,mod.func來訪問其成員。 原本toDerived*的參數是CBase*,但是從C++向Lua函數傳參數的時候我調用了lua_pushlightuserdata,結果在腳本中報錯,說toDerived*應當接受CBase*而非userdata。于是干脆把參數修改成void*,這下lua不再叫喚了。 好了,到了列出驅動文件的時候了。CallLuaFunc.cpp:
#include " lua.hpp " #include " tlclass.h " CDerived1 * toDerived1( void * p) ... { return dynamic_cast < CDerived1 *> ((CBase * )p); } CDerived2 * toDerived2( void * p) ... { return dynamic_cast < CDerived2 *> ((CBase * )p); } int tolua_calllua_open(lua_State * ); int _tmain( int argc,_TCHAR * argv[]) ... { lua_State * L = luaL_newstate(); luaopen_base(L); tolua_calllua_open(L); luaL_dofile(L, " ../scripts/CallLuaFunc.lua " ); // callluafunction CBase * p1 = new CDerived1(); CBase * p2 = new CDerived2(); // callDerived1Test lua_getglobal(L, " Derived1Test " ); lua_pushlightuserdata(L,p1); if (lua_pcall(L, 1 , 0 , 0 ) != 0 ) ... { fprintf(stderr, " callDerived1Testfailed:%s " ,lua_tostring(L, - 1 )); } // callDerived2Test lua_getglobal(L, " Derived2Test " ); lua_pushlightuserdata(L,p2); if (lua_pcall(L, 1 , 0 , 0 ) != 0 ) ... { fprintf(stderr, " callDerived2Testfailed:%s " ,lua_tostring(L, - 1 )); } printf( " ThisinfoisprintinC++! CDerived2.GetNumber()=%d " ,((CDerived2 * )p2) -> GetNumber()); deletep1; deletep2; lua_close(L); return 0 ; }
這次驅動文件有了點新的變化:1)兩個全局導出函數;2)調用lua函數的代碼。分開來看。 導出函數toDerived*很簡單,只是調用dynamic_cast來向下轉換而已。如果轉換失敗,dynamic_cast會返回null。當我們要從基類指針轉換到派生類指針時,最好用dynamci_cast,直接強制轉換是危險的,除非你明確的知道某個指針指向的對象是什么。 在C++中調用lua腳本的函數大概分為三步: a..找到函數并入棧;(這里是 lua_getglobal(L, " Derived1Test " );) b..參數入棧;(這里是 lua_pushlightuserdata(L,p1);) c..調用lua_pcall進行實際調用 第一步不必說了;第二步可以傳遞任意個任意類型的參數,lua_pushnumber,lua_pushstring,lua_pushboolean等等可以調用;第三步是調用lua_pcall,lua_pcall第一個參數是lua_State*,這是我們的工作環境了。第二參數是要傳遞的參數個數,我們這里是1;第三個參數是lua函數返回的結果個數,我們的lua函數不返回結果,設為0。第四個參數是比較復雜,為0時指lua_pcall會在調用失敗時把原始錯誤信息放到棧上;其它值代表棧的索引,該索引處放了一個錯誤處理函數,lua_pcall失敗時會根據這個索引去調用該函數。 調用失敗的時候我只是簡單地打印一條出錯信息,這個錯誤碼放在棧頂,我們用lua_tostring(L,-1)訪問并轉換為字符串。可以修改下驅動代碼,比如把第二次調用傳入p1,這樣就可以看見錯誤信息。 最后我還是在C++代碼中打印了下CDerived2對象的值,以驗證lua和C++中訪問的是同一個對象。 Lua和C++的交互都是通過棧,所以要寫交互部分的代碼就要不停的出棧入棧,煩死個人。不過這也是Lua靈活的地方。牛人啊,頂禮膜拜吧。 有時間要好好研究下《Programming Lua》,CSDN上有中文版的, lua官方網站 上有英文的。雖然這個是針對5.0版本的lua,但絕大部分東西還是有用的。針對5.1.3的第二版已經出了,可惜我在網上沒有找到鏈接,哪位看到分享一下。 下面看看lua文件callluafunc.lua吧:
print( " nowinCallLuaFunc.lua! " ) -- luafunctiontotestCDerived1,CDerived2,they ' llbecalledfromC++ functionDerived1Test(e) d1 = toDerived1(e); if d1then d1:ShowMessage(); d1:ShowDerived1(); else print( " invalidd1(nil)! " ); end end functionDerived2Test(e) d2 = toDerived2(e); if d2then d2:ShowMessage(); d2:ShowDerived2(); d2:SetNumber( 180 ); print(d2:GetNumber()); else print( " invalidd2(nil) " ); end end
lua中定義了函數Derived1Test和Derived2Test。上面的版本已經不會導致出錯信息了,原始的Derived*Test函數如下:
functionDerived1Test(e) d1 = toDerived1(e); d1:ShowMessage(); d1:ShowDerived1(); end functionDerived2Test(e) d2 = toDerived2(e); d2:ShowMessage(); d2:ShowDerived2(); d2:SetNumber( 180 ); print(d2:GetNumber()); end
原始的Derived*Test函數沒有錯誤檢查,所以從C++中用lua_pcall調用時可能會產生錯誤信息。 又想了下,這樣的類型轉換太復雜了,tolua++提供了轉換機制,可以用的。CEGUI用的就是。 tolua++生成了一些工具函數,在tolua為名的module中。其中tolua.cast就是用來做類型轉換的。只需要改動tlclass.pkg文件,加入下面的代碼:
$[ testHelper = ... {} functiontestHelper.toDerived1(e) return tolua.cast(e, " CDerived1 " ) end functiontestHelper.toDerived2(e) return tolua.cast(e, " CDerived2 " ) end $]
$[和$]結合,用來直接插入lua代碼。我生成一個名為testHelper的table,給testHelper添加兩個轉換函數。 重新用tolua++編譯,再編譯工程。就可以在腳本中調用testHelper.toDerived*來轉換了。 下面是更改后的
callluafunc.lua文件:
print( " nowinCallLuaFunc.lua! " ) -- luafunctiontotestCDerived1,CDerived2,they ' llbecalledfromC++ functionDerived1Test(e) d1 = testHelper.toDerived1(e); if d1then d1:ShowMessage(); d1:ShowDerived1(); else print( " invalidd1(nil)! " ); end end functionDerived2Test(e) d2 = testHelper.toDerived2(e); if d2then d2:ShowMessage(); d2:ShowDerived2(); d2:SetNumber( 180 ); print(d2:GetNumber()); else print( " invalidd2(nil) " ); end end
僅僅是將toDerived*調用轉換成了testHelper.toDerived*。運行了一下,結果是正常的。
好啦好啦,就到這里啦。 通過兩天的學習,我已經確定可以在項目中使用tolua++了,它是"AS IS"的,可以用于任何目的。到目前位置所演示的一些特性,可以滿足我的需要。 嗯,有些未完成的東西,比如UNICODE、多線程環境下對lua的調用等,慢慢用到了再說吧。

tolua++初探(六)


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

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

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 日韩精品在线一区 | 国产91福利在线精品剧情尤物 | 黄色在线观看 | 国产第一亚洲 | 亚洲精视频 | 国内久久 | 国产精品久久精品 | 久久福利电影 | 亚洲国产高清高潮精品美女 | 精品日韩视频 | 国产成人精品日本亚洲麻豆 | 成年人在线免费 | 男人午夜免费视频 | av毛片| 久久精品国产精品青草图片 | 国产成人综合在线观看网站 | 亚洲视频在线观看 | 91高清视频在线 | feise.av | 国产成人综合欧美精品久久 | 国产成人最新毛片基地 | 色橹橹欧美在线观看视频高清免费 | 少妇特黄a一区二区三区88av | 久草福利在线视频 | 五月婷六月丁香狠狠躁狠狠爱 | 欧美亚洲韩国国产综合五月天 | www伊人 | 草莓福利视频 | 国产九一精品 | 精品视频手机在线观看免费 | 亚洲精品无码成人A片九色播放 | 精品国产成a人在线观看 | 欧美色性 | 美女污直播 | 日韩精品区 | 国产精品人妻无码八区仙踪林 | 婷婷激情综合色五月久久竹菊影视 | 亚洲欧美国产精品久久久久久久 | 天天夜天干天天爽 | 免费观看成人拍拍拍1000视频 | 天天插天天操天天射 |