C++要想跟tolua完整的相互调用,中间需要很多的库和执行程序,包括tolua.lib tolua++.exe等交互。
1、必须先下载lua 1.5,下载好后,把/src目录的除开lua.c,luac.c的文件全部放到一个新建的静态链接库的工程项目里,然后编译出一个静态链接库xxxxx.lib。
2、去tolua++官网下载一个tolua++的包,解压出来,再次新建一个静态链接库的项目,把tolua++的/src/lib里的.h .c的文件拷贝到静态链接库的项目里,然后编译出一个XXX++.lib 的库。
3、再次新建一个控制台程序的项目,把编译好的lua静态库和tolua++的静态库放在项目里附加,然后把tolua++的/src/bin/里的tolua.c,luabind.h,luabind.c文件放在项目里,然后把tolua++的/include里的tolua++.h和lua1.5的目录里的/src的所有头文件放到项目里,然后编译生成xxxx++.exe
4、预备工作做好了,现在要了解一下tolua++的一些概念,要想c++与tolua交互,我们需要两个文件,一个是用来解析pkg文件的C++代码,和一个编译好的tolua++.lib或者.dll的静态或动态库,
tolua通过pkg文件解析捆绑c++代码,生成一个解析好的lua能识别的文件(就是通过编译好的xxx++.exe控制台程序生成的),我们通过一串命令来执行生成
tolua -n 链接的名字 -o /xxxx.h或者.cpp xxxxx.pkg
这样lua就可以调用C++的代码了,pkg文件也有一些规范,具体规范请参考 http://blog.csdn.net/OBsona/archive/2008/12/08/3478518.aspx
所有lua的API函数中文解释参考
lua调用C++的方式
首先编辑好解析的pkg和生成链接lua的文件,然后在主运行入口里main()
加载lua文件
lua_State* L = lua_open();
luaL_openlibs(L);
tolua_xxxx( 链接的名字)_open(L);
luaL_dofile(L, "xxxxx.lua");
lua_close(L);
C++调用lua的方式(最复杂的)
1、由于tolua没有完整的封装C++调用的lua的方式,对于习惯C++调用函数和变量的人来说有点别扭,不过可以尝试自己封装
C++调用lua的函数和全局变量,都要通过入栈出栈的方式调用。
可以这样理解,我们调用luaL_dofile(L,"xxx.lua")时,就把lua相应的函数和变量放在一个内存栈里了,当我们需要调用lua的函数或者变量时,就把相应名字索引的栈空间值重新压入到一个新的栈里进行操作。
lua_State* L = lua_open();
luaL_openlibs(L);
tolua_xxxx( 链接的名字)_open(L);
luaL_dofile(L, "xxxxx.lua");
2、调用基本类型变量
lua_getglobal(L,"demo");(demo具体的函数名或者变量)
这个值在栈顶,现在加入我们要取得一个lua的全局变量demo,我们已经把变量压到栈里,现在就是取出它的时候
type demo = lua_tonumber(L,-1);在这里具体取出什么类型的值,请看上面的API,lua的栈取值的索引很有趣,可以正着取也可以反着取,通常是反着取,就是从栈顶向下数,-1就是栈顶.
3、调用函数(无参)
现在我们取一个函数试试,这个函数假设没参数
( xxx.lua里
function TestFuc()
print("lua脚本函数")
end
)
lua_getglobal(L,"TestFuc");
lua_pcall(L,0,0,0);调用lua函数需要调用这个接口,第二参数为函数的参数个数,第三参数为返回参数个数,第四参数为错误信息,当调用lua函数错误时会返回相应的错误信息
4、重点,调用函数(带参数)
( xxx.lua里
function TestFuc(xxx)
xxxxx........
end
)
lua_getglobal(L,"TestFuc");
由于不同的参数调用不同故分开写
传入数字类型时
lua_pushnumber(L,250);压入第一个参数当做函数的第一个参数也可以用tolua_pushnumber(L,250)
传入字符串类型时
lua_pushstring(L,"hello world");或者
std::string temp("hello world");
lua_pushstring(L,temp.c_str());
传入一个表结构时
lua_newtable(L);首先先创建一个空表到栈里 假设表为tab = {[1]="array1",[2]="array2",[3]={"aaa","bbb"}}
lua_pushnumber(L,1);传入KEY
lua_pushstring(L,"array1");传入值
lua_settable(L,-3);找到表的栈的位置,设置键和值进入,这里注意只能一对键值对的设置,不能一起设置
lua_pushnumber(L,2);传入KEY
lua_pushstring(L,"array2");传入值
lua_settable(L,-3);
嵌套表的插入
lua_newtable(L);
lua_pushnumber(L,1);传入KEY
lua_pushstring(L,"aaa");传入值
lua_settable(L,-3);
lua_pushnumber(L,2);传入KEY
lua_pushstring(L,"bbb");传入值
lua_settable(L,-3);
lua_settable(L,-3);
这里可能对栈里表的位置有疑惑,明明又压入两个元素为什么表的位置还是-3,设置一次表后,参数会被pop出栈,跟调用函数一样,调用完函数之后参数会被pop出栈
参数是C++对象的时
( xxx.lua里
function TestFuc(testClass)
local name=testClass.m_name
testClass:testFuc()
testClass.m_name="dfdfdf"
end
)
需要预先通过pkg生成解析文件,lua通过解析文件能知道C++的自定义类型
假设pkg里解析了一个类testClass 里面有一个成员变量m_name和成员函数testFuc()
只要有解析文件,我们只需要把解析好的类型指针传入即可
testClass* tempPtr= new testClass;
tolua_pushusertype(L,tempPtr,"testClass");
lua_close(L);