目录

C虚拟栈技术

压入元素

查询元素

其他栈操作

lua_is*函数

lua_to*函数从栈中获取一个值

练习

C调用Lua的函数、全局变量

Lua调用C的函数


C虚拟栈技术

Lua和C语言通信一个技术。几乎所有的API调用都会操作这个栈上的值。

压入元素

void lua_pushnil(lua_State *L); void lua_pushboolean(lua_State *L,int bool); void lua_pushnumber(lua_State *L, lua_Number n); void lua_pushinteger(lua_State *L, lua_Integer); void lua_pushlstring(lua_State *L, const char *s, size_t len); void lua_pushstring(lua_State *L, const char *s); 判断虚拟栈内是否有足够的空间 int lua_checkstack(lua_State *L, int sz);

查询元素

API使用索引来引用栈中的元素。第一个压入栈中的元素索引为1(栈底),第二个压入为2.用负数来访问栈中的元素,-1表示栈顶元素,-2表示栈顶下面的元素,以此类推

其他栈操作

int lua_gettop(lua_State *L);//返回栈顶索引,相当于求栈长度 void lua_settop(lua_State *L, int index);//将栈顶指定某个位置 void lua_pushvalue(lua_State *L, int index);//赋值index元素并压入栈 void lua_remove(lua_State *L, int index);//将index的元素删除 void lua_insert(lua_State *L, int index);//将栈顶元素插入到index位置,index之后的位置往栈上方移动一位 void lua_replace(lua_State *L, int index);//将栈顶元素替换index的元素 void lua_pop(lua_State *L, int n);//删除n个栈顶元素

lua_is*函数

为了检查一个元素是否为特定的类型,API提供了lua_is*.lua_isnumber、lua_isstring、lua_istable等 int lua_is*(lua_State int index); --给定的索引值是,在L中的索引 ​ 实际上,lua_isnumber是检查值是否能转换为数字类型,lua_isstring也有同样的行为

lua_to*函数从栈中获取一个值

int lua_toboolean(lua_State *L, int index); lua_Number lua_tonumber(lua_State *L, int index); --index为负数时,就是出栈? lua_Integer lua_tointeger(lua_State *L, int index); const char *lua_tolstring(lua_State *L, int index, size_t *len); size_t lua_objlen(lua_State *L, int index); ​ lua_tolstring函数返回的是指向内部字符串副本的指针,并且不能修改。当对应的字符还在Lua的栈内,那么这个指针就会一直有效。当Lua调用一个C函数返回时,Lua就会清空它的栈。这就形成了一条规则,不要在函数之外使用在C函数内获得指向Lua字符串的指针 ​ lua_lstring返回的字符串在其末尾都会有一个额外的零。字符串长度会在函数第三个参数返回。

练习

功能:由下而上打印栈内元素

【main.cpp】

#include<stdio.h>

extern "C"
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
lua_State *L;

static void stackDump()
{
int lens = lua_gettop(L);
for(int i = 1; i <= lens; ++i){
int type = lua_type(L, i);
switch(type)
{
case LUA_TSTRING:{
printf("%s", lua_tostring(L, i));
break;
}
case LUA_TBOOLEAN:{
printf(lua_toboolean(L, i) ? "True" : "False");
break;
}
case LUA_TNUMBER:{
printf("%g", lua_tonumber(L, i));
break;
}
default:{
printf("%s", lua_typename(L, i));
}
}
printf("\n");
}
}

void run()
{
lua_getglobal(L, "width");
lua_getglobal(L, "length");
lua_getglobal(L, "height");

stackDump();
}

int main()
{
L = luaL_newstate();
luaL_openlibs(L);
luaL_dofile(L, "add.lua");
run();
}
【add.lua】
width = 7
length = 8
height = 9

function add(x, y)
-- print("x:",x,"y:",y)
return x + y
end

C调用Lua的函数、全局变量

步骤:

1、函数入栈,参数按正序入栈

2、void lua_call(lua_State,*L int nargs, int results)//nargs是参数的个数,results是返回的数量   会从栈中取出元素

3、从栈顶取出函数进行运算,将结果压入栈中

4、以上操作会把参数、函数本身出栈

通过lua_getglobal函数获取Lua的函数名、全局变量

通过虚拟栈进行数据交换

【main.cpp】

#include<bits/stdc++.h>
using namespace std;
extern "C"
{
#include "lua.hpp"
#include "lualib.h"
#include "lauxlib.h"
}

lua_State *L;

int add(int x, int y)
{
lua_getglobal(L, "add");//调用函数的步骤,放入函数,参数按序放入,然后调用lua_call
lua_pushnumber(L, x);
lua_pushnumber(L, y);
lua_call(L, 2, 1); //栈取出栈2个参数、1个返回值入栈

int sum = lua_tonumber(L, - 1);

lua_getglobal(L, "width");
lua_getglobal(L, "height");
lua_getglobal(L, "length");

int lens = lua_gettop(L);
printf("lens: %d\n", lens);
for(int i = 1; i <= lens; ++i){
int num = lua_tonumber(L, i);
printf("num:%d\n", num);
}
return sum;
}

int main()
{
L = luaL_newstate();
luaL_openlibs(L);
luaL_dofile(L, "add.lua");
int sum = add(10, 20);
printf("%d\n", sum);
lua_close(L);
return 0;
}

【add.lua】

width = 1
height = 2
length = 3

function add(x, y)
return x + y
end

Lua调用C的函数

其实还是在C工程下运行,只不过注册函数到Lua中,Lua调用了C函数

比较精妙的一点是,C注册函数至Lua后,Lua调用这个函数时传递的参数个数是动态的,会全部放入只属于这个函数的虚拟栈内,C函数通过取出栈内元素进行操作。

操作后的答案继续放入栈中,并且返回一个整数,代表答案的个数,Lua内通过相同数量的全局变量即可获得所有答案

注册函数两种方法

方法1: lua_register(L, "addmethod", Addmethod);

方法2:

lua_pushcfunction(L, Addmethod);  lua_setglobal(L, "addmethod");

【main.cpp】

#include<bits/stdc++.h>
using namespace std;

extern "C"
{
#include "lua.hpp"
#include "lualib.h"
#include "lauxlib.h"
}

lua_State *L;

static int Addmethod(lua_State *t)
{
int first = luaL_checknumber(t, 1);
int second = luaL_checknumber(t, 2);
lua_pushnumber(t, first + second);
return 1;
}

static int Printmethod(lua_State *t)
{
int answer = luaL_checknumber(t, 1);
printf("answer:%d\n", answer);
return 0;
}


int main()
{
L = luaL_newstate();
luaL_openlibs(L);

lua_register(L, "addmethod", Addmethod);
lua_register(L, "printmethod", Printmethod);

luaL_dofile(L, "add.lua");


lua_close(L);
return 0;
}

【add.lua】

first = 10
second = 20
local ans = addmethod(10, 20)
printmethod(ans)