FFI: Allow cdata types for integer arguments of ffi.* functions.

This commit is contained in:
Mike Pall 2011-02-07 17:13:14 +01:00
parent 8da287cab8
commit 51e8fe9cf0
2 changed files with 23 additions and 6 deletions

View File

@ -78,6 +78,18 @@ static void *ffi_checkptr(lua_State *L, int narg, CTypeID id)
return p; return p;
} }
/* Convert argument to int32_t. */
static int32_t ffi_checkint(lua_State *L, int narg)
{
CTState *cts = ctype_cts(L);
TValue *o = L->base + narg-1;
int32_t i;
if (o >= L->top)
lj_err_arg(L, narg, LJ_ERR_NOVAL);
lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, 0);
return i;
}
/* -- C type metamethods -------------------------------------------------- */ /* -- C type metamethods -------------------------------------------------- */
#define LJLIB_MODULE_ffi_meta #define LJLIB_MODULE_ffi_meta
@ -324,7 +336,7 @@ LJLIB_CF(ffi_new) LJLIB_REC(.)
if ((info & CTF_VLA)) { if ((info & CTF_VLA)) {
o++; o++;
sz = lj_ctype_vlsize(cts, ctype_raw(cts, id), sz = lj_ctype_vlsize(cts, ctype_raw(cts, id),
(CTSize)lj_lib_checkint(L, 2)); (CTSize)ffi_checkint(L, 2));
} }
if (sz == CTSIZE_INVALID) if (sz == CTSIZE_INVALID)
lj_err_arg(L, 1, LJ_ERR_FFI_INVSIZE); lj_err_arg(L, 1, LJ_ERR_FFI_INVSIZE);
@ -361,7 +373,7 @@ LJLIB_CF(ffi_sizeof)
} else { } else {
CType *ct = lj_ctype_rawref(cts, id); CType *ct = lj_ctype_rawref(cts, id);
if (ctype_isvltype(ct->info)) if (ctype_isvltype(ct->info))
sz = lj_ctype_vlsize(cts, ct, (CTSize)lj_lib_checkint(L, 2)); sz = lj_ctype_vlsize(cts, ct, (CTSize)ffi_checkint(L, 2));
else else
sz = ctype_hassize(ct->info) ? ct->size : CTSIZE_INVALID; sz = ctype_hassize(ct->info) ? ct->size : CTSIZE_INVALID;
if (LJ_UNLIKELY(sz == CTSIZE_INVALID)) { if (LJ_UNLIKELY(sz == CTSIZE_INVALID)) {
@ -431,7 +443,7 @@ LJLIB_CF(ffi_string) LJLIB_REC(.)
const char *p; const char *p;
size_t len; size_t len;
if (o+1 < L->top) { if (o+1 < L->top) {
len = (size_t)lj_lib_checkint(L, 2); len = (size_t)ffi_checkint(L, 2);
lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CVOID), (uint8_t *)&p, o, 0); lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CVOID), (uint8_t *)&p, o, 0);
} else { } else {
lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CCHAR), (uint8_t *)&p, o, 0); lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CCHAR), (uint8_t *)&p, o, 0);
@ -452,7 +464,7 @@ LJLIB_CF(ffi_copy)
if (tvisstr(o) && o+1 >= L->top) { if (tvisstr(o) && o+1 >= L->top) {
sz = strV(o)->len+1; /* Copy Lua string including trailing '\0'. */ sz = strV(o)->len+1; /* Copy Lua string including trailing '\0'. */
} else { } else {
sz = (CTSize)lj_lib_checkint(L, 3); sz = (CTSize)ffi_checkint(L, 3);
if (tvisstr(o) && sz > strV(o)->len+1) if (tvisstr(o) && sz > strV(o)->len+1)
sz = strV(o)->len+1; /* Max. copy length is string length. */ sz = strV(o)->len+1; /* Max. copy length is string length. */
} }
@ -463,7 +475,7 @@ LJLIB_CF(ffi_copy)
LJLIB_CF(ffi_fill) LJLIB_CF(ffi_fill)
{ {
void *dp = ffi_checkptr(L, 1, CTID_P_VOID); void *dp = ffi_checkptr(L, 1, CTID_P_VOID);
CTSize sz = (CTSize)lj_lib_checkint(L, 2); CTSize sz = (CTSize)ffi_checkint(L, 2);
int32_t fill = lj_lib_optint(L, 3, 0); int32_t fill = lj_lib_optint(L, 3, 0);
memset(dp, fill, sz); memset(dp, fill, sz);
return 0; return 0;

View File

@ -947,6 +947,11 @@ void LJ_FASTCALL recff_clib_index(jit_State *J, RecordFFData *rd)
/* -- FFI library functions ----------------------------------------------- */ /* -- FFI library functions ----------------------------------------------- */
static TRef crec_toint(jit_State *J, CTState *cts, TRef sp, TValue *sval)
{
return crec_ct_tv(J, ctype_get(cts, CTID_INT32), 0, sp, sval);
}
void LJ_FASTCALL recff_ffi_new(jit_State *J, RecordFFData *rd) void LJ_FASTCALL recff_ffi_new(jit_State *J, RecordFFData *rd)
{ {
crec_alloc(J, rd, argv2ctype(J, J->base[0], &rd->argv[0])); crec_alloc(J, rd, argv2ctype(J, J->base[0], &rd->argv[0]));
@ -959,7 +964,7 @@ void LJ_FASTCALL recff_ffi_string(jit_State *J, RecordFFData *rd)
if (tr) { if (tr) {
TRef trlen = J->base[1]; TRef trlen = J->base[1];
if (trlen) { if (trlen) {
trlen = lj_ir_toint(J, trlen); trlen = crec_toint(J, cts, trlen, &rd->argv[1]);
tr = crec_ct_tv(J, ctype_get(cts, CTID_P_CVOID), 0, tr, &rd->argv[0]); tr = crec_ct_tv(J, ctype_get(cts, CTID_P_CVOID), 0, tr, &rd->argv[0]);
} else { } else {
tr = crec_ct_tv(J, ctype_get(cts, CTID_P_CCHAR), 0, tr, &rd->argv[0]); tr = crec_ct_tv(J, ctype_get(cts, CTID_P_CCHAR), 0, tr, &rd->argv[0]);