Refactor and extend library loading

This commit is contained in:
Ilari Liusvaara 2012-10-13 21:30:53 +03:00
parent 68ccf06684
commit 92c6d5f5af
5 changed files with 109 additions and 76 deletions

View file

@ -1,10 +0,0 @@
#ifndef _loadlib__hpp__included__
#define _loadlib__hpp__included__
#include <string>
void load_library(const std::string& filename);
extern const bool load_library_supported;
extern const char* library_is_called;
#endif

View file

@ -1,4 +1,4 @@
#include "core/loadlib.hpp"
#include "library/loadlib.hpp"
#include "core/command.hpp"
#include <stdexcept>
#include <sstream>
@ -8,7 +8,7 @@ namespace {
"Syntax: load-library <file>\nLoad library <file>\n",
[](arg_filename args) throw(std::bad_alloc, std::runtime_error) {
try {
load_library(args);
new loaded_library(args);
} catch(std::exception& e) {
std::ostringstream x;
x << "Can't load '" << std::string(args) << "': " << e.what();
@ -16,60 +16,3 @@ namespace {
}
});
}
#if !defined(NO_DLFCN) && !defined(_WIN32) && !defined(_WIN64)
#include <dlfcn.h>
#include <unistd.h>
void load_library(const std::string& filename)
{
char buffer[16384];
getcwd(buffer, 16383);
std::string _filename = filename;
if(filename.find_first_of("/") >= filename.length())
_filename = buffer + std::string("/") + filename;
void* h = dlopen(_filename.c_str(), RTLD_LOCAL | RTLD_NOW);
if(!h)
throw std::runtime_error(dlerror());
}
extern const bool load_library_supported = true;
#ifdef __APPLE__
const char* library_is_called = "Dynamic Library";
#else
const char* library_is_called = "Shared Object";
#endif
#elif defined(_WIN32) || defined(_WIN64)
#include <windows.h>
void load_library(const std::string& filename)
{
char buffer[16384];
GetCurrentDirectory(16383, buffer);
std::string _filename = filename;
if(filename.find_first_of("/\\") >= filename.length())
_filename = buffer + std::string("/") + filename;
HMODULE h = LoadLibraryA(_filename.c_str());
if(!h) {
int errcode = GetLastError();
char errorbuffer[1024];
if(FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errcode, 0,
errorbuffer, sizeof(errorbuffer), NULL))
throw std::runtime_error(errorbuffer);
else {
std::ostringstream str;
str << "Unknown system error (code " << errcode << ")";
throw std::runtime_error(str.str());
}
}
}
extern const bool load_library_supported = true;
const char* library_is_called = "Dynamic Link Library";
#else
void load_library(const std::string& filename)
{
throw std::runtime_error("Library loader not supported on this platform");
}
extern const bool load_library_supported = false;
const char* library_is_called = NULL;
#endif

100
src/library/loadlib.cpp Normal file
View file

@ -0,0 +1,100 @@
#include "library/loadlib.hpp"
#if !defined(NO_DLFCN) && !defined(_WIN32) && !defined(_WIN64)
#include <dlfcn.h>
#include <unistd.h>
#endif
namespace
{
#if defined(_WIN32) || defined(_WIN64)
std::string callsign = "dynamic link library";
#elif !defined(NO_DLFCN)
#if defined(__APPLE__)
std::string callsign = "dynamic library";
#else
std::string callsign = "shared object";
#endif
#else
std::string callsign = "";
#endif
}
loaded_library::loaded_library(const std::string& filename) throw(std::bad_alloc, std::runtime_error)
{
#if !defined(NO_DLFCN) && !defined(_WIN32) && !defined(_WIN64)
char buffer[16384];
getcwd(buffer, 16383);
std::string _filename = filename;
if(filename.find_first_of("/") >= filename.length())
_filename = buffer + std::string("/") + filename;
handle = dlopen(_filename.c_str(), RTLD_LOCAL | RTLD_NOW);
if(!handle)
throw std::runtime_error(dlerror());
#elif defined(_WIN32) || defined(_WIN64)
char buffer[16384];
GetCurrentDirectory(16383, buffer);
std::string _filename = filename;
if(filename.find_first_of("/\\") >= filename.length())
_filename = buffer + std::string("/") + filename;
handle = LoadLibraryA(_filename.c_str());
if(!handle) {
int errcode = GetLastError();
char errorbuffer[1024];
if(FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errcode, 0,
errorbuffer, sizeof(errorbuffer), NULL))
throw std::runtime_error(errorbuffer);
else {
std::ostringstream str;
str << "Unknown system error (code " << errcode << ")";
throw std::runtime_error(str.str());
}
}
#else
throw std::runtime_error("Loading libraries is not supported");
#endif
}
loaded_library::~loaded_library() throw()
{
#if !defined(NO_DLFCN) && !defined(_WIN32) && !defined(_WIN64)
dlclose(handle);
#elif defined(_WIN32) || defined(_WIN64)
FreeLibrary(handle);
#endif
}
void* loaded_library::operator[](const std::string& symbol) throw(std::bad_alloc, std::runtime_error)
{
#if !defined(NO_DLFCN) && !defined(_WIN32) && !defined(_WIN64)
dlerror();
void* s = dlsym(handle, symbol.c_str());
if(s)
return s;
char* e = dlerror();
if(e)
throw std::runtime_error(e);
return NULL; //Yes, real NULL symbol.
#elif defined(_WIN32) || defined(_WIN64)
void* s = GetProcAddress(handle, symbol.c_str());
if(s)
return s;
int errcode = GetLastError();
char errorbuffer[1024];
if(FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errcode, 0,
errorbuffer, sizeof(errorbuffer), NULL))
throw std::runtime_error(errorbuffer);
else {
std::ostringstream str;
str << "Unknown system error (code " << errcode << ")";
throw std::runtime_error(str.str());
}
#else
throw std::runtime_error("Library loading not supported");
#endif
}
const std::string& loaded_library::call_library() throw()
{
return callsign;
}

View file

@ -9,7 +9,7 @@
#include "core/dispatch.hpp"
#include "core/framebuffer.hpp"
#include "core/framerate.hpp"
#include "core/loadlib.hpp"
#include "library/loadlib.hpp"
#include "lua/lua.hpp"
#include "core/mainloop.hpp"
#include "core/memorywatch.hpp"
@ -772,9 +772,9 @@ wxwin_mainwindow::wxwin_mainwindow()
menu_entry(wxID_LOAD_STATE_RW, wxT("State (read-write)..."));
menu_entry(wxID_LOAD_STATE_P, wxT("State (preserve input)..."));
menu_entry(wxID_LOAD_MOVIE, wxT("Movie..."));
if(load_library_supported) {
if(loaded_library::call_library() != "") {
menu_separator();
menu_entry(wxID_LOAD_LIBRARY, towxstring(std::string("Load ") + library_is_called));
menu_entry(wxID_LOAD_LIBRARY, towxstring(std::string("Load ") + loaded_library::call_library()));
}
menu_separator();
menu_entry(wxID_RELOAD_ROM_IMAGE, wxT("Reload ROM"));
@ -1213,8 +1213,8 @@ void wxwin_mainwindow::handle_menu_click_cancelable(wxCommandEvent& e)
set_speed(-1);
break;
case wxID_LOAD_LIBRARY: {
std::string name = std::string("load ") + library_is_called;
load_library(pick_file(this, name, ".", false));
std::string name = std::string("load ") + loaded_library::call_library();
new loaded_library(pick_file(this, name, ".", false));
break;
}
case wxID_SETTINGS:

View file

@ -6,7 +6,7 @@
#include "core/dispatch.hpp"
#include "core/framerate.hpp"
#include "core/keymapper.hpp"
#include "core/loadlib.hpp"
#include "library/loadlib.hpp"
#include "lua/lua.hpp"
#include "core/mainloop.hpp"
#include "core/misc.hpp"
@ -163,7 +163,7 @@ namespace
}
} else if(a.length() >= 12 && a.substr(0, 15) == "--load-library=")
try {
load_library(a.substr(15));
new loaded_library(a.substr(15));
} catch(std::runtime_error& e) {
std::cerr << "Can't load '" << a.substr(15) << "': " << e.what() << std::endl;
exit(1);