较为常见的是c/c++中调用lua文件,在lua中使用luaL_dofile
加载lua文件,并执行lua代码。
extern "C"
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "luaconf.h"
};
#include <string.h>
int main()
{
int error;
lua_State* L = luaL_newstate();
luaL_openlibs(L);
int ret = luaL_dofile(L, "sum_test.lua");
if (ret != 0)
{
printf("%s", lua_tostring(L, -1));
}
lua_getglobal(L, "Sum");
lua_pushnumber(L, 2);//第一个参数
lua_pushnumber(L, 3);//第二个参数
lua_pushnumber(L, 4);//第三个参数
lua_pcall(L, 3, 2, 0);
double sum = 0, ave = 0;
if (lua_isnumber(L, 1))
{
sum = lua_tonumber(L, 1);
}
if (lua_isnumber(L, 2))
{
ave = lua_tonumber(L, 2);
}
lua_close(L);
return 0;
}
lua的代码如下:
function Sum(...)
local s=0
local num=0
for k,v in pairs{...} do
s = s + v
num = k
end
return s,s/num
end
lua和c参数栈平衡
这里面涉及到一个关键的问题,就是c/c++和lua的参数是如何进行传递的。在lua的设计时采用的是栈方式的交互模式。其中lua_getglobal
表示从全局变量中取出特定的变量,放到栈中,lua_pushnumber
把数据放入到栈中,经过:
lua_getglobal(L, "Sum");
lua_pushnumber(L, 2);//第一个参数
lua_pushnumber(L, 3);//第二个参数
lua_pushnumber(L, 4);//第三个参数
后,栈的情况如下所示:
在进行lua_pcall(L, 3, 2, 0)
后,表明函数有3个参数,2个返回值,函数调用后把之前的函数相关参数出栈,把函数返回值入栈。栈情况变为:
从栈中取出数据使用的是lua_tonumber
,
sum = lua_tonumber(L, 1);
从栈底开始取数据,整数从栈底开始数起,负数从栈顶开始数起。
把数据压入栈中
这里就明白了c语言和lua进行交互的时候使用的是栈,在栈的使用中需要注意的几个函数这里都有一定的前缀。
lua_pushfstring 将一个格式化字符串压入堆栈,并返回指向这个字符串的指针;
lua_pushlstring 将一个指定大小的字符串压入堆栈;
lua_pushvalue 将栈中指定索引的元素复制一份到栈顶;
对于lua_pushx的函数是指把数据压到栈中,相反的一个操作就是从栈中取出数据,使用的是lua_tox。
从栈中获取数据
lua_tostring 等价于参数len=NULL时的lua_tolstring;
lua_tonumber 将给定index索引处的元素转换为double类型;
lua_tox可以指定获取栈位置的数据。
在使用栈的时候,有时候我们已经确认了某个栈位置应该是什么样类型,在使用的时候为了确认数据类型正确与否,可以使用luaL_check来进行确认。
栈的其他操作
对于栈还有如下的一些操作:
lua_pop 从栈中弹出n个元素;
lua_gettop 返回栈顶元素的索引(也即元素个数);
lua_concat 将栈顶开始的n个元素连接起来,并将它们出栈,然后将结果入栈;
lua_getfield 将t[k]压入堆栈,t由参数index指定在栈中的位置;
lua_setfield 相当于t[k]=v,t由参数index指定在栈中的位置,v是栈顶元素,改函数会将栈顶的value出栈;
lua_getglobal(L,s) 等价于 lua_getfield(L, LUA_GLOBALSINDEX, s),注意:栈中LUA_GLOBALSINDEX索引位置处是当前Lua状态机的全局变量环境。
lua_setglobal(L,s) 等价于 lua_setfield(L, LUA_GLOBALSINDEX, s);
lua_insert 移动栈顶元素到index指定的位置;
lua_remove 移除index处的元素,index之上的元素均下移一个位置;
lua_replace 将栈顶元素移到指定位置,并取代原来的元素,原先的栈顶元素弹出;
lua_next 弹出一个key,然后将t[key]入栈,t是参数index处的table;在利用lua_next遍历栈中的table时,对key使用lua_tolstring尤其需要注意,除非知道key都是string类型。
lua_objlen 返回index处元素的长度,对string,返回字符串长度;对table,返回"#"运算符的结果;对userdata,返回内存大小;其它类型返回0;
luaL_checkstack 增加栈大小(新增sz个元素的空间),如果grow失败,引发一个错误,msg参数传递错误消息。