aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2011-01-10 03:43:18 +0100
committerMike Pall <mike>2011-01-10 03:43:18 +0100
commitddf65963332f048838b759bb3d926c58b1b11ce3 (patch)
treec282aeef6c9c612ffa4f53f6e3465359c7b7edf7 /src
parentd215747fd5a97b3299262f8190803994a492b4d1 (diff)
downloadluajit-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/Makefile2
-rw-r--r--src/Makefile.dep24
-rw-r--r--src/lib_ffi.c88
-rw-r--r--src/lj_cdata.c3
-rw-r--r--src/lj_cdata.h5
-rw-r--r--src/lj_clib.c294
-rw-r--r--src/lj_clib.h26
-rw-r--r--src/lj_ctype.h1
-rw-r--r--src/lj_errmsg.h1
-rw-r--r--src/lj_obj.h1
-rw-r--r--src/ljamalg.c5
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
23lib_ffi.o: lib_ffi.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ 23lib_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
26lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h 27lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h
27lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ 28lib_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 \
63lj_cdata.o: lj_cdata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 64lj_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
65lj_char.o: lj_char.c lj_char.h lj_def.h lua.h luaconf.h 66lj_char.o: lj_char.c lj_char.h lj_def.h lua.h luaconf.h
67lj_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
66lj_cparse.o: lj_cparse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 70lj_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
168luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h 172luajit.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. */
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! */
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)
38static LJ_AINLINE GCcdata *lj_cdata_new(CTState *cts, CTypeID id, CTSize sz) 38static 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
34LJ_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
45static 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
61static 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
69static void clib_unloadlib(CLibrary *cl)
70{
71 if (!cl->handle && cl->handle != CLIB_DEFHANDLE)
72 dlclose(cl->handle);
73}
74
75static 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
92BOOL WINAPI GetModuleHandleExA(DWORD, LPCSTR, HMODULE*);
93#endif
94
95#define CLIB_DEFHANDLE ((void *)-1)
96
97/* Default libraries. */
98enum {
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
108static void *clib_def_handle[CLIB_HANDLE_MAX];
109
110LJ_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
121static 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
130static 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
140static 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
148static 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
160static 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
200static 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
207static void clib_unloadlib(CLibrary *cl)
208{
209 UNUSED(cl);
210}
211
212static 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. */
228TValue *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. */
259static 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. */
273void 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. */
281void lj_clib_unload(CLibrary *cl)
282{
283 clib_unloadlib(cl);
284 cl->handle = NULL;
285}
286
287/* Create the default C library object. */
288void 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. */
14typedef 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
19LJ_FUNC TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name);
20LJ_FUNC void lj_clib_load(lua_State *L, GCtab *mt, GCstr *name, int global);
21LJ_FUNC void lj_clib_unload(CLibrary *cl);
22LJ_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")
153ERRDEF(FFI_BADMEMBER, LUA_QS " has no member named " LUA_QS) 153ERRDEF(FFI_BADMEMBER, LUA_QS " has no member named " LUA_QS)
154ERRDEF(FFI_BADIDX, LUA_QS " cannot be indexed") 154ERRDEF(FFI_BADIDX, LUA_QS " cannot be indexed")
155ERRDEF(FFI_WRCONST, "attempt to write to constant location") 155ERRDEF(FFI_WRCONST, "attempt to write to constant location")
156ERRDEF(FFI_NODECL, "missing declaration for symbol " LUA_QS)
156ERRDEF(FFI_NYIPACKBIT, "NYI: packed bit fields") 157ERRDEF(FFI_NYIPACKBIT, "NYI: packed bit fields")
157ERRDEF(FFI_NYICALL, "NYI: cannot call this C function (yet)") 158ERRDEF(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 {
247enum { 247enum {
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"