Lua脚本学习
LUA脚本学习 从lua调用C++函数和对象 int CStyleAddFunc(LuaState * state)? void TestCFunctionCallBack()? ?? state->DoString("ret = Add(1,5); print(ret)");该句用来从执行Lua命令串。我们先调用Add并将结果赋值给ret变量,然后打印ret的值。 main函数如下:? ?? 编译运行,一切OK。???? 我们也可以从Lua脚本文件中调用注册的回调函数,第一篇中有演示。???? 要注册类的成员函数,则需要调用Register的另一种形式Register( const char* funcName,const Callee& callee,int (Callee::*func)(LuaState*),int nupvalues = 0 );,提供类实例指针和函数即可完成注册。下面是示例代码: class CTestCallBack? ? 二、任意形式C++函数注册
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",CForRegDirect::SeeMessage); state->DoString("print(VirCMsg('haha,Do you see me?'))"); }
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();"); } ????首先我们需要生成一个元表(metatable),将C++类的成员函数注册到该元表中。然后依据CMultiObject的实例生成lua中与其对应的对象(也是表),将该对象的metatable(也即该表的__object成员)设置为之前产生的元表。最后将新生成的lua对象放置到全局作用域中,这样后面就可以直接引用这些对象。???? 我们可以做这样的近似理解:每个实例的数据元素存放在与已对应的lua table中,而类的成员函数则存放在metatable中(函子对象)。当调用obj1obj:Print()时,会先找到其metatable,然后在metatable中找Print()函数。???? 这样便实现了类似C++中的类结构。每个实例有自己的数据,而所有实例共享一份方法列表。???????? 另外一种方式是利用表的userdata来实现,需要先创建一个lua表对象,然后将C++对象obj1设置为该表的userdata(也是设置其__object成员),再将该表对象的metatable设置为我们之前创建的元表。最后就可以用表明来调用Print函数。代码如下: 注册函子对象(RegisterObjectFunctor)这种方式的限制在于:要注册的函数必须符合原型(int Callback(LuaState* state);)。为了打破这种限制,LuaPlus提供了另外一种方式。 ??? 直接注册函子对象(RegisterObjectDirect)和RegisterDirect类似,不考虑函数原型,可以直接向元表注册任意形式的函数。???? 为CMultiObject添加新的成员函数: ??? 注销回调是件简单的事情,调用SetNil("yourCallBack")即可,如:? ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 引擎中的简单应用: 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::LoseHPInstant ); metaTableObj.RegisterObjectDirect( "LoseMPInstant",&CAICharacterCore::LoseMPInstant ); metaTableObj.RegisterObjectDirect( "RestoreHPInstant",&CAICharacterCore::RestoreHPInstant ); metaTableObj.RegisterObjectDirect( "RestoreMPInstant",&CAICharacterCore::RestoreMPInstant ); metaTableObj.RegisterObjectDirect( "GetHP",&CAICharacterCore::GetHP ); metaTableObj.RegisterObjectDirect( "GetMP",&CAICharacterCore::GetMP ); metaTableObj.RegisterObjectDirect( "GetHPMax",&CAICharacterCore::GetHPMax ); metaTableObj.RegisterObjectDirect( "GetMPMax",&CAICharacterCore::GetMPMax ); metaTableObj.RegisterObjectDirect( "UseSkill",&CAICharacterCore::UseSkill ); metaTableObj.RegisterObjectDirect( "Say",&CAICharacterCore::Say ); metaTableObj.RegisterObjectDirect( "SayAdvance",&CAICharacterCore::SayAdvance ); metaTableObj.RegisterObjectDirect( "GetRand",&CAICharacterCore::GetRand ); metaTableObj.RegisterObjectDirect( "GetLevel",&CAICharacterCore::GetLevel ); metaTableObj.RegisterObjectDirect( "DropItemRand",&CAICharacterCore::DropItemRand ); metaTableObj.RegisterObjectDirect( "AddTimer",&CAICharacterCore::AddTimer ); metaTableObj.RegisterObjectDirect( "GetTimer",&CAICharacterCore::GetTimer ); metaTableObj.RegisterObjectDirect( "GetTargetHP",&CAICharacterCore::GetTargetHP ); metaTableObj.RegisterObjectDirect( "GetTargetMP",&CAICharacterCore::GetTargetMP ); metaTableObj.RegisterObjectDirect( "GetTargetHPMax",&CAICharacterCore::GetTargetHPMax ); metaTableObj.RegisterObjectDirect( "GetTargetMPMax",&CAICharacterCore::GetTargetMPMax ); metaTableObj.RegisterObjectDirect( "GetTargetLevel",&CAICharacterCore::GetTargetLevel ); metaTableObj.RegisterObjectDirect( "GetTargetEnmity",&CAICharacterCore::GetTargetEnmity ); metaTableObj.RegisterObjectDirect( "SetTargetEnmity",&CAICharacterCore::SetTargetEnmity ); metaTableObj.RegisterObjectDirect( "GetTargetDistance",&CAICharacterCore::GetTargetDistance ); metaTableObj.RegisterObjectDirect( "SetArray",&CAICharacterCore::SetArray ); metaTableObj.RegisterObjectDirect( "GetArray",&CAICharacterCore::GetArray ); metaTableObj.RegisterObjectDirect( "SetBoolArray",&CAICharacterCore::SetBoolArray ); metaTableObj.RegisterObjectDirect( "GetBoolArray",&CAICharacterCore::GetBoolArray ); metaTableObj.RegisterObjectDirect( "SelfMurder",&CAICharacterCore::SelfMurder ); //metaTableObj.RegisterObjectDirect( "GetTargetName",&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( 0,0 ); } //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脚本载入错误: %s",m_data.szCharacterName,e.GetErrorMessage()); GetErrorLog()->logString(szErr); m_bLuaScriptLoaded = false; } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |