Support requiring dll/so files;

Still WIP
This commit is contained in:
bjorn 2018-07-07 13:54:53 -07:00
parent 22f6e7831b
commit 0214c7605e
5 changed files with 102 additions and 16 deletions

View File

@ -32,8 +32,7 @@ static int pushDirectoryItem(void* userdata, const char* path, const char* filen
int l_lovrFilesystemLoad(lua_State* L);
// Loader to help Lua's require understand PhysFS.
static int filesystemLoader(lua_State* L) {
static int moduleLoader(lua_State* L) {
const char* module = luaL_gsub(L, lua_tostring(L, -1), ".", "/");
lua_pop(L, 2);
@ -49,6 +48,58 @@ static int filesystemLoader(lua_State* L) {
return 0;
}
static const char* libraryExtensions[] = {
#ifdef _WIN32
".dll", NULL
#elif __APPLE__
".so", ".dylib", NULL
#else
".so", NULL
#endif
};
static int libraryLoader(lua_State* L) {
const char* modulePath = luaL_gsub(L, lua_tostring(L, -1), ".", "/");
const char* moduleFunction = luaL_gsub(L, lua_tostring(L, -1), ".", "_");
lua_pop(L, 3);
char* path; int i;
vec_foreach(lovrFilesystemGetCRequirePath(), path, i) {
for (const char** extension = libraryExtensions; *extension != NULL; extension++) {
char buffer[64];
snprintf(buffer, 63, "%s%s", modulePath, *extension);
const char* filename = luaL_gsub(L, path, "??", buffer);
filename = luaL_gsub(L, filename, "?", modulePath);
lua_pop(L, 2);
if (lovrFilesystemIsFile(filename)) {
const char* realPath = lovrFilesystemGetRealDirectory(filename);
void* library = lovrLoadLibrary(realPath);
snprintf(buffer, 63, "luaopen_%s", moduleFunction);
void* function = lovrLoadSymbol(library, buffer);
if (!function) {
snprintf(buffer, 63, "loveopen_%s", moduleFunction);
function = dlsym(library, buffer);
if (!function) {
snprintf(buffer, 63, "lovropen_%s", moduleFunction);
function = dlsym(library, buffer);
}
}
if (function) {
lua_pushcfunction(L, (lua_CFunction) function);
return 1;
} else {
lovrCloseLibrary(library);
}
}
}
}
return 0;
}
int l_lovrFilesystemInit(lua_State* L) {
lua_newtable(L);
luaL_register(L, NULL, lovrFilesystem);
@ -61,20 +112,8 @@ int l_lovrFilesystemInit(lua_State* L) {
lovrFilesystemInit(arg0, arg1);
lua_pop(L, 3);
// Add custom package loader
lua_getglobal(L, "table");
lua_getfield(L, -1, "insert");
lua_getglobal(L, "package");
lua_getfield(L, -1, "loaders");
lua_remove(L, -2);
if (lua_istable(L, -1)) {
lua_pushinteger(L, 2); // Insert our loader after package.preload
lua_pushcfunction(L, filesystemLoader);
lua_call(L, 3, 0);
}
lua_pop(L, 1);
luax_registerloader(L, moduleLoader, 2);
luax_registerloader(L, libraryLoader, 3);
return 1;
}

View File

@ -45,6 +45,20 @@ int luax_emptymodule(lua_State* L) {
return 1;
}
void luax_registerloader(lua_State* L, lua_CFunction loader, int index) {
lua_getglobal(L, "table");
lua_getfield(L, -1, "insert");
lua_getglobal(L, "package");
lua_getfield(L, -1, "loaders");
lua_remove(L, -2);
if (lua_istable(L, -1)) {
lua_pushinteger(L, index);
lua_pushcfunction(L, loader);
lua_call(L, 3, 0);
}
lua_pop(L, 1);
}
void luax_registertype(lua_State* L, const char* name, const luaL_Reg* functions) {
// Push metatable

View File

@ -31,6 +31,7 @@
int luax_preloadmodule(lua_State* L, const char* key, lua_CFunction f);
int luax_emptymodule(lua_State* L);
void luax_registerloader(lua_State* L, lua_CFunction loader, int index);
void luax_registertype(lua_State* L, const char* name, const luaL_Reg* functions);
void luax_extendtype(lua_State* L, const char* base, const char* name, const luaL_Reg* baseFunctions, const luaL_Reg* functions);
int luax_releasetype(lua_State* L);

View File

@ -8,6 +8,7 @@
#include <Windows.h>
#else
#include <unistd.h>
#include <dlfcn.h>
#endif
_Thread_local void* lovrErrorContext = NULL;
@ -45,6 +46,34 @@ void lovrRelease(void* object) {
if (ref && --ref->count == 0) ref->free(object);
}
void* lovrLoadLibrary(const char* filename) {
#ifdef _WIN32
return LoadLibrary(WIN_UTF8ToString(filename));
#elif EMSCRIPTEN
return NULL;
#else
return dlopen(filename, RTLD_LAZY);
#endif
}
void* lovrLoadSymbol(void* library, const char* symbol) {
#ifdef _WIN32
return GetProcAddress((HMODULE) library, symbol);
#elif EMSCRIPTEN
return NULL;
#else
return dlsym(library, symbol);
#endif
}
void lovrCloseLibrary(void* library) {
#ifdef _WIN32
FreeLibrary((HMODULE) library);
#elif !defined(EMSCRIPTEN)
dlclose(library);
#endif
}
// https://github.com/starwing/luautf8
size_t utf8_decode(const char *s, const char *e, unsigned *pch) {
unsigned ch;

View File

@ -29,5 +29,8 @@ void lovrSleep(double seconds);
void* lovrAlloc(size_t size, void (*destructor)(void* object));
void lovrRetain(void* object);
void lovrRelease(void* object);
void* lovrLoadLibrary(const char* filename);
void* lovrLoadSymbol(void* library, const char* symbol);
void lovrCloseLibrary(void* library);
size_t utf8_decode(const char *s, const char *e, unsigned *pch);
uint32_t nextPo2(uint32_t x);