-
在注册给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 );
-
建立Lua字符串到C enum的映射
-
在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
-
实现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; }
使用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')
Recent Comments