diff options
| author | Mike Pall <mike> | 2011-11-14 14:15:57 +0100 |
|---|---|---|
| committer | Mike Pall <mike> | 2011-11-14 14:18:25 +0100 |
| commit | 71d00a56dbab6c29c0346093dbe530d7b7608be4 (patch) | |
| tree | 5e28e19b4d2f20168d5ee0e4fe500b1e2b233c1c /src/lib_ffi.c | |
| parent | e9eb4fdb4a08baaa2d9190187a6c38d5b3f8b091 (diff) | |
| download | luajit-71d00a56dbab6c29c0346093dbe530d7b7608be4.tar.gz luajit-71d00a56dbab6c29c0346093dbe530d7b7608be4.tar.bz2 luajit-71d00a56dbab6c29c0346093dbe530d7b7608be4.zip | |
FFI: Add callback support (for x86/x64).
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); |
