mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 23:24:09 +00:00
FFI: Add support for parameterized C types.
This commit is contained in:
parent
ca6bf2d9a4
commit
946c7418d5
@ -35,7 +35,7 @@
|
|||||||
/* -- C type checks ------------------------------------------------------- */
|
/* -- C type checks ------------------------------------------------------- */
|
||||||
|
|
||||||
/* Check first argument for a C type and returns its ID. */
|
/* Check first argument for a C type and returns its ID. */
|
||||||
static CTypeID ffi_checkctype(lua_State *L, CTState *cts)
|
static CTypeID ffi_checkctype(lua_State *L, CTState *cts, TValue *param)
|
||||||
{
|
{
|
||||||
TValue *o = L->base;
|
TValue *o = L->base;
|
||||||
if (!(o < L->top)) {
|
if (!(o < L->top)) {
|
||||||
@ -50,6 +50,7 @@ static CTypeID ffi_checkctype(lua_State *L, CTState *cts)
|
|||||||
cp.cts = cts;
|
cp.cts = cts;
|
||||||
cp.srcname = strdata(s);
|
cp.srcname = strdata(s);
|
||||||
cp.p = strdata(s);
|
cp.p = strdata(s);
|
||||||
|
cp.param = param;
|
||||||
cp.mode = CPARSE_MODE_ABSTRACT|CPARSE_MODE_NOIMPLICIT;
|
cp.mode = CPARSE_MODE_ABSTRACT|CPARSE_MODE_NOIMPLICIT;
|
||||||
errcode = lj_cparse(&cp);
|
errcode = lj_cparse(&cp);
|
||||||
if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */
|
if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */
|
||||||
@ -57,6 +58,7 @@ static CTypeID ffi_checkctype(lua_State *L, CTState *cts)
|
|||||||
} else {
|
} else {
|
||||||
GCcdata *cd;
|
GCcdata *cd;
|
||||||
if (!tviscdata(o)) goto err_argtype;
|
if (!tviscdata(o)) goto err_argtype;
|
||||||
|
if (param && param < L->top) lj_err_arg(L, 1, LJ_ERR_FFI_NUMPARAM);
|
||||||
cd = cdataV(o);
|
cd = cdataV(o);
|
||||||
return cd->typeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) : cd->typeid;
|
return cd->typeid == CTID_CTYPEID ? *(CTypeID *)cdataptr(cd) : cd->typeid;
|
||||||
}
|
}
|
||||||
@ -442,6 +444,7 @@ LJLIB_CF(ffi_cdef)
|
|||||||
cp.cts = ctype_cts(L);
|
cp.cts = ctype_cts(L);
|
||||||
cp.srcname = strdata(s);
|
cp.srcname = strdata(s);
|
||||||
cp.p = strdata(s);
|
cp.p = strdata(s);
|
||||||
|
cp.param = L->base+1;
|
||||||
cp.mode = CPARSE_MODE_MULTI|CPARSE_MODE_DIRECT;
|
cp.mode = CPARSE_MODE_MULTI|CPARSE_MODE_DIRECT;
|
||||||
errcode = lj_cparse(&cp);
|
errcode = lj_cparse(&cp);
|
||||||
if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */
|
if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */
|
||||||
@ -452,7 +455,7 @@ LJLIB_CF(ffi_cdef)
|
|||||||
LJLIB_CF(ffi_new) LJLIB_REC(.)
|
LJLIB_CF(ffi_new) LJLIB_REC(.)
|
||||||
{
|
{
|
||||||
CTState *cts = ctype_cts(L);
|
CTState *cts = ctype_cts(L);
|
||||||
CTypeID id = ffi_checkctype(L, cts);
|
CTypeID id = ffi_checkctype(L, cts, NULL);
|
||||||
CType *ct = ctype_raw(cts, id);
|
CType *ct = ctype_raw(cts, id);
|
||||||
CTSize sz;
|
CTSize sz;
|
||||||
CTInfo info = lj_ctype_info(cts, id, &sz);
|
CTInfo info = lj_ctype_info(cts, id, &sz);
|
||||||
@ -492,7 +495,7 @@ LJLIB_CF(ffi_new) LJLIB_REC(.)
|
|||||||
LJLIB_CF(ffi_cast) LJLIB_REC(ffi_new)
|
LJLIB_CF(ffi_cast) LJLIB_REC(ffi_new)
|
||||||
{
|
{
|
||||||
CTState *cts = ctype_cts(L);
|
CTState *cts = ctype_cts(L);
|
||||||
CTypeID id = ffi_checkctype(L, cts);
|
CTypeID id = ffi_checkctype(L, cts, NULL);
|
||||||
CType *d = ctype_raw(cts, id);
|
CType *d = ctype_raw(cts, id);
|
||||||
TValue *o = lj_lib_checkany(L, 2);
|
TValue *o = lj_lib_checkany(L, 2);
|
||||||
L->top = o+1; /* Make sure this is the last item on the stack. */
|
L->top = o+1; /* Make sure this is the last item on the stack. */
|
||||||
@ -510,7 +513,7 @@ LJLIB_CF(ffi_cast) LJLIB_REC(ffi_new)
|
|||||||
LJLIB_CF(ffi_typeof)
|
LJLIB_CF(ffi_typeof)
|
||||||
{
|
{
|
||||||
CTState *cts = ctype_cts(L);
|
CTState *cts = ctype_cts(L);
|
||||||
CTypeID id = ffi_checkctype(L, cts);
|
CTypeID id = ffi_checkctype(L, cts, L->base+1);
|
||||||
GCcdata *cd = lj_cdata_new(cts, CTID_CTYPEID, 4);
|
GCcdata *cd = lj_cdata_new(cts, CTID_CTYPEID, 4);
|
||||||
*(CTypeID *)cdataptr(cd) = id;
|
*(CTypeID *)cdataptr(cd) = id;
|
||||||
setcdataV(L, L->top-1, cd);
|
setcdataV(L, L->top-1, cd);
|
||||||
@ -521,7 +524,7 @@ LJLIB_CF(ffi_typeof)
|
|||||||
LJLIB_CF(ffi_istype) LJLIB_REC(ffi_istype)
|
LJLIB_CF(ffi_istype) LJLIB_REC(ffi_istype)
|
||||||
{
|
{
|
||||||
CTState *cts = ctype_cts(L);
|
CTState *cts = ctype_cts(L);
|
||||||
CTypeID id1 = ffi_checkctype(L, cts);
|
CTypeID id1 = ffi_checkctype(L, cts, NULL);
|
||||||
TValue *o = lj_lib_checkany(L, 2);
|
TValue *o = lj_lib_checkany(L, 2);
|
||||||
int b = 0;
|
int b = 0;
|
||||||
if (tviscdata(o)) {
|
if (tviscdata(o)) {
|
||||||
@ -551,7 +554,7 @@ LJLIB_CF(ffi_istype) LJLIB_REC(ffi_istype)
|
|||||||
LJLIB_CF(ffi_sizeof)
|
LJLIB_CF(ffi_sizeof)
|
||||||
{
|
{
|
||||||
CTState *cts = ctype_cts(L);
|
CTState *cts = ctype_cts(L);
|
||||||
CTypeID id = ffi_checkctype(L, cts);
|
CTypeID id = ffi_checkctype(L, cts, NULL);
|
||||||
CTSize sz;
|
CTSize sz;
|
||||||
if (LJ_UNLIKELY(tviscdata(L->base) && cdataisv(cdataV(L->base)))) {
|
if (LJ_UNLIKELY(tviscdata(L->base) && cdataisv(cdataV(L->base)))) {
|
||||||
sz = cdatavlen(cdataV(L->base));
|
sz = cdatavlen(cdataV(L->base));
|
||||||
@ -573,7 +576,7 @@ LJLIB_CF(ffi_sizeof)
|
|||||||
LJLIB_CF(ffi_alignof)
|
LJLIB_CF(ffi_alignof)
|
||||||
{
|
{
|
||||||
CTState *cts = ctype_cts(L);
|
CTState *cts = ctype_cts(L);
|
||||||
CTypeID id = ffi_checkctype(L, cts);
|
CTypeID id = ffi_checkctype(L, cts, NULL);
|
||||||
CTSize sz = 0;
|
CTSize sz = 0;
|
||||||
CTInfo info = lj_ctype_info(cts, id, &sz);
|
CTInfo info = lj_ctype_info(cts, id, &sz);
|
||||||
setintV(L->top-1, 1 << ctype_align(info));
|
setintV(L->top-1, 1 << ctype_align(info));
|
||||||
@ -583,7 +586,7 @@ LJLIB_CF(ffi_alignof)
|
|||||||
LJLIB_CF(ffi_offsetof)
|
LJLIB_CF(ffi_offsetof)
|
||||||
{
|
{
|
||||||
CTState *cts = ctype_cts(L);
|
CTState *cts = ctype_cts(L);
|
||||||
CTypeID id = ffi_checkctype(L, cts);
|
CTypeID id = ffi_checkctype(L, cts, NULL);
|
||||||
GCstr *name = lj_lib_checkstr(L, 2);
|
GCstr *name = lj_lib_checkstr(L, 2);
|
||||||
CType *ct = lj_ctype_rawref(cts, id);
|
CType *ct = lj_ctype_rawref(cts, id);
|
||||||
CTSize ofs;
|
CTSize ofs;
|
||||||
@ -700,7 +703,7 @@ LJLIB_PUSH(top-8) LJLIB_SET(!) /* Store reference to miscmap table. */
|
|||||||
LJLIB_CF(ffi_metatype)
|
LJLIB_CF(ffi_metatype)
|
||||||
{
|
{
|
||||||
CTState *cts = ctype_cts(L);
|
CTState *cts = ctype_cts(L);
|
||||||
CTypeID id = ffi_checkctype(L, cts);
|
CTypeID id = ffi_checkctype(L, cts, NULL);
|
||||||
GCtab *mt = lj_lib_checktab(L, 2);
|
GCtab *mt = lj_lib_checktab(L, 2);
|
||||||
GCtab *t = cts->miscmap;
|
GCtab *t = cts->miscmap;
|
||||||
CType *ct = ctype_get(cts, id); /* Only allow raw types. */
|
CType *ct = ctype_get(cts, id); /* Only allow raw types. */
|
||||||
|
@ -121,6 +121,7 @@ LJ_NORET static void cp_errmsg(CPState *cp, CPToken tok, ErrMsg em, ...)
|
|||||||
tokstr = NULL;
|
tokstr = NULL;
|
||||||
} else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING ||
|
} else if (tok == CTOK_IDENT || tok == CTOK_INTEGER || tok == CTOK_STRING ||
|
||||||
tok >= CTOK_FIRSTDECL) {
|
tok >= CTOK_FIRSTDECL) {
|
||||||
|
if (cp->sb.n == 0) cp_save(cp, '$');
|
||||||
cp_save(cp, '\0');
|
cp_save(cp, '\0');
|
||||||
tokstr = cp->sb.buf;
|
tokstr = cp->sb.buf;
|
||||||
} else {
|
} else {
|
||||||
@ -203,6 +204,38 @@ static CPToken cp_ident(CPState *cp)
|
|||||||
return CTOK_IDENT;
|
return CTOK_IDENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse parameter. */
|
||||||
|
static CPToken cp_param(CPState *cp)
|
||||||
|
{
|
||||||
|
CPChar c = cp_get(cp);
|
||||||
|
TValue *o = cp->param;
|
||||||
|
if (lj_char_isident(c) || c == '$') /* Reserve $xyz for future extensions. */
|
||||||
|
cp_errmsg(cp, c, LJ_ERR_XSYNTAX);
|
||||||
|
if (!o || o >= cp->L->top)
|
||||||
|
cp_err(cp, LJ_ERR_FFI_NUMPARAM);
|
||||||
|
cp->param = o+1;
|
||||||
|
if (tvisstr(o)) {
|
||||||
|
cp->str = strV(o);
|
||||||
|
cp->val.id = lj_ctype_getname(cp->cts, &cp->ct, cp->str, cp->tmask);
|
||||||
|
if (ctype_type(cp->ct->info) == CT_KW)
|
||||||
|
return ctype_cid(cp->ct->info);
|
||||||
|
return CTOK_IDENT;
|
||||||
|
} else if (tvisnumber(o)) {
|
||||||
|
cp->val.i32 = numberVint(o);
|
||||||
|
cp->val.id = CTID_INT32;
|
||||||
|
return CTOK_INTEGER;
|
||||||
|
} else {
|
||||||
|
GCcdata *cd;
|
||||||
|
if (!tviscdata(o)) lj_err_argtype(cp->L, o-cp->L->base+1, "type parameter");
|
||||||
|
cd = cdataV(o);
|
||||||
|
if (cd->typeid == CTID_CTYPEID)
|
||||||
|
cp->val.id = *(CTypeID *)cdataptr(cd);
|
||||||
|
else
|
||||||
|
cp->val.id = cd->typeid;
|
||||||
|
return '$';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse string or character constant. */
|
/* Parse string or character constant. */
|
||||||
static CPToken cp_string(CPState *cp)
|
static CPToken cp_string(CPState *cp)
|
||||||
{
|
{
|
||||||
@ -317,6 +350,8 @@ static CPToken cp_next_(CPState *cp)
|
|||||||
return '>';
|
return '>';
|
||||||
case '-':
|
case '-':
|
||||||
cp_get(cp); if (cp->c != '>') return '-'; cp_get(cp); return CTOK_DEREF;
|
cp_get(cp); if (cp->c != '>') return '-'; cp_get(cp); return CTOK_DEREF;
|
||||||
|
case '$':
|
||||||
|
return cp_param(cp);
|
||||||
case '\0': return CTOK_EOF;
|
case '\0': return CTOK_EOF;
|
||||||
default: { CPToken c = cp->c; cp_get(cp); return c; }
|
default: { CPToken c = cp->c; cp_get(cp); return c; }
|
||||||
}
|
}
|
||||||
@ -403,6 +438,7 @@ static int cp_istypedecl(CPState *cp)
|
|||||||
{
|
{
|
||||||
if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECL) return 1;
|
if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECL) return 1;
|
||||||
if (cp->tok == CTOK_IDENT && ctype_istypedef(cp->ct->info)) return 1;
|
if (cp->tok == CTOK_IDENT && ctype_istypedef(cp->ct->info)) return 1;
|
||||||
|
if (cp->tok == '$') return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1441,7 +1477,7 @@ static CTypeID cp_decl_enum(CPState *cp, CPDecl *sdecl)
|
|||||||
static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl)
|
static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl)
|
||||||
{
|
{
|
||||||
uint32_t cds = 0, sz = 0;
|
uint32_t cds = 0, sz = 0;
|
||||||
CTInfo tdef = 0;
|
CTypeID tdef = 0;
|
||||||
|
|
||||||
decl->cp = cp;
|
decl->cp = cp;
|
||||||
decl->mode = cp->mode;
|
decl->mode = cp->mode;
|
||||||
@ -1471,6 +1507,10 @@ static CPscl cp_decl_spec(CPState *cp, CPDecl *decl, CPscl scl)
|
|||||||
tdef = ctype_cid(cp->ct->info); /* Get typedef. */
|
tdef = ctype_cid(cp->ct->info); /* Get typedef. */
|
||||||
cp_next(cp);
|
cp_next(cp);
|
||||||
break;
|
break;
|
||||||
|
case '$':
|
||||||
|
tdef = cp->val.id;
|
||||||
|
cp_next(cp);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECLFLAG) {
|
if (cp->tok >= CTOK_FIRSTDECL && cp->tok <= CTOK_LASTDECLFLAG) {
|
||||||
uint32_t cbit;
|
uint32_t cbit;
|
||||||
@ -1826,6 +1866,8 @@ static TValue *cpcparser(lua_State *L, lua_CFunction dummy, void *ud)
|
|||||||
cp_decl_multi(cp);
|
cp_decl_multi(cp);
|
||||||
else
|
else
|
||||||
cp_decl_single(cp);
|
cp_decl_single(cp);
|
||||||
|
if (cp->param && cp->param != cp->L->top)
|
||||||
|
cp_err(cp, LJ_ERR_FFI_NUMPARAM);
|
||||||
lua_assert(cp->depth == 0);
|
lua_assert(cp->depth == 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@ typedef struct CPState {
|
|||||||
SBuf sb; /* String buffer for tokens. */
|
SBuf sb; /* String buffer for tokens. */
|
||||||
lua_State *L; /* Lua state. */
|
lua_State *L; /* Lua state. */
|
||||||
CTState *cts; /* C type state. */
|
CTState *cts; /* C type state. */
|
||||||
|
TValue *param; /* C type parameters. */
|
||||||
const char *srcname; /* Current source name. */
|
const char *srcname; /* Current source name. */
|
||||||
BCLine linenumber; /* Input line counter. */
|
BCLine linenumber; /* Input line counter. */
|
||||||
int depth; /* Recursive declaration depth. */
|
int depth; /* Recursive declaration depth. */
|
||||||
|
@ -149,6 +149,7 @@ ERRDEF(FFI_BADSCL, "bad storage class")
|
|||||||
ERRDEF(FFI_DECLSPEC, "declaration specifier expected")
|
ERRDEF(FFI_DECLSPEC, "declaration specifier expected")
|
||||||
ERRDEF(FFI_BADTAG, "undeclared or implicit tag " LUA_QS)
|
ERRDEF(FFI_BADTAG, "undeclared or implicit tag " LUA_QS)
|
||||||
ERRDEF(FFI_REDEF, "attempt to redefine " LUA_QS)
|
ERRDEF(FFI_REDEF, "attempt to redefine " LUA_QS)
|
||||||
|
ERRDEF(FFI_NUMPARAM, "wrong number of type parameters")
|
||||||
ERRDEF(FFI_INITOV, "too many initializers for " LUA_QS)
|
ERRDEF(FFI_INITOV, "too many initializers for " LUA_QS)
|
||||||
ERRDEF(FFI_BADCONV, "cannot convert " LUA_QS " to " LUA_QS)
|
ERRDEF(FFI_BADCONV, "cannot convert " LUA_QS " to " LUA_QS)
|
||||||
ERRDEF(FFI_BADLEN, "attempt to get length of " LUA_QS)
|
ERRDEF(FFI_BADLEN, "attempt to get length of " LUA_QS)
|
||||||
|
Loading…
Reference in New Issue
Block a user