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.c88
1 files changed, 86 insertions, 2 deletions
diff --git a/src/lib_ffi.c b/src/lib_ffi.c
index 3c52f7f8..2b895ed5 100644
--- a/src/lib_ffi.c
+++ b/src/lib_ffi.c
@@ -22,6 +22,7 @@
22#include "lj_cdata.h" 22#include "lj_cdata.h"
23#include "lj_cconv.h" 23#include "lj_cconv.h"
24#include "lj_ccall.h" 24#include "lj_ccall.h"
25#include "lj_clib.h"
25#include "lj_ff.h" 26#include "lj_ff.h"
26#include "lj_lib.h" 27#include "lj_lib.h"
27 28
@@ -357,6 +358,77 @@ checkgc:
357 358
358#include "lj_libdef.h" 359#include "lj_libdef.h"
359 360
361/* -- C library metamethods ----------------------------------------------- */
362
363#define LJLIB_MODULE_ffi_clib
364
365/* Index C library by a name. */
366static TValue *ffi_clib_index(lua_State *L)
367{
368 TValue *o = L->base;
369 CLibrary *cl;
370 if (!(o < L->top && tvisudata(o) && udataV(o)->udtype == UDTYPE_FFI_CLIB))
371 lj_err_argt(L, 1, LUA_TUSERDATA);
372 cl = (CLibrary *)uddata(udataV(o));
373 if (!(o+1 < L->top && tvisstr(o+1)))
374 lj_err_argt(L, 2, LUA_TSTRING);
375 return lj_clib_index(L, cl, strV(o+1));
376}
377
378LJLIB_CF(ffi_clib___index)
379{
380 TValue *tv = ffi_clib_index(L);
381 if (tviscdata(tv)) {
382 CTState *cts = ctype_cts(L);
383 GCcdata *cd = cdataV(tv);
384 CType *s = ctype_get(cts, cd->typeid);
385 if (ctype_isextern(s->info)) {
386 CTypeID sid = ctype_cid(s->info);
387 void *sp = *(void **)cdataptr(cd);
388 if (lj_cconv_tv_ct(cts, ctype_raw(cts, sid), sid, L->top-1, sp))
389 lj_gc_check(L);
390 return 1;
391 }
392 }
393 copyTV(L, L->top-1, tv);
394 return 1;
395}
396
397LJLIB_CF(ffi_clib___newindex)
398{
399 TValue *tv = ffi_clib_index(L);
400 TValue *o = L->base+2;
401 if (o < L->top && tviscdata(tv)) {
402 CTState *cts = ctype_cts(L);
403 GCcdata *cd = cdataV(tv);
404 CType *d = ctype_get(cts, cd->typeid);
405 if (ctype_isextern(d->info)) {
406 CTInfo qual = 0;
407 for (;;) { /* Skip attributes and collect qualifiers. */
408 d = ctype_child(cts, d);
409 if (!ctype_isattrib(d->info)) break;
410 if (ctype_attrib(d->info) == CTA_QUAL) qual |= d->size;
411 }
412 if (!((d->info|qual) & CTF_CONST)) {
413 lj_cconv_ct_tv(cts, d, *(void **)cdataptr(cd), o, 0);
414 return 0;
415 }
416 }
417 }
418 lj_err_caller(L, LJ_ERR_FFI_WRCONST);
419 return 0; /* unreachable */
420}
421
422LJLIB_CF(ffi_clib___gc)
423{
424 TValue *o = L->base;
425 if (o < L->top && tvisudata(o) && udataV(o)->udtype == UDTYPE_FFI_CLIB)
426 lj_clib_unload((CLibrary *)uddata(udataV(o)));
427 return 0;
428}
429
430#include "lj_libdef.h"
431
360/* -- FFI library functions ----------------------------------------------- */ 432/* -- FFI library functions ----------------------------------------------- */
361 433
362#define LJLIB_MODULE_ffi 434#define LJLIB_MODULE_ffi
@@ -567,6 +639,17 @@ LJLIB_CF(ffi_abi)
567 639
568#undef H_ 640#undef H_
569 641
642LJLIB_PUSH(top-5) LJLIB_SET(!) /* Store clib metatable in func environment. */
643
644LJLIB_CF(ffi_load)
645{
646 GCstr *name = lj_lib_checkstr(L, 1);
647 int global = (L->base+1 < L->top && tvistruecond(L->base+1));
648 lj_clib_load(L, tabref(curr_func(L)->c.env), name, global);
649 return 1;
650}
651
652LJLIB_PUSH(top-4) LJLIB_SET(C)
570LJLIB_PUSH(top-3) LJLIB_SET(os) 653LJLIB_PUSH(top-3) LJLIB_SET(os)
571LJLIB_PUSH(top-2) LJLIB_SET(arch) 654LJLIB_PUSH(top-2) LJLIB_SET(arch)
572 655
@@ -579,8 +662,9 @@ LUALIB_API int luaopen_ffi(lua_State *L)
579 lj_ctype_init(L); 662 lj_ctype_init(L);
580 LJ_LIB_REG_(L, NULL, ffi_meta); 663 LJ_LIB_REG_(L, NULL, ffi_meta);
581 /* NOBARRIER: basemt is a GC root. */ 664 /* NOBARRIER: basemt is a GC root. */
582 L->top--; 665 setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1)));
583 setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top))); 666 LJ_LIB_REG_(L, NULL, ffi_clib);
667 lj_clib_default(L, tabV(L->top-1)); /* Create ffi.C default namespace. */
584 lua_pushliteral(L, LJ_OS_NAME); 668 lua_pushliteral(L, LJ_OS_NAME);
585 lua_pushliteral(L, LJ_ARCH_NAME); 669 lua_pushliteral(L, LJ_ARCH_NAME);
586 LJ_LIB_REG_(L, NULL, ffi); /* Note: no global "ffi" created! */ 670 LJ_LIB_REG_(L, NULL, ffi); /* Note: no global "ffi" created! */