aboutsummaryrefslogtreecommitdiff
path: root/src/lib_ffi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib_ffi.c')
-rw-r--r--src/lib_ffi.c59
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
392static 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
417LJLIB_CF(ffi_callback_free)
418{
419 return ffi_callback_set(L, NULL);
420}
421
422LJLIB_CF(ffi_callback_set)
423{
424 GCfunc *fn = lj_lib_checkfunc(L, 2);
425 return ffi_callback_set(L, fn);
426}
427
428LJLIB_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
653LJLIB_PUSH(top-8) LJLIB_SET(!) /* Store reference to metatype table. */ 698LJLIB_PUSH(top-8) LJLIB_SET(!) /* Store reference to miscmap table. */
654 699
655LJLIB_CF(ffi_metatype) 700LJLIB_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)
745LUALIB_API int luaopen_ffi(lua_State *L) 790LUALIB_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);