Created
July 29, 2013 09:49
-
-
Save rtsisyk/6103290 to your computer and use it in GitHub Desktop.
An example how to work with CDATA (LuaJIT FFI) objects using lua_State
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void * | |
luaL_pushcdata(struct lua_State *L, uint32_t ctypeid, uint32_t size) | |
{ | |
/* | |
* ctypeid is actually has CTypeID type. | |
* CTypeId is defined somewhere inside luajit's internal headers | |
* which should not be included in init.h header. | |
*/ | |
static_assert(sizeof(ctypeid) == sizeof(CTypeID), | |
"sizeof(ctypeid) == sizeof(CTypeID)"); | |
CTState *cts = ctype_cts(L); | |
CType *ct = ctype_raw(cts, ctypeid); | |
CTSize sz; | |
lj_ctype_info(cts, ctypeid, &sz); | |
GCcdata *cd = lj_cdata_new(cts, ctypeid, size); | |
TValue *o = L->top; | |
setcdataV(L, o, cd); | |
lj_cconv_ct_init(cts, ct, sz, (uint8_t *) cdataptr(cd), o, 0); | |
incr_top(L); | |
return cdataptr(cd); | |
} | |
void * | |
luaL_checkcdata(struct lua_State *L, int idx, uint32_t *ctypeid, | |
const char *ctypename) | |
{ | |
/* Calculate absolute value in the stack. */ | |
if (idx < 0) | |
idx = lua_gettop(L) + idx + 1; | |
if (lua_type(L, idx) != LUA_TCDATA) { | |
luaL_error(L, "expected cdata as %d argument", ctypename, idx); | |
return NULL; | |
} | |
GCcdata *cd = cdataV(L->base + idx - 1); | |
*ctypeid = cd->ctypeid; | |
return (void *)cdataptr(cd); | |
} | |
uint32_t | |
tarantool_lua_ctypeid(struct lua_State *L) | |
{ | |
int idx = lua_gettop(L); | |
CTypeID ctypeid; | |
GCcdata *cd; | |
/* Get ref to ffi.typeof */ | |
luaL_loadstring(L, "return require('ffi').typeof"); | |
/* lua_call must be wrapped by try .. catch */ | |
try { | |
lua_call(L, 0, 1); | |
if (lua_gettop(L) > 1 || !lua_isfunction(L, 1)) | |
goto fail; | |
/* Push the first argument to ffi.typeof */ | |
lua_pushstring(L, ctypename); | |
/* Call ffi.typeof() */ | |
lua_call(L, 1, 1); | |
} catch(...) { | |
goto fail; | |
} | |
/* Returned type should be LUA_TCDATA with CTID_CTYPEID */ | |
if (lua_type(L, 1) != LUA_TCDATA) | |
goto fail; | |
cd = cdataV(L->base); | |
if (cd->ctypeid != CTID_CTYPEID) | |
goto fail; | |
ctypeid = *(CTypeID *)cdataptr(cd); | |
lua_settop(L, idx); | |
return ctypeid; | |
fail: | |
lua_settop(L, idx); | |
panic("lua call to ffi.typeof failed"); | |
} | |
struct request; | |
static const struct request * | |
lbox_checkrequest(struct lua_State *L, int idx) | |
{ | |
uint32_t ctypeid; | |
void *cdata = luaL_checkcdata(L, idx, &ctypeid, "struct request"); | |
if (ctypeid == CTID_STRUCT_REQUEST || | |
ctypeid == CTID_CONST_STRUCT_REQUEST) { | |
return (const struct request *) cdata; | |
} else if (ctypeid == CTID_CONST_STRUCT_REQUEST_REF || | |
ctypeid == CTID_CONST_STRUCT_REQUEST_PTR || | |
ctypeid == CTID_STRUCT_REQUEST_REF || | |
ctypeid == CTID_STRUCT_REQUEST_PTR) { | |
return *(const struct request **) cdata; | |
} else { | |
luaL_error(L, "expected 'struct request' as %d argument", idx); | |
return NULL; | |
} | |
} | |
static void | |
lbox_pushrequest(struct lua_State *L, const struct request *request) | |
{ | |
void *cdata = luaL_pushcdata(L, CTID_CONST_STRUCT_REQUEST_REF, | |
sizeof(request)); | |
*(const struct request **) cdata = request; | |
} | |
/* Get CTIDs using calls to ffi.typeof() */ | |
CTID_STRUCT_REQUEST = tarantool_lua_ctypeid(L, "struct request"); | |
CTID_STRUCT_REQUEST_PTR = tarantool_lua_ctypeid(L, "struct request *"); | |
CTID_STRUCT_REQUEST_REF = tarantool_lua_ctypeid(L, "struct request &"); | |
CTID_CONST_STRUCT_REQUEST = tarantool_lua_ctypeid(L, "const struct request"); | |
CTID_CONST_STRUCT_REQUEST_PTR = tarantool_lua_ctypeid(L, "const struct request *"); | |
CTID_CONST_STRUCT_REQUEST_REF = tarantool_lua_ctypeid(L, "const struct request &"); | |
Execute ffi.cdef before first call to tarantool_lua_ctypeid: | |
ffi.cdef([[ | |
/* from request.h */ | |
struct request | |
{ | |
/* Some members */ | |
}; | |
]]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment