diff options
Diffstat (limited to 'src/lua-plugin.cc')
-rw-r--r-- | src/lua-plugin.cc | 120 |
1 files changed, 114 insertions, 6 deletions
diff --git a/src/lua-plugin.cc b/src/lua-plugin.cc index e80f0f8..fe4b0b5 100644 --- a/src/lua-plugin.cc +++ b/src/lua-plugin.cc @@ -1,4 +1,5 @@ #include <lua-plugin.h> +#include <Input.h> #if defined(_WIN32) #define SHARED_EXT "dll" @@ -12,6 +13,7 @@ typedef void(*init_ptr_t)(Lua *); #if defined(_WIN32) #include <windows.h> +#include "MemoryModule.h" void LuaLoadPlugin(const String & _fname, Lua * L) throw (GeneralException) { HMODULE handle; @@ -20,40 +22,146 @@ void LuaLoadPlugin(const String & _fname, Lua * L) throw (GeneralException) { Base::printm(M_INFO, "Loading library " + fname + "\n"); if (!(handle = LoadLibraryEx(fname.to_charp(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH)) && - !(handle = LoadLibraryEx(fname.to_charp(), NULL, NULL))) { - throw GeneralException("File not found or error loading shared object file: " + fname + "; Error #" + String((int) GetLastError())); + !(handle = LoadLibraryEx(fname.to_charp(), NULL, NULL))) { + LuaLoadPlugin(&Input(fname), L); + return; } init_ptr_t init_ptr = (init_ptr_t) GetProcAddress(handle, "init_plugin"); if (!init_ptr) { - throw GeneralException("No init pointer on plugin " + fname); + FreeLibrary(handle); + throw GeneralException("No init pointer on plugin " + fname); } Base::printm(M_INFO, "Library loaded, init ptr = %p\n", init_ptr); init_ptr(L); } + +void LuaLoadPlugin(Handle * h, Lua * L) throw (GeneralException) { + Byte * buffer; + + buffer = (Byte *) malloc(h->GetSize()); + h->read(buffer, h->GetSize()); + + HMEMORYMODULE module; + + if (!(module = ModuleLoadMemory(buffer))) + throw("Can't load library " + h->GetName() + " from memory."); + + init_ptr_t init_ptr = (init_ptr_t) MemoryGetProcAddress(module, "init_plugin"); + + if (!init_ptr) { + MemoryFreeLibrary(module); + throw GeneralException("No init pointer on plugin " + h->GetName()); + } + + Base::printm(M_INFO, "Library loaded, init ptr = %p\n", init_ptr); + + init_ptr(L); + + free(buffer); +} + #else #include <dlfcn.h> void LuaLoadPlugin(const String & fname, Lua * L) throw (GeneralException) { - void * handle = dlopen(("./" + fname + "." SHARED_EXT).to_charp(), RTLD_NOW | RTLD_GLOBAL); + String full_fname = "./" + fname + "." SHARED_EXT; + void * handle = dlopen(full_fname.to_charp(), RTLD_NOW | RTLD_GLOBAL); Base::printm(M_INFO, "Loading library " + fname + "\n"); if (!handle) { - throw GeneralException("File not found or error loading shared object file: " + fname + "; " + dlerror()); + LuaLoadPlugin(&Input(full_fname), L); + return; } init_ptr_t init_ptr = (init_ptr_t) dlsym(handle, "init_plugin"); if (!init_ptr) { - throw GeneralException("No init pointer on plugin " + fname); + dlclose(handle); + throw GeneralException("No init pointer on plugin " + fname); } Base::printm(M_INFO, "Library loaded, init ptr = %p\n", init_ptr); init_ptr(L); } + +#if defined(__APPLE__) +void LuaLoadPlugin(Handle * h, Lua * L) throw (GeneralException) { + Byte * buffer; + NSObjectFileImage image; + + kern_return_t result = vm_allocate(mach_task_self(), (vm_address_t *) &buffer, h->GetSize(), VM_FLAGS_ANYWHERE); + h->read(buffer, h->GetSize()); + + if (NSCreateObjectFileImageFromMemory(buffer, h->GetSize(), &image) != NSObjectFileImageSuccess) + throw("Can't load library " + h->GetName() + " from memory."); + + if (!NSLinkModule(image, h->GetName().get_charp(), NSLINKMODULE_OPTION_PRIVATE)) + throw("Can't link library " + h->GetName() + " from memory."); + + NSSymbol symbol = NSLookupSymbolInModule(module, "init_plugin"); + init_ptr_t init_ptr = (init_ptr_t) NSAddressOfSymbol(symbol); + + if (!init_ptr) { + NSDestroyObjectFileImage(image); + throw GeneralException("No init pointer on plugin " + fname); + } + + Base::printm(M_INFO, "Library loaded, init ptr = %p\n", init_ptr); + + init_ptr(L); + +} +#else + +#include <unistd.h> + +// I don't know of any good way of doing this under linux except this one... *shrug* +void LuaLoadPlugin(Handle * h, Lua * L) throw (GeneralException) { + char ftemplate[] = "/tmp/luaplugin.so.XXXXXX"); + int h; + + if ((h = mkstemp(ftemplate)) == -1) + throw GeneralException("Can't create temporary file to load plugin " + h->Getname()); + + Byte * buffer; + buffer = (Byte *) malloc(h->GetSize()); + h->read(buffer, h->GetSize()); + + if (write(h, buffer, h->GetSize()) != h->GetSize()) { + free(buffer); + close(h); + unlink(ftemplate); + throw GeneralException("Couldn't write to temporary file."); + } + + free(buffer); + void * handle = dlopen(ftemplate, RTLD_NOW | RTLD_GLOBAL); + unlink(ftemplate); + close(h); + + Base::printm(M_INFO, "Loading library " + fname + "\n"); + + if (!handle) + throw("Can't load library " + h->GetName() + " from memory."); + + init_ptr_t init_ptr = (init_ptr_t) dlsym(handle, "init_plugin"); + + if (!init_ptr) { + dlclose(handle); + throw GeneralException("No init pointer on plugin " + h->GetName()); + } + + Base::printm(M_INFO, "Library loaded, init ptr = %p\n", init_ptr); + + init_ptr(L); +} + +#endif + #endif |