5.lua api

1.lua的数据类型

#define LUA_TNONE		(-1)          	//无类型

#define LUA_TNIL			0           //空类型
#define LUA_TBOOLEAN		1         	//bool
#define LUA_TLIGHTUSERDATA	2     		//指针(需要关注内存释放)
#define LUA_TNUMBER			3           //数据
#define LUA_TSTRING			4           //string
#define LUA_TTABLE			5           //表
#define LUA_TFUNCTION		6         	//函数
#define LUA_TUSERDATA		7         	//指针(不需要关注内存释放)
#define LUA_TTHREAD			8           //lua虚拟机、协程

2.lua栈

2.1 栈底、栈顶和当前栈顶

struct lua_State {
...
  StkId top;  			//当前栈顶,指向一个未使用的位置
...
  StkId stack_last;  	//栈顶
  StkId stack;  		//栈底,栈基址
...
};

2.2栈的元素和初始化

static void stack_init (lua_State *L1, lua_State *L) {
...
  L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); //申请BASIC_STACK_SIZE + EXTRA_STACK个StackValue大小的内存
  L1->tbclist = L1->stack;
  for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++)	//clean
    setnilvalue(s2v(L1->stack + i));  /* erase new stack */
  L1->top = L1->stack;
  L1->stack_last = L1->stack + BASIC_STACK_SIZE;
...
}

这个函数调用的时候L1和L是同一个东西

static void f_luaopen (lua_State *L, void *ud) {
...
  stack_init(L, L);  /* init stack */
...
}

StackValue是这个栈的元素,这个结构的定义如下

#define TValuefields	Value value_; lu_byte tt_

typedef struct TValue {
  TValuefields;
} TValue;

typedef union StackValue {
  TValue val;
  struct {
    TValuefields;
    unsigned short delta;
  } tbclist;
} StackValue;

typedef StackValue *StkId;
#define s2v(o)	(&(o)->val)

可以看到StkIdStackValue的指针类型,我们的栈指针都是这个类型。StackValue本质是一个TValue类型(可以使用s2v这个宏转为TValue),也就是说这个栈可以存在lua的所有类型的数据
有关Tvalue的实现之前写过一篇,这里不再继续写 https://blog.csdn.net/qq_41252394/article/details/117868916

3.lua中操作栈的api

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vpg7XUXS-1630855807694)(./栈.png)]
栈索引

3.1 栈当前大小设置

LUA_API int   (lua_gettop) (lua_State *L);			 //获取当前的栈大小
LUA_API void  (lua_settop) (lua_State *L, int idx);	 //设置当前的栈大小
LUA_API int lua_gettop (lua_State *L) {
  return cast_int(L->top - (L->ci->func + 1));      //当前栈顶 - 当前函数基地址
}

LUA_API void lua_settop (lua_State *L, int idx) {
  CallInfo *ci;
  StkId func, newtop;
  ptrdiff_t diff;  /* difference for new top */
  lua_lock(L);
  ci = L->ci;
  func = ci->func;
  if (idx >= 0) {
    api_check(L, idx <= ci->top - (func + 1), "new top too large");
    diff = ((func + 1) + idx) - L->top;				//计算相对位置
    for (; diff > 0; diff--)
      setnilvalue(s2v(L->top++));  					//如果大于当前栈顶,把多余值置空
  }
  else {
    api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top");
    diff = idx + 1;  								//计算相对位置,-1是栈顶
  }
  api_check(L, L->tbclist < L->top, "previous pop of an unclosed slot");
  newtop = L->top + diff;							//计算新的栈顶位置
  if (diff < 0 && L->tbclist >= newtop) {			//栈基址大于新的栈顶位置
    lua_assert(hastocloseCfunc(ci->nresults));
    luaF_close(L, newtop, CLOSEKTOP, 0);
  }
  L->top = newtop;  								//设置新的栈顶位置
  lua_unlock(L);
}

3.2 在栈中取值

idx的各个范围

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AuLZEU8x-1630855807697)(./index_set.png)]

idx > 0:栈的正常索引

LUA_REGISTRYINDEX< idx <= 0:栈的正常索引

idx = LUA_REGISTRYINDEX: G(L)->l_registry

idx < LUA_REGISTRYINDEX:访问的是当前函数的upval表

#define ispseudo(i)		((i) <= LUA_REGISTRYINDEX)

static TValue *index2value (lua_State *L, int idx) {
  CallInfo *ci = L->ci;
  if (idx > 0) {								//正常的正数索引
    StkId o = ci->func + idx;					//取值
    api_check(L, idx <= L->ci->top - (ci->func + 1), "unacceptable index");
    if (o >= L->top) return &G(L)->nilvalue;	//如果这个值的地址大于当前栈顶,直接返回空值
    else return s2v(o);							//把值转为TValue
  }
  else if (!ispseudo(idx)) {  					//LUA_REGISTRYINDEX< idx <= 0 ,正常的负数索引
    api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index");
    return s2v(L->top + idx);
  }
  else if (idx == LUA_REGISTRYINDEX)			//idx = LUA_REGISTRYINDEX
    return &G(L)->l_registry;
  else {  										//idx < LUA_REGISTRYINDEX
    idx = LUA_REGISTRYINDEX - idx;				//>1
    api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large");
    if (ttislcf(s2v(ci->func)))  				//如果当前函数是c函数,返回空
      return &G(L)->nilvalue;
    else {										//返回idx-1的upval表
      CClosure *func = clCvalue(s2v(ci->func));
      return (idx <= func->nupvalues) ? &func->upvalue[idx-1]
                                      : &G(L)->nilvalue;
    }
  }
}

3.3 压栈

#define api_incr_top(L)   {L->top++; api_check(L, L->top <= L->ci->top, \
				"stack overflow");}

LUA_API void lua_pushvalue (lua_State *L, int idx) {
  lua_lock(L);
  setobj2s(L, L->top, index2value(L, idx));		//获取idx索引的值,写入当前栈顶
  api_incr_top(L);								//抬栈
  lua_unlock(L);
}

栈拷贝

LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) {
  TValue *fr, *to;
  lua_lock(L);
  fr = index2value(L, fromidx);
  to = index2value(L, toidx);
  api_check(L, isvalid(L, to), "invalid index");
  setobj(L, to, fr);			//拷贝
  if (isupvalue(toidx))  /* function upvalue? */
    luaC_barrier(L, clCvalue(s2v(L->ci->func)), fr);
  /* LUA_REGISTRYINDEX does not need gc barrier
     (collector revisits it before finishing collection) */
  lua_unlock(L);
}

各个类型版本的压栈

LUA_API void        (lua_pushnil) (lua_State *L);
LUA_API void        (lua_pushnumber) (lua_State *L, lua_Number n);
LUA_API void        (lua_pushinteger) (lua_State *L, lua_Integer n);
LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len);
LUA_API const char *(lua_pushstring) (lua_State *L, const char *s);
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
                                                      va_list argp);
LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
LUA_API void  (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
LUA_API void  (lua_pushboolean) (lua_State *L, int b);
LUA_API void  (lua_pushlightuserdata) (lua_State *L, void *p);
LUA_API int   (lua_pushthread) (lua_State *L);

这些函数都是类似的逻辑

  • 设置值
  • 抬栈

如:

LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
  lua_lock(L);
  setfltvalue(s2v(L->top), n);	//写值
  api_incr_top(L);				//抬栈
  lua_unlock(L);
}

3.4 类型相关的api

//类型判断
LUA_API int             (lua_isnumber) (lua_State *L, int idx);
LUA_API int             (lua_isstring) (lua_State *L, int idx);
LUA_API int             (lua_iscfunction) (lua_State *L, int idx);
LUA_API int             (lua_isinteger) (lua_State *L, int idx);
LUA_API int             (lua_isuserdata) (lua_State *L, int idx);


LUA_API int             (lua_type) (lua_State *L, int idx);			//返回类型
LUA_API const char     *(lua_typename) (lua_State *L, int tp);		//返回类型名

//类型转换
LUA_API lua_Number      (lua_tonumberx) (lua_State *L, int idx, int *isnum);
LUA_API lua_Integer     (lua_tointegerx) (lua_State *L, int idx, int *isnum);
LUA_API int             (lua_toboolean) (lua_State *L, int idx);
LUA_API const char     *(lua_tolstring) (lua_State *L, int idx, size_t *len);
LUA_API lua_CFunction   (lua_tocfunction) (lua_State *L, int idx);
LUA_API void	       *(lua_touserdata) (lua_State *L, int idx);
LUA_API lua_State      *(lua_tothread) (lua_State *L, int idx);
LUA_API const void     *(lua_topointer) (lua_State *L, int idx);

LUA_API lua_Unsigned    (lua_rawlen) (lua_State *L, int idx);		//取长度 #

这些代码相对简单不再展开

3.5 比较api

LUA_API int   (lua_rawequal) (lua_State *L, int idx1, int idx2);
LUA_API int   (lua_compare) (lua_State *L, int idx1, int idx2, int op);
LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
  const TValue *o1 = index2value(L, index1);		//取值
  const TValue *o2 = index2value(L, index2);		//取值
  return (isvalid(L, o1) && isvalid(L, o2)) ? luaV_rawequalobj(o1, o2) : 0; //如果都不为空,则开始比较
}

#define luaV_rawequalobj(t1,t2)		luaV_equalobj(NULL,t1,t2)

int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
  const TValue *tm;
  if (ttypetag(t1) != ttypetag(t2)) {  							//判断两个值的类型
    if (ttype(t1) != ttype(t2) || ttype(t1) != LUA_TNUMBER)		//判断两个值具体类型(int double)
      return 0;  /* only numbers can be equal with different variants */
    else {														//两个值一个是int,一个是double,转成int比较
      lua_Integer i1, i2;
      return (luaV_tointegerns(t1, &i1, F2Ieq) &&
              luaV_tointegerns(t2, &i2, F2Ieq) &&
              i1 == i2);
    }
  }
  //其他类型的比较
  switch (ttypetag(t1)) {
    case LUA_VNIL: case LUA_VFALSE: case LUA_VTRUE: return 1;
    case LUA_VNUMINT: return (ivalue(t1) == ivalue(t2));
    case LUA_VNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2));
    case LUA_VLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
    case LUA_VLCF: return fvalue(t1) == fvalue(t2);
    case LUA_VSHRSTR: return eqshrstr(tsvalue(t1), tsvalue(t2));
    case LUA_VLNGSTR: return luaS_eqlngstr(tsvalue(t1), tsvalue(t2));
    case LUA_VUSERDATA: {
      if (uvalue(t1) == uvalue(t2)) return 1;
      else if (L == NULL) return 0;
      tm = fasttm(L, uvalue(t1)->metatable, TM_EQ);
      if (tm == NULL)
        tm = fasttm(L, uvalue(t2)->metatable, TM_EQ);
      break;  /* will try TM */
    }
    case LUA_VTABLE: {
      if (hvalue(t1) == hvalue(t2)) return 1;
      else if (L == NULL) return 0;
      tm = fasttm(L, hvalue(t1)->metatable, TM_EQ);
      if (tm == NULL)
        tm = fasttm(L, hvalue(t2)->metatable, TM_EQ);
      break;  /* will try TM */
    }
    default:
      return gcvalue(t1) == gcvalue(t2);
  }
  if (tm == NULL)  /* no TM? */
    return 0;  /* objects are different */
  else {
    luaT_callTMres(L, tm, t1, t2, L->top);  /* call TM */
    return !l_isfalse(s2v(L->top));
  }
}

3.6 全局信息表

LUA_API int (lua_getglobal) (lua_State *L, const char *name);	//获取全局信息表,返回在栈中,函数返回值为该数据的类型
LUA_API void  (lua_setglobal) (lua_State *L, const char *name);	//设置全局信息表

全局信息表的位置

#define LUA_RIDX_GLOBALS	2
#define getGtable(L)  \
	(&hvalue(&G(L)->l_registry)->array[LUA_RIDX_GLOBALS - 1])

获取全局信息表

#define luaV_fastget(L,t,k,slot,f) \
  (!ttistable(t)  \
   ? (slot = NULL, 0)  /* not a table; 'slot' is NULL and result is 0 */  \
   : (slot = f(hvalue(t), k),  /* else, do raw access */  \
      !isempty(slot)))  /* result not empty? */

static int auxgetstr (lua_State *L, const TValue *t, const char *k) {
  const TValue *slot;
  TString *str = luaS_new(L, k);
  if (luaV_fastget(L, t, str, slot, luaH_getstr)) {	//获取key为k的值,输出到slot
    setobj2s(L, L->top, slot);						//如果slot不为空,把值压入栈中
    api_incr_top(L);
  }
  else {
    setsvalue2s(L, L->top, str);
    api_incr_top(L);
    luaV_finishget(L, t, s2v(L->top - 1), L->top - 1, slot);
  }
  lua_unlock(L);
  return ttype(s2v(L->top - 1));					//返回压入值的类型
}

//key为name,该值对应的val压入栈中
LUA_API int lua_getglobal (lua_State *L, const char *name) {
  const TValue *G;
  lua_lock(L);
  G = getGtable(L);				//获取全局信息表
  return auxgetstr(L, G, name);
}

设置全局信息表

#define luaV_finishfastset(L,t,slot,v) \
    { setobj2t(L, cast(TValue *,slot), v); \
      luaC_barrierback(L, gcvalue(t), v); }

static void auxsetstr (lua_State *L, const TValue *t, const char *k) {
  const TValue *slot;
  TString *str = luaS_new(L, k);
  api_checknelems(L, 1);
  if (luaV_fastget(L, t, str, slot, luaH_getstr)) {	 //获取key为k的值,输出到slot
    luaV_finishfastset(L, t, slot, s2v(L->top - 1)); //设置这个key的值
    L->top--;  /* pop value */
  }
  else {
    setsvalue2s(L, L->top, str);  /* push 'str' (to make it a TValue) */
    api_incr_top(L);
    luaV_finishset(L, t, s2v(L->top - 1), s2v(L->top - 2), slot);
    L->top -= 2;  /* pop value and key */
  }
  lua_unlock(L);  /* lock done by caller */
}

//key为name,val是压栈的值
LUA_API void lua_setglobal (lua_State *L, const char *name) {
  const TValue *G;
  lua_lock(L);  /* unlock done in 'auxsetstr' */
  G = getGtable(L);
  auxsetstr(L, G, name);
}

3.7 表操作

3.7.1 创建表

//创建表,压入栈中
LUA_API void  (lua_createtable) (lua_State *L, int narr, int nrec);

3.7.2 表的获取和修改

//获取表数据
LUA_API int (lua_gettable) (lua_State *L, int idx);
LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k);
LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n);
LUA_API int (lua_rawget) (lua_State *L, int idx);
LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p);
//设置表数据
LUA_API void  (lua_settable) (lua_State *L, int idx);
LUA_API void  (lua_setfield) (lua_State *L, int idx, const char *k);
LUA_API void  (lua_seti) (lua_State *L, int idx, lua_Integer n);
LUA_API void  (lua_rawset) (lua_State *L, int idx);
LUA_API void  (lua_rawseti) (lua_State *L, int idx, lua_Integer n);
LUA_API void  (lua_rawsetp) (lua_State *L, int idx, const void *p);
//idx为表在栈中的索引,key为刚压入栈的值,获取的值覆盖key的值
LUA_API int lua_gettable (lua_State *L, int idx) {
  const TValue *slot;
  TValue *t;
  lua_lock(L);
  t = index2value(L, idx);										//获取表的位置
  if (luaV_fastget(L, t, s2v(L->top - 1), slot, luaH_get)) {	//获取key为L->top - 1的值,赋值到slot
    setobj2s(L, L->top - 1, slot);								//覆盖key的值
  }
  else
    luaV_finishget(L, t, s2v(L->top - 1), L->top - 1, slot);
  lua_unlock(L);
  return ttype(s2v(L->top - 1));
}
//idx为表在栈中的索引,key第一次压入的值,value为第二次压入的值.把对应的key->val压入表中
LUA_API void lua_settable (lua_State *L, int idx) {
  TValue *t;
  const TValue *slot;
  lua_lock(L);
  api_checknelems(L, 2);
  t = index2value(L, idx);										//获取表的位置
  if (luaV_fastget(L, t, s2v(L->top - 2), slot, luaH_get)) {	//获取key为L->top - 2的值,赋值到slot
    luaV_finishfastset(L, t, slot, s2v(L->top - 1));			//设置这个key的值
  }
  else
    luaV_finishset(L, t, s2v(L->top - 2), s2v(L->top - 1), slot);
  L->top -= 2;  /* pop index and value */
  lua_unlock(L);
}

这组api和上面两个类似,只是key不用再压栈换成了函数的参数

LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k);
LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n);

LUA_API void  (lua_setfield) (lua_State *L, int idx, const char *k);
LUA_API void  (lua_seti) (lua_State *L, int idx, lua_Integer n);

3.7.3 元表

元表是table类型的一个子表

typedef struct Table {
  CommonHeader;
  lu_byte flags;  /* 1<<p means tagmethod(p) is not present */
  lu_byte lsizenode;  /* log2 of size of 'node' array */
  unsigned int alimit;  /* "limit" of 'array' array */
  TValue *array;  /* array part */
  Node *node;
  Node *lastfree;  /* any free position is before this position */
  struct Table *metatable; 	//元表
  GCObject *gclist;
} Table;
3.7.3.1 创建元表
LUALIB_API int   (luaL_newmetatable) (lua_State *L, const char *tname);

//返回元表压入栈中
LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
  if (luaL_getmetatable(L, tname) != LUA_TNIL)  //检查名称是否被使用
    return 0;  /* leave previous value on top, but return 0 */
  lua_pop(L, 1);								//弹出栈中的nil值
  lua_createtable(L, 0, 2);  					//创建table
  lua_pushstring(L, tname);						
  lua_setfield(L, -2, "__name");  				//metatable[__name] = tname
  lua_pushvalue(L, -1);
  lua_setfield(L, LUA_REGISTRYINDEX, tname);  	//registry.name = metatable
  return 1;
}
3.7.3.2 设置元表
LUALIB_API void  (luaL_setmetatable) (lua_State *L, const char *tname);

LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) {
  luaL_getmetatable(L, tname);					//获取元表
  lua_setmetatable(L, -2);
}

LUA_API int lua_setmetatable (lua_State *L, int objindex) {
  TValue *obj;
  Table *mt;
  lua_lock(L);
  api_checknelems(L, 1);
  obj = index2value(L, objindex);				//获取设置元表的对象
  if (ttisnil(s2v(L->top - 1)))					//如果元表为空,直接设置为NULL
    mt = NULL;
  else {
    api_check(L, ttistable(s2v(L->top - 1)), "table expected");
    mt = hvalue(s2v(L->top - 1));				//如果不为空,TValue转成Table
  }
  switch (ttype(obj)) {
    case LUA_TTABLE: {
      hvalue(obj)->metatable = mt;				//设置元表
      if (mt) {
        luaC_objbarrier(L, gcvalue(obj), mt);
        luaC_checkfinalizer(L, gcvalue(obj), mt);
      }
      break;
    }
    case LUA_TUSERDATA: {
      uvalue(obj)->metatable = mt;
      if (mt) {
        luaC_objbarrier(L, uvalue(obj), mt);
        luaC_checkfinalizer(L, gcvalue(obj), mt);
      }
      break;
    }
    default: {
      G(L)->mt[ttype(obj)] = mt;
      break;
    }
  }
  L->top--;
  lua_unlock(L);
  return 1;
}

4.lua和c交互

4.1 lua文件解析和函数调用

#define luaL_dofile(L, fn) \
	(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))

luaL_loadfile是lua的文件解析函数返回一个Closure对象压入栈中
lua_pcall是函数执行函数负责执行Closure对象函数对象

4.2 全局变量的获取

lua脚本中的常用的类型 number、string、table、function。
获取全局变量的函数只要使用 lua_getglobal

首先我们使用lua api去执行这个脚本,执行完lua脚本。脚本执行完后lua状态机的一些信息将会被修改。
如全局变量表G(L)->l_registry 将会加入这些全局变量的符号。之后使用lua_getglobal获取这些信息

反之我们可以使用lua api去改变lua状态机,然后再去执行lua脚本。这样就可以在c中设置一下全局变量给lua

4.2.1 脚本执行

int main(int argc,char *argv[])
{
	//创建lua状态机
    lua_State *ls = luaL_newstate();
	//编译并且执行lua脚本
    int ret = luaL_loadfile(ls,"../lua/test.lua") || lua_pcall(ls,0,0,0);
    if (ret) {
        fprintf(stderr,"%s\n",lua_tostring(ls,-1));
        lua_pop(ls,1);
        return -1;
    }
	//释放状态机资源
	lua_close(ls);
	
	return 0;
}

4.2.2 lua_getglobal的使用

width = 10
height = 30
str = "hello lua"

tab = {a=12,b=14,c=30}

function number_max(a,b)
    if a > b then
        return a
    end

    return b
end

获取number

//获取int值
int get_int_val(lua_State *L,const char *name,lua_Integer *val)
{
    lua_getglobal(L,name);
    if (!lua_isinteger(L,-1)) {
        return -1;
    }
	
    *val = lua_tointeger(L,-1);
    lua_pop(L,1);

    return 0;
}

int main(int argc,char *argv[])
{
	//创建lua状态机
    lua_State *ls = luaL_newstate();
	//编译并且执行lua脚本
    int ret = luaL_loadfile(ls,"../lua/test.lua") || lua_pcall(ls,0,0,0);
    if (ret) {
        fprintf(stderr,"%s\n",lua_tostring(ls,-1));
        lua_pop(ls,1);
        return -1;
    }
	
	lua_Integer width = 0;
    get_int_val(ls,"width",&width);

    lua_Integer height = 0;
    get_int_val(ls,"height",&height);

    printf("width = %lld\nheight = %lld\n",width,height);
	
	//释放状态机资源
	lua_close(ls);
	
	return 0;
}

获取string

	lua_getglobal(ls,"str");
    const char *str = lua_tostring(ls,-1);
    lua_pop(ls,1);
    printf("str = %s\n",str);

获取table

    lua_getglobal(ls,"tab");

    lua_getfield(ls,-1,"a");
    lua_Integer a = lua_tointeger(ls,-1);
    lua_pop(ls,1);
    lua_getfield(ls,-1,"b");
    lua_Integer b = lua_tointeger(ls,-1);
    lua_pop(ls,1);
    printf("a = %lld\nb = %lld\n",a,b);

    lua_pop(ls,1);

也可以使用原生table的数据结构的api

    lua_getglobal(ls,"tab");
    Table *table = hvalue(s2v(ls->top-1));
    const TValue *pa = luaH_getstr(table,luaS_newliteral(ls,"a"));
    const TValue *pb = luaH_getstr(table,luaS_newliteral(ls,"b"));
    lua_pop(ls,1);
    printf("a = %lld\nb = %lld\n",ivalue(pa),ivalue(pb));

函数

	lua_getglobal(ls,"number_max");
	//参数从左到右压栈
    lua_pushinteger(ls,20);
    lua_pushinteger(ls,99);
	//函数执行,两个参数,一个返回值
    lua_call(ls,2,1);
	//函数执行完,函数返回值压栈
    lua_Integer max_ret = lua_tointeger(ls,-1);
    printf("call function return %lld\n",max_ret);
    lua_pop(ls,1);

4.2.3 lua_setglobal的使用

print("width = "..width)
print("height = "..height)
print("str = "..str)

print(tab)
for k,v in pairs(tab) do
    print(k,v)
end

print("max = "..number_max(20,40))

设置number

int main_set(int argc,char *argv[])
{
    lua_State *ls = luaL_newstate();
    luaL_openlibs(ls);

    lua_pushinteger(ls,480);
    lua_setglobal(ls,"width");

    lua_pushinteger(ls,1080);
    lua_setglobal(ls,"height");

    int ret = luaL_loadfile(ls,"../lua/lua_api_set.lua") || lua_pcall(ls,0,0,0);
    if (ret) {
        fprintf(stderr,"%s\n",lua_tostring(ls,-1)); //
        lua_pop(ls,1);
        return -1;
    }

    return 0;
}

设置string

    lua_pushstring(ls,"hello lua");
    lua_setglobal(ls,"str")

设置table

    lua_newtable(ls);			//创建table,创建完table会压入栈中

    lua_pushnumber(ls,30);
    lua_setfield(ls,-2,"a");	//tab["a"] = 30
    lua_pushnumber(ls,99);
    lua_setfield(ls,-2,"b");

    lua_setglobal(ls,"tab");

函数

int lua_max(lua_State *ls)
{
    lua_Integer a = luaL_checkinteger(ls,-2);
    lua_Integer b = luaL_checkinteger(ls,-1);

    lua_pushinteger(ls,(a > b ? a : b));

    return 1;
}

    lua_pushcfunction(ls,lua_max);
    lua_setglobal(ls,"number_max");

lua函数的格式

typedef int (*lua_CFunction) (lua_State *L);
  • 函数的返回值是lua函数返回的参数个数
  • lua函数调用时的参数,是通过压栈的方式传入c函数中的
  • lua函数的返回值是c函数压栈传出的
  • 可以通过当前函数的栈顶来确认传入c函数的参数个数 lua_gettop
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值