diff options
Diffstat (limited to 'src/lib_ffi.c')
-rw-r--r-- | src/lib_ffi.c | 88 |
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. */ | ||
366 | static 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 | |||
378 | LJLIB_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 | |||
397 | LJLIB_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 | |||
422 | LJLIB_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 | ||
642 | LJLIB_PUSH(top-5) LJLIB_SET(!) /* Store clib metatable in func environment. */ | ||
643 | |||
644 | LJLIB_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 | |||
652 | LJLIB_PUSH(top-4) LJLIB_SET(C) | ||
570 | LJLIB_PUSH(top-3) LJLIB_SET(os) | 653 | LJLIB_PUSH(top-3) LJLIB_SET(os) |
571 | LJLIB_PUSH(top-2) LJLIB_SET(arch) | 654 | LJLIB_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! */ |