• <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>
            隨筆 - 132  文章 - 51  trackbacks - 0
            <2010年9月>
            2930311234
            567891011
            12131415161718
            19202122232425
            262728293012
            3456789

            常用鏈接

            留言簿(7)

            隨筆分類(lèi)

            隨筆檔案

            文章分類(lèi)

            文章檔案

            cocos2d-x

            OGRE

            OPenGL

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

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

            int CStyleAddFunc(LuaState * state)
            {    LuaStack args(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)訪(fǎng)問(wèn)參數(shù),棧中可以存貯多個(gè)參數(shù),LuaStack args(state);語(yǔ)句獲取棧對(duì)象供后續(xù)訪(fǎng)問(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()
            {
               LuaStateOwner state;      //"print" need this
               state->OpenLibs();      //register my function CStyleAddFunc to Add
               state->GetGlobals().Register("Add", CStyleAddFunc);      //call my function and print the result  
               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è)類(lèi)的成員函數(shù),則需要調(diào)用Register的另一種形式Register( const char* funcName, const Callee& callee, int (Callee::*func)(LuaState*), int nupvalues = 0 );,提供類(lèi)實(shí)例指針和函數(shù)即可完成注冊(cè)。下面是示例代碼:

            class CTestCallBack
            {
            public:
               int NonVirtualFunc(LuaState *state)    
               {  
                LuaStack args(state);    
                printf("In non-virtual member function. no msg. ");   
                return 0;
               }   
              
               int virtual VirtualFunc(LuaState *state)   
               {
                LuaStack args(state);    
                printf("In virtual member function.msg=%s ", args[1].GetString());     
                return 0;
               }
            };

            void TestClassMemberFuncReg()
            {   
               LuaStateOwner state;      //"print" need this   
               state->OpenLibs();  
               LuaObject globalobj = state->GetGlobals();
               CTestCallBack tcb;   
               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è)類(lèi)的成員函數(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;
            }      //const is necessary
            virtual void SeeMessage(const char *msg)    
            {
                 printf("msg=%s ", msg);
            }
            };

            void TestRegisterDirect()
            {
            LuaStateOwner state;
            state->OpenLibs();
            LuaObject gobj = state->GetGlobals();        //register global function directly    
            gobj.RegisterDirect("Add", Add);    
            state->DoString("print(Add(1.5, 2.3))");      //register memberfunction    
            CForRegDirect forobj;    
            gobj.RegisterDirect("MemberSum", forobj, CForRegDirect::Sum);    
            state->DoString("print(MemberSum(1,2,7))");     
            gobj.RegisterDirect("VirCMsg", forobj, CForRegDirect::SeeMessage);    
            state->DoString("print(VirCMsg('haha,Do you see me?'))");
            }


            三、注冊(cè)函子對(duì)象
                上面兩節(jié)的方式可以實(shí)現(xiàn)簡(jiǎn)單的回調(diào)注冊(cè),注冊(cè)類(lèi)的成員函數(shù)時(shí)需要顯式提供類(lèi)指針,不適合用于映射C++中的類(lèi)結(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++中的類(lèi)對(duì)象,注冊(cè)函子對(duì)象正是利用了這種特性來(lái)實(shí)現(xiàn)的。     下面我們將一個(gè)C++類(lèi)映射到Lua中。類(lèi)代碼如下:


            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()
            {
               LuaStateOwner state;
               state->OpenLibs();      //create metaTable

               LuaObject metaTableObj = state->GetGlobals().CreateTable("MultiObjectMetaTable");
               metaTableObj.SetObject("__index", metaTableObj);     //register functor for multiobject
               metaTableObj.RegisterObjectFunctor("Print", CMultiObject::Print);      //get a instances of CMultiObject

               CMultiObject obj1(10);     //"clone" a object in lua, the lua object(here is table) has obj1's data
               LuaObject obj1Obj = state->BoxPointer(&obj1);     //set lua object's metatable to MetaTableObj  
               obj1Obj.SetMetaTable(metaTableObj);     //put lua object to Global scope, thus it can be accessed later.
               state->GetGlobals().SetObject("obj1", obj1Obj);   

               CMultiObject obj2(20);
               LuaObject obj2Obj = state->BoxPointer(&obj2);    
               obj2Obj.SetMetaTable(metaTableObj);
               state->GetGlobals().SetObject("obj2", obj2Obj);      //now call Print and Print2    
               state->DoString("obj1:Print();");
               state->DoString("obj2:Print();");
            }

                首先我們需要生成一個(gè)元表(metatable),將C++類(lèi)的成員函數(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中,而類(lèi)的成員函數(shù)則存放在metatable中(函子對(duì)象)。當(dāng)調(diào)用obj1obj:Print()時(shí),會(huì)先找到其metatable,然后在metatable中找Print()函數(shù)。     這樣便實(shí)現(xiàn)了類(lèi)似C++中的類(lèi)結(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ù)。代碼如下:
               
            LuaObject table1Obj = state->GetGlobals().CreateTable("table1");
            table1Obj.SetLightUserData("__object", &obj1);  
            table1Obj.SetMetaTable(metaTableObj);   
            LuaObject table2Obj = 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類(lèi)似,不考慮函數(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)");

            五、注銷(xiāo)回調(diào)

                注銷(xiā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,源碼包中帶的。

            轉(zhuǎn)載自http://hi.baidu.com/li9chuan/blog/item/e65e1d6dc0bd79f642169461.html

            參考:http://gpwiki.org/index.php/Scripting_with_LuaPlus_and_Cpp  簡(jiǎn)單的LUA腳本編寫(xiě)
                        http://wwhiz.com/LuaPlus/LuaPlus.html
                        http://www.shnenglu.com/iwangchuchu/default.html?page=2



            ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
            引擎中的簡(jiǎn)單應(yīng)用:

            void CAICharacterCore::LoadLuaScript( const char* LuaFileName )
            {


                
            try
                
            {
                 
            //LuaScript->GetGlobals().RegisterDirect( "Thinking", *this, &CAICharacterCore::Thinking );

                 
            //////////////////////////////////////////////////////////////////////////

                 LuaObject metaTableObj 
            = m_LuaScript->GetGlobals().CreateTable("MultiObjectMetaTable");
                 metaTableObj.SetObject(
            "__index", metaTableObj);
                 
            //metaTableObj.RegisterObjectFunctor( "ClearMoveStep", &CAICharacterCore::ClearMoveStep );
                 
            //metaTableObj.RegisterObjectFunctor( "RestoreHPInstant", &CAICharacterCore::RestoreHPInstant );
                 
            //metaTableObj.RegisterObjectDirect( "SetSayTimeInterval", (CAICharacterCore*)0, &CAICharacterCore::SetSayTimeInterval );


                 metaTableObj.RegisterObjectDirect( 
            "LoseHPInstant", (CAICharacterCore*)0&CAICharacterCore::LoseHPInstant );
                 metaTableObj.RegisterObjectDirect( 
            "LoseMPInstant", (CAICharacterCore*)0&CAICharacterCore::LoseMPInstant );
                 metaTableObj.RegisterObjectDirect( 
            "RestoreHPInstant", (CAICharacterCore*)0&CAICharacterCore::RestoreHPInstant );
                 metaTableObj.RegisterObjectDirect( 
            "RestoreMPInstant", (CAICharacterCore*)0&CAICharacterCore::RestoreMPInstant );
                 metaTableObj.RegisterObjectDirect( 
            "GetHP", (CAICharacterCore*)0&CAICharacterCore::GetHP );
                 metaTableObj.RegisterObjectDirect( 
            "GetMP", (CAICharacterCore*)0&CAICharacterCore::GetMP );
                 metaTableObj.RegisterObjectDirect( 
            "GetHPMax", (CAICharacterCore*)0&CAICharacterCore::GetHPMax );
                 metaTableObj.RegisterObjectDirect( 
            "GetMPMax", (CAICharacterCore*)0&CAICharacterCore::GetMPMax );
                 metaTableObj.RegisterObjectDirect( 
            "UseSkill", (CAICharacterCore*)0&CAICharacterCore::UseSkill );
                 metaTableObj.RegisterObjectDirect( 
            "Say", (CAICharacterCore*)0&CAICharacterCore::Say );
                 metaTableObj.RegisterObjectDirect( 
            "SayAdvance", (CAICharacterCore*)0&CAICharacterCore::SayAdvance );
                 metaTableObj.RegisterObjectDirect( 
            "GetRand", (CAICharacterCore*)0&CAICharacterCore::GetRand );
                 metaTableObj.RegisterObjectDirect( 
            "GetLevel", (CAICharacterCore*)0&CAICharacterCore::GetLevel );
                 metaTableObj.RegisterObjectDirect( 
            "DropItemRand", (CAICharacterCore*)0&CAICharacterCore::DropItemRand );
                 metaTableObj.RegisterObjectDirect( 
            "AddTimer", (CAICharacterCore*)0&CAICharacterCore::AddTimer );
                 metaTableObj.RegisterObjectDirect( 
            "GetTimer", (CAICharacterCore*)0&CAICharacterCore::GetTimer );
                 metaTableObj.RegisterObjectDirect( 
            "GetTargetHP", (CAICharacterCore*)0&CAICharacterCore::GetTargetHP );
                 metaTableObj.RegisterObjectDirect( 
            "GetTargetMP", (CAICharacterCore*)0&CAICharacterCore::GetTargetMP );
                 metaTableObj.RegisterObjectDirect( 
            "GetTargetHPMax", (CAICharacterCore*)0&CAICharacterCore::GetTargetHPMax );
                 metaTableObj.RegisterObjectDirect( 
            "GetTargetMPMax", (CAICharacterCore*)0&CAICharacterCore::GetTargetMPMax );
                 metaTableObj.RegisterObjectDirect( 
            "GetTargetLevel", (CAICharacterCore*)0&CAICharacterCore::GetTargetLevel );
                 metaTableObj.RegisterObjectDirect( 
            "GetTargetEnmity", (CAICharacterCore*)0&CAICharacterCore::GetTargetEnmity );
                 metaTableObj.RegisterObjectDirect( 
            "SetTargetEnmity", (CAICharacterCore*)0&CAICharacterCore::SetTargetEnmity );
                    metaTableObj.RegisterObjectDirect( 
            "GetTargetDistance", (CAICharacterCore*)0&CAICharacterCore::GetTargetDistance );
                    metaTableObj.RegisterObjectDirect( 
            "SetArray", (CAICharacterCore*)0&CAICharacterCore::SetArray );
                 metaTableObj.RegisterObjectDirect( 
            "GetArray", (CAICharacterCore*)0&CAICharacterCore::GetArray );
                 metaTableObj.RegisterObjectDirect( 
            "SetBoolArray", (CAICharacterCore*)0&CAICharacterCore::SetBoolArray );
                 metaTableObj.RegisterObjectDirect( 
            "GetBoolArray", (CAICharacterCore*)0&CAICharacterCore::GetBoolArray );


                 metaTableObj.RegisterObjectDirect( 
            "SelfMurder", (CAICharacterCore*)0&CAICharacterCore::SelfMurder );

                 
            //metaTableObj.RegisterObjectDirect( "GetTargetName", (CAICharacterCore*)0, &CAICharacterCore::GetTargetName );

                 LuaObject CAICharacterCoreObj 
            = m_LuaScript->BoxPointer(this);

                 CAICharacterCoreObj.SetMetaTable(metaTableObj);

                 m_LuaScript
            ->GetGlobals().SetObject( "AI", CAICharacterCoreObj );

                 
            if!m_LuaScript->LoadFile( LuaFileName ) )
                 
            {
                  m_bLuaScriptLoaded 
            = true;
                  m_LuaScript
            ->Call( 00 );
                 }


                 
            //LuaStateOwner LuaScript;
                 
            //LuaScript->LoadFile( "D:/ArenWorkstation/XSanguoRun/Server/Script/AI/test.lua" );
                 
            //LuaObject luaFun = LuaScript->GetGlobal( "Event_OnInit" );

                 
            //if( luaFun.IsFunction() )
                 
            //{
                 
            // int y = 0;
                 
            //}

                 
            //m_LuaScript->DoString("print(obj1:ClearMoveStep())");
                 
            //LuaScript->LoadFile( "D:/ArenWorkstation/XSanguoRun/Server/test.lua" );
                }

                
            catch (LuaPlus::LuaException &e)
                
            {
                    
            char szErr[1024= {0};
                    _snprintf(szErr, 
            sizeof(szErr)-1"怪物 %s AI腳本載入錯(cuò)誤: %s", m_data.szCharacterName, e.GetErrorMessage());
                    GetErrorLog()
            ->logString(szErr);
                    m_bLuaScriptLoaded 
            = false;
                }


            }

            posted on 2010-09-06 18:18 風(fēng)輕云淡 閱讀(2773) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): LUA
            99久久免费国产精品| 国产精久久一区二区三区| 伊人情人综合成人久久网小说| 久久综合九色欧美综合狠狠| 亚洲精品99久久久久中文字幕| 无码AV波多野结衣久久| 国产成人香蕉久久久久| 亚洲精品无码久久久影院相关影片| 秋霞久久国产精品电影院| 久久久久人妻精品一区三寸蜜桃| 亚洲精品国产美女久久久| segui久久国产精品| 国产色综合久久无码有码| 久久久久亚洲AV无码去区首| 人妻无码中文久久久久专区| 久久青青草视频| 色综合久久综合网观看| 精品久久久久久无码专区不卡| 亚洲国产成人精品久久久国产成人一区二区三区综 | 精品久久久久成人码免费动漫 | 久久国产美女免费观看精品| 亚洲伊人久久大香线蕉综合图片| 亚洲国产成人久久综合碰| 久久综合丝袜日本网| 三上悠亚久久精品| 综合人妻久久一区二区精品| 久久久久亚洲AV无码专区网站| 精品熟女少妇aⅴ免费久久| 97久久精品国产精品青草| 国内精品久久久久伊人av| 亚洲欧美日韩久久精品第一区| 亚洲国产另类久久久精品黑人 | 亚洲国产综合久久天堂| 亚洲国产精品无码久久青草| 色综合久久精品中文字幕首页 | 亚洲国产精品无码久久久久久曰| 久久婷婷人人澡人人| 久久天天躁狠狠躁夜夜av浪潮| 久久99热这里只有精品国产| 成人午夜精品久久久久久久小说 | 久久精品这里只有精99品|