diff options
| author | Mike Pall <mike> | 2011-01-10 03:43:18 +0100 |
|---|---|---|
| committer | Mike Pall <mike> | 2011-01-10 03:43:18 +0100 |
| commit | ddf65963332f048838b759bb3d926c58b1b11ce3 (patch) | |
| tree | c282aeef6c9c612ffa4f53f6e3465359c7b7edf7 /src | |
| parent | d215747fd5a97b3299262f8190803994a492b4d1 (diff) | |
| download | luajit-ddf65963332f048838b759bb3d926c58b1b11ce3.tar.gz luajit-ddf65963332f048838b759bb3d926c58b1b11ce3.tar.bz2 luajit-ddf65963332f048838b759bb3d926c58b1b11ce3.zip | |
FFI: Add ffi.load() and ffi.C default namespace.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile | 2 | ||||
| -rw-r--r-- | src/Makefile.dep | 24 | ||||
| -rw-r--r-- | src/lib_ffi.c | 88 | ||||
| -rw-r--r-- | src/lj_cdata.c | 3 | ||||
| -rw-r--r-- | src/lj_cdata.h | 5 | ||||
| -rw-r--r-- | src/lj_clib.c | 294 | ||||
| -rw-r--r-- | src/lj_clib.h | 26 | ||||
| -rw-r--r-- | src/lj_ctype.h | 1 | ||||
| -rw-r--r-- | src/lj_errmsg.h | 1 | ||||
| -rw-r--r-- | src/lj_obj.h | 1 | ||||
| -rw-r--r-- | src/ljamalg.c | 5 |
11 files changed, 435 insertions, 15 deletions
diff --git a/src/Makefile b/src/Makefile index b1197f3b..d40a4927 100644 --- a/src/Makefile +++ b/src/Makefile | |||
| @@ -328,7 +328,7 @@ LJCORE_O= lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o \ | |||
| 328 | lj_opt_dce.o lj_opt_loop.o \ | 328 | lj_opt_dce.o lj_opt_loop.o \ |
| 329 | lj_mcode.o lj_snap.o lj_record.o lj_crecord.o lj_ffrecord.o \ | 329 | lj_mcode.o lj_snap.o lj_record.o lj_crecord.o lj_ffrecord.o \ |
| 330 | lj_asm.o lj_trace.o lj_gdbjit.o \ | 330 | lj_asm.o lj_trace.o lj_gdbjit.o \ |
| 331 | lj_ctype.o lj_cdata.o lj_cconv.o lj_ccall.o lj_cparse.o \ | 331 | lj_ctype.o lj_cdata.o lj_cconv.o lj_ccall.o lj_clib.o lj_cparse.o \ |
| 332 | lj_lib.o lj_alloc.o lib_aux.o \ | 332 | lj_lib.o lj_alloc.o lib_aux.o \ |
| 333 | $(LJLIB_O) lib_init.o | 333 | $(LJLIB_O) lib_init.o |
| 334 | 334 | ||
diff --git a/src/Makefile.dep b/src/Makefile.dep index 8481b9f0..ba31804c 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep | |||
| @@ -22,7 +22,8 @@ lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ | |||
| 22 | lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h lj_libdef.h | 22 | lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h lj_libdef.h |
| 23 | lib_ffi.o: lib_ffi.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ | 23 | lib_ffi.o: lib_ffi.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ |
| 24 | lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cparse.h \ | 24 | lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cparse.h \ |
| 25 | lj_cdata.h lj_cconv.h lj_ccall.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h | 25 | lj_cdata.h lj_cconv.h lj_ccall.h lj_clib.h lj_ff.h lj_ffdef.h lj_lib.h \ |
| 26 | lj_libdef.h | ||
| 26 | lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h | 27 | lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h |
| 27 | lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ | 28 | lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ |
| 28 | lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ff.h lj_ffdef.h \ | 29 | lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ff.h lj_ffdef.h \ |
| @@ -63,6 +64,9 @@ lj_cconv.o: lj_cconv.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | |||
| 63 | lj_cdata.o: lj_cdata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 64 | lj_cdata.o: lj_cdata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| 64 | lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cconv.h lj_cdata.h | 65 | lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cconv.h lj_cdata.h |
| 65 | lj_char.o: lj_char.c lj_char.h lj_def.h lua.h luaconf.h | 66 | lj_char.o: lj_char.c lj_char.h lj_def.h lua.h luaconf.h |
| 67 | lj_clib.o: lj_clib.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ | ||
| 68 | lj_err.h lj_errmsg.h lj_tab.h lj_str.h lj_udata.h lj_ctype.h lj_cconv.h \ | ||
| 69 | lj_cdata.h lj_clib.h | ||
| 66 | lj_cparse.o: lj_cparse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 70 | lj_cparse.o: lj_cparse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| 67 | lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cparse.h lj_frame.h \ | 71 | lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cparse.h lj_frame.h \ |
| 68 | lj_bc.h lj_vm.h lj_char.h | 72 | lj_bc.h lj_vm.h lj_char.h |
| @@ -156,13 +160,13 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_gc.c lj_obj.h lj_def.h \ | |||
| 156 | lj_func.c lj_udata.c lj_meta.c lj_state.c lj_lex.h lj_alloc.h \ | 160 | lj_func.c lj_udata.c lj_meta.c lj_state.c lj_lex.h lj_alloc.h \ |
| 157 | lj_dispatch.c lj_ff.h lj_ffdef.h luajit.h lj_vmevent.c lj_vmevent.h \ | 161 | lj_dispatch.c lj_ff.h lj_ffdef.h luajit.h lj_vmevent.c lj_vmevent.h \ |
| 158 | lj_api.c lj_parse.h lj_lex.c lualib.h lj_parse.c lj_ctype.c lj_cdata.c \ | 162 | lj_api.c lj_parse.h lj_lex.c lualib.h lj_parse.c lj_ctype.c lj_cdata.c \ |
| 159 | lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h lj_cparse.c lj_cparse.h \ | 163 | lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h lj_clib.c lj_clib.h \ |
| 160 | lj_lib.c lj_lib.h lj_ir.c lj_iropt.h lj_opt_mem.c lj_opt_fold.c \ | 164 | lj_cparse.c lj_cparse.h lj_lib.c lj_lib.h lj_ir.c lj_iropt.h \ |
| 161 | lj_folddef.h lj_opt_narrow.c lj_opt_dce.c lj_opt_loop.c lj_snap.h \ | 165 | lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \ |
| 162 | lj_mcode.c lj_mcode.h lj_snap.c lj_target.h lj_target_*.h lj_record.c \ | 166 | lj_opt_loop.c lj_snap.h lj_mcode.c lj_mcode.h lj_snap.c lj_target.h \ |
| 163 | lj_record.h lj_ffrecord.h lj_crecord.c lj_crecord.h lj_ffrecord.c \ | 167 | lj_target_*.h lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \ |
| 164 | lj_recdef.h lj_asm.c lj_asm.h lj_trace.c lj_gdbjit.h lj_gdbjit.c \ | 168 | lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_trace.c \ |
| 165 | lj_alloc.c lib_aux.c lib_base.c lj_libdef.h lib_math.c lib_string.c \ | 169 | lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c lib_base.c lj_libdef.h \ |
| 166 | lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_bit.c \ | 170 | lib_math.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c \ |
| 167 | lib_jit.c lib_ffi.c lib_init.c | 171 | lib_debug.c lib_bit.c lib_jit.c lib_ffi.c lib_init.c |
| 168 | luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h | 172 | luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h |
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! */ |
diff --git a/src/lj_cdata.c b/src/lj_cdata.c index fd16c86c..5bd55237 100644 --- a/src/lj_cdata.c +++ b/src/lj_cdata.c | |||
| @@ -55,7 +55,8 @@ void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd) | |||
| 55 | if (LJ_LIKELY(!cdataisv(cd))) { | 55 | if (LJ_LIKELY(!cdataisv(cd))) { |
| 56 | CType *ct = ctype_raw(ctype_ctsG(g), cd->typeid); | 56 | CType *ct = ctype_raw(ctype_ctsG(g), cd->typeid); |
| 57 | CTSize sz = ctype_hassize(ct->info) ? ct->size : CTSIZE_PTR; | 57 | CTSize sz = ctype_hassize(ct->info) ? ct->size : CTSIZE_PTR; |
| 58 | lua_assert(ctype_hassize(ct->info) || ctype_isfunc(ct->info)); | 58 | lua_assert(ctype_hassize(ct->info) || ctype_isfunc(ct->info) || |
| 59 | ctype_isextern(ct->info)); | ||
| 59 | lj_mem_free(g, cd, sizeof(GCcdata) + sz); | 60 | lj_mem_free(g, cd, sizeof(GCcdata) + sz); |
| 60 | } else { | 61 | } else { |
| 61 | lj_mem_free(g, memcdatav(cd), sizecdatav(cd)); | 62 | lj_mem_free(g, memcdatav(cd), sizecdatav(cd)); |
diff --git a/src/lj_cdata.h b/src/lj_cdata.h index f1ab2153..5b6bd17b 100644 --- a/src/lj_cdata.h +++ b/src/lj_cdata.h | |||
| @@ -38,7 +38,10 @@ static LJ_AINLINE void cdata_setptr(void *p, CTSize sz, const void *v) | |||
| 38 | static LJ_AINLINE GCcdata *lj_cdata_new(CTState *cts, CTypeID id, CTSize sz) | 38 | static LJ_AINLINE GCcdata *lj_cdata_new(CTState *cts, CTypeID id, CTSize sz) |
| 39 | { | 39 | { |
| 40 | GCcdata *cd; | 40 | GCcdata *cd; |
| 41 | lua_assert(lj_ctype_size(cts, id) == sz); | 41 | #ifdef LUA_USE_ASSERT |
| 42 | CType *ct = ctype_raw(cts, id); | ||
| 43 | lua_assert((ctype_hassize(ct->info) ? ct->size : CTSIZE_PTR) == sz); | ||
| 44 | #endif | ||
| 42 | cd = (GCcdata *)lj_mem_newgco(cts->L, sizeof(GCcdata) + sz); | 45 | cd = (GCcdata *)lj_mem_newgco(cts->L, sizeof(GCcdata) + sz); |
| 43 | cd->gct = ~LJ_TCDATA; | 46 | cd->gct = ~LJ_TCDATA; |
| 44 | cd->typeid = ctype_check(cts, id); | 47 | cd->typeid = ctype_check(cts, id); |
diff --git a/src/lj_clib.c b/src/lj_clib.c new file mode 100644 index 00000000..91309eb2 --- /dev/null +++ b/src/lj_clib.c | |||
| @@ -0,0 +1,294 @@ | |||
| 1 | /* | ||
| 2 | ** FFI C library loader. | ||
| 3 | ** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include "lj_obj.h" | ||
| 7 | |||
| 8 | #if LJ_HASFFI | ||
| 9 | |||
| 10 | #include "lj_gc.h" | ||
| 11 | #include "lj_err.h" | ||
| 12 | #include "lj_tab.h" | ||
| 13 | #include "lj_str.h" | ||
| 14 | #include "lj_udata.h" | ||
| 15 | #include "lj_ctype.h" | ||
| 16 | #include "lj_cconv.h" | ||
| 17 | #include "lj_cdata.h" | ||
| 18 | #include "lj_clib.h" | ||
| 19 | |||
| 20 | /* -- OS-specific functions ----------------------------------------------- */ | ||
| 21 | |||
| 22 | #if LJ_TARGET_DLOPEN | ||
| 23 | |||
| 24 | #include <dlfcn.h> | ||
| 25 | |||
| 26 | #if defined(RTLD_DEFAULT) | ||
| 27 | #define CLIB_DEFHANDLE RTLD_DEFAULT | ||
| 28 | #elif LJ_TARGET_OSX || LJ_TARGET_BSD | ||
| 29 | #define CLIB_DEFHANDLE ((void *)-2) | ||
| 30 | #else | ||
| 31 | #define CLIB_DEFHANDLE NULL | ||
| 32 | #endif | ||
| 33 | |||
| 34 | LJ_NORET LJ_NOINLINE static void clib_error(lua_State *L) | ||
| 35 | { | ||
| 36 | lj_err_callermsg(L, dlerror()); | ||
| 37 | } | ||
| 38 | |||
| 39 | #if LJ_TARGET_OSX | ||
| 40 | #define CLIB_SOEXT "%s.dylib" | ||
| 41 | #else | ||
| 42 | #define CLIB_SOEXT "%s.so" | ||
| 43 | #endif | ||
| 44 | |||
| 45 | static const char *clib_extname(lua_State *L, GCstr *name) | ||
| 46 | { | ||
| 47 | const char *s = strdata(name); | ||
| 48 | if (!strchr(s, '/')) { | ||
| 49 | if (!strchr(s, '.')) { | ||
| 50 | s = lj_str_pushf(L, CLIB_SOEXT, s); | ||
| 51 | L->top--; | ||
| 52 | } | ||
| 53 | if (!(s[0] == 'l' && s[1] == 'i' && s[2] == 'b')) { | ||
| 54 | s = lj_str_pushf(L, "lib%s", s); | ||
| 55 | L->top--; | ||
| 56 | } | ||
| 57 | } | ||
| 58 | return s; | ||
| 59 | } | ||
| 60 | |||
| 61 | static void *clib_loadlib(lua_State *L, GCstr *name, int global) | ||
| 62 | { | ||
| 63 | void *h = dlopen(clib_extname(L, name), | ||
| 64 | RTLD_LAZY | (global?RTLD_GLOBAL:RTLD_LOCAL)); | ||
| 65 | if (!h) clib_error(L); | ||
| 66 | return h; | ||
| 67 | } | ||
| 68 | |||
| 69 | static void clib_unloadlib(CLibrary *cl) | ||
| 70 | { | ||
| 71 | if (!cl->handle && cl->handle != CLIB_DEFHANDLE) | ||
| 72 | dlclose(cl->handle); | ||
| 73 | } | ||
| 74 | |||
| 75 | static void *clib_getsym(lua_State *L, CLibrary *cl, GCstr *name) | ||
| 76 | { | ||
| 77 | void *p = dlsym(cl->handle, strdata(name)); | ||
| 78 | if (!p) clib_error(L); | ||
| 79 | return p; | ||
| 80 | } | ||
| 81 | |||
| 82 | #elif LJ_TARGET_WINDOWS | ||
| 83 | |||
| 84 | #define WIN32_LEAN_AND_MEAN | ||
| 85 | #ifndef WINVER | ||
| 86 | #define WINVER 0x0500 | ||
| 87 | #endif | ||
| 88 | #include <windows.h> | ||
| 89 | |||
| 90 | #ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | ||
| 91 | #define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 4 | ||
| 92 | BOOL WINAPI GetModuleHandleExA(DWORD, LPCSTR, HMODULE*); | ||
| 93 | #endif | ||
| 94 | |||
| 95 | #define CLIB_DEFHANDLE ((void *)-1) | ||
| 96 | |||
| 97 | /* Default libraries. */ | ||
| 98 | enum { | ||
| 99 | CLIB_HANDLE_EXE, | ||
| 100 | CLIB_HANDLE_DLL, | ||
| 101 | CLIB_HANDLE_CRT, | ||
| 102 | CLIB_HANDLE_KERNEL32, | ||
| 103 | CLIB_HANDLE_USER32, | ||
| 104 | CLIB_HANDLE_GDI32, | ||
| 105 | CLIB_HANDLE_MAX | ||
| 106 | }; | ||
| 107 | |||
| 108 | static void *clib_def_handle[CLIB_HANDLE_MAX]; | ||
| 109 | |||
| 110 | LJ_NORET LJ_NOINLINE static void clib_error(lua_State *L, const char *fmt, | ||
| 111 | const char *name) | ||
| 112 | { | ||
| 113 | DWORD err = GetLastError(); | ||
| 114 | char buf[128]; | ||
| 115 | if (!FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_FROM_SYSTEM, | ||
| 116 | NULL, err, 0, buf, sizeof(buf), NULL)) | ||
| 117 | buf[0] = '\0'; | ||
| 118 | lj_err_callermsg(L, lj_str_pushf(L, fmt, name, buf)); | ||
| 119 | } | ||
| 120 | |||
| 121 | static int clib_needext(const char *s) | ||
| 122 | { | ||
| 123 | while (*s) { | ||
| 124 | if (*s == '/' || *s == '\\' || *s == '.') return 0; | ||
| 125 | s++; | ||
| 126 | } | ||
| 127 | return 1; | ||
| 128 | } | ||
| 129 | |||
| 130 | static const char *clib_extname(lua_State *L, GCstr *name) | ||
| 131 | { | ||
| 132 | const char *s = strdata(name); | ||
| 133 | if (clib_needext(s)) { | ||
| 134 | s = lj_str_pushf(L, "%s.dll", s); | ||
| 135 | L->top--; | ||
| 136 | } | ||
| 137 | return s; | ||
| 138 | } | ||
| 139 | |||
| 140 | static void *clib_loadlib(lua_State *L, GCstr *name, int global) | ||
| 141 | { | ||
| 142 | void *h = (void *)LoadLibraryA(clib_extname(L, name)); | ||
| 143 | if (!h) clib_error(L, "cannot load module " LUA_QS ": %s", strdata(name)); | ||
| 144 | UNUSED(global); | ||
| 145 | return h; | ||
| 146 | } | ||
| 147 | |||
| 148 | static void clib_unloadlib(CLibrary *cl) | ||
| 149 | { | ||
| 150 | if (cl->handle == CLIB_DEFHANDLE) { | ||
| 151 | MSize i; | ||
| 152 | for (i = 0; i < CLIB_HANDLE_MAX; i++) | ||
| 153 | if (clib_def_handle[i]) | ||
| 154 | FreeLibrary((HINSTANCE)clib_def_handle[i]); | ||
| 155 | } else if (!cl->handle) { | ||
| 156 | FreeLibrary((HINSTANCE)cl->handle); | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | static void *clib_getsym(lua_State *L, CLibrary *cl, GCstr *name) | ||
| 161 | { | ||
| 162 | const char *sym = strdata(name); | ||
| 163 | void *p; | ||
| 164 | if (cl->handle == CLIB_DEFHANDLE) { /* Search default libraries. */ | ||
| 165 | MSize i; | ||
| 166 | for (i = 0; i < CLIB_HANDLE_MAX; i++) { | ||
| 167 | HINSTANCE h = (HINSTANCE)clib_def_handle[i]; | ||
| 168 | if (!(void *)h) { /* Resolve default library handles (once). */ | ||
| 169 | switch (i) { | ||
| 170 | case CLIB_HANDLE_EXE: GetModuleHandleExA(0, NULL, &h); break; | ||
| 171 | case CLIB_HANDLE_DLL: | ||
| 172 | GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, | ||
| 173 | (const char *)clib_def_handle, &h); | ||
| 174 | break; | ||
| 175 | case CLIB_HANDLE_CRT: | ||
| 176 | GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, | ||
| 177 | (const char *)&_fmode, &h); | ||
| 178 | break; | ||
| 179 | case CLIB_HANDLE_KERNEL32: h = LoadLibraryA("kernel32.dll"); break; | ||
| 180 | case CLIB_HANDLE_USER32: h = LoadLibraryA("user32.dll"); break; | ||
| 181 | case CLIB_HANDLE_GDI32: h = LoadLibraryA("gdi32.dll"); break; | ||
| 182 | } | ||
| 183 | if (!h) continue; | ||
| 184 | clib_def_handle[i] = (void *)h; | ||
| 185 | } | ||
| 186 | p = (void *)GetProcAddress(h, sym); | ||
| 187 | if (p) break; | ||
| 188 | } | ||
| 189 | } else { | ||
| 190 | p = (void *)GetProcAddress((HINSTANCE)cl->handle, sym); | ||
| 191 | } | ||
| 192 | if (!p) clib_error(L, "cannot resolve symbol " LUA_QS ": %s", sym); | ||
| 193 | return p; | ||
| 194 | } | ||
| 195 | |||
| 196 | #else | ||
| 197 | |||
| 198 | #define CLIB_DEFHANDLE NULL | ||
| 199 | |||
| 200 | static void *clib_loadlib(lua_State *L, GCstr *name, int global) | ||
| 201 | { | ||
| 202 | lj_err_callermsg(L, "no support for loading dynamic libraries for this OS"); | ||
| 203 | UNUSED(name); UNUSED(global); | ||
| 204 | return NULL; | ||
| 205 | } | ||
| 206 | |||
| 207 | static void clib_unloadlib(CLibrary *cl) | ||
| 208 | { | ||
| 209 | UNUSED(cl); | ||
| 210 | } | ||
| 211 | |||
| 212 | static void *clib_getsym(lua_State *L, CLibrary *cl, GCstr *name) | ||
| 213 | { | ||
| 214 | lj_err_callermsg(L, "no support for resolving symbols for this OS"); | ||
| 215 | UNUSED(cl); UNUSED(name); | ||
| 216 | return NULL; | ||
| 217 | } | ||
| 218 | |||
| 219 | #endif | ||
| 220 | |||
| 221 | /* -- C library indexing -------------------------------------------------- */ | ||
| 222 | |||
| 223 | /* Namespace for C library indexing. */ | ||
| 224 | #define CLNS_INDEX \ | ||
| 225 | ((1u<<CT_FUNC)|(1u<<CT_EXTERN)|(1u<<CT_CONSTVAL)) | ||
| 226 | |||
| 227 | /* Index a C library by name. */ | ||
| 228 | TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name) | ||
| 229 | { | ||
| 230 | TValue *tv = lj_tab_setstr(L, cl->cache, name); | ||
| 231 | if (LJ_UNLIKELY(tvisnil(tv))) { | ||
| 232 | CTState *cts = ctype_cts(L); | ||
| 233 | CType *ct; | ||
| 234 | CTypeID id = lj_ctype_getname(cts, &ct, name, CLNS_INDEX); | ||
| 235 | if (!id) | ||
| 236 | lj_err_callerv(L, LJ_ERR_FFI_NODECL, strdata(name)); | ||
| 237 | if (ctype_isconstval(ct->info)) { | ||
| 238 | CType *ctt = ctype_child(cts, ct); | ||
| 239 | lua_assert(ctype_isinteger(ctt->info) && ctt->size <= 4); | ||
| 240 | if ((ctt->info & CTF_UNSIGNED) && ctt->size == 4) | ||
| 241 | setnumV(tv, (lua_Number)(uint32_t)ct->size); | ||
| 242 | else | ||
| 243 | setnumV(tv, (lua_Number)(int32_t)ct->size); | ||
| 244 | } else { | ||
| 245 | void *p = clib_getsym(L, cl, name); | ||
| 246 | GCcdata *cd; | ||
| 247 | lua_assert(ctype_isfunc(ct->info) || ctype_isextern(ct->info)); | ||
| 248 | cd = lj_cdata_new(cts, id, CTSIZE_PTR); | ||
| 249 | *(void **)cdataptr(cd) = p; | ||
| 250 | setcdataV(L, tv, cd); | ||
| 251 | } | ||
| 252 | } | ||
| 253 | return tv; | ||
| 254 | } | ||
| 255 | |||
| 256 | /* -- C library management ------------------------------------------------ */ | ||
| 257 | |||
| 258 | /* Create a new CLibrary object and push it on the stack. */ | ||
| 259 | static CLibrary *clib_new(lua_State *L, GCtab *mt) | ||
| 260 | { | ||
| 261 | GCtab *t = lj_tab_new(L, 0, 0); | ||
| 262 | GCudata *ud = lj_udata_new(L, sizeof(CLibrary), t); | ||
| 263 | CLibrary *cl = (CLibrary *)uddata(ud); | ||
| 264 | cl->cache = t; | ||
| 265 | ud->udtype = UDTYPE_FFI_CLIB; | ||
| 266 | /* NOBARRIER: The GCudata is new (marked white). */ | ||
| 267 | setgcref(ud->metatable, obj2gco(mt)); | ||
| 268 | setudataV(L, L->top++, ud); | ||
| 269 | return cl; | ||
| 270 | } | ||
| 271 | |||
| 272 | /* Load a C library. */ | ||
| 273 | void lj_clib_load(lua_State *L, GCtab *mt, GCstr *name, int global) | ||
| 274 | { | ||
| 275 | void *handle = clib_loadlib(L, name, global); | ||
| 276 | CLibrary *cl = clib_new(L, mt); | ||
| 277 | cl->handle = handle; | ||
| 278 | } | ||
| 279 | |||
| 280 | /* Unload a C library. */ | ||
| 281 | void lj_clib_unload(CLibrary *cl) | ||
| 282 | { | ||
| 283 | clib_unloadlib(cl); | ||
| 284 | cl->handle = NULL; | ||
| 285 | } | ||
| 286 | |||
| 287 | /* Create the default C library object. */ | ||
| 288 | void lj_clib_default(lua_State *L, GCtab *mt) | ||
| 289 | { | ||
| 290 | CLibrary *cl = clib_new(L, mt); | ||
| 291 | cl->handle = CLIB_DEFHANDLE; | ||
| 292 | } | ||
| 293 | |||
| 294 | #endif | ||
diff --git a/src/lj_clib.h b/src/lj_clib.h new file mode 100644 index 00000000..86045d24 --- /dev/null +++ b/src/lj_clib.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | /* | ||
| 2 | ** FFI C library loader. | ||
| 3 | ** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef _LJ_CLIB_H | ||
| 7 | #define _LJ_CLIB_H | ||
| 8 | |||
| 9 | #include "lj_obj.h" | ||
| 10 | |||
| 11 | #if LJ_HASFFI | ||
| 12 | |||
| 13 | /* C library namespace. */ | ||
| 14 | typedef struct CLibrary { | ||
| 15 | void *handle; /* Opaque handle for dynamic library loader. */ | ||
| 16 | GCtab *cache; /* Cache for resolved symbols. Anchored in ud->env. */ | ||
| 17 | } CLibrary; | ||
| 18 | |||
| 19 | LJ_FUNC TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name); | ||
| 20 | LJ_FUNC void lj_clib_load(lua_State *L, GCtab *mt, GCstr *name, int global); | ||
| 21 | LJ_FUNC void lj_clib_unload(CLibrary *cl); | ||
| 22 | LJ_FUNC void lj_clib_default(lua_State *L, GCtab *mt); | ||
| 23 | |||
| 24 | #endif | ||
| 25 | |||
| 26 | #endif | ||
diff --git a/src/lj_ctype.h b/src/lj_ctype.h index 0c581370..c804b706 100644 --- a/src/lj_ctype.h +++ b/src/lj_ctype.h | |||
| @@ -187,6 +187,7 @@ typedef struct CTState { | |||
| 187 | #define ctype_isfield(info) (ctype_type((info)) == CT_FIELD) | 187 | #define ctype_isfield(info) (ctype_type((info)) == CT_FIELD) |
| 188 | #define ctype_isbitfield(info) (ctype_type((info)) == CT_BITFIELD) | 188 | #define ctype_isbitfield(info) (ctype_type((info)) == CT_BITFIELD) |
| 189 | #define ctype_isconstval(info) (ctype_type((info)) == CT_CONSTVAL) | 189 | #define ctype_isconstval(info) (ctype_type((info)) == CT_CONSTVAL) |
| 190 | #define ctype_isextern(info) (ctype_type((info)) == CT_EXTERN) | ||
| 190 | #define ctype_hassize(info) (ctype_type((info)) <= CT_HASSIZE) | 191 | #define ctype_hassize(info) (ctype_type((info)) <= CT_HASSIZE) |
| 191 | 192 | ||
| 192 | /* Combined type and flag checks. */ | 193 | /* Combined type and flag checks. */ |
diff --git a/src/lj_errmsg.h b/src/lj_errmsg.h index 2d54d1e9..b139fa8d 100644 --- a/src/lj_errmsg.h +++ b/src/lj_errmsg.h | |||
| @@ -153,6 +153,7 @@ ERRDEF(FFI_NUMARG, "wrong number of arguments for function call") | |||
| 153 | ERRDEF(FFI_BADMEMBER, LUA_QS " has no member named " LUA_QS) | 153 | ERRDEF(FFI_BADMEMBER, LUA_QS " has no member named " LUA_QS) |
| 154 | ERRDEF(FFI_BADIDX, LUA_QS " cannot be indexed") | 154 | ERRDEF(FFI_BADIDX, LUA_QS " cannot be indexed") |
| 155 | ERRDEF(FFI_WRCONST, "attempt to write to constant location") | 155 | ERRDEF(FFI_WRCONST, "attempt to write to constant location") |
| 156 | ERRDEF(FFI_NODECL, "missing declaration for symbol " LUA_QS) | ||
| 156 | ERRDEF(FFI_NYIPACKBIT, "NYI: packed bit fields") | 157 | ERRDEF(FFI_NYIPACKBIT, "NYI: packed bit fields") |
| 157 | ERRDEF(FFI_NYICALL, "NYI: cannot call this C function (yet)") | 158 | ERRDEF(FFI_NYICALL, "NYI: cannot call this C function (yet)") |
| 158 | #endif | 159 | #endif |
diff --git a/src/lj_obj.h b/src/lj_obj.h index f40ef706..f49b12f9 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h | |||
| @@ -247,6 +247,7 @@ typedef struct GCudata { | |||
| 247 | enum { | 247 | enum { |
| 248 | UDTYPE_USERDATA, /* Regular userdata. */ | 248 | UDTYPE_USERDATA, /* Regular userdata. */ |
| 249 | UDTYPE_IO_FILE, /* I/O library FILE. */ | 249 | UDTYPE_IO_FILE, /* I/O library FILE. */ |
| 250 | UDTYPE_FFI_CLIB, /* FFI C library namespace. */ | ||
| 250 | UDTYPE__MAX | 251 | UDTYPE__MAX |
| 251 | }; | 252 | }; |
| 252 | 253 | ||
diff --git a/src/ljamalg.c b/src/ljamalg.c index 5dafc1b5..d273753a 100644 --- a/src/ljamalg.c +++ b/src/ljamalg.c | |||
| @@ -21,6 +21,10 @@ | |||
| 21 | #define _GNU_SOURCE | 21 | #define _GNU_SOURCE |
| 22 | #endif | 22 | #endif |
| 23 | 23 | ||
| 24 | #ifndef WINVER | ||
| 25 | #define WINVER 0x0500 | ||
| 26 | #endif | ||
| 27 | |||
| 24 | #include "lua.h" | 28 | #include "lua.h" |
| 25 | #include "lauxlib.h" | 29 | #include "lauxlib.h" |
| 26 | 30 | ||
| @@ -44,6 +48,7 @@ | |||
| 44 | #include "lj_cdata.c" | 48 | #include "lj_cdata.c" |
| 45 | #include "lj_cconv.c" | 49 | #include "lj_cconv.c" |
| 46 | #include "lj_ccall.c" | 50 | #include "lj_ccall.c" |
| 51 | #include "lj_clib.c" | ||
| 47 | #include "lj_cparse.c" | 52 | #include "lj_cparse.c" |
| 48 | #include "lj_lib.c" | 53 | #include "lj_lib.c" |
| 49 | #include "lj_ir.c" | 54 | #include "lj_ir.c" |
