Luajit ffi 怎样调用 time.h 中的函数?

我尝试这种方式调用 math.h 中的 tan 函数(直接复制声明),它可以工作:

local ffi = require("ffi")
ffi.cdef[[
    double tan(double x);
]]
print(ffi.C.tan(45))

但是当我以同样的方式调用 time.h 中的 localtime 函数时:

local ffi = require("ffi")
ffi.cdef[[
    struct tm *localtime(const time_t *tp);
]]
print(ffi.C.localtime(1234544))

会得到如下错误:

lua: C:\Users\xiang\Desktop\bm.lua:4: declaration specifier expected near 'time_t'
stack traceback:
    [C]: in function 'cdef'
    C:\Users\xiang\Desktop\bm.lua:4: in main chunk
    [C]: at 0x00401f00
[Finished in 0.1s with exit code 1]

我已经查看了官方手册 thisthis,但仍然感到困惑。

点赞
用户6874929
用户6874929

你不能使用 time_t,因为它不是 C 语言的本地类型。请用合适的本地类型代替它,或者使用相应的结构体 typedef。这样它就可以正常工作了。

2016-09-24 14:37:27
用户134758
用户134758

在调用 FFI 中的每个函数之前,都需要先定义它。如果没有定义,LuaJIT 就无法解析 FFI 函数调用,无法进行从 Lua 到 C(以及反之)的数据类型转换等操作。

记住这一点,为使你的代码正常工作,你需要定义 time_tstruct tmtime_t 通常被定义为有符号整数,你可以在 localtime 文档中找到 struct tm 的定义(_man localtime_)。

ffi.cdef[[
   struct tm {
      int tm_sec;    /* 秒(0-60) */
      int tm_min;    /* 分钟(0-59) */
      int tm_hour;   /* 小时(0-23) */
      int tm_mday;   /* 月份中的第几天(1-31) */
      int tm_mon;    /* 月份(0-11) */
      int tm_year;   /* 年份 - 1900 */
      int tm_wday;   /* 星期几(0-6,星期日为 0) */
      int tm_yday;   /* 年份中的第几天(0-365,1 月 1 日为 0) */
      int tm_isdst;  /* 夏令时 */
   };
   struct tm *localtime(const int32_t *tp);
]]

另外,函数 localtime 需要一个指针值,而不是一个常量整数。因此,需要向 localtime 传递一个存储整数的 c-data 指针。这里有一个 LuaJIT 的习惯用法。

local time = ffi.new("int32_t[1]")
time[0] = 1234544
local tm = C.localtime(time)

由于 C 中的数组和指针在大多数情况下可以互换使用,所以这种用法是有效的。

最后,不能直接打印 struct tm。应该将其存储到一个变量中,并打印你感兴趣的字段。

print(tm.tm_sec)
2016-10-25 19:38:08