前两篇文章中介绍了C++调用lua、lua栈操作的一些相关知识。
下面说一下Lua的工具。我们下一步要用到其中的一个帮助我们的开发,其实,Lua里面有很多简化开发的工具,你可以去www.sourceforge.net去找一下。它们能够帮助你简化C++对象与Lua对象互转之间的代码。这里说几个有名的,当然可能不全。
(lua tinker)如果你的系统在windows下,而且不考虑移植,那么我强烈推荐你去下载一个叫做lua tinker的小工具,整个工具非常简单,一个.h和一个.cpp。直接就可以引用到你的工程中,连独立编译都不用,这是一个韩国人写的Lua与 C++接口转换的类,十分方便,代码简洁(居家旅行,必备良药)。它是基于模板的,所以你可以很轻松的把你的C++对象绑定到Lua中。代码较长,呵呵,有兴趣的朋友可以给我留言索要lua tinker的例子。就不贴在这里了。不过我个人不推荐这个东西,因为它在Linux下是编译不过去的。它使用了一种g++不支持的模板写法,虽然有人在尝试把它修改到Linux下编译,但据我所知,修改后效果较好的似乎还没有。不过如果你只是在 windows下,那就没什么可犹豫的,强烈推荐,你会喜欢它的。
(Luabinder)相信用过Boost库的朋友,或许对这个家伙很熟悉。它是一个很强大的Linux下Lua扩展包,帮你封装了很多Lua的复杂操作,主要解决了绑定C++对象和Lua对象互动的关系,非常强大,不过嘛,对于freeeyes而言,还是不推荐,因为freeeyes很懒,不想为了一个Lua还要去编译一个庞大的boost库,当然,见仁见智,如果你的程序本身就已经加载了boost,那么就应该毫不犹豫的选择它。
(lua++)呵呵,这是我最喜欢,也是我一直用到现在的库,比较前两个而言,lua++的封装性没有那么好,很多东西还是需要一点代码的,不过之所以我喜欢,是因为它是用C写的,可以在windows下和linux下轻松转换。如果鱼与熊掌不能兼得,那么我宁愿选择一个兼顾两者的东西,如果有的话,呵呵。当然,lua++就是这么一个东西,如果你继续看我的文章,或许你也会喜欢它的。
这里我们选择lua++作为我们继续进行下去的垫脚石吧。说到Lua++(http://www.codenix.com/~tolua/),这个东西还是挺有渊源的,请你先下载一个。我教你怎么编译。下面是我下载的lua++的目录结构:
还记得我昨天说过如何编译Lua么,现在请你再做一遍,不同的是,请把lua++的程序包中的src/lib中的所有h和cpp,还有include下的那个.h拷贝到你上次建立的lua工程中。最后记得把tolua++.h放在你的Include文件夹下。下图为整个项目的目录结构(最终运行成功的目录结构):
行了,我们把上次CLuaFn类稍微改一下。
extern "C" { #include "lua.h" #include "lualib.h" #include "lauxlib.h" #include "tolua++.h" //这里加一行 }; #include "_ParamData.h" #include "CTest.h" class CLuaFn { public: CLuaFn(void); ~CLuaFn(void); void Init(); //初始化Lua对象指针参数 void Close(); //关闭Lua对象指针 bool LoadLuaFile(const char* pFileName); //加载指定的Lua文件 bool CLuaFn::CallFileFn(const char* pFunctionName, CParamGroup& ParamIn, CParamGroup& ParamOut); //执行指定Lua文件中的函数 //参数入栈 bool CLuaFn::PushLuaData(lua_State* pState, _ParamData* pParam); //参数出栈 bool CLuaFn:: PopLuaData(lua_State* pState, _ParamData* pParam, int nIndex); //新对象的创建、销毁 static int tolua_new_CTest(lua_State* pState); static int tolua_delete_CTest(lua_State* pState) ; static int tolua_SetData_CTest(lua_State* pState); static int tolua_GetData_CTest(lua_State* pState); bool InitClass(); private: lua_State* m_pState; //这个是Lua的State对象指针,你可以一个Lua文件对应一个 };
行了,这样我们就能用Lua++下的功能了。
昨天,大家看到了 bool CallFileFn(const char* pFunctionName, int nParam1, int nParam2);这个函数的运用。演示了真么调用Lua函数。
下面,我改一下,这个函数。为什么?还是因为freeeyes很懒,我可不想每有一个函数,我都要写一个C++函数去调用,太累!我要写一个通用的!支持任意函数调用的接口!
于是我创建了两个类。支持任意参数的输入和输出,并打包送给lua去执行
//支持任意参数的输入和输出,并打包送给lua去执行 #ifndef _PARAMDATA_H #define _PARAMDATA_H #include <vector> #define MAX_PARAM_200 200 using namespace std; struct _ParamData { public: void* m_pParam; char m_szType[MAX_PARAM_200]; int m_TypeLen; public: _ParamData() { m_pParam = NULL; m_szType[0] = '