好记性不如铅笔头

C && C++, Lua, 编程

Lua快速学习笔记:在C/C++中调用Lua脚本API

备注:

1 本笔记只记录了LUA的一小部分内容,对于LUA的描述并不全面,以后随用随增加吧。
2 本笔记参考《Lua程序设计 第二版》,截图和代码属于原作者所有。
3 作者初学LUA,经验和能力有限,笔记可能有错误,还请各位路过的大牛们给予指点。
4 API参考网址:参考网址: http://www.codingnow.com/2000/download/lua_manual.html

lua_load:

读取lua脚本字符进入lua环境中,内部函数。

int lua_load (lua_State *L,
              lua_Reader reader,
              void *data,
              const char *chunkname);
加载一个 Lua chunk 。 如果没有错误, lua_load 把一个编译好的 chunk 作为一个 Lua 函数压入堆栈。 否则,压入出错信息。 l ua_load 的返回值可以是:
0: 没有错误;
LUA_ERRSYNTAX: 在预编译时碰到语法错误;
LUA_ERRMEM: 内存分配错误。
这个函数仅仅加栽 chunk ;而不会去运行它
lua_load 会自动检测 chunk 是文本的还是二进制的, 然后做对应的加载操作(参见程序 luac)。
lua_load 函数使用一个用户提供的 reader 函数来 读取 chunk (参见 lua_Reader)。 data 参数会被传入读取器函数。
chunkname 这个参数可以赋予 chunk 一个名字, 这个名字被用于出错信息和调试信息(参见 §3.8)。

luaL_loadfile:

int luaL_loadfile (lua_State *L, const char *filename);
Loads a file as a Lua chunk. This function uses lua_load to load the chunk in the file named filename. If filename is NULL, then it loads from the standard input. The first line in the file is ignored if it starts with a #.
This function returns the same results as lua_load, but it has an extra error code LUA_ERRFILE if it cannot open/read the file.
As lua_load, this function only loads the chunk; it does not run it.

luaL_loadstring:

int luaL_loadstring (lua_State *L, const char *s);
Loads a string as a Lua chunk. This function uses lua_load to load the chunk in the zero-terminated string s.
This function returns the same results as lua_load.

Also as lua_load, this function only loads the chunk; it does not run it.

lua_call:

调用一个函数。

void lua_call (lua_State *L, int nargs, int nresults);
要调用一个函数请遵循以下协议:
首先,要调用的函数应该被压入堆栈
接着,把需要传递给这个函数的参数按正序压栈; 这是指第一个参数首先压栈
最后,调用一下 lua_callnargs 是你压入堆栈的参数个数。 
当函数调用完毕后,所有的参数以及函数本身都会出栈,而函数的返回值这时则被压入堆栈
返回值的个数将被调整为 nresults 个, 除非 nresults 被设置成 LUA_MULTRET。 在这种情况下,所有的返回值都被压入堆栈中。 Lua 会保证返回值都放入栈空间中。 函数返回值将按正序压栈(第一个返回值首先压栈), 因此在调用结束后,最后一个返回值将被放在栈顶。
被调用函数内发生的错误将(通过 longjmp)一直上抛。

下面的例子中,这行 Lua 代码等价于在宿主程序用 C 代码做一些工作:
a = f(“how”, t.x, 14)
这里是 C 里的代码:

     lua_getfield(L, LUA_GLOBALSINDEX, "f");          /* 将调用的函数 */
     lua_pushstring(L, "how");                          /* 第一个参数 */
     lua_getfield(L, LUA_GLOBALSINDEX, "t");          /* table 的索引 */
     lua_getfield(L, -1, "x");         /* 压入 t.x 的值(第 2 个参数)*/
     lua_remove(L, -2);                           /* 从堆栈中移去 't' */
     lua_pushinteger(L, 14);                           /* 第 3 个参数 */
     lua_call(L, 3, 1); /* 调用 'f',传入 3 个参数,并索取 1 个返回值 */
     lua_setfield(L, LUA_GLOBALSINDEX, "a");      /* 设置全局变量 'a' */

注意上面这段代码是“平衡”的: 到了最后,堆栈恢复成原由的配置。 这是一种良好的编程习惯。

lua_pcall:

保护模式调用一个函数。
lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);
nargs 和 nresults 的含义与 lua_call 中的相同。 如果在调用过程中没有发生错误lua_pcall 的行为和 lua_call 完全一致。 但是,如果有错误发生的话, lua_pcall 会捕获它, 然后把单一的值(错误信息)压入堆栈,然后返回错误码。 同 lua_call 一样, lua_pcall 总是把函数本身和它的参数从栈上移除。
如果 errfunc 是 0,返回在栈顶的错误信息就和原始错误信息完全一致。 否则,errfunc 就被当成是错误处理函数在栈上的索引。 (在当前的实现里,这个索引不能是伪索引。) 在发生运行时错误时, 这个函数会被调用而参数就是错误信息。 错误处理函数的返回值将被 lua_pcall 作为出错信息返回在堆栈上。
典型的用法中,错误处理函数被用来在出错信息上加上更多的调试信息,比如栈跟踪信息 (stack traceback) 。 这些信息在 lua_pcall 返回后,因为栈已经展开 (unwound) , 所以收集不到了。
lua_pcall 函数在调用成功时返回 0 , 否则返回以下(定义在 lua.h 中的)错误代码中的一个:
LUA_ERRRUN: 运行时错误。
LUA_ERRMEM: 内存分配错误。 对于这种错,Lua 调用不了错误处理函数。
LUA_ERRERR: 在运行错误处理函数时发生的错误。

luaL_dofile:

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

luaL_dostring:

#define luaL_dostring(L, s) \
(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))

发表评论

1 × 5 =

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据