tcpiper
tcpiper

Reputation: 2544

Luajit ffi how to call funcitons in time.h?

I tried to call function tan of math.h this way (directly copy the declaration) and it works:

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

But when I tried to call the function localtime of time.h the same way:

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

And get error:

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]

I've checked the official manual this and this but still confused.

Upvotes: 1

Views: 1713

Answers (2)

Diego Pino
Diego Pino

Reputation: 11586

Every function you would like to call from FFI, it needs to be defined before. If not LuaJIT does not how to parse a FFI function call, how to do data-type conversion from Lua to C (and viceversa), etc.

Keeping that in my mind, to make your code work you would need to define time_t and struct tm. time_t is generally defined as a signed integer. You can find the definition of struct tm in localtime docs (man localtime).

ffi.cdef[[
   struct tm {
      int tm_sec;    /* Seconds (0-60) */
      int tm_min;    /* Minutes (0-59) */
      int tm_hour;   /* Hours (0-23) */
      int tm_mday;   /* Day of the month (1-31) */
      int tm_mon;    /* Month (0-11) */
      int tm_year;   /* Year - 1900 */
      int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
      int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
      int tm_isdst;  /* Daylight saving time */
   };
   struct tm *localtime(const int32_t *tp);
]]

In addition, function localtime expects a pointer value, not a constant integer. So it would be necessary to pass a c-data pointer storing an integer to localtime. There's a sort of LuaJIT idiom for that.

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

Since arrays and pointers in C, although not the exactly same, are interchangeable in most cases.

Lastly, you cannot print a struct tm directly. Should store it into a variable and print out the fields you're interested.

print(tm.tm_sec)

Upvotes: 3

user6874929
user6874929

Reputation: 1

You cannot use time_t as it isn't native C type. Replace it with proper native type or use a corresponding struct typedef. Then it should work.

Upvotes: 0

Related Questions