mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 23:24:09 +00:00
FFI: Add ffi.load() and ffi.C default namespace.
This commit is contained in:
parent
d215747fd5
commit
ddf6596333
@ -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_mcode.o lj_snap.o lj_record.o lj_crecord.o lj_ffrecord.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 \
|
||||
$(LJLIB_O) lib_init.o
|
||||
|
||||
|
@ -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
|
||||
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_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_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 \
|
||||
@ -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_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_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_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
|
||||
@ -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_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_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h lj_cparse.c lj_cparse.h \
|
||||
lj_lib.c lj_lib.h lj_ir.c lj_iropt.h lj_opt_mem.c lj_opt_fold.c \
|
||||
lj_folddef.h lj_opt_narrow.c lj_opt_dce.c lj_opt_loop.c lj_snap.h \
|
||||
lj_mcode.c lj_mcode.h lj_snap.c lj_target.h lj_target_*.h lj_record.c \
|
||||
lj_record.h lj_ffrecord.h lj_crecord.c lj_crecord.h lj_ffrecord.c \
|
||||
lj_recdef.h lj_asm.c lj_asm.h lj_trace.c lj_gdbjit.h lj_gdbjit.c \
|
||||
lj_alloc.c lib_aux.c lib_base.c lj_libdef.h lib_math.c lib_string.c \
|
||||
lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_bit.c \
|
||||
lib_jit.c lib_ffi.c lib_init.c
|
||||
lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h lj_clib.c lj_clib.h \
|
||||
lj_cparse.c lj_cparse.h lj_lib.c lj_lib.h lj_ir.c lj_iropt.h \
|
||||
lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \
|
||||
lj_opt_loop.c lj_snap.h lj_mcode.c lj_mcode.h lj_snap.c lj_target.h \
|
||||
lj_target_*.h lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \
|
||||
lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_trace.c \
|
||||
lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c lib_base.c lj_libdef.h \
|
||||
lib_math.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.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
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "lj_cdata.h"
|
||||
#include "lj_cconv.h"
|
||||
#include "lj_ccall.h"
|
||||
#include "lj_clib.h"
|
||||
#include "lj_ff.h"
|
||||
#include "lj_lib.h"
|
||||
|
||||
@ -357,6 +358,77 @@ checkgc:
|
||||
|
||||
#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 ----------------------------------------------- */
|
||||
|
||||
#define LJLIB_MODULE_ffi
|
||||
@ -567,6 +639,17 @@ LJLIB_CF(ffi_abi)
|
||||
|
||||
#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-2) LJLIB_SET(arch)
|
||||
|
||||
@ -579,8 +662,9 @@ LUALIB_API int luaopen_ffi(lua_State *L)
|
||||
lj_ctype_init(L);
|
||||
LJ_LIB_REG_(L, NULL, ffi_meta);
|
||||
/* NOBARRIER: basemt is a GC root. */
|
||||
L->top--;
|
||||
setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top)));
|
||||
setgcref(basemt_it(G(L), LJ_TCDATA), obj2gco(tabV(L->top-1)));
|
||||
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_ARCH_NAME);
|
||||
LJ_LIB_REG_(L, NULL, ffi); /* Note: no global "ffi" created! */
|
||||
|
@ -55,7 +55,8 @@ void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd)
|
||||
if (LJ_LIKELY(!cdataisv(cd))) {
|
||||
CType *ct = ctype_raw(ctype_ctsG(g), cd->typeid);
|
||||
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);
|
||||
} else {
|
||||
lj_mem_free(g, memcdatav(cd), sizecdatav(cd));
|
||||
|
@ -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)
|
||||
{
|
||||
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->gct = ~LJ_TCDATA;
|
||||
cd->typeid = ctype_check(cts, id);
|
||||
|
294
src/lj_clib.c
Normal file
294
src/lj_clib.c
Normal 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
26
src/lj_clib.h
Normal 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
|
@ -187,6 +187,7 @@ typedef struct CTState {
|
||||
#define ctype_isfield(info) (ctype_type((info)) == CT_FIELD)
|
||||
#define ctype_isbitfield(info) (ctype_type((info)) == CT_BITFIELD)
|
||||
#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)
|
||||
|
||||
/* Combined type and flag checks. */
|
||||
|
@ -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_BADIDX, LUA_QS " cannot be indexed")
|
||||
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_NYICALL, "NYI: cannot call this C function (yet)")
|
||||
#endif
|
||||
|
@ -247,6 +247,7 @@ typedef struct GCudata {
|
||||
enum {
|
||||
UDTYPE_USERDATA, /* Regular userdata. */
|
||||
UDTYPE_IO_FILE, /* I/O library FILE. */
|
||||
UDTYPE_FFI_CLIB, /* FFI C library namespace. */
|
||||
UDTYPE__MAX
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,10 @@
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#ifndef WINVER
|
||||
#define WINVER 0x0500
|
||||
#endif
|
||||
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
|
||||
@ -44,6 +48,7 @@
|
||||
#include "lj_cdata.c"
|
||||
#include "lj_cconv.c"
|
||||
#include "lj_ccall.c"
|
||||
#include "lj_clib.c"
|
||||
#include "lj_cparse.c"
|
||||
#include "lj_lib.c"
|
||||
#include "lj_ir.c"
|
||||
|
Loading…
Reference in New Issue
Block a user