Newer
Older
/**
* @file voltu.cpp
* @copyright Copyright (c) 2020 Nicolas Pope, MIT License
* @author Nicolas Pope
*/
#include <voltu/initialise.hpp>
#include <voltu/types/errors.hpp>
#include <voltu/voltu.hpp>
#if defined(WIN32)
#include <windows.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
static bool g_init = false;
typedef void* Library;
static Library loadLibrary(const char *file)
{
#if defined(WIN32)
return (Library)LoadLibraryEx(file, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
#else
return (Library)dlopen(file, RTLD_LOCAL | RTLD_NOW);
#endif
}
static void *getFunction(Library lib, const char *fname)
{
#if defined(WIN32)
return (void*)GetProcAddress((HMODULE)lib, fname);
#else
return dlsym(lib, fname);
#endif
}
static void unloadLibrary(Library lib)
{
if (!lib) return;
#if defined(WIN32)
FreeLibrary((HMODULE)lib);
#else
dlclose(lib);
#endif
}
static bool is_file(const std::string &path) {
#ifdef WIN32
WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFile(path.c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE) return false;
FindClose(hFind);
return true;
#else
struct stat s;
if (::stat(path.c_str(), &s) == 0) {
return true;
} else {
return false;
}
#endif
}
// TODO: Use full paths and find correct versions
#if defined(WIN32)
return "voltu.dll";
#else
std::string name = "libvoltu.so";
std::string vname = name + std::string(".") + std::to_string(VOLTU_VERSION_MAJOR) + std::string(".") + std::to_string(VOLTU_VERSION_MINOR);
if (is_file(std::string("./") + vname)) return std::string("./") + vname;
else if (is_file(std::string("./") + name)) return std::string("./") + name;
else if (is_file(std::string("../") + vname)) return std::string("../") + vname;
else if (is_file(std::string("../") + name)) return std::string("../") + name;
else if (is_file(std::string("/usr/local/lib/") + vname)) return std::string("/usr/local/lib/") + vname;
else if (is_file(std::string("/usr/local/lib/") + name)) return std::string("/usr/local/lib/") + name;
return name;
#endif
}
std::shared_ptr<voltu::System> voltu::instance()
{
if (g_init) return nullptr;
std::string name = locateLibrary();
std::cout << "Loading VolTu Runtime: " << name << std::endl;
Library handle = loadLibrary(name.c_str());
if (handle)
{
voltu::System* (*init)();
init = (voltu::System* (*)())getFunction(handle, "voltu_initialise");
if (init)
{
g_init = true;
std::shared_ptr<voltu::System> instance(init());
if (!instance)
{
throw voltu::exceptions::RuntimeAlreadyInUse();
// FIXME: Perhaps use a C method instead for safety?
auto ver = instance->getVersion();
if (ver.major != VOLTU_VERSION_MAJOR || ver.minor != VOLTU_VERSION_MINOR)
{
throw voltu::exceptions::RuntimeVersionMismatch();