diff options
Diffstat (limited to 'src/lib_ffi.c')
-rw-r--r-- | src/lib_ffi.c | 59 |
1 files changed, 54 insertions, 5 deletions
diff --git a/src/lib_ffi.c b/src/lib_ffi.c index af500118..850805e6 100644 --- a/src/lib_ffi.c +++ b/src/lib_ffi.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "lj_cconv.h" | 27 | #include "lj_cconv.h" |
28 | #include "lj_carith.h" | 28 | #include "lj_carith.h" |
29 | #include "lj_ccall.h" | 29 | #include "lj_ccall.h" |
30 | #include "lj_ccallback.h" | ||
30 | #include "lj_clib.h" | 31 | #include "lj_clib.h" |
31 | #include "lj_ff.h" | 32 | #include "lj_ff.h" |
32 | #include "lj_lib.h" | 33 | #include "lj_lib.h" |
@@ -384,6 +385,50 @@ LJLIB_CF(ffi_clib___gc) | |||
384 | 385 | ||
385 | #include "lj_libdef.h" | 386 | #include "lj_libdef.h" |
386 | 387 | ||
388 | /* -- Callback function metamethods --------------------------------------- */ | ||
389 | |||
390 | #define LJLIB_MODULE_ffi_callback | ||
391 | |||
392 | static int ffi_callback_set(lua_State *L, GCfunc *fn) | ||
393 | { | ||
394 | GCcdata *cd = ffi_checkcdata(L, 1); | ||
395 | CTState *cts = ctype_cts(L); | ||
396 | CType *ct = ctype_raw(cts, cd->typeid); | ||
397 | if (ctype_isptr(ct->info) && (LJ_32 || ct->size == 8)) { | ||
398 | MSize slot = lj_ccallback_ptr2slot(cts, *(void **)cdataptr(cd)); | ||
399 | if (slot < cts->cb.sizeid && cts->cb.cbid[slot] != 0) { | ||
400 | GCtab *t = cts->miscmap; | ||
401 | TValue *tv = lj_tab_setint(L, t, (int32_t)slot); | ||
402 | if (fn) { | ||
403 | setfuncV(L, tv, fn); | ||
404 | lj_gc_anybarriert(L, t); | ||
405 | } else { | ||
406 | setnilV(tv); | ||
407 | cts->cb.cbid[slot] = 0; | ||
408 | cts->cb.topid = slot < cts->cb.topid ? slot : cts->cb.topid; | ||
409 | } | ||
410 | return 0; | ||
411 | } | ||
412 | } | ||
413 | lj_err_caller(L, LJ_ERR_FFI_BADCBACK); | ||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | LJLIB_CF(ffi_callback_free) | ||
418 | { | ||
419 | return ffi_callback_set(L, NULL); | ||
420 | } | ||
421 | |||
422 | LJLIB_CF(ffi_callback_set) | ||
423 | { | ||
424 | GCfunc *fn = lj_lib_checkfunc(L, 2); | ||
425 | return ffi_callback_set(L, fn); | ||
426 | } | ||
427 | |||
428 | LJLIB_PUSH(top-1) LJLIB_SET(__index) | ||
429 | |||
430 | #include "lj_libdef.h" | ||
431 | |||
387 | /* -- FFI library functions ----------------------------------------------- */ | 432 | /* -- FFI library functions ----------------------------------------------- */ |
388 | 433 | ||
389 | #define LJLIB_MODULE_ffi | 434 | #define LJLIB_MODULE_ffi |
@@ -428,7 +473,7 @@ LJLIB_CF(ffi_new) LJLIB_REC(.) | |||
428 | o, (MSize)(L->top - o)); /* Initialize cdata. */ | 473 | o, (MSize)(L->top - o)); /* Initialize cdata. */ |
429 | if (ctype_isstruct(ct->info)) { | 474 | if (ctype_isstruct(ct->info)) { |
430 | /* Handle ctype __gc metamethod. Use the fast lookup here. */ | 475 | /* Handle ctype __gc metamethod. Use the fast lookup here. */ |
431 | cTValue *tv = lj_tab_getint(cts->metatype, (int32_t)id); | 476 | cTValue *tv = lj_tab_getinth(cts->miscmap, -(int32_t)id); |
432 | if (tv && tvistab(tv) && (tv = lj_meta_fast(L, tabV(tv), MM_gc))) { | 477 | if (tv && tvistab(tv) && (tv = lj_meta_fast(L, tabV(tv), MM_gc))) { |
433 | GCtab *t = cts->finalizer; | 478 | GCtab *t = cts->finalizer; |
434 | if (gcref(t->metatable)) { | 479 | if (gcref(t->metatable)) { |
@@ -650,21 +695,21 @@ LJLIB_CF(ffi_abi) LJLIB_REC(.) | |||
650 | 695 | ||
651 | #undef H_ | 696 | #undef H_ |
652 | 697 | ||
653 | LJLIB_PUSH(top-8) LJLIB_SET(!) /* Store reference to metatype table. */ | 698 | LJLIB_PUSH(top-8) LJLIB_SET(!) /* Store reference to miscmap table. */ |
654 | 699 | ||
655 | LJLIB_CF(ffi_metatype) | 700 | LJLIB_CF(ffi_metatype) |
656 | { | 701 | { |
657 | CTState *cts = ctype_cts(L); | 702 | CTState *cts = ctype_cts(L); |
658 | CTypeID id = ffi_checkctype(L, cts); | 703 | CTypeID id = ffi_checkctype(L, cts); |
659 | GCtab *mt = lj_lib_checktab(L, 2); | 704 | GCtab *mt = lj_lib_checktab(L, 2); |
660 | GCtab *t = cts->metatype; | 705 | GCtab *t = cts->miscmap; |
661 | CType *ct = ctype_get(cts, id); /* Only allow raw types. */ | 706 | CType *ct = ctype_get(cts, id); /* Only allow raw types. */ |
662 | TValue *tv; | 707 | TValue *tv; |
663 | GCcdata *cd; | 708 | GCcdata *cd; |
664 | if (!(ctype_isstruct(ct->info) || ctype_iscomplex(ct->info) || | 709 | if (!(ctype_isstruct(ct->info) || ctype_iscomplex(ct->info) || |
665 | ctype_isvector(ct->info))) | 710 | ctype_isvector(ct->info))) |
666 | lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE); | 711 | lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE); |
667 | tv = lj_tab_setint(L, t, (int32_t)id); | 712 | tv = lj_tab_setinth(L, t, -(int32_t)id); |
668 | if (!tvisnil(tv)) | 713 | if (!tvisnil(tv)) |
669 | lj_err_caller(L, LJ_ERR_PROTMT); | 714 | lj_err_caller(L, LJ_ERR_PROTMT); |
670 | settabV(L, tv, mt); | 715 | settabV(L, tv, mt); |
@@ -745,12 +790,16 @@ static void ffi_register_module(lua_State *L) | |||
745 | LUALIB_API int luaopen_ffi(lua_State *L) | 790 | LUALIB_API int luaopen_ffi(lua_State *L) |
746 | { | 791 | { |
747 | CTState *cts = lj_ctype_init(L); | 792 | CTState *cts = lj_ctype_init(L); |
748 | settabV(L, L->top++, (cts->metatype = lj_tab_new(L, 0, 0))); | 793 | settabV(L, L->top++, (cts->miscmap = lj_tab_new(L, 0, 1))); |
749 | cts->finalizer = ffi_finalizer(L); | 794 | cts->finalizer = ffi_finalizer(L); |
750 | LJ_LIB_REG(L, NULL, ffi_meta); | 795 | LJ_LIB_REG(L, NULL, ffi_meta); |
751 | /* NOBARRIER: basemt is a GC root. */ | 796 | /* NOBARRIER: basemt is a GC root. */ |
752 | setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1))); | 797 | setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1))); |
753 | LJ_LIB_REG(L, NULL, ffi_clib); | 798 | LJ_LIB_REG(L, NULL, ffi_clib); |
799 | LJ_LIB_REG(L, NULL, ffi_callback); | ||
800 | /* NOBARRIER: the key is new and lj_tab_newkey() handles the barrier. */ | ||
801 | settabV(L, lj_tab_setstr(L, cts->miscmap, &cts->g->strempty), tabV(L->top-1)); | ||
802 | L->top--; | ||
754 | lj_clib_default(L, tabV(L->top-1)); /* Create ffi.C default namespace. */ | 803 | lj_clib_default(L, tabV(L->top-1)); /* Create ffi.C default namespace. */ |
755 | lua_pushliteral(L, LJ_OS_NAME); | 804 | lua_pushliteral(L, LJ_OS_NAME); |
756 | lua_pushliteral(L, LJ_ARCH_NAME); | 805 | lua_pushliteral(L, LJ_ARCH_NAME); |