|
|
|
|
@ -10,13 +10,14 @@
|
|
|
|
|
#include "lauxlib.h"
|
|
|
|
|
#include "lualib.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define REG_PACKAGE_IS_CONSTRUCTOR 0
|
|
|
|
|
#define REG_MODULES_AS_GLOBALS 0
|
|
|
|
|
#define REG_OBJECTS_AS_GLOBALS 0
|
|
|
|
|
#define OBJ_DATA_HIDDEN_METATABLE 1
|
|
|
|
|
#define LUAJIT_FFI 0
|
|
|
|
|
#define USE_FIELD_GET_SET_METHODS 0
|
|
|
|
|
#define LUAJIT_FFI 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -95,19 +96,26 @@ typedef int bool;
|
|
|
|
|
#define assert_obj_type(type, obj)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef obj_type_free
|
|
|
|
|
void *nobj_realloc(void *ptr, size_t osize, size_t nsize);
|
|
|
|
|
|
|
|
|
|
void *nobj_realloc(void *ptr, size_t osize, size_t nsize) {
|
|
|
|
|
(void)osize;
|
|
|
|
|
if(0 == nsize) {
|
|
|
|
|
free(ptr);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return realloc(ptr, nsize);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define obj_type_free(type, obj) do { \
|
|
|
|
|
assert_obj_type(type, obj); \
|
|
|
|
|
free((obj)); \
|
|
|
|
|
nobj_realloc((obj), sizeof(type), 0); \
|
|
|
|
|
} while(0)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef obj_type_new
|
|
|
|
|
#define obj_type_new(type, obj) do { \
|
|
|
|
|
assert_obj_type(type, obj); \
|
|
|
|
|
(obj) = malloc(sizeof(type)); \
|
|
|
|
|
(obj) = nobj_realloc(NULL, 0, sizeof(type)); \
|
|
|
|
|
} while(0)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
typedef struct obj_type obj_type;
|
|
|
|
|
|
|
|
|
|
@ -165,15 +173,22 @@ typedef struct obj_field {
|
|
|
|
|
uint32_t flags; /**< is_writable:1bit */
|
|
|
|
|
} obj_field;
|
|
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
|
REG_OBJECT,
|
|
|
|
|
REG_PACKAGE,
|
|
|
|
|
REG_META,
|
|
|
|
|
} module_reg_type;
|
|
|
|
|
|
|
|
|
|
typedef struct reg_sub_module {
|
|
|
|
|
obj_type *type;
|
|
|
|
|
int is_package;
|
|
|
|
|
module_reg_type req_type;
|
|
|
|
|
const luaL_reg *pub_funcs;
|
|
|
|
|
const luaL_reg *methods;
|
|
|
|
|
const luaL_reg *metas;
|
|
|
|
|
const obj_base *bases;
|
|
|
|
|
const obj_field *fields;
|
|
|
|
|
const obj_const *constants;
|
|
|
|
|
int bidirectional_consts;
|
|
|
|
|
} reg_sub_module;
|
|
|
|
|
|
|
|
|
|
#define OBJ_UDATA_FLAG_OWN (1<<0)
|
|
|
|
|
@ -185,18 +200,26 @@ typedef struct obj_udata {
|
|
|
|
|
} obj_udata;
|
|
|
|
|
|
|
|
|
|
/* use static pointer as key to weak userdata table. */
|
|
|
|
|
static char *obj_udata_weak_ref_key = "obj_udata_weak_ref_key";
|
|
|
|
|
static char obj_udata_weak_ref_key[] = "obj_udata_weak_ref_key";
|
|
|
|
|
|
|
|
|
|
/* use static pointer as key to module's private table. */
|
|
|
|
|
static char obj_udata_private_key[] = "obj_udata_private_key";
|
|
|
|
|
|
|
|
|
|
#if LUAJIT_FFI
|
|
|
|
|
typedef int (*ffi_export_func_t)(void);
|
|
|
|
|
typedef struct ffi_export_symbol {
|
|
|
|
|
const char *name;
|
|
|
|
|
void *sym;
|
|
|
|
|
union {
|
|
|
|
|
void *data;
|
|
|
|
|
ffi_export_func_t func;
|
|
|
|
|
} sym;
|
|
|
|
|
} ffi_export_symbol;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static obj_type obj_types[] = {
|
|
|
|
|
#define obj_type_id_Lua_LLThread 0
|
|
|
|
|
#define obj_type_Lua_LLThread (obj_types[obj_type_id_Lua_LLThread])
|
|
|
|
|
@ -205,10 +228,101 @@ static obj_type obj_types[] = {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if LUAJIT_FFI
|
|
|
|
|
|
|
|
|
|
/* nobj_ffi_support_enabled_hint should be set to 1 when FFI support is enabled in at-least one
|
|
|
|
|
* instance of a LuaJIT state. It should never be set back to 0. */
|
|
|
|
|
static int nobj_ffi_support_enabled_hint = 0;
|
|
|
|
|
static const char nobj_ffi_support_key[] = "LuaNativeObject_FFI_SUPPORT";
|
|
|
|
|
static const char nobj_check_ffi_support_code[] =
|
|
|
|
|
"local stat, ffi=pcall(require,\"ffi\")\n" /* try loading LuaJIT`s FFI module. */
|
|
|
|
|
"if not stat then return false end\n"
|
|
|
|
|
"return true\n";
|
|
|
|
|
|
|
|
|
|
static int nobj_check_ffi_support(lua_State *L) {
|
|
|
|
|
int rc;
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
/* check if ffi test has already been done. */
|
|
|
|
|
lua_pushstring(L, nobj_ffi_support_key);
|
|
|
|
|
lua_rawget(L, LUA_REGISTRYINDEX);
|
|
|
|
|
if(!lua_isnil(L, -1)) {
|
|
|
|
|
rc = lua_toboolean(L, -1);
|
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
return rc; /* return results of previous check. */
|
|
|
|
|
}
|
|
|
|
|
lua_pop(L, 1); /* pop nil. */
|
|
|
|
|
|
|
|
|
|
err = luaL_loadbuffer(L, nobj_check_ffi_support_code,
|
|
|
|
|
sizeof(nobj_check_ffi_support_code) - 1, nobj_ffi_support_key);
|
|
|
|
|
if(0 == err) {
|
|
|
|
|
err = lua_pcall(L, 0, 1, 0);
|
|
|
|
|
}
|
|
|
|
|
if(err) {
|
|
|
|
|
const char *msg = "<err not a string>";
|
|
|
|
|
if(lua_isstring(L, -1)) {
|
|
|
|
|
msg = lua_tostring(L, -1);
|
|
|
|
|
}
|
|
|
|
|
printf("Error when checking for FFI-support: %s\n", msg);
|
|
|
|
|
lua_pop(L, 1); /* pop error message. */
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/* check results of test. */
|
|
|
|
|
rc = lua_toboolean(L, -1);
|
|
|
|
|
lua_pop(L, 1); /* pop results. */
|
|
|
|
|
/* cache results. */
|
|
|
|
|
lua_pushstring(L, nobj_ffi_support_key);
|
|
|
|
|
lua_pushboolean(L, rc);
|
|
|
|
|
lua_rawset(L, LUA_REGISTRYINDEX);
|
|
|
|
|
|
|
|
|
|
/* turn-on hint that there is FFI code enabled. */
|
|
|
|
|
if(rc) {
|
|
|
|
|
nobj_ffi_support_enabled_hint = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name,
|
|
|
|
|
const char *ffi_init_code, const ffi_export_symbol *ffi_exports, int priv_table)
|
|
|
|
|
{
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
/* export symbols to priv_table. */
|
|
|
|
|
while(ffi_exports->name != NULL) {
|
|
|
|
|
lua_pushstring(L, ffi_exports->name);
|
|
|
|
|
lua_pushlightuserdata(L, ffi_exports->sym.data);
|
|
|
|
|
lua_settable(L, priv_table);
|
|
|
|
|
ffi_exports++;
|
|
|
|
|
}
|
|
|
|
|
err = luaL_loadbuffer(L, ffi_init_code, strlen(ffi_init_code), ffi_mod_name);
|
|
|
|
|
if(0 == err) {
|
|
|
|
|
lua_pushvalue(L, -2); /* dup C module's table. */
|
|
|
|
|
lua_pushvalue(L, priv_table); /* move priv_table to top of stack. */
|
|
|
|
|
lua_remove(L, priv_table);
|
|
|
|
|
lua_pushvalue(L, LUA_REGISTRYINDEX);
|
|
|
|
|
err = lua_pcall(L, 3, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
if(err) {
|
|
|
|
|
const char *msg = "<err not a string>";
|
|
|
|
|
if(lua_isstring(L, -1)) {
|
|
|
|
|
msg = lua_tostring(L, -1);
|
|
|
|
|
}
|
|
|
|
|
printf("Failed to install FFI-based bindings: %s\n", msg);
|
|
|
|
|
lua_pop(L, 1); /* pop error message. */
|
|
|
|
|
}
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef REG_PACKAGE_IS_CONSTRUCTOR
|
|
|
|
|
#define REG_PACKAGE_IS_CONSTRUCTOR 1
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef REG_MODULES_AS_GLOBALS
|
|
|
|
|
#define REG_MODULES_AS_GLOBALS 0
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef REG_OBJECTS_AS_GLOBALS
|
|
|
|
|
#define REG_OBJECTS_AS_GLOBALS 0
|
|
|
|
|
#endif
|
|
|
|
|
@ -296,6 +410,25 @@ static FUNC_UNUSED obj_udata *obj_udata_luacheck_internal(lua_State *L, int _ind
|
|
|
|
|
return ud;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* handle cdata. */
|
|
|
|
|
/* get private table. */
|
|
|
|
|
lua_pushlightuserdata(L, obj_udata_private_key);
|
|
|
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* private table. */
|
|
|
|
|
/* get cdata type check function from private table. */
|
|
|
|
|
lua_pushlightuserdata(L, type);
|
|
|
|
|
lua_rawget(L, -2);
|
|
|
|
|
|
|
|
|
|
/* pass cdata value to type checking function. */
|
|
|
|
|
lua_pushvalue(L, _index);
|
|
|
|
|
lua_call(L, 1, 1);
|
|
|
|
|
if(!lua_isnil(L, -1)) {
|
|
|
|
|
/* valid type get pointer from cdata. */
|
|
|
|
|
lua_pop(L, 2);
|
|
|
|
|
*obj = *(void **)lua_topointer(L, _index);
|
|
|
|
|
return ud;
|
|
|
|
|
}
|
|
|
|
|
lua_pop(L, 2);
|
|
|
|
|
}
|
|
|
|
|
if(not_delete) {
|
|
|
|
|
luaL_typerror(L, _index, type->name); /* is not a userdata value. */
|
|
|
|
|
@ -309,6 +442,15 @@ static FUNC_UNUSED void *obj_udata_luacheck(lua_State *L, int _index, obj_type *
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FUNC_UNUSED void *obj_udata_luaoptional(lua_State *L, int _index, obj_type *type) {
|
|
|
|
|
void *obj = NULL;
|
|
|
|
|
if(lua_isnil(L, _index)) {
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
obj_udata_luacheck_internal(L, _index, &(obj), type, 1);
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FUNC_UNUSED void *obj_udata_luadelete(lua_State *L, int _index, obj_type *type, int *flags) {
|
|
|
|
|
void *obj;
|
|
|
|
|
obj_udata *ud = obj_udata_luacheck_internal(L, _index, &(obj), type, 0);
|
|
|
|
|
@ -327,6 +469,17 @@ static FUNC_UNUSED void obj_udata_luapush(lua_State *L, void *obj, obj_type *typ
|
|
|
|
|
lua_pushnil(L);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#if LUAJIT_FFI
|
|
|
|
|
lua_pushlightuserdata(L, type);
|
|
|
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */
|
|
|
|
|
if(nobj_ffi_support_enabled_hint && lua_isfunction(L, -1)) {
|
|
|
|
|
/* call special FFI "void *" to FFI object convertion function. */
|
|
|
|
|
lua_pushlightuserdata(L, obj);
|
|
|
|
|
lua_pushinteger(L, flags);
|
|
|
|
|
lua_call(L, 2, 1);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
/* check for type caster. */
|
|
|
|
|
if(type->dcaster) {
|
|
|
|
|
(type->dcaster)(&obj, &type);
|
|
|
|
|
@ -336,8 +489,12 @@ static FUNC_UNUSED void obj_udata_luapush(lua_State *L, void *obj, obj_type *typ
|
|
|
|
|
ud->obj = obj;
|
|
|
|
|
ud->flags = flags;
|
|
|
|
|
/* get obj_type metatable. */
|
|
|
|
|
#if LUAJIT_FFI
|
|
|
|
|
lua_insert(L, -2); /* move userdata below metatable. */
|
|
|
|
|
#else
|
|
|
|
|
lua_pushlightuserdata(L, type);
|
|
|
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */
|
|
|
|
|
#endif
|
|
|
|
|
lua_setmetatable(L, -2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -383,6 +540,18 @@ static FUNC_UNUSED void obj_udata_luapush_weak(lua_State *L, void *obj, obj_type
|
|
|
|
|
}
|
|
|
|
|
lua_pop(L, 1); /* pop nil. */
|
|
|
|
|
|
|
|
|
|
#if LUAJIT_FFI
|
|
|
|
|
lua_pushlightuserdata(L, type);
|
|
|
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */
|
|
|
|
|
if(nobj_ffi_support_enabled_hint && lua_isfunction(L, -1)) {
|
|
|
|
|
lua_remove(L, -2);
|
|
|
|
|
/* call special FFI "void *" to FFI object convertion function. */
|
|
|
|
|
lua_pushlightuserdata(L, obj);
|
|
|
|
|
lua_pushinteger(L, flags);
|
|
|
|
|
lua_call(L, 2, 1);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
/* create new userdata. */
|
|
|
|
|
ud = (obj_udata *)lua_newuserdata(L, sizeof(obj_udata));
|
|
|
|
|
|
|
|
|
|
@ -390,8 +559,12 @@ static FUNC_UNUSED void obj_udata_luapush_weak(lua_State *L, void *obj, obj_type
|
|
|
|
|
ud->obj = obj;
|
|
|
|
|
ud->flags = flags;
|
|
|
|
|
/* get obj_type metatable. */
|
|
|
|
|
#if LUAJIT_FFI
|
|
|
|
|
lua_insert(L, -2); /* move userdata below metatable. */
|
|
|
|
|
#else
|
|
|
|
|
lua_pushlightuserdata(L, type);
|
|
|
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */
|
|
|
|
|
#endif
|
|
|
|
|
lua_setmetatable(L, -2);
|
|
|
|
|
|
|
|
|
|
/* add weak reference to object. */
|
|
|
|
|
@ -455,15 +628,39 @@ static FUNC_UNUSED void * obj_simple_udata_luacheck(lua_State *L, int _index, ob
|
|
|
|
|
return ud;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* handle cdata. */
|
|
|
|
|
/* get private table. */
|
|
|
|
|
lua_pushlightuserdata(L, obj_udata_private_key);
|
|
|
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* private table. */
|
|
|
|
|
/* get cdata type check function from private table. */
|
|
|
|
|
lua_pushlightuserdata(L, type);
|
|
|
|
|
lua_rawget(L, -2);
|
|
|
|
|
|
|
|
|
|
/* pass cdata value to type checking function. */
|
|
|
|
|
lua_pushvalue(L, _index);
|
|
|
|
|
lua_call(L, 1, 1);
|
|
|
|
|
if(!lua_isnil(L, -1)) {
|
|
|
|
|
/* valid type get pointer from cdata. */
|
|
|
|
|
lua_pop(L, 2);
|
|
|
|
|
return (void *)lua_topointer(L, _index);
|
|
|
|
|
}
|
|
|
|
|
lua_pop(L, 2);
|
|
|
|
|
}
|
|
|
|
|
luaL_typerror(L, _index, type->name); /* is not a userdata value. */
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FUNC_UNUSED void * obj_simple_udata_luadelete(lua_State *L, int _index, obj_type *type, int *flags) {
|
|
|
|
|
static FUNC_UNUSED void * obj_simple_udata_luaoptional(lua_State *L, int _index, obj_type *type) {
|
|
|
|
|
if(lua_isnil(L, _index)) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return obj_simple_udata_luacheck(L, _index, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FUNC_UNUSED void * obj_simple_udata_luadelete(lua_State *L, int _index, obj_type *type) {
|
|
|
|
|
void *obj;
|
|
|
|
|
obj = obj_simple_udata_luacheck(L, _index, type);
|
|
|
|
|
*flags = OBJ_UDATA_FLAG_OWN;
|
|
|
|
|
/* clear the metatable to invalidate userdata. */
|
|
|
|
|
lua_pushnil(L);
|
|
|
|
|
lua_setmetatable(L, _index);
|
|
|
|
|
@ -472,12 +669,26 @@ static FUNC_UNUSED void * obj_simple_udata_luadelete(lua_State *L, int _index, o
|
|
|
|
|
|
|
|
|
|
static FUNC_UNUSED void *obj_simple_udata_luapush(lua_State *L, void *obj, int size, obj_type *type)
|
|
|
|
|
{
|
|
|
|
|
#if LUAJIT_FFI
|
|
|
|
|
lua_pushlightuserdata(L, type);
|
|
|
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */
|
|
|
|
|
if(nobj_ffi_support_enabled_hint && lua_isfunction(L, -1)) {
|
|
|
|
|
/* call special FFI "void *" to FFI object convertion function. */
|
|
|
|
|
lua_pushlightuserdata(L, obj);
|
|
|
|
|
lua_call(L, 1, 1);
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
/* create new userdata. */
|
|
|
|
|
void *ud = lua_newuserdata(L, size);
|
|
|
|
|
memcpy(ud, obj, size);
|
|
|
|
|
/* get obj_type metatable. */
|
|
|
|
|
#if LUAJIT_FFI
|
|
|
|
|
lua_insert(L, -2); /* move userdata below metatable. */
|
|
|
|
|
#else
|
|
|
|
|
lua_pushlightuserdata(L, type);
|
|
|
|
|
lua_rawget(L, LUA_REGISTRYINDEX); /* type's metatable. */
|
|
|
|
|
#endif
|
|
|
|
|
lua_setmetatable(L, -2);
|
|
|
|
|
|
|
|
|
|
return ud;
|
|
|
|
|
@ -526,7 +737,8 @@ static int obj_constructor_call_wrapper(lua_State *L) {
|
|
|
|
|
return lua_gettop(L);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void obj_type_register_constants(lua_State *L, const obj_const *constants, int tab_idx) {
|
|
|
|
|
static void obj_type_register_constants(lua_State *L, const obj_const *constants, int tab_idx,
|
|
|
|
|
int bidirectional) {
|
|
|
|
|
/* register constants. */
|
|
|
|
|
while(constants->name != NULL) {
|
|
|
|
|
lua_pushstring(L, constants->name);
|
|
|
|
|
@ -544,6 +756,22 @@ static void obj_type_register_constants(lua_State *L, const obj_const *constants
|
|
|
|
|
lua_pushnil(L);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* map values back to keys. */
|
|
|
|
|
if(bidirectional) {
|
|
|
|
|
/* check if value already exists. */
|
|
|
|
|
lua_pushvalue(L, -1);
|
|
|
|
|
lua_rawget(L, tab_idx - 3);
|
|
|
|
|
if(lua_isnil(L, -1)) {
|
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
/* add value->key mapping. */
|
|
|
|
|
lua_pushvalue(L, -1);
|
|
|
|
|
lua_pushvalue(L, -3);
|
|
|
|
|
lua_rawset(L, tab_idx - 4);
|
|
|
|
|
} else {
|
|
|
|
|
/* value already exists. */
|
|
|
|
|
lua_pop(L, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lua_rawset(L, tab_idx - 2);
|
|
|
|
|
constants++;
|
|
|
|
|
}
|
|
|
|
|
@ -558,20 +786,48 @@ static void obj_type_register_package(lua_State *L, const reg_sub_module *type_r
|
|
|
|
|
luaL_register(L, NULL, reg_list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
obj_type_register_constants(L, type_reg->constants, -1);
|
|
|
|
|
obj_type_register_constants(L, type_reg->constants, -1, type_reg->bidirectional_consts);
|
|
|
|
|
|
|
|
|
|
lua_pop(L, 1); /* drop package table */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void obj_type_register_meta(lua_State *L, const reg_sub_module *type_reg) {
|
|
|
|
|
const luaL_reg *reg_list;
|
|
|
|
|
|
|
|
|
|
/* create public functions table. */
|
|
|
|
|
reg_list = type_reg->pub_funcs;
|
|
|
|
|
if(reg_list != NULL && reg_list[0].name != NULL) {
|
|
|
|
|
/* register functions */
|
|
|
|
|
luaL_register(L, NULL, reg_list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
obj_type_register_constants(L, type_reg->constants, -1, type_reg->bidirectional_consts);
|
|
|
|
|
|
|
|
|
|
/* register methods. */
|
|
|
|
|
luaL_register(L, NULL, type_reg->methods);
|
|
|
|
|
|
|
|
|
|
/* create metatable table. */
|
|
|
|
|
lua_newtable(L);
|
|
|
|
|
luaL_register(L, NULL, type_reg->metas); /* fill metatable */
|
|
|
|
|
/* setmetatable on meta-object. */
|
|
|
|
|
lua_setmetatable(L, -2);
|
|
|
|
|
|
|
|
|
|
lua_pop(L, 1); /* drop meta-object */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int priv_table) {
|
|
|
|
|
const luaL_reg *reg_list;
|
|
|
|
|
obj_type *type = type_reg->type;
|
|
|
|
|
const obj_base *base = type_reg->bases;
|
|
|
|
|
|
|
|
|
|
if(type_reg->is_package == 1) {
|
|
|
|
|
if(type_reg->req_type == REG_PACKAGE) {
|
|
|
|
|
obj_type_register_package(L, type_reg);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(type_reg->req_type == REG_META) {
|
|
|
|
|
obj_type_register_meta(L, type_reg);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* create public functions table. */
|
|
|
|
|
reg_list = type_reg->pub_funcs;
|
|
|
|
|
@ -620,14 +876,10 @@ static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int
|
|
|
|
|
lua_pushvalue(L, -2); /* dup metatable. */
|
|
|
|
|
lua_rawset(L, LUA_REGISTRYINDEX); /* REGISTRY[type] = metatable */
|
|
|
|
|
|
|
|
|
|
#if LUAJIT_FFI
|
|
|
|
|
/* add metatable to 'priv_table' */
|
|
|
|
|
lua_pushstring(L, type->name);
|
|
|
|
|
lua_pushvalue(L, -2); /* dup metatable. */
|
|
|
|
|
lua_rawset(L, priv_table); /* priv_table["<object_name>"] = metatable */
|
|
|
|
|
#else
|
|
|
|
|
(void)priv_table;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
luaL_register(L, NULL, type_reg->metas); /* fill metatable */
|
|
|
|
|
|
|
|
|
|
@ -638,7 +890,7 @@ static void obj_type_register(lua_State *L, const reg_sub_module *type_reg, int
|
|
|
|
|
base++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
obj_type_register_constants(L, type_reg->constants, -2);
|
|
|
|
|
obj_type_register_constants(L, type_reg->constants, -2, type_reg->bidirectional_consts);
|
|
|
|
|
|
|
|
|
|
lua_pushliteral(L, "__index");
|
|
|
|
|
lua_pushvalue(L, -3); /* dup methods table */
|
|
|
|
|
@ -658,54 +910,12 @@ static FUNC_UNUSED int lua_checktype_ref(lua_State *L, int _index, int _type) {
|
|
|
|
|
return luaL_ref(L, LUA_REGISTRYINDEX);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if LUAJIT_FFI
|
|
|
|
|
static int nobj_udata_new_ffi(lua_State *L) {
|
|
|
|
|
size_t size = luaL_checkinteger(L, 1);
|
|
|
|
|
luaL_checktype(L, 2, LUA_TTABLE);
|
|
|
|
|
lua_settop(L, 2);
|
|
|
|
|
/* create userdata. */
|
|
|
|
|
lua_newuserdata(L, size);
|
|
|
|
|
lua_replace(L, 1);
|
|
|
|
|
/* set userdata's metatable. */
|
|
|
|
|
lua_setmetatable(L, 1);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name,
|
|
|
|
|
const char *ffi_init_code, const ffi_export_symbol *ffi_exports, int priv_table)
|
|
|
|
|
{
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
/* export symbols to priv_table. */
|
|
|
|
|
while(ffi_exports->name != NULL) {
|
|
|
|
|
lua_pushstring(L, ffi_exports->name);
|
|
|
|
|
lua_pushlightuserdata(L, ffi_exports->sym);
|
|
|
|
|
lua_settable(L, priv_table);
|
|
|
|
|
ffi_exports++;
|
|
|
|
|
}
|
|
|
|
|
err = luaL_loadbuffer(L, ffi_init_code, strlen(ffi_init_code), ffi_mod_name);
|
|
|
|
|
if(0 == err) {
|
|
|
|
|
lua_pushvalue(L, -2); /* dup C module's table. */
|
|
|
|
|
lua_pushvalue(L, priv_table); /* move priv_table to top of stack. */
|
|
|
|
|
lua_remove(L, priv_table);
|
|
|
|
|
lua_pushcfunction(L, nobj_udata_new_ffi);
|
|
|
|
|
err = lua_pcall(L, 3, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
if(err) {
|
|
|
|
|
const char *msg = "<err not a string>";
|
|
|
|
|
if(lua_isstring(L, -1)) {
|
|
|
|
|
msg = lua_tostring(L, -1);
|
|
|
|
|
}
|
|
|
|
|
printf("Failed to install FFI-based bindings: %s\n", msg);
|
|
|
|
|
lua_pop(L, 1); /* pop error message. */
|
|
|
|
|
}
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define obj_type_Lua_LLThread_check(L, _index) \
|
|
|
|
|
obj_udata_luacheck(L, _index, &(obj_type_Lua_LLThread))
|
|
|
|
|
#define obj_type_Lua_LLThread_optional(L, _index) \
|
|
|
|
|
obj_udata_luaoptional(L, _index, &(obj_type_Lua_LLThread))
|
|
|
|
|
#define obj_type_Lua_LLThread_delete(L, _index, flags) \
|
|
|
|
|
obj_udata_luadelete_weak(L, _index, &(obj_type_Lua_LLThread), flags)
|
|
|
|
|
#define obj_type_Lua_LLThread_push(L, obj, flags) \
|
|
|
|
|
@ -714,8 +924,6 @@ static int nobj_try_loading_ffi(lua_State *L, const char *ffi_mod_name,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* maximum recursive depth of table copies. */
|
|
|
|
|
#define MAX_COPY_DEPTH 30
|
|
|
|
|
|
|
|
|
|
@ -1106,7 +1314,7 @@ static Lua_LLThread *llthread_create(lua_State *L, const char *code, size_t code
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* method: delete */
|
|
|
|
|
/* method: _priv */
|
|
|
|
|
static int Lua_LLThread__delete__meth(lua_State *L) {
|
|
|
|
|
int this_flags_idx1 = 0;
|
|
|
|
|
Lua_LLThread * this_idx1 = obj_type_Lua_LLThread_delete(L,1,&(this_flags_idx1));
|
|
|
|
|
@ -1264,14 +1472,21 @@ static const obj_const llthreads_constants[] = {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const reg_sub_module reg_sub_modules[] = {
|
|
|
|
|
{ &(obj_type_Lua_LLThread), 0, obj_Lua_LLThread_pub_funcs, obj_Lua_LLThread_methods, obj_Lua_LLThread_metas, obj_Lua_LLThread_bases, obj_Lua_LLThread_fields, obj_Lua_LLThread_constants},
|
|
|
|
|
{NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL}
|
|
|
|
|
{ &(obj_type_Lua_LLThread), REG_OBJECT, obj_Lua_LLThread_pub_funcs, obj_Lua_LLThread_methods, obj_Lua_LLThread_metas, obj_Lua_LLThread_bases, obj_Lua_LLThread_fields, obj_Lua_LLThread_constants, 0},
|
|
|
|
|
{NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, 0}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if LUAJIT_FFI
|
|
|
|
|
static const ffi_export_symbol llthreads_ffi_export[] = {
|
|
|
|
|
{NULL, { .data = NULL } }
|
|
|
|
|
};
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const luaL_Reg submodule_libs[] = {
|
|
|
|
|
@ -1304,20 +1519,26 @@ LUA_NOBJ_API int luaopen_llthreads(lua_State *L) {
|
|
|
|
|
const luaL_Reg *submodules = submodule_libs;
|
|
|
|
|
int priv_table = -1;
|
|
|
|
|
|
|
|
|
|
#if LUAJIT_FFI
|
|
|
|
|
/* private table to hold reference to object metatables. */
|
|
|
|
|
lua_newtable(L);
|
|
|
|
|
priv_table = lua_gettop(L);
|
|
|
|
|
#endif
|
|
|
|
|
lua_pushlightuserdata(L, obj_udata_private_key);
|
|
|
|
|
lua_pushvalue(L, priv_table);
|
|
|
|
|
lua_rawset(L, LUA_REGISTRYINDEX); /* store private table in registry. */
|
|
|
|
|
|
|
|
|
|
/* create object cache. */
|
|
|
|
|
create_object_instance_cache(L);
|
|
|
|
|
|
|
|
|
|
/* module table. */
|
|
|
|
|
#if REG_MODULES_AS_GLOBALS
|
|
|
|
|
luaL_register(L, "llthreads", llthreads_function);
|
|
|
|
|
#else
|
|
|
|
|
lua_newtable(L);
|
|
|
|
|
luaL_register(L, NULL, llthreads_function);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* register module constants. */
|
|
|
|
|
obj_type_register_constants(L, llthreads_constants, -1);
|
|
|
|
|
obj_type_register_constants(L, llthreads_constants, -1, 0);
|
|
|
|
|
|
|
|
|
|
for(; submodules->func != NULL ; submodules++) {
|
|
|
|
|
lua_pushcfunction(L, submodules->func);
|
|
|
|
|
@ -1338,9 +1559,14 @@ LUA_NOBJ_API int luaopen_llthreads(lua_State *L) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if LUAJIT_FFI
|
|
|
|
|
if(nobj_check_ffi_support(L)) {
|
|
|
|
|
nobj_try_loading_ffi(L, "llthreads", llthreads_ffi_lua_code,
|
|
|
|
|
llthreads_ffi_export, priv_table);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|