【发布时间】:2011-06-22 02:51:19
【问题描述】:
这是一个小的 C 测试程序来演示我所看到的。它用 Lua 注册一个新的对象类型并执行一个 Lua 脚本。当脚本调用 __len 元方法时,我希望堆栈上只传递一个参数 - 对象 userdata。相反,它传递了 userdata 和一个神秘的 nil。
len.c:
#include <stdio.h>
#include <lua5.1/lua.h>
#include <lua5.1/lauxlib.h>
#include <lua5.1/lualib.h>
#define OBJECT_LEN 123456
/* Dummy object */
typedef struct {
int length;
} object;
/* Create the new object and set the length to OBJECT_LEN */
static int object_new( lua_State *L ) {
object *new = lua_newuserdata( L, sizeof( object ) );
new->length = OBJECT_LEN;
luaL_getmetatable( L, "metatable" );
lua_setmetatable( L, 1 );
return 1;
}
/* Get the objects length. */
static int object_len( lua_State *L ) {
/* Print the Lua stack - always 2 args, userdata and nil */
static const char *const lua_types[] = {
"nil", "boolean", "light userdata", "number", "string",
"table", "function", "userdata", "thread",
};
int arg_count = lua_gettop( L );
int i;
for ( i = arg_count; i > 0; -- i ) {
int type = lua_type( L, i );
printf( "%d:%s\n", i, lua_types[ type ] );
}
/* Push the objects length onto the Lua stack */
object *obj = luaL_checkudata( L, 1, "metatable" );
lua_pop( L, 2 ); /* pop the mystery 'nil' and userdata */
lua_pushinteger( L, obj->length );
return 1;
}
static const luaL_reg object_constructor[] = {
{ "new", object_new },
{ NULL, NULL }
};
static const luaL_reg object_methods[] = {
{ "__len", object_len },
{ NULL, NULL }
};
int main( int argc, char **argv ) {
lua_State *L = lua_open();
luaL_openlibs( L );
/* Create the 'object' type */
luaL_newmetatable( L, "metatable" );
lua_pushvalue( L, -1 );
lua_setfield( L, -2, "__index" );
luaL_register( L, NULL, object_methods );
luaL_register( L, "object", object_constructor );
lua_pop( L, 2 );
/* Run the lua script */
int result = luaL_dofile( L, "meta.lua" );
if ( result != 0 ) {
fprintf( stderr, "error:%s\n", lua_tostring( L, 1 ) );
}
lua_close( L );
return 0;
}
meta.lua:创建一个对象,打印它的长度。
obj = object.new()
print( "obj length:", #obj )
编译并执行:
$ gcc -Wall len.c -o len -llua5.1 && ./len
2:nil
1:userdata
obj length: 123456
堆栈上的 nil 有什么用?
【问题讨论】:
-
我知道这是 C,但是命名变量
new让我很不舒服 :) -
luaL_register折旧以支持luaL_setfuncs,如有必要,lua_setglobal。luaL_register具有创建全局的副作用(在模块中工作时是一件坏事(tm))。 -
@Sean,感谢您对旧问题的反馈!我已经将我的 Lua 包装器更新为 C++,但我仍在使用 Lua 5.1。如果我更改为 5.2+,我一定会听取您的建议。谢谢!