grbc/src/ext_dynamic.cc

72 lines
1.9 KiB
C++

#include "grbc/ext_dynamic.h"
extern "C" {
#include "dlopen.h"
}
#include "grbc/ext.h"
#include "grbc/helpers.h"
#include "grbc/spec.h"
#include <filesystem>
typedef const char *(*EXT_GetName)();
void EXT_dynamic_ext(const std::string &extension_name) {
const std::array<std::string, 4 > extension_paths = {"./grbc_ext",
"C:\\grbc\\ext", "./", "./build"};
std::filesystem::path good_extension_path;
for (size_t i = 0; i < extension_paths.size(); i++) {
std::filesystem::path extension_path =
std::filesystem::path(extension_paths[i]) /
std::filesystem::path(extension_name + ".grbcext");
if (std::filesystem::exists(extension_path)) {
good_extension_path = extension_path;
break;
} else {
log_msg(("no extension at: " + extension_path.generic_string()).c_str());
}
}
if (good_extension_path.empty())
grbc_exception("Failed to find GRBC dynamic extension!");
struct hotwire_dll_t dll = hw_dlopen(good_extension_path.c_str(), 0x00002);
EXT_HookInit hook_init = (EXT_HookInit)hw_dlsym(dll, "GRBC_Hook_Init");
EXT_GetName get_name = (EXT_GetName)hw_dlsym(dll, "GRBC_Get_Name");
if (hook_init == nullptr)
grbc_exception(
"Dynamic extension is missing public GRBC_Hook_Init symbol!");
if (get_name == nullptr)
grbc_exception("Dynamic extension is missing public GRBC_Get_Name symbol!");
Extension ext{};
ext.name = get_name();
ext.hook_init = hook_init;
log_msg(
("loaded dynamic extension from: " + good_extension_path.generic_string())
.c_str());
grbc_register_ext(ext);
}
void grbc_dynamic_init(sol::state &lua) {
lua.set("grbc_dynamic_ext", EXT_dynamic_ext);
log_msg("dynamic extension support loaded!");
}
Extension grbc_dynamic() {
Extension ext{};
ext.name = GRBC_EXT_dynamic_extensions_NAME;
ext.hook_init = grbc_dynamic_init;
return ext;
}