Merge pull request #527 from adamharrison/native-interop
Native Plugins
This commit is contained in:
@@ -651,6 +651,85 @@ static int f_set_window_opacity(lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Symbol table for native plugin loading. Allows for a statically
|
||||
// bound lua library to be used by native plugins.
|
||||
typedef struct {
|
||||
const char* symbol;
|
||||
void* address;
|
||||
} lua_function_node;
|
||||
|
||||
#define P(FUNC) { "lua_" #FUNC, (void*)(lua_##FUNC) }
|
||||
#define U(FUNC) { "luaL_" #FUNC, (void*)(luaL_##FUNC) }
|
||||
static void* api_require(const char* symbol) {
|
||||
static lua_function_node nodes[] = {
|
||||
P(absindex), P(arith), P(atpanic), P(callk), P(checkstack),
|
||||
P(close), P(compare), P(concat), P(copy), P(createtable), P(dump),
|
||||
P(error), P(gc), P(getallocf), P(getctx), P(getfield), P(getglobal),
|
||||
P(gethook), P(gethookcount), P(gethookmask), P(getinfo), P(getlocal),
|
||||
P(getmetatable), P(getstack), P(gettable), P(gettop), P(getupvalue),
|
||||
P(getuservalue), P(insert), P(isnumber), P(isstring), P(isuserdata),
|
||||
P(len), P(load), P(newstate), P(newthread), P(newuserdata), P(next),
|
||||
P(pcallk), P(pushboolean), P(pushcclosure), P(pushfstring), P(pushinteger),
|
||||
P(pushlightuserdata), P(pushlstring), P(pushnil), P(pushnumber),
|
||||
P(pushstring), P(pushthread), P(pushunsigned), P(pushvalue),
|
||||
P(pushvfstring), P(rawequal), P(rawget), P(rawgeti), P(rawgetp), P(rawlen),
|
||||
P(rawset), P(rawseti), P(rawsetp), P(remove), P(replace), P(resume),
|
||||
P(setallocf), P(setfield), P(setglobal), P(sethook), P(setlocal),
|
||||
P(setmetatable), P(settable), P(settop), P(setupvalue), P(setuservalue),
|
||||
P(status), P(tocfunction), P(tointegerx), P(tolstring), P(toboolean),
|
||||
P(tonumberx), P(topointer), P(tothread), P(tounsignedx), P(touserdata),
|
||||
P(type), P(typename), P(upvalueid), P(upvaluejoin), P(version), P(xmove),
|
||||
P(yieldk), U(checkversion_), U(getmetafield), U(callmeta), U(tolstring),
|
||||
U(argerror), U(checknumber), U(optnumber), U(checkinteger),
|
||||
U(checkunsigned), U(checkstack), U(checktype), U(checkany),
|
||||
U(newmetatable), U(setmetatable), U(testudata), U(checkudata), U(where),
|
||||
U(error), U(fileresult), U(execresult), U(ref), U(unref), U(loadstring),
|
||||
U(newstate), U(len), U(setfuncs), U(getsubtable), U(buffinit),
|
||||
U(prepbuffsize), U(addlstring), U(addstring), U(addvalue), U(pushresult),
|
||||
U(pushresultsize), U(buffinitsize)
|
||||
};
|
||||
for (int i = 0; i < sizeof(nodes) / sizeof(lua_function_node); ++i) {
|
||||
if (strcmp(nodes[i].symbol, symbol) == 0)
|
||||
return nodes[i].address;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int f_load_native_plugin(lua_State* L) {
|
||||
size_t sname, namelen, pathlen;
|
||||
int results;
|
||||
char olib[512]; olib[sizeof(olib)-1] = 0;
|
||||
const char* name = luaL_checklstring(L, -2, &namelen);
|
||||
const char* path = luaL_checklstring(L, -1, &pathlen);
|
||||
void* library = SDL_LoadObject(path);
|
||||
if (name == 0 || !library)
|
||||
return luaL_error(L, "Unable to load %s: %s", name, SDL_GetError());
|
||||
lua_getglobal(L, "package");
|
||||
lua_getfield(L, -1, "native_plugins");
|
||||
lua_pushlightuserdata(L, library);
|
||||
lua_setfield(L, -2, name);
|
||||
lua_pop(L, 1);
|
||||
for (sname = namelen - 1; sname > 0 && name[sname] != '.'; --sname);
|
||||
snprintf(olib, sizeof(olib), "lua_open_lite_xl_%s", &name[sname+1]);
|
||||
int (*ext_entrypoint)(lua_State* L, void*) = SDL_LoadFunction(library, olib);
|
||||
if (!ext_entrypoint) {
|
||||
snprintf(olib, sizeof(olib), "lua_open_%s", &name[sname+1]);
|
||||
int (*entrypoint)(lua_State* L) = SDL_LoadFunction(library, olib);
|
||||
if (!entrypoint) {
|
||||
return luaL_error(L, "Unable to load %s: Can't find entrypoint. Requires a "
|
||||
"function defined as int lua_open_lite_xl_%s(lua_State* L, void* XL)",
|
||||
name, &name[sname+1]);
|
||||
}
|
||||
results = entrypoint(L);
|
||||
} else {
|
||||
results = ext_entrypoint(L, api_require);
|
||||
}
|
||||
if (!results)
|
||||
return luaL_error(L, "Unable to load %s: Your entrypoint must return at "
|
||||
" least one value.", name);
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg lib[] = {
|
||||
{ "poll_event", f_poll_event },
|
||||
@@ -678,6 +757,7 @@ static const luaL_Reg lib[] = {
|
||||
{ "exec", f_exec },
|
||||
{ "fuzzy_match", f_fuzzy_match },
|
||||
{ "set_window_opacity", f_set_window_opacity },
|
||||
{ "load_native_plugin", f_load_native_plugin },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
@@ -140,8 +140,6 @@ init_lua:
|
||||
lua_setglobal(L, "EXEFILE");
|
||||
|
||||
#ifdef __APPLE__
|
||||
lua_pushboolean(L, true);
|
||||
lua_setglobal(L, "MACOS");
|
||||
enable_momentum_scroll();
|
||||
#ifdef MACOS_USE_BUNDLE
|
||||
set_macos_bundle_resources(L);
|
||||
|
||||
Reference in New Issue
Block a user