diff options
Diffstat (limited to 'src/lib_ffi.c')
-rw-r--r-- | src/lib_ffi.c | 77 |
1 files changed, 58 insertions, 19 deletions
diff --git a/src/lib_ffi.c b/src/lib_ffi.c index e88b6f54..674bbf00 100644 --- a/src/lib_ffi.c +++ b/src/lib_ffi.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "lj_gc.h" | 17 | #include "lj_gc.h" |
18 | #include "lj_err.h" | 18 | #include "lj_err.h" |
19 | #include "lj_str.h" | 19 | #include "lj_str.h" |
20 | #include "lj_tab.h" | ||
20 | #include "lj_ctype.h" | 21 | #include "lj_ctype.h" |
21 | #include "lj_cparse.h" | 22 | #include "lj_cparse.h" |
22 | #include "lj_cdata.h" | 23 | #include "lj_cdata.h" |
@@ -353,6 +354,24 @@ LJLIB_CF(ffi_new) LJLIB_REC(.) | |||
353 | return 1; | 354 | return 1; |
354 | } | 355 | } |
355 | 356 | ||
357 | LJLIB_CF(ffi_cast) LJLIB_REC(ffi_new) | ||
358 | { | ||
359 | CTState *cts = ctype_cts(L); | ||
360 | CTypeID id = ffi_checkctype(L, cts); | ||
361 | CType *d = ctype_raw(cts, id); | ||
362 | TValue *o = lj_lib_checkany(L, 2); | ||
363 | L->top = o+1; /* Make sure this is the last item on the stack. */ | ||
364 | if (!(ctype_isnum(d->info) || ctype_isptr(d->info) || ctype_isenum(d->info))) | ||
365 | lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE); | ||
366 | if (!(tviscdata(o) && cdataV(o)->typeid == id)) { | ||
367 | GCcdata *cd = lj_cdata_new(cts, id, d->size); | ||
368 | lj_cconv_ct_tv(cts, d, cdataptr(cd), o, CCF_CAST); | ||
369 | setcdataV(L, o, cd); | ||
370 | lj_gc_check(L); | ||
371 | } | ||
372 | return 1; | ||
373 | } | ||
374 | |||
356 | LJLIB_CF(ffi_typeof) | 375 | LJLIB_CF(ffi_typeof) |
357 | { | 376 | { |
358 | CTState *cts = ctype_cts(L); | 377 | CTState *cts = ctype_cts(L); |
@@ -419,24 +438,6 @@ LJLIB_CF(ffi_offsetof) | |||
419 | return 0; | 438 | return 0; |
420 | } | 439 | } |
421 | 440 | ||
422 | LJLIB_CF(ffi_cast) LJLIB_REC(ffi_new) | ||
423 | { | ||
424 | CTState *cts = ctype_cts(L); | ||
425 | CTypeID id = ffi_checkctype(L, cts); | ||
426 | CType *d = ctype_raw(cts, id); | ||
427 | TValue *o = lj_lib_checkany(L, 2); | ||
428 | L->top = o+1; /* Make sure this is the last item on the stack. */ | ||
429 | if (!(ctype_isnum(d->info) || ctype_isptr(d->info) || ctype_isenum(d->info))) | ||
430 | lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE); | ||
431 | if (!(tviscdata(o) && cdataV(o)->typeid == id)) { | ||
432 | GCcdata *cd = lj_cdata_new(cts, id, d->size); | ||
433 | lj_cconv_ct_tv(cts, d, cdataptr(cd), o, CCF_CAST); | ||
434 | setcdataV(L, o, cd); | ||
435 | lj_gc_check(L); | ||
436 | } | ||
437 | return 1; | ||
438 | } | ||
439 | |||
440 | LJLIB_CF(ffi_string) LJLIB_REC(.) | 441 | LJLIB_CF(ffi_string) LJLIB_REC(.) |
441 | { | 442 | { |
442 | CTState *cts = ctype_cts(L); | 443 | CTState *cts = ctype_cts(L); |
@@ -520,6 +521,30 @@ LJLIB_CF(ffi_abi) LJLIB_REC(.) | |||
520 | 521 | ||
521 | #undef H_ | 522 | #undef H_ |
522 | 523 | ||
524 | LJLIB_PUSH(top-7) LJLIB_SET(!) /* Store reference to weak table. */ | ||
525 | |||
526 | LJLIB_CF(ffi_gc) | ||
527 | { | ||
528 | GCcdata *cd = ffi_checkcdata(L, 1); | ||
529 | TValue *fin = lj_lib_checkany(L, 2); | ||
530 | CTState *cts = ctype_cts(L); | ||
531 | GCtab *t = cts->finalizer; | ||
532 | CType *ct = ctype_raw(cts, cd->typeid); | ||
533 | if (!(ctype_isptr(ct->info) || ctype_isstruct(ct->info) || | ||
534 | ctype_isrefarray(ct->info))) | ||
535 | lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE); | ||
536 | if (gcref(t->metatable)) { /* Update finalizer table, if still enabled. */ | ||
537 | copyTV(L, lj_tab_set(L, t, L->base), fin); | ||
538 | lj_gc_anybarriert(L, t); | ||
539 | if (!tvisnil(fin)) | ||
540 | cd->marked |= LJ_GC_CDATA_FIN; | ||
541 | else | ||
542 | cd->marked &= ~LJ_GC_CDATA_FIN; | ||
543 | } | ||
544 | L->top = L->base+1; /* Pass through the cdata object. */ | ||
545 | return 1; | ||
546 | } | ||
547 | |||
523 | LJLIB_PUSH(top-5) LJLIB_SET(!) /* Store clib metatable in func environment. */ | 548 | LJLIB_PUSH(top-5) LJLIB_SET(!) /* Store clib metatable in func environment. */ |
524 | 549 | ||
525 | LJLIB_CF(ffi_load) | 550 | LJLIB_CF(ffi_load) |
@@ -538,9 +563,23 @@ LJLIB_PUSH(top-2) LJLIB_SET(arch) | |||
538 | 563 | ||
539 | /* ------------------------------------------------------------------------ */ | 564 | /* ------------------------------------------------------------------------ */ |
540 | 565 | ||
566 | /* Create special weak-keyed finalizer table. */ | ||
567 | static GCtab *ffi_finalizer(lua_State *L) | ||
568 | { | ||
569 | /* NOBARRIER: The table is new (marked white). */ | ||
570 | GCtab *t = lj_tab_new(L, 0, 1); | ||
571 | settabV(L, L->top++, t); | ||
572 | setgcref(t->metatable, obj2gco(t)); | ||
573 | setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "__mode")), | ||
574 | lj_str_newlit(L, "K")); | ||
575 | t->nomm = (uint8_t)(~(1u<<MM_mode)); | ||
576 | return t; | ||
577 | } | ||
578 | |||
541 | LUALIB_API int luaopen_ffi(lua_State *L) | 579 | LUALIB_API int luaopen_ffi(lua_State *L) |
542 | { | 580 | { |
543 | lj_ctype_init(L); | 581 | CTState *cts = lj_ctype_init(L); |
582 | cts->finalizer = ffi_finalizer(L); | ||
544 | LJ_LIB_REG(L, NULL, ffi_meta); | 583 | LJ_LIB_REG(L, NULL, ffi_meta); |
545 | /* NOBARRIER: basemt is a GC root. */ | 584 | /* NOBARRIER: basemt is a GC root. */ |
546 | setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1))); | 585 | setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1))); |