mirror of https://github.com/bjornbytes/lovr.git
parent
22f6e7831b
commit
0214c7605e
|
@ -32,8 +32,7 @@ static int pushDirectoryItem(void* userdata, const char* path, const char* filen
|
||||||
|
|
||||||
int l_lovrFilesystemLoad(lua_State* L);
|
int l_lovrFilesystemLoad(lua_State* L);
|
||||||
|
|
||||||
// Loader to help Lua's require understand PhysFS.
|
static int moduleLoader(lua_State* L) {
|
||||||
static int filesystemLoader(lua_State* L) {
|
|
||||||
const char* module = luaL_gsub(L, lua_tostring(L, -1), ".", "/");
|
const char* module = luaL_gsub(L, lua_tostring(L, -1), ".", "/");
|
||||||
lua_pop(L, 2);
|
lua_pop(L, 2);
|
||||||
|
|
||||||
|
@ -49,6 +48,58 @@ static int filesystemLoader(lua_State* L) {
|
||||||
return 0;
|
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) {
|
int l_lovrFilesystemInit(lua_State* L) {
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
luaL_register(L, NULL, lovrFilesystem);
|
luaL_register(L, NULL, lovrFilesystem);
|
||||||
|
@ -61,20 +112,8 @@ int l_lovrFilesystemInit(lua_State* L) {
|
||||||
lovrFilesystemInit(arg0, arg1);
|
lovrFilesystemInit(arg0, arg1);
|
||||||
lua_pop(L, 3);
|
lua_pop(L, 3);
|
||||||
|
|
||||||
// Add custom package loader
|
luax_registerloader(L, moduleLoader, 2);
|
||||||
lua_getglobal(L, "table");
|
luax_registerloader(L, libraryLoader, 3);
|
||||||
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);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
src/luax.c
14
src/luax.c
|
@ -45,6 +45,20 @@ int luax_emptymodule(lua_State* L) {
|
||||||
return 1;
|
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) {
|
void luax_registertype(lua_State* L, const char* name, const luaL_Reg* functions) {
|
||||||
|
|
||||||
// Push metatable
|
// Push metatable
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
int luax_preloadmodule(lua_State* L, const char* key, lua_CFunction f);
|
int luax_preloadmodule(lua_State* L, const char* key, lua_CFunction f);
|
||||||
int luax_emptymodule(lua_State* L);
|
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_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);
|
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);
|
int luax_releasetype(lua_State* L);
|
||||||
|
|
29
src/util.c
29
src/util.c
|
@ -8,6 +8,7 @@
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_Thread_local void* lovrErrorContext = NULL;
|
_Thread_local void* lovrErrorContext = NULL;
|
||||||
|
@ -45,6 +46,34 @@ void lovrRelease(void* object) {
|
||||||
if (ref && --ref->count == 0) ref->free(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
|
// https://github.com/starwing/luautf8
|
||||||
size_t utf8_decode(const char *s, const char *e, unsigned *pch) {
|
size_t utf8_decode(const char *s, const char *e, unsigned *pch) {
|
||||||
unsigned ch;
|
unsigned ch;
|
||||||
|
|
|
@ -29,5 +29,8 @@ void lovrSleep(double seconds);
|
||||||
void* lovrAlloc(size_t size, void (*destructor)(void* object));
|
void* lovrAlloc(size_t size, void (*destructor)(void* object));
|
||||||
void lovrRetain(void* object);
|
void lovrRetain(void* object);
|
||||||
void lovrRelease(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);
|
size_t utf8_decode(const char *s, const char *e, unsigned *pch);
|
||||||
uint32_t nextPo2(uint32_t x);
|
uint32_t nextPo2(uint32_t x);
|
||||||
|
|
Loading…
Reference in New Issue