Lua相关问题整理(3)

  1. 在注册给Lua的C函数中为Lua提供默认参数

    使用luaL_optstring, luaL_optnumber, luaL_optinteger等Lua API,如下示例,函数有一个默认字符串参数,默认值为””,这样在Lua中调用whatever的时候,whatever()或者whatever( “whatever”)均可。(Oh…whatever…随便…都行…)

    // C code
    int Whatever( lua_State *L )
    {
    	string str = luaL_optstring( L, 1, "" );
    	//...omitted code...
    }
    lua_register( L, "whatever", Whatever );
    
  2. 建立Lua字符串到C enum的映射

  3. 使用luaL_checkoption这个Lua API,它可以把从Lua传来的string转换为相应的C string array中的index,从而可以建立Lua字符串和C enum的映射。以下是个简单的示例:

    // C code
    enum PlayerType
    {
    	PLAYER_TYPE_UNDEFINED = -1,
    	PLAYER_TYPE_KING = 0, // 主公
    	PLAYER_TYPE_INSURGENT, // 反贼
    	PLAYER_TYPE_LOYAL, // 忠臣
    	PLAYER_TYPE_TREACHEROUS, //内奸-_^
    	NUM_PLAYER_TYPE // just a sentinel
    };
    
    const char * const PlayerTypeList[NUM_PLAYER_TYPE + 1] =
    {
    	"KING",
    	"INSURGENT",
    	"LOYAL",
    	"TREACHEROUS",
    	NULL
    };
    
    static int testPlayerType( lua_State *L )
    {
    	PlayerType type = static_cast< PlayerType >( 
    						luaL_checkoption( L, 1, 
    						"INSURGENT", PlayerTypeList ) );
    	std::cout << "Type index is " << type 
    		      << " - " << PlayerTypeList[type] 
    		      << std::endl;
    	return 0;
    }
    
    lua_register( L, "setPlayerType", setPlayerType )
    

    首先enum PlayerType定义了一组角色类型,来自人人都爱的三国杀:-)。

    接着PlayerTypeList定义了一个字符串数组,给Lua使用。注意需要保证enum和字符串数组的对应,比如PlayerTypeList[PLAYER_TYPE_KING]是“KING”,同时,PlayerTypeList必须以NULL结尾。

    在定义给Lua的函数testPlayerType中,就可以用luaL_checkoption将Lua传来的字符串参数转换为相应enum的值。luaL_checkoption还支持默认参数,比如在上面例子中,将第三个参数设为“INSURGENT”,如果Lua中没有提供任何参数,则PlayerType就为与“INSURGENT”相对应的PLAYER_TYPE_INSURGENT。

    以下是一组测试及结果:

    --Lua code
    testPlayerType( "KING" ) -- Type index is 0 - KING
    testPlayerType() -- Type index is 1 - INSURGENT
    testPlayerType( "whatever" ) -- bad argument #1 to 'testPlayerType' (invalid option 'whatever')
    
  4. 在Lua中实现eval函数

    众所周知,JavaScript中有一个著名的eval函数,它用于把一个字符串当作一段JS代码去执行,在Lua中没有提供类似的函数,但稍微包装下Lua的库函数loadstring即可实现,以下是代码。

    --Lua code
    function eval( str )
    	local func = loadstring( "return " ..str );
    	return func()
    end
    

    这样已经可以了,不过相比于JS的eval函数,功能稍微差一些,因为它不支持赋值语句,这是Lua语言天然的原因,因为Lua的赋值运算符没有返回值,在其他语言中常见传递赋值的“i=j=1”(先赋值j=1,然后将(j=1)的返回值j赋值给i),在Lua中是不允许的。所以当eval执行的是赋值运算(比如i=1)的时候,return i=1就会出错。

    下面是一些测试例子:

    --Lua code
    print( eval( "3+4" ) ) -- OK, 打印7
    
    function Multiply( a, b )
    	return a*b
    end
    
    print( eval( "Multiply( 3, 4 )" ) ) -- OK,打印12
    
    print( eval( "i = 1" ) ) -- 错误, attempt to call a nil value
    i = 1
    print( eval( "i" ) ) -- OK,打印1
    print( eval( "i = i + 1" ) ) -- 错误, attempt to call a nil value
    
  5. 实现luaL_checkbool

    不知道为什么Lua的API没有提供luaL_checkbook函数,不过很容易实现:

    // C code
    BOOL luaL_checkbool( lua_State *luaVM, int numArg )
    {
    	BOOL b = FALSE;
    	if ( lua_type( L, numArg ) == LUA_TBOOLEAN )
    	{
    		b = lua_toboolean( L, numArg );
    	}
    	else
    	{
    		luaL_typerror( L, numArg, lua_typename( L, LUA_TBOOLEAN ) )
    	}
    	return b;
    }
    
This entry was written by Benny Chen , posted on Sunday November 28 2010at 10:11 pm , filed under Lua and tagged , , , , . Bookmark the permalink . Post a comment below or leave a trackback: Trackback URL.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>