5.lua api

本文详细剖析了Lua的数据类型、栈结构及其API,包括栈顶设置、值的压栈与复制,以及lua与C的交互过程,重点讲解了lua表操作、元表、全局信息表和函数调用等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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
#if USE_UNI_LUA using LuaAPI = UniLua.Lua; using RealStatePtr = UniLua.ILuaState; using LuaCSFunction = UniLua.CSharpFunctionDelegate; #else using LuaAPI = XLua.LuaDLL.Lua; using RealStatePtr = System.IntPtr; using LuaCSFunction = XLua.LuaDLL.lua_CSFunction; #endif using XLua; using System.Collections.Generic; namespace CSObjectWrap { public class UnityEngineWWWWrap { public static void __Register(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); Utils.BeginObjectRegister(typeof(UnityEngine.WWW), L, translator, 0, 5, 15, 1); Utils.RegisterFunc(L, Utils.METHOD_IDX, "Dispose", Dispose); Utils.RegisterFunc(L, Utils.METHOD_IDX, "InitWWW", InitWWW); Utils.RegisterFunc(L, Utils.METHOD_IDX, "GetAudioClip", GetAudioClip); Utils.RegisterFunc(L, Utils.METHOD_IDX, "GetAudioClipCompressed", GetAudioClipCompressed); Utils.RegisterFunc(L, Utils.METHOD_IDX, "LoadImageIntoTexture", LoadImageIntoTexture); Utils.RegisterFunc(L, Utils.GETTER_IDX, "responseHeaders", get_responseHeaders); Utils.RegisterFunc(L, Utils.GETTER_IDX, "text", get_text); Utils.RegisterFunc(L, Utils.GETTER_IDX, "bytes", get_bytes); Utils.RegisterFunc(L, Utils.GETTER_IDX, "size", get_size); Utils.RegisterFunc(L, Utils.GETTER_IDX, "error", get_error); Utils.RegisterFunc(L, Utils.GETTER_IDX, "texture", get_texture); Utils.RegisterFunc(L, Utils.GETTER_IDX, "textureNonReadable", get_textureNonReadable); Utils.RegisterFunc(L, Utils.GETTER_IDX, "audioClip", get_audioClip); Utils.RegisterFunc(L, Utils.GETTER_IDX, "isDone", get_isDone); Utils.RegisterFunc(L, Utils.GETTER_IDX, "progress", get_progress); Utils.RegisterFunc(L, Utils.GETTER_IDX, "uploadProgress", get_uploadProgress); Utils.RegisterFunc(L, Utils.GETTER_IDX, "bytesDownloaded", get_bytesDownloaded); Utils.RegisterFunc(L, Utils.GETTER_IDX, "url", get_url); Utils.RegisterFunc(L, Utils.GETTER_IDX, "assetBundle", get_assetBundle); Utils.RegisterFunc(L, Utils.GETTER_IDX, "threadPriority", get_threadPriority); Utils.RegisterFunc(L, Utils.SETTER_IDX, "threadPriority", set_threadPriority); Utils.EndObjectRegister(typeof(UnityEngine.WWW), L, translator, null, null, null, null, null); Utils.BeginClassRegister(typeof(UnityEngine.WWW), L, __CreateInstance, 4, 0, 0); Utils.RegisterFunc(L, Utils.CLS_IDX, "EscapeURL", EscapeURL_xlua_st_); Utils.RegisterFunc(L, Utils.CLS_IDX, "UnEscapeURL", UnEscapeURL_xlua_st_); Utils.RegisterFunc(L, Utils.CLS_IDX, "LoadFromCacheOrDownload", LoadFromCacheOrDownload_xlua_st_); Utils.RegisterObject(L, translator, Utils.CLS_IDX, "UnderlyingSystemType", typeof(UnityEngine.WWW)); Utils.EndClassRegister(typeof(UnityEngine.WWW), L, translator); } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int __CreateInstance(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { if(LuaAPI.lua_gettop(L) == 2 && (LuaAPI.lua_isnil(L, 2) || LuaAPI.lua_type(L, 2) == LuaTypes.LUA_TSTRING)) { string url = LuaAPI.lua_tostring(L, 2); UnityEngine.WWW __cl_gen_ret = new UnityEngine.WWW(url); translator.Push(L, __cl_gen_ret); return 1; } if(LuaAPI.lua_gettop(L) == 3 && (LuaAPI.lua_isnil(L, 2) || LuaAPI.lua_type(L, 2) == LuaTypes.LUA_TSTRING) && translator.Assignable<UnityEngine.WWWForm>(L, 3)) { string url = LuaAPI.lua_tostring(L, 2); UnityEngine.WWWForm form = (UnityEngine.WWWForm)translator.GetObject(L, 3, typeof(UnityEngine.WWWForm)); UnityEngine.WWW __cl_gen_ret = new UnityEngine.WWW(url, form); translator.Push(L, __cl_gen_ret); return 1; } if(LuaAPI.lua_gettop(L) == 3 && (LuaAPI.lua_isnil(L, 2) || LuaAPI.lua_type(L, 2) == LuaTypes.LUA_TSTRING) && (LuaAPI.lua_isnil(L, 3) || LuaAPI.lua_type(L, 3) == LuaTypes.LUA_TSTRING)) { string url = LuaAPI.lua_tostring(L, 2); byte[] postData = LuaAPI.lua_tobytes(L, 3); UnityEngine.WWW __cl_gen_ret = new UnityEngine.WWW(url, postData); translator.Push(L, __cl_gen_ret); return 1; } if(LuaAPI.lua_gettop(L) == 4 && (LuaAPI.lua_isnil(L, 2) || LuaAPI.lua_type(L, 2) == LuaTypes.LUA_TSTRING) && (LuaAPI.lua_isnil(L, 3) || LuaAPI.lua_type(L, 3) == LuaTypes.LUA_TSTRING) && translator.Assignable<System.Collections.Generic.Dictionary<string, string>>(L, 4)) { string url = LuaAPI.lua_tostring(L, 2); byte[] postData = LuaAPI.lua_tobytes(L, 3); System.Collections.Generic.Dictionary<string, string> headers = (System.Collections.Generic.Dictionary<string, string>)translator.GetObject(L, 4, typeof(System.Collections.Generic.Dictionary<string, string>)); UnityEngine.WWW __cl_gen_ret = new UnityEngine.WWW(url, postData, headers); translator.Push(L, __cl_gen_ret); return 1; } } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return LuaAPI.luaL_error(L, "invalid arguments to UnityEngine.WWW constructor!"); } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int Dispose(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); try { { __cl_gen_to_be_invoked.Dispose( ); return 0; } } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int InitWWW(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); try { { string url = LuaAPI.lua_tostring(L, 2); byte[] postData = LuaAPI.lua_tobytes(L, 3); string[] iHeaders = (string[])translator.GetObject(L, 4, typeof(string[])); __cl_gen_to_be_invoked.InitWWW( url, postData, iHeaders ); return 0; } } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int EscapeURL_xlua_st_(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); int __gen_param_count = LuaAPI.lua_gettop(L); try { if(__gen_param_count == 1&& (LuaAPI.lua_isnil(L, 1) || LuaAPI.lua_type(L, 1) == LuaTypes.LUA_TSTRING)) { string s = LuaAPI.lua_tostring(L, 1); string __cl_gen_ret = UnityEngine.WWW.EscapeURL( s ); LuaAPI.lua_pushstring(L, __cl_gen_ret); return 1; } if(__gen_param_count == 2&& (LuaAPI.lua_isnil(L, 1) || LuaAPI.lua_type(L, 1) == LuaTypes.LUA_TSTRING)&& translator.Assignable<System.Text.Encoding>(L, 2)) { string s = LuaAPI.lua_tostring(L, 1); System.Text.Encoding e = (System.Text.Encoding)translator.GetObject(L, 2, typeof(System.Text.Encoding)); string __cl_gen_ret = UnityEngine.WWW.EscapeURL( s, e ); LuaAPI.lua_pushstring(L, __cl_gen_ret); return 1; } } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return LuaAPI.luaL_error(L, "invalid arguments to UnityEngine.WWW.EscapeURL!"); } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int UnEscapeURL_xlua_st_(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); int __gen_param_count = LuaAPI.lua_gettop(L); try { if(__gen_param_count == 1&& (LuaAPI.lua_isnil(L, 1) || LuaAPI.lua_type(L, 1) == LuaTypes.LUA_TSTRING)) { string s = LuaAPI.lua_tostring(L, 1); string __cl_gen_ret = UnityEngine.WWW.UnEscapeURL( s ); LuaAPI.lua_pushstring(L, __cl_gen_ret); return 1; } if(__gen_param_count == 2&& (LuaAPI.lua_isnil(L, 1) || LuaAPI.lua_type(L, 1) == LuaTypes.LUA_TSTRING)&& translator.Assignable<System.Text.Encoding>(L, 2)) { string s = LuaAPI.lua_tostring(L, 1); System.Text.Encoding e = (System.Text.Encoding)translator.GetObject(L, 2, typeof(System.Text.Encoding)); string __cl_gen_ret = UnityEngine.WWW.UnEscapeURL( s, e ); LuaAPI.lua_pushstring(L, __cl_gen_ret); return 1; } } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return LuaAPI.luaL_error(L, "invalid arguments to UnityEngine.WWW.UnEscapeURL!"); } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int GetAudioClip(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); int __gen_param_count = LuaAPI.lua_gettop(L); try { if(__gen_param_count == 2&& LuaTypes.LUA_TBOOLEAN == LuaAPI.lua_type(L, 2)) { bool threeD = LuaAPI.lua_toboolean(L, 2); UnityEngine.AudioClip __cl_gen_ret = __cl_gen_to_be_invoked.GetAudioClip( threeD ); translator.Push(L, __cl_gen_ret); return 1; } if(__gen_param_count == 3&& LuaTypes.LUA_TBOOLEAN == LuaAPI.lua_type(L, 2)&& LuaTypes.LUA_TBOOLEAN == LuaAPI.lua_type(L, 3)) { bool threeD = LuaAPI.lua_toboolean(L, 2); bool stream = LuaAPI.lua_toboolean(L, 3); UnityEngine.AudioClip __cl_gen_ret = __cl_gen_to_be_invoked.GetAudioClip( threeD, stream ); translator.Push(L, __cl_gen_ret); return 1; } if(__gen_param_count == 4&& LuaTypes.LUA_TBOOLEAN == LuaAPI.lua_type(L, 2)&& LuaTypes.LUA_TBOOLEAN == LuaAPI.lua_type(L, 3)&& translator.Assignable<UnityEngine.AudioType>(L, 4)) { bool threeD = LuaAPI.lua_toboolean(L, 2); bool stream = LuaAPI.lua_toboolean(L, 3); UnityEngine.AudioType audioType;translator.Get(L, 4, out audioType); UnityEngine.AudioClip __cl_gen_ret = __cl_gen_to_be_invoked.GetAudioClip( threeD, stream, audioType ); translator.Push(L, __cl_gen_ret); return 1; } } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return LuaAPI.luaL_error(L, "invalid arguments to UnityEngine.WWW.GetAudioClip!"); } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int GetAudioClipCompressed(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); int __gen_param_count = LuaAPI.lua_gettop(L); try { if(__gen_param_count == 1) { UnityEngine.AudioClip __cl_gen_ret = __cl_gen_to_be_invoked.GetAudioClipCompressed( ); translator.Push(L, __cl_gen_ret); return 1; } if(__gen_param_count == 2&& LuaTypes.LUA_TBOOLEAN == LuaAPI.lua_type(L, 2)) { bool threeD = LuaAPI.lua_toboolean(L, 2); UnityEngine.AudioClip __cl_gen_ret = __cl_gen_to_be_invoked.GetAudioClipCompressed( threeD ); translator.Push(L, __cl_gen_ret); return 1; } if(__gen_param_count == 3&& LuaTypes.LUA_TBOOLEAN == LuaAPI.lua_type(L, 2)&& translator.Assignable<UnityEngine.AudioType>(L, 3)) { bool threeD = LuaAPI.lua_toboolean(L, 2); UnityEngine.AudioType audioType;translator.Get(L, 3, out audioType); UnityEngine.AudioClip __cl_gen_ret = __cl_gen_to_be_invoked.GetAudioClipCompressed( threeD, audioType ); translator.Push(L, __cl_gen_ret); return 1; } } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return LuaAPI.luaL_error(L, "invalid arguments to UnityEngine.WWW.GetAudioClipCompressed!"); } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int LoadImageIntoTexture(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); try { { UnityEngine.Texture2D tex = (UnityEngine.Texture2D)translator.GetObject(L, 2, typeof(UnityEngine.Texture2D)); __cl_gen_to_be_invoked.LoadImageIntoTexture( tex ); return 0; } } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int LoadFromCacheOrDownload_xlua_st_(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); int __gen_param_count = LuaAPI.lua_gettop(L); try { if(__gen_param_count == 2&& (LuaAPI.lua_isnil(L, 1) || LuaAPI.lua_type(L, 1) == LuaTypes.LUA_TSTRING)&& LuaTypes.LUA_TNUMBER == LuaAPI.lua_type(L, 2)) { string url = LuaAPI.lua_tostring(L, 1); int version = LuaAPI.xlua_tointeger(L, 2); UnityEngine.WWW __cl_gen_ret = UnityEngine.WWW.LoadFromCacheOrDownload( url, version ); translator.Push(L, __cl_gen_ret); return 1; } if(__gen_param_count == 3&& (LuaAPI.lua_isnil(L, 1) || LuaAPI.lua_type(L, 1) == LuaTypes.LUA_TSTRING)&& LuaTypes.LUA_TNUMBER == LuaAPI.lua_type(L, 2)&& LuaTypes.LUA_TNUMBER == LuaAPI.lua_type(L, 3)) { string url = LuaAPI.lua_tostring(L, 1); int version = LuaAPI.xlua_tointeger(L, 2); uint crc = LuaAPI.xlua_touint(L, 3); UnityEngine.WWW __cl_gen_ret = UnityEngine.WWW.LoadFromCacheOrDownload( url, version, crc ); translator.Push(L, __cl_gen_ret); return 1; } if(__gen_param_count == 2&& (LuaAPI.lua_isnil(L, 1) || LuaAPI.lua_type(L, 1) == LuaTypes.LUA_TSTRING)&& translator.Assignable<UnityEngine.Hash128>(L, 2)) { string url = LuaAPI.lua_tostring(L, 1); UnityEngine.Hash128 hash;translator.Get(L, 2, out hash); UnityEngine.WWW __cl_gen_ret = UnityEngine.WWW.LoadFromCacheOrDownload( url, hash ); translator.Push(L, __cl_gen_ret); return 1; } if(__gen_param_count == 3&& (LuaAPI.lua_isnil(L, 1) || LuaAPI.lua_type(L, 1) == LuaTypes.LUA_TSTRING)&& translator.Assignable<UnityEngine.Hash128>(L, 2)&& LuaTypes.LUA_TNUMBER == LuaAPI.lua_type(L, 3)) { string url = LuaAPI.lua_tostring(L, 1); UnityEngine.Hash128 hash;translator.Get(L, 2, out hash); uint crc = LuaAPI.xlua_touint(L, 3); UnityEngine.WWW __cl_gen_ret = UnityEngine.WWW.LoadFromCacheOrDownload( url, hash, crc ); translator.Push(L, __cl_gen_ret); return 1; } } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return LuaAPI.luaL_error(L, "invalid arguments to UnityEngine.WWW.LoadFromCacheOrDownload!"); } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int get_responseHeaders(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); translator.Push(L, __cl_gen_to_be_invoked.responseHeaders); } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return 1; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int get_text(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); LuaAPI.lua_pushstring(L, __cl_gen_to_be_invoked.text); } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return 1; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int get_bytes(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); LuaAPI.lua_pushstring(L, __cl_gen_to_be_invoked.bytes); } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return 1; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int get_size(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); LuaAPI.xlua_pushinteger(L, __cl_gen_to_be_invoked.size); } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return 1; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int get_error(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); LuaAPI.lua_pushstring(L, __cl_gen_to_be_invoked.error); } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return 1; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int get_texture(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); translator.Push(L, __cl_gen_to_be_invoked.texture); } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return 1; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int get_textureNonReadable(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); translator.Push(L, __cl_gen_to_be_invoked.textureNonReadable); } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return 1; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int get_audioClip(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); translator.Push(L, __cl_gen_to_be_invoked.GetAudioClip()); } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return 1; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int get_isDone(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); LuaAPI.lua_pushboolean(L, __cl_gen_to_be_invoked.isDone); } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return 1; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int get_progress(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); LuaAPI.lua_pushnumber(L, __cl_gen_to_be_invoked.progress); } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return 1; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int get_uploadProgress(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); LuaAPI.lua_pushnumber(L, __cl_gen_to_be_invoked.uploadProgress); } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return 1; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int get_bytesDownloaded(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); LuaAPI.xlua_pushinteger(L, __cl_gen_to_be_invoked.bytesDownloaded); } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return 1; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int get_url(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); LuaAPI.lua_pushstring(L, __cl_gen_to_be_invoked.url); } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return 1; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int get_assetBundle(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); translator.Push(L, __cl_gen_to_be_invoked.assetBundle); } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return 1; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int get_threadPriority(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); translator.Push(L, __cl_gen_to_be_invoked.threadPriority); } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return 1; } [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int set_threadPriority(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { UnityEngine.WWW __cl_gen_to_be_invoked = (UnityEngine.WWW)translator.FastGetCSObj(L, 1); UnityEngine.ThreadPriority __cl_gen_value;translator.Get(L, 2, out __cl_gen_value); __cl_gen_to_be_invoked.threadPriority = __cl_gen_value; } catch(System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return 0; } } } 这个代码是Unity5.3.3f1版本的,现在升级到Unity2021.3.45f1版本,提示Assets\XLua\Gen\UnityEngineWWWWrap.cs(167,44): error CS1061: 'WWW' does not contain a definition for 'InitWWW' and no accessible extension method 'InitWWW' accepting a first argument of type 'WWW' could be found (are you missing a using directive or an assembly reference?) Assets\XLua\Gen\UnityEngineRandomWrap.cs(60,6): error CS0723: Cannot declare a variable of static type 'Random' Assets\XLua\Gen\UnityEngineRandomWrap.cs(60,40): error CS0712: Cannot create an instance of the static class 'Random' Assets\XLua\Gen\UnityEngineShaderWrap.cs(69,44): error CS1729: 'Shader' does not contain a constructor that takes 0 arguments 请问怎么解决
最新发布
07-07
<think>根据错误信息,主要问题集中在三个地方: 1. UnityEngine.WWW 类在 Unity2021 中已经移除了 `InitWWW` 方法。 2. UnityEngine.Random 是静态类,不能创建实例。 3. UnityEngine.Shader 没有无参构造函数。 解决方案: 1. **UnityEngineWWWWrap.cs**:移除对 `InitWWW` 方法的注册和实现。 修改注册部分:将方法数量从5改为4,并移除 `InitWWW` 的注册。 同时删除 `InitWWW` 方法的具体实现代码(167行附近的方法)。 2. **UnityEngineRandomWrap.cs**:由于 `Random` 是静态类,不应该有实例方法。需要检查代码中是否有尝试创建 `Random` 实例的地方,并修改为直接调用静态方法。 具体错误在60行,可能是尝试创建 `Random` 实例。需要删除创建实例的代码,改为使用静态类的方式。 3. **UnityEngineShaderWrap.cs**:`Shader` 类没有无参构造函数,因此不能使用无参构造。需要检查代码中是否有尝试调用无参构造函数的地方,并修改为使用 `Shader` 的静态方法(如 `Find`)来获取实例。 下面分别给出修改代码示例: ### 1. 修改 UnityEngineWWWWrap.cs 找到注册方法的部分,将方法数量改为4,并移除 `InitWWW` 的注册: ```csharp // 修改前: Utils.BeginObjectRegister(typeof(UnityEngine.WWW), L, translator, 0, 5, 15, 1); Utils.RegisterFunc(L, Utils.METHOD_IDX, "Dispose", Dispose); Utils.RegisterFunc(L, Utils.METHOD_IDX, "InitWWW", InitWWW); // 移除这一行 Utils.RegisterFunc(L, Utils.METHOD_IDX, "GetAudioClip", GetAudioClip); Utils.RegisterFunc(L, Utils.METHOD_IDX, "GetAudioClipCompressed", GetAudioClipCompressed); Utils.RegisterFunc(L, Utils.METHOD_IDX, "LoadImageIntoTexture", LoadImageIntoTexture); // 修改后: Utils.BeginObjectRegister(typeof(UnityEngine.WWW), L, translator, 0, 4, 15, 1); // 方法数量改为4 Utils.RegisterFunc(L, Utils.METHOD_IDX, "Dispose", Dispose); // 移除 InitWWW 的注册 Utils.RegisterFunc(L, Utils.METHOD_IDX, "GetAudioClip", GetAudioClip); Utils.RegisterFunc(L, Utils.METHOD_IDX, "GetAudioClipCompressed", GetAudioClipCompressed); Utils.RegisterFunc(L, Utils.METHOD_IDX, "LoadImageIntoTexture", LoadImageIntoTexture); ``` 然后删除 `InitWWW` 方法的具体实现(整个方法体,大约在167行附近): ```csharp // 删除以下整个方法 // [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] // static int InitWWW(RealStatePtr L) // { // ... // } ``` ### 2. 修改 UnityEngineRandomWrap.cs 错误提示在60行,可能是尝试创建 `Random` 实例。由于 `Random` 是静态类,不能实例化。需要修改代码,避免创建实例。 例如,如果代码中有类似这样的行: ```csharp Random __cl_gen_to_be_invoked = new Random(); // 错误行 ``` 应该改为直接使用静态类,不需要实例。具体修改需要根据上下文,但通常对于静态类的封装,我们只注册静态方法,不创建实例。 在 `__CreateInstance` 方法中(如果存在),应该直接返回错误,因为不能创建实例。或者修改为不创建实例,而是直接使用类型。 由于没有提供完整的 `UnityEngineRandomWrap.cs` 代码,这里假设在 `__CreateInstance` 方法中尝试创建实例。我们可以修改 `__CreateInstance` 方法,使其返回一个错误,或者返回一个代表静态类的特殊对象(但通常XLua对静态类不需要实例)。 一个简单的修改是:如果 `__CreateInstance` 方法中尝试创建实例,直接移除创建实例的代码,并返回0(表示没有创建实例)。或者改为返回静态类的类型信息。 但是,根据错误信息,我们也可以这样修改: ```csharp // 在 UnityEngineRandomWrap.cs 中找到 __CreateInstance 方法 [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int __CreateInstance(RealStatePtr L) { // 由于Random是静态类,不能创建实例,所以直接返回错误 return LuaAPI.luaL_error(L, "cannot create instance of static class Random"); } ``` 同时,在注册类时,应该使用 `Utils.BeginClassRegister` 注册静态类,并且确保没有尝试创建实例。 另外,检查类注册部分,确保在注册类时,`__CreateInstance` 参数传入的是正确的函数(或者对于静态类,可以传入null)。例如: ```csharp Utils.BeginClassRegister(typeof(UnityEngine.Random), L, null, ...); // 第三个参数为null,表示没有创建实例的函数 ``` ### 3. 修改 UnityEngineShaderWrap.cs 错误提示:`Shader` 没有无参构造函数。因此,不能在 `__CreateInstance` 方法中调用无参构造函数。 在 `__CreateInstance` 方法中,应该使用 `Shader` 的静态方法(如 `Find`)来获取实例,或者避免创建实例(因为 `Shader` 通常不需要创建实例,而是通过静态方法获取)。 但是,查看 `Shader` 类的API,它并没有提供公共的构造函数。因此,我们只能通过已有的静态方法获取 `Shader` 对象。所以,在Lua中创建 `Shader` 实例可能是不合理的。 我们需要修改 `__CreateInstance` 方法,使其支持通过 `Find` 等静态方法获取 `Shader` 对象。或者,不允许创建 `Shader` 实例,只允许调用静态方法。 由于没有提供完整的 `UnityEngineShaderWrap.cs` 代码,这里给出一个可能的修改:在 `__CreateInstance` 方法中,如果参数是一个字符串(shader路径),则调用 `Shader.Find` 方法。 ```csharp [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int __CreateInstance(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { if (LuaAPI.lua_gettop(L) == 2 && LuaAPI.lua_type(L, 2) == LuaTypes.LUA_TSTRING) { string shaderPath = LuaAPI.lua_tostring(L, 2); UnityEngine.Shader shader = UnityEngine.Shader.Find(shaderPath); if (shader == null) { // 可以返回nil或者抛出错误 return LuaAPI.luaL_error(L, "shader not found: " + shaderPath); } translator.Push(L, shader); return 1; } } catch (System.Exception e) { return LuaAPI.luaL_error(L, "c# exception: " + e); } return LuaAPI.luaL_error(L, "invalid arguments to Shader constructor: must provide a shader path string."); } ``` 同时,在注册类时,确保 `__CreateInstance` 方法被正确注册。 另外,如果 `Shader` 类在Lua中主要是调用静态方法,那么也可以禁止创建实例,只注册静态方法。这取决于你的需求。 ### 总结 以上修改需要针对每个文件进行。由于Unity升级导致API变化,我们需要调整XLua生成的包装代码以适应新版本的Unity API。建议在修改后重新生成XLua代码(如果可能),或者手动修改生成的包装代码。 注意:由于Unity2021中 `WWW` 类已经被标记为过时(obsolete),建议使用 `UnityWebRequest` 替代。如果可能,尽量避免使用 `WWW` 类。 如果问题仍然存在,可能需要检查XLua的版本是否支持Unity2021,并考虑升级XLua。 §§相关问题§§: 1. 在Unity2021中,替代WWW类的推荐方案是什么? 2. XLua如何正确封装C#静态类? 3. 如何处理Unity API在不同版本间的兼容性问题? 4. 如何升级XLua以支持新版本的Unity?</think>### 解决方案 #### 问题分析 1. **UnityEngine.WWW.InitWWW 方法不存在**:在 Unity 5.3 到 Unity 2021 的升级过程中,`WWW.InitWWW` 方法已被移除 2. **UnityEngine.Random 静态类问题**:`Random` 是静态类,不能实例化 3. **UnityEngine.Shader 构造函数问题**:`Shader` 类没有无参构造函数 #### 修复代码 ##### 1. 修复 UnityEngineWWWWrap.cs (移除 InitWWW 方法) ```csharp{3,5-6,8-9,18-38} public static void __Register(RealStatePtr L) { // 修改方法注册数量为4(移除InitWWW) Utils.BeginObjectRegister(typeof(UnityEngine.WWW), L, translator, 0, 4, 15, 1); // 只注册存在的4个方法 Utils.RegisterFunc(L, Utils.METHOD_IDX, "Dispose", Dispose); // Utils.RegisterFunc(L, Utils.METHOD_IDX, "InitWWW", InitWWW); // 已移除 Utils.RegisterFunc(L, Utils.METHOD_IDX, "GetAudioClip", GetAudioClip); Utils.RegisterFunc(L, Utils.METHOD_IDX, "GetAudioClipCompressed", GetAudioClipCompressed); Utils.RegisterFunc(L, Utils.METHOD_IDX, "LoadImageIntoTexture", LoadImageIntoTexture); // ... 属性注册保持不变 ... } // 完全移除 InitWWW 方法定义 /* [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int InitWWW(RealStatePtr L) { // ... 删除此方法体 ... } */ ``` ##### 2. 修复 UnityEngineRandomWrap.cs (处理静态类) ```csharp{3,5-6,8-9} // 修改 __CreateInstance 方法 [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int __CreateInstance(RealStatePtr L) { // 静态类不应创建实例 return LuaAPI.luaL_error(L, "UnityEngine.Random is a static class and cannot be instantiated"); } // 修改类注册 public static void __Register(RealStatePtr L) { // 使用 null 作为创建实例的函数 Utils.BeginClassRegister(typeof(UnityEngine.Random), L, null, 0, 0, 0); // ... 其他注册代码 ... } ``` ##### 3. 修复 UnityEngineShaderWrap.cs (添加有效构造函数) ```csharp{3-20} // 修改 __CreateInstance 方法 [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))] static int __CreateInstance(RealStatePtr L) { ObjectTranslator translator = ObjectTranslatorPool.Instance.Find(L); try { // 添加有效的构造函数重载 if (LuaAPI.lua_gettop(L) == 2 && LuaAPI.lua_type(L, 2) == LuaTypes.LUA_TSTRING) { string shaderPath = LuaAPI.lua_tostring(L, 2); UnityEngine.Shader shader = UnityEngine.Shader.Find(shaderPath); if (shader != null) { translator.Push(L, shader); return 1; } } } catch (System.Exception __gen_e) { return LuaAPI.luaL_error(L, "c# exception:" + __gen_e); } return LuaAPI.luaL_error(L, "invalid arguments to UnityEngine.Shader constructor!"); } ``` ### 解释说明 1. **WWW.InitWWW 移除**: - Unity 2021 已完全移除了 `InitWWW` 方法 - 解决方案:从注册表中移除该方法引用并删除方法实现 2. **Random 静态类问题**: - `Random` 是工具类,所有方法都是静态的 - 解决方案:禁止实例化并修改类注册方式 3. **Shader 构造函数问题**: - `Shader` 必须通过 `Shader.Find` 或资源加载创建 - 解决方案:添加基于着色器路径的有效构造函数重载 ### 额外建议 1. **替代 WWW 类**:考虑迁移到 `UnityWebRequest`: ```csharp using UnityEngine.Networking; UnityWebRequest request = UnityWebRequest.Get(url); yield return request.SendWebRequest(); ``` 2. **XLua 升级**:确保使用最新版 XLua(支持 Unity 2021)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值