summaryrefslogtreecommitdiff
path: root/src/lib_ffi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib_ffi.c')
-rw-r--r--src/lib_ffi.c77
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
357LJLIB_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
356LJLIB_CF(ffi_typeof) 375LJLIB_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
422LJLIB_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
440LJLIB_CF(ffi_string) LJLIB_REC(.) 441LJLIB_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
524LJLIB_PUSH(top-7) LJLIB_SET(!) /* Store reference to weak table. */
525
526LJLIB_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
523LJLIB_PUSH(top-5) LJLIB_SET(!) /* Store clib metatable in func environment. */ 548LJLIB_PUSH(top-5) LJLIB_SET(!) /* Store clib metatable in func environment. */
524 549
525LJLIB_CF(ffi_load) 550LJLIB_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. */
567static 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
541LUALIB_API int luaopen_ffi(lua_State *L) 579LUALIB_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)));