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" |