目錄
C虛拟棧技術
壓入元素
查詢元素
其他棧操作
lua_is*函數
lua_to*函數從棧中擷取一個值
練習
C調用Lua的函數、全局變量
Lua調用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個棧頂元素
為了檢查一個元素是否為特定的類型,API提供了lua_is*.lua_isnumber、lua_isstring、lua_istable等 int lua_is*(lua_State int index); --給定的索引值是,在L中的索引 實際上,lua_isnumber是檢查值是否能轉換為數字類型,lua_isstring也有同樣的行為
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的函數名、全局變量
通過虛拟棧進行資料交換
#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");
#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;
}
first = 10
second = 20
local ans = addmethod(10, 20)
printmethod(ans)