FFI: Add ffi.load() and ffi.C default namespace.

This commit is contained in:
Mike Pall 2011-01-10 03:43:18 +01:00
parent d215747fd5
commit ddf6596333
11 changed files with 435 additions and 15 deletions

View File

@ -328,7 +328,7 @@ LJCORE_O= lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o \
lj_opt_dce.o lj_opt_loop.o \ lj_opt_dce.o lj_opt_loop.o \
lj_mcode.o lj_snap.o lj_record.o lj_crecord.o lj_ffrecord.o \ lj_mcode.o lj_snap.o lj_record.o lj_crecord.o lj_ffrecord.o \
lj_asm.o lj_trace.o lj_gdbjit.o \ lj_asm.o lj_trace.o lj_gdbjit.o \
lj_ctype.o lj_cdata.o lj_cconv.o lj_ccall.o lj_cparse.o \ lj_ctype.o lj_cdata.o lj_cconv.o lj_ccall.o lj_clib.o lj_cparse.o \
lj_lib.o lj_alloc.o lib_aux.o \ lj_lib.o lj_alloc.o lib_aux.o \
$(LJLIB_O) lib_init.o $(LJLIB_O) lib_init.o

View File

@ -22,7 +22,8 @@ lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h lj_libdef.h lj_def.h lj_arch.h lj_err.h lj_errmsg.h lj_lib.h lj_libdef.h
lib_ffi.o: lib_ffi.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ lib_ffi.o: lib_ffi.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cparse.h \ lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cparse.h \
lj_cdata.h lj_cconv.h lj_ccall.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h lj_cdata.h lj_cconv.h lj_ccall.h lj_clib.h lj_ff.h lj_ffdef.h lj_lib.h \
lj_libdef.h
lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h
lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ lib_io.o: lib_io.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ff.h lj_ffdef.h \ 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 \
lj_cdata.o: lj_cdata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_cdata.o: lj_cdata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cconv.h lj_cdata.h lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cconv.h lj_cdata.h
lj_char.o: lj_char.c lj_char.h lj_def.h lua.h luaconf.h lj_char.o: lj_char.c lj_char.h lj_def.h lua.h luaconf.h
lj_clib.o: lj_clib.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
lj_err.h lj_errmsg.h lj_tab.h lj_str.h lj_udata.h lj_ctype.h lj_cconv.h \
lj_cdata.h lj_clib.h
lj_cparse.o: lj_cparse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_cparse.o: lj_cparse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cparse.h lj_frame.h \ lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_ctype.h lj_cparse.h lj_frame.h \
lj_bc.h lj_vm.h lj_char.h 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 \
lj_func.c lj_udata.c lj_meta.c lj_state.c lj_lex.h lj_alloc.h \ lj_func.c lj_udata.c lj_meta.c lj_state.c lj_lex.h lj_alloc.h \
lj_dispatch.c lj_ff.h lj_ffdef.h luajit.h lj_vmevent.c lj_vmevent.h \ lj_dispatch.c lj_ff.h lj_ffdef.h luajit.h lj_vmevent.c lj_vmevent.h \
lj_api.c lj_parse.h lj_lex.c lualib.h lj_parse.c lj_ctype.c lj_cdata.c \ lj_api.c lj_parse.h lj_lex.c lualib.h lj_parse.c lj_ctype.c lj_cdata.c \
lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h lj_cparse.c lj_cparse.h \ lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h lj_clib.c lj_clib.h \
lj_lib.c lj_lib.h lj_ir.c lj_iropt.h lj_opt_mem.c lj_opt_fold.c \ lj_cparse.c lj_cparse.h lj_lib.c lj_lib.h lj_ir.c lj_iropt.h \
lj_folddef.h lj_opt_narrow.c lj_opt_dce.c lj_opt_loop.c lj_snap.h \ lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \
lj_mcode.c lj_mcode.h lj_snap.c lj_target.h lj_target_*.h lj_record.c \ lj_opt_loop.c lj_snap.h lj_mcode.c lj_mcode.h lj_snap.c lj_target.h \
lj_record.h lj_ffrecord.h lj_crecord.c lj_crecord.h lj_ffrecord.c \ lj_target_*.h lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \
lj_recdef.h lj_asm.c lj_asm.h lj_trace.c lj_gdbjit.h lj_gdbjit.c \ lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_trace.c \
lj_alloc.c lib_aux.c lib_base.c lj_libdef.h lib_math.c lib_string.c \ lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c lib_base.c lj_libdef.h \
lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_bit.c \ lib_math.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c \
lib_jit.c lib_ffi.c lib_init.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c lib_init.c
luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h

View File

@ -22,6 +22,7 @@
#include "lj_cdata.h" #include "lj_cdata.h"
#include "lj_cconv.h" #include "lj_cconv.h"
#include "lj_ccall.h" #include "lj_ccall.h"
#include "lj_clib.h"
#include "lj_ff.h" #include "lj_ff.h"
#include "lj_lib.h" #include "lj_lib.h"
@ -357,6 +358,77 @@ checkgc:
#include "lj_libdef.h" #include "lj_libdef.h"
/* -- C library metamethods ----------------------------------------------- */
#define LJLIB_MODULE_ffi_clib
/* Index C library by a name. */
static TValue *ffi_clib_index(lua_State *L)
{
TValue *o = L->base;
CLibrary *cl;
if (!(o < L->top && tvisudata(o) && udataV(o)->udtype == UDTYPE_FFI_CLIB))
lj_err_argt(L, 1, LUA_TUSERDATA);
cl = (CLibrary *)uddata(udataV(o));
if (!(o+1 < L->top && tvisstr(o+1)))
lj_err_argt(L, 2, LUA_TSTRING);
return lj_clib_index(L, cl, strV(o+1));
}
LJLIB_CF(ffi_clib___index)
{
TValue *tv = ffi_clib_index(L);
if (tviscdata(tv)) {
CTState *cts = ctype_cts(L);
GCcdata *cd = cdataV(tv);
CType *s = ctype_get(cts, cd->typeid);
if (ctype_isextern(s->info)) {
CTypeID sid = ctype_cid(s->info);
void *sp = *(void **)cdataptr(cd);
if (lj_cconv_tv_ct(cts, ctype_raw(cts, sid), sid, L->top-1, sp))
lj_gc_check(L);
return 1;
}
}
copyTV(L, L->top-1, tv);
return 1;
}
LJLIB_CF(ffi_clib___newindex)
{
TValue *tv = ffi_clib_index(L);
TValue *o = L->base+2;
if (o < L->top && tviscdata(tv)) {
CTState *cts = ctype_cts(L);
GCcdata *cd = cdataV(tv);
CType *d = ctype_get(cts, cd->typeid);
if (ctype_isextern(d->info)) {
CTInfo qual = 0;
for (;;) { /* Skip attributes and collect qualifiers. */
d = ctype_child(cts, d);
if (!ctype_isattrib(d->info)) break;
if (ctype_attrib(d->info) == CTA_QUAL) qual |= d->size;
}
if (!((d->info|qual) & CTF_CONST)) {
lj_cconv_ct_tv(cts, d, *(void **)cdataptr(cd), o, 0);
return 0;
}
}
}
lj_err_caller(L, LJ_ERR_FFI_WRCONST);
return 0; /* unreachable */
}
LJLIB_CF(ffi_clib___gc)
{
TValue *o = L->base;
if (o < L->top && tvisudata(o) && udataV(o)->udtype == UDTYPE_FFI_CLIB)
lj_clib_unload((CLibrary *)uddata(udataV(o)));
return 0;
}
#include "lj_libdef.h"
/* -- FFI library functions ----------------------------------------------- */ /* -- FFI library functions ----------------------------------------------- */
#define LJLIB_MODULE_ffi #define LJLIB_MODULE_ffi
@ -567,6 +639,17 @@ LJLIB_CF(ffi_abi)
#undef H_ #undef H_
LJLIB_PUSH(top-5) LJLIB_SET(!) /* Store clib metatable in func environment. */
LJLIB_CF(ffi_load)
{
GCstr *name = lj_lib_checkstr(L, 1);
int global = (L->base+1 < L->top && tvistruecond(L->base+1));
lj_clib_load(L, tabref(curr_func(L)->c.env), name, global);
return 1;
}
LJLIB_PUSH(top-4) LJLIB_SET(C)
LJLIB_PUSH(top-3) LJLIB_SET(os) LJLIB_PUSH(top-3) LJLIB_SET(os)
LJLIB_PUSH(top-2) LJLIB_SET(arch) LJLIB_PUSH(top-2) LJLIB_SET(arch)
@ -579,8 +662,9 @@ LUALIB_API int luaopen_ffi(lua_State *L)
lj_ctype_init(L); lj_ctype_init(L);
LJ_LIB_REG_(L, NULL, ffi_meta); LJ_LIB_REG_(L, NULL, ffi_meta);
/* NOBARRIER: basemt is a GC root. */ /* NOBARRIER: basemt is a GC root. */
L->top--; setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1)));
setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top))); LJ_LIB_REG_(L, NULL, ffi_clib);
lj_clib_default(L, tabV(L->top-1)); /* Create ffi.C default namespace. */
lua_pushliteral(L, LJ_OS_NAME); lua_pushliteral(L, LJ_OS_NAME);
lua_pushliteral(L, LJ_ARCH_NAME); lua_pushliteral(L, LJ_ARCH_NAME);
LJ_LIB_REG_(L, NULL, ffi); /* Note: no global "ffi" created! */ LJ_LIB_REG_(L, NULL, ffi); /* Note: no global "ffi" created! */

View File

@ -55,7 +55,8 @@ void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd)
if (LJ_LIKELY(!cdataisv(cd))) { if (LJ_LIKELY(!cdataisv(cd))) {
CType *ct = ctype_raw(ctype_ctsG(g), cd->typeid); CType *ct = ctype_raw(ctype_ctsG(g), cd->typeid);
CTSize sz = ctype_hassize(ct->info) ? ct->size : CTSIZE_PTR; CTSize sz = ctype_hassize(ct->info) ? ct->size : CTSIZE_PTR;
lua_assert(ctype_hassize(ct->info) || ctype_isfunc(ct->info)); lua_assert(ctype_hassize(ct->info) || ctype_isfunc(ct->info) ||
ctype_isextern(ct->info));
lj_mem_free(g, cd, sizeof(GCcdata) + sz); lj_mem_free(g, cd, sizeof(GCcdata) + sz);
} else { } else {
lj_mem_free(g, memcdatav(cd), sizecdatav(cd)); lj_mem_free(g, memcdatav(cd), sizecdatav(cd));

View File

@ -38,7 +38,10 @@ static LJ_AINLINE void cdata_setptr(void *p, CTSize sz, const void *v)
static LJ_AINLINE GCcdata *lj_cdata_new(CTState *cts, CTypeID id, CTSize sz) static LJ_AINLINE GCcdata *lj_cdata_new(CTState *cts, CTypeID id, CTSize sz)
{ {
GCcdata *cd; GCcdata *cd;
lua_assert(lj_ctype_size(cts, id) == sz); #ifdef LUA_USE_ASSERT
CType *ct = ctype_raw(cts, id);
lua_assert((ctype_hassize(ct->info) ? ct->size : CTSIZE_PTR) == sz);
#endif
cd = (GCcdata *)lj_mem_newgco(cts->L, sizeof(GCcdata) + sz); cd = (GCcdata *)lj_mem_newgco(cts->L, sizeof(GCcdata) + sz);
cd->gct = ~LJ_TCDATA; cd->gct = ~LJ_TCDATA;
cd->typeid = ctype_check(cts, id); cd->typeid = ctype_check(cts, id);

294
src/lj_clib.c Normal file
View File

@ -0,0 +1,294 @@
/*
** FFI C library loader.
** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h
*/
#include "lj_obj.h"
#if LJ_HASFFI
#include "lj_gc.h"
#include "lj_err.h"
#include "lj_tab.h"
#include "lj_str.h"
#include "lj_udata.h"
#include "lj_ctype.h"
#include "lj_cconv.h"
#include "lj_cdata.h"
#include "lj_clib.h"
/* -- OS-specific functions ----------------------------------------------- */
#if LJ_TARGET_DLOPEN
#include <dlfcn.h>
#if defined(RTLD_DEFAULT)
#define CLIB_DEFHANDLE RTLD_DEFAULT
#elif LJ_TARGET_OSX || LJ_TARGET_BSD
#define CLIB_DEFHANDLE ((void *)-2)
#else
#define CLIB_DEFHANDLE NULL
#endif
LJ_NORET LJ_NOINLINE static void clib_error(lua_State *L)
{
lj_err_callermsg(L, dlerror());
}
#if LJ_TARGET_OSX
#define CLIB_SOEXT "%s.dylib"
#else
#define CLIB_SOEXT "%s.so"
#endif
static const char *clib_extname(lua_State *L, GCstr *name)
{
const char *s = strdata(name);
if (!strchr(s, '/')) {
if (!strchr(s, '.')) {
s = lj_str_pushf(L, CLIB_SOEXT, s);
L->top--;
}
if (!(s[0] == 'l' && s[1] == 'i' && s[2] == 'b')) {
s = lj_str_pushf(L, "lib%s", s);
L->top--;
}
}
return s;
}
static void *clib_loadlib(lua_State *L, GCstr *name, int global)
{
void *h = dlopen(clib_extname(L, name),
RTLD_LAZY | (global?RTLD_GLOBAL:RTLD_LOCAL));
if (!h) clib_error(L);
return h;
}
static void clib_unloadlib(CLibrary *cl)
{
if (!cl->handle && cl->handle != CLIB_DEFHANDLE)
dlclose(cl->handle);
}
static void *clib_getsym(lua_State *L, CLibrary *cl, GCstr *name)
{
void *p = dlsym(cl->handle, strdata(name));
if (!p) clib_error(L);
return p;
}
#elif LJ_TARGET_WINDOWS
#define WIN32_LEAN_AND_MEAN
#ifndef WINVER
#define WINVER 0x0500
#endif
#include <windows.h>
#ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
#define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 4
BOOL WINAPI GetModuleHandleExA(DWORD, LPCSTR, HMODULE*);
#endif
#define CLIB_DEFHANDLE ((void *)-1)
/* Default libraries. */
enum {
CLIB_HANDLE_EXE,
CLIB_HANDLE_DLL,
CLIB_HANDLE_CRT,
CLIB_HANDLE_KERNEL32,
CLIB_HANDLE_USER32,
CLIB_HANDLE_GDI32,
CLIB_HANDLE_MAX
};
static void *clib_def_handle[CLIB_HANDLE_MAX];
LJ_NORET LJ_NOINLINE static void clib_error(lua_State *L, const char *fmt,
const char *name)
{
DWORD err = GetLastError();
char buf[128];
if (!FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_FROM_SYSTEM,
NULL, err, 0, buf, sizeof(buf), NULL))
buf[0] = '\0';
lj_err_callermsg(L, lj_str_pushf(L, fmt, name, buf));
}
static int clib_needext(const char *s)
{
while (*s) {
if (*s == '/' || *s == '\\' || *s == '.') return 0;
s++;
}
return 1;
}
static const char *clib_extname(lua_State *L, GCstr *name)
{
const char *s = strdata(name);
if (clib_needext(s)) {
s = lj_str_pushf(L, "%s.dll", s);
L->top--;
}
return s;
}
static void *clib_loadlib(lua_State *L, GCstr *name, int global)
{
void *h = (void *)LoadLibraryA(clib_extname(L, name));
if (!h) clib_error(L, "cannot load module " LUA_QS ": %s", strdata(name));
UNUSED(global);
return h;
}
static void clib_unloadlib(CLibrary *cl)
{
if (cl->handle == CLIB_DEFHANDLE) {
MSize i;
for (i = 0; i < CLIB_HANDLE_MAX; i++)
if (clib_def_handle[i])
FreeLibrary((HINSTANCE)clib_def_handle[i]);
} else if (!cl->handle) {
FreeLibrary((HINSTANCE)cl->handle);
}
}
static void *clib_getsym(lua_State *L, CLibrary *cl, GCstr *name)
{
const char *sym = strdata(name);
void *p;
if (cl->handle == CLIB_DEFHANDLE) { /* Search default libraries. */
MSize i;
for (i = 0; i < CLIB_HANDLE_MAX; i++) {
HINSTANCE h = (HINSTANCE)clib_def_handle[i];
if (!(void *)h) { /* Resolve default library handles (once). */
switch (i) {
case CLIB_HANDLE_EXE: GetModuleHandleExA(0, NULL, &h); break;
case CLIB_HANDLE_DLL:
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(const char *)clib_def_handle, &h);
break;
case CLIB_HANDLE_CRT:
GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(const char *)&_fmode, &h);
break;
case CLIB_HANDLE_KERNEL32: h = LoadLibraryA("kernel32.dll"); break;
case CLIB_HANDLE_USER32: h = LoadLibraryA("user32.dll"); break;
case CLIB_HANDLE_GDI32: h = LoadLibraryA("gdi32.dll"); break;
}
if (!h) continue;
clib_def_handle[i] = (void *)h;
}
p = (void *)GetProcAddress(h, sym);
if (p) break;
}
} else {
p = (void *)GetProcAddress((HINSTANCE)cl->handle, sym);
}
if (!p) clib_error(L, "cannot resolve symbol " LUA_QS ": %s", sym);
return p;
}
#else
#define CLIB_DEFHANDLE NULL
static void *clib_loadlib(lua_State *L, GCstr *name, int global)
{
lj_err_callermsg(L, "no support for loading dynamic libraries for this OS");
UNUSED(name); UNUSED(global);
return NULL;
}
static void clib_unloadlib(CLibrary *cl)
{
UNUSED(cl);
}
static void *clib_getsym(lua_State *L, CLibrary *cl, GCstr *name)
{
lj_err_callermsg(L, "no support for resolving symbols for this OS");
UNUSED(cl); UNUSED(name);
return NULL;
}
#endif
/* -- C library indexing -------------------------------------------------- */
/* Namespace for C library indexing. */
#define CLNS_INDEX \
((1u<<CT_FUNC)|(1u<<CT_EXTERN)|(1u<<CT_CONSTVAL))
/* Index a C library by name. */
TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name)
{
TValue *tv = lj_tab_setstr(L, cl->cache, name);
if (LJ_UNLIKELY(tvisnil(tv))) {
CTState *cts = ctype_cts(L);
CType *ct;
CTypeID id = lj_ctype_getname(cts, &ct, name, CLNS_INDEX);
if (!id)
lj_err_callerv(L, LJ_ERR_FFI_NODECL, strdata(name));
if (ctype_isconstval(ct->info)) {
CType *ctt = ctype_child(cts, ct);
lua_assert(ctype_isinteger(ctt->info) && ctt->size <= 4);
if ((ctt->info & CTF_UNSIGNED) && ctt->size == 4)
setnumV(tv, (lua_Number)(uint32_t)ct->size);
else
setnumV(tv, (lua_Number)(int32_t)ct->size);
} else {
void *p = clib_getsym(L, cl, name);
GCcdata *cd;
lua_assert(ctype_isfunc(ct->info) || ctype_isextern(ct->info));
cd = lj_cdata_new(cts, id, CTSIZE_PTR);
*(void **)cdataptr(cd) = p;
setcdataV(L, tv, cd);
}
}
return tv;
}
/* -- C library management ------------------------------------------------ */
/* Create a new CLibrary object and push it on the stack. */
static CLibrary *clib_new(lua_State *L, GCtab *mt)
{
GCtab *t = lj_tab_new(L, 0, 0);
GCudata *ud = lj_udata_new(L, sizeof(CLibrary), t);
CLibrary *cl = (CLibrary *)uddata(ud);
cl->cache = t;
ud->udtype = UDTYPE_FFI_CLIB;
/* NOBARRIER: The GCudata is new (marked white). */
setgcref(ud->metatable, obj2gco(mt));
setudataV(L, L->top++, ud);
return cl;
}
/* Load a C library. */
void lj_clib_load(lua_State *L, GCtab *mt, GCstr *name, int global)
{
void *handle = clib_loadlib(L, name, global);
CLibrary *cl = clib_new(L, mt);
cl->handle = handle;
}
/* Unload a C library. */
void lj_clib_unload(CLibrary *cl)
{
clib_unloadlib(cl);
cl->handle = NULL;
}
/* Create the default C library object. */
void lj_clib_default(lua_State *L, GCtab *mt)
{
CLibrary *cl = clib_new(L, mt);
cl->handle = CLIB_DEFHANDLE;
}
#endif

26
src/lj_clib.h Normal file
View File

@ -0,0 +1,26 @@
/*
** FFI C library loader.
** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h
*/
#ifndef _LJ_CLIB_H
#define _LJ_CLIB_H
#include "lj_obj.h"
#if LJ_HASFFI
/* C library namespace. */
typedef struct CLibrary {
void *handle; /* Opaque handle for dynamic library loader. */
GCtab *cache; /* Cache for resolved symbols. Anchored in ud->env. */
} CLibrary;
LJ_FUNC TValue *lj_clib_index(lua_State *L, CLibrary *cl, GCstr *name);
LJ_FUNC void lj_clib_load(lua_State *L, GCtab *mt, GCstr *name, int global);
LJ_FUNC void lj_clib_unload(CLibrary *cl);
LJ_FUNC void lj_clib_default(lua_State *L, GCtab *mt);
#endif
#endif

View File

@ -187,6 +187,7 @@ typedef struct CTState {
#define ctype_isfield(info) (ctype_type((info)) == CT_FIELD) #define ctype_isfield(info) (ctype_type((info)) == CT_FIELD)
#define ctype_isbitfield(info) (ctype_type((info)) == CT_BITFIELD) #define ctype_isbitfield(info) (ctype_type((info)) == CT_BITFIELD)
#define ctype_isconstval(info) (ctype_type((info)) == CT_CONSTVAL) #define ctype_isconstval(info) (ctype_type((info)) == CT_CONSTVAL)
#define ctype_isextern(info) (ctype_type((info)) == CT_EXTERN)
#define ctype_hassize(info) (ctype_type((info)) <= CT_HASSIZE) #define ctype_hassize(info) (ctype_type((info)) <= CT_HASSIZE)
/* Combined type and flag checks. */ /* Combined type and flag checks. */

View File

@ -153,6 +153,7 @@ ERRDEF(FFI_NUMARG, "wrong number of arguments for function call")
ERRDEF(FFI_BADMEMBER, LUA_QS " has no member named " LUA_QS) ERRDEF(FFI_BADMEMBER, LUA_QS " has no member named " LUA_QS)
ERRDEF(FFI_BADIDX, LUA_QS " cannot be indexed") ERRDEF(FFI_BADIDX, LUA_QS " cannot be indexed")
ERRDEF(FFI_WRCONST, "attempt to write to constant location") ERRDEF(FFI_WRCONST, "attempt to write to constant location")
ERRDEF(FFI_NODECL, "missing declaration for symbol " LUA_QS)
ERRDEF(FFI_NYIPACKBIT, "NYI: packed bit fields") ERRDEF(FFI_NYIPACKBIT, "NYI: packed bit fields")
ERRDEF(FFI_NYICALL, "NYI: cannot call this C function (yet)") ERRDEF(FFI_NYICALL, "NYI: cannot call this C function (yet)")
#endif #endif

View File

@ -247,6 +247,7 @@ typedef struct GCudata {
enum { enum {
UDTYPE_USERDATA, /* Regular userdata. */ UDTYPE_USERDATA, /* Regular userdata. */
UDTYPE_IO_FILE, /* I/O library FILE. */ UDTYPE_IO_FILE, /* I/O library FILE. */
UDTYPE_FFI_CLIB, /* FFI C library namespace. */
UDTYPE__MAX UDTYPE__MAX
}; };

View File

@ -21,6 +21,10 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#endif #endif
#ifndef WINVER
#define WINVER 0x0500
#endif
#include "lua.h" #include "lua.h"
#include "lauxlib.h" #include "lauxlib.h"
@ -44,6 +48,7 @@
#include "lj_cdata.c" #include "lj_cdata.c"
#include "lj_cconv.c" #include "lj_cconv.c"
#include "lj_ccall.c" #include "lj_ccall.c"
#include "lj_clib.c"
#include "lj_cparse.c" #include "lj_cparse.c"
#include "lj_lib.c" #include "lj_lib.c"
#include "lj_ir.c" #include "lj_ir.c"