Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

数据类型转换

Lua 是动态类型语言,C 是静态类型语言。交互时需要在两者之间转换。

Lua ↔ C 类型对照

Lua 类型C API 检查C API 读取C API 写入
nillua_isnillua_pushnil
booleanlua_isbooleanlua_tobooleanlua_pushboolean
integerlua_isintegerlua_tointegerlua_pushinteger
number (float)lua_isnumberlua_tonumberlua_pushnumber
stringlua_isstring*lua_tostringlua_pushstring
tablelua_istablelua_newtable
functionlua_isfunctionlua_pushcfunction
userdatalua_isuserdatalua_touserdatalua_newuserdatauv
threadlua_isthreadlua_tothread

*注意:lua_isstring 对 number 也返回 true,因为 number 可以自动转换为 string。

类型检查与转换

安全读取(带默认值)

lua_Integer n = luaL_optinteger(L, 1, 10);   // 第1参数不是整数则返回10 
lua_Number  x = luaL_optnumber(L, 2, 0.0);
const char *s = luaL_optstring(L, 3, "default");

严格检查(C 函数参数校验)

lua_Integer n = luaL_checkinteger(L, 1);     // 类型不对则抛出 Lua 错误 
lua_Number  x = luaL_checknumber(L, 2);
const char *s = luaL_checkstring(L, 3);

字符串处理

lua_tostring 返回的指针指向 Lua 内部字符串,只要该字符串还在栈上或未被 GC,指针就有效。不要 free 它。

对于包含 \0 的二进制字符串,使用 lua_pushlstring / lua_tolstring

size_t len;
const char *data = lua_tolstring(L, -1, &len);  // 获取长度和内容 
lua_pushlstring(L, data, len);                  // 压入二进制串 

boolean 陷阱

lua_toboolean 对以下值返回 0(false):

  • nil
  • false
  • 其余所有值(包括 0 和空字符串)都返回 1(true)

这与 C 的“0 为假”逻辑不同,需特别注意。

完整代码


#include <assert.h>
#include <lauxlib.h>
#include <lua.h>
#include <stdio.h>
#include <string.h>

int main(void) {
    lua_State *L = luaL_newstate();

    lua_pushnil(L);
    lua_pushboolean(L, 1);
    lua_pushinteger(L, 42);
    lua_pushnumber(L, 3.14);
    lua_pushstring(L, "hello");
    lua_pushlstring(L, "hi\x00world", 8);

    assert(lua_type(L, -1) == LUA_TSTRING);
    assert(lua_isinteger(L, -2) == 0);

    size_t len;
    const char *s = lua_tolstring(L, -1, &len);
    assert(strcmp(s, "hi") == 0);
    assert(len == 8);

    assert(lua_tointeger(L, 3) == 42);
    assert(lua_tonumber(L, 4) == 3.14);

    lua_settop(L, 0);
    lua_pushinteger(L, 100);
    assert(luaL_checkinteger(L, 1) == 100);
    assert(luaL_optinteger(L, 2, 99) == 99);

    lua_close(L);
    puts("02-types: ok");
    return 0;
}