c++中载入lua的代码
#include <>
extern "C"
{
#include "include/lua.h"
#include "include/lualib.h"
#include "include/lauxlib.h"
#pragma comment(lib, "lua.lib")
};
int main(void)
{
}
在Programming in lua中载入库的方法是分别载入5个库,分别是base、table、io、string、math,但是在使用中(lua5.1.3 + vs.net2003)发现io库在载入的时候会出现错误,程序无法继续执行,但不提示错误。
在网上查询了一下,有些人遇到的是非法引用内存(见这里),他的解决方法是改成上面代码中的方式:直接载入全部库。
在这里有一段解释:“关于luaopen_io调用失败的问题,在Lua的maillist里问了一下,有人说是因为io库里有些函数的运行是依赖于Lua建立的特定的环境,所以要用lua_call来调用,要么,就直接用luaL_openlibs来引入所有标准库。看了看帮助文档,还有Lua的源代码,似乎好像就是这么回事啊!”
再查官方文档(http://www.lua.org/manual/5.1/manual.html)中有一段:
最后这句的意思是:“这些函数在lualib.h中定义并且不能直接调用:你必须以其他C函数调用方式来进行调用,例如使用lua_call。”
接着是lua_call的用法:
lua_call
原型:void lua_call (lua_State *L, int nargs, int nresults);
Calls a function.
功能:调用一个方法
To call a function you must use the following protocol: first, the function to be called is pushed onto the stack; then, the arguments to the function are pushed in direct order; that is, the first argument is pushed first. Finally you call lua_call; nargs is the number of arguments that you pushed onto the stack. All arguments and the function value are popped from the stack when the function is called. The function results are pushed onto the stack when the function returns. The number of results is adjusted to nresults, unless nresults is LUA_MULTRET. In this case, all results from the function are pushed. Lua takes care that the returned values fit into the stack space. The function results are pushed onto the stack in direct order (the first result is pushed first), so that after the call the last result is on the top of the stack.
调用一个函数必须按照以下的规则:首先,将要调用的函数入栈;之后,将函数参数按顺序入栈,就是说第一个参数最先入栈。最后调用lua_call;nargs是入栈的参数数。当函数被调用时弹出全部的参数和函数值。当函数返回后函数结果会压入栈。结果的数量取决于nresults(lua_call的最后一个参数)。除非nresults的值是LUA_MULTRET。以这种方式所有的函数结果都被入栈。由Lua管理栈空间中的这些返回值。函数的结果按顺序入栈(第一个元素最先入栈),所以在调用完成后最后一个参数在栈顶。
Any error inside the called function is propagated upwards (with a longjmp).
在函数调用中产生的error会被向上传递(使用longjmp方式)。
The following example shows how the host program may do the equivalent to this Lua code:
下面的例子展示了如何使宿主程序做如下lua代码的功能:
Here it is in C:
这是在C中:
如果看不明白(其实我也不明白)那就直接按照最上面的代码中所写的方式载入lua库吧。
学习LUA也有一些时日了,个人认为对于LUA中的栈的理解很重要,嗯,写个小文章(真的很小)
如果你看了LUA的文档,那么就应该很清楚LUA与C交互数据时都是用到LUA中所谓的stack。那么当我调用lua_open函数之后栈是什么样的呢?空的(luaopen_base等会往栈上加进一些东西)。那么至于如何操作栈上的数据,我想官方文档上已经说得很清楚了,不过最初我对于栈的顺序有一些迷糊,所以就说说这个。现在假如我有如下的一段代码:
lua_State*
lua_pushnumber(
lua_pushnumber(
lua_newtable(
lua_close(
那么当执行完lua_newtable之后栈上有三个元素,大致就是这样:
211
222
table
现在211是第一个元素,index为1,不过LUA也可以用负数来表示,那么现在他是多少?
index
1
2
3
嗯,很简单,再看看如果我们要设置一个TABLE的值怎么做?文档中说用lua_settable或是lua_rawset(这两者有什么区别应该和这里说的无关),它们参数意义、以及准备工作都一样,-1是值,-2是键值
lua_settable(
第一个参数是要操作的脚本环境,第二个则是要操作的表在栈上的位置
一般的写法可能是这样
//
lua_getglobal(
lua_pushstring(
lua_pushnumber(
lua_settable(
如果我是想把hp这个值设置到全局表中呢?一般通过调用lua_setglobal宏
lua_pushnumber(
lua_setglobal(
就这么简单,不过我们来看看lua_setglobal这个宏
#define
这么看来实际上我们上面的代码被替换成了
lua_pushnumber(
lua_pushstring(
lua_insert(
lua_settable(
将上面的代码与代码A结合起来看,在lua_settable时index值不同,而它做的工作是如果发现index是LUA_GLOBALSINDEX
实际上lua中与c的接口也就主要在栈的操作上,基本上你在写一个lua与C结合的程序时你最最需要做的工作就是明白你当前栈上有什么元素以及它们的位置。我一般会在纸上画出他们的位置,如果你熟了,对于几句在一起有关联的lua调用则可以很快的看出栈的变化。比如
lua_gettable/lua_rawget
lua_pushstring(
lua_gettable(
只看第一句,栈顶是一个字符串,但两句放在一起,最终栈顶是一个全局表上一个名为hp的实际值
lua_pushstring(
lua_pushnumber(
lua_settable(
无论第二句pushnumber还是pushvalue,pushstring什么的,最终这三句执行之后对于栈来说是没有任何变化的,因为lua_settable/lua_rawset会移走-1和-2
总之,对于栈的变化,在看一个函数的文档时先看它参数又需要栈上那些位置的元素并正确设置栈上的值,看清楚他会取栈上那些位置的元素作为这个lua
lua_gettable lua_getglobal(L, "mytable") <== push mytable lua_pushnumber(L, 1) lua_gettable(L, -2) lua_settable lua_getglobal(L, "mytable") <== push mytable lua_pushnumber(L, 1) lua_pushstring(L, "abc") lua_settable(L, -3) lua_rawget: 用法同lua_gettable,但更快(因为当key不存在时不用访问元方法__index) lua_rawset: 用法同lua_settable,但更快(因为当key不存在时不用访问元方法__newindex) lua_rawgeti必须为数值键 lua_getglobal(L, "mytable") <== push mytable lua_rawgeti(L, -1, --lua_pushnumber(L, 1) --lua_rawget(L,-2) lua_rawseti必须为数值键 lua_getglobal(L, "mytable") <== push mytable lua_pushstring(L, "abc") lua_rawseti(L, -2, 1) lua_getfield必须为字符串键 lua_getglobal(L, "mytable") <== push mytable lua_getfield(L, -1, --lua_pushstring(L, "x") --lua_gettable(L,-2) lua_setfield必须为字符串键 lua_getglobal(L, "mytable") <== push mytable lua_pushstring(L, "abc") lua_setfield(L, -2, "x") |