Skip to content

Commit

Permalink
Refactor plugin system
Browse files Browse the repository at this point in the history
- load all plugins at once and determine which one it is based on type
  • Loading branch information
dvsku committed Jan 26, 2024
1 parent 1bfb8ca commit fe3bbe0
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 97 deletions.
13 changes: 8 additions & 5 deletions include/devue_core/systems/dv_sys_plugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,19 @@ namespace devue::core {
dv_sys_plugin& operator=(dv_sys_plugin&&) = delete;

void prepare();
void release_plugin(dv_plugin& plugin);
void release();

void reload_plugins();

private:
dv_systems_bundle* m_systems;

private:
void create_texture_plugins();
void create_model_plugins();
void prepare_plugins();
void release_plugins();

void release_plugin(dv_plugin& plugin);

dv_texture_plugin load_texture_plugin(const std::filesystem::path& path);
dv_model_plugin load_model_plugin(const std::filesystem::path& path);
void load_plugin(const std::filesystem::path& path, devue::uuid uuid);
};
}
168 changes: 76 additions & 92 deletions src/devue_core/src/systems/dv_sys_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,37 +27,29 @@ dv_sys_plugin::dv_sys_plugin(dv_systems_bundle* systems)
: m_systems(systems) {}

dv_sys_plugin::~dv_sys_plugin() {
for (auto& [uuid, plugin] : model_plugins)
release_plugin(plugin);

for (auto& [uuid, plugin] : texture_plugins)
release_plugin(plugin);
release();
}

void dv_sys_plugin::prepare() {
create_model_plugins();
create_texture_plugins();

prepare_plugins();
m_systems->model.update_supported_file_types();
}

void dv_sys_plugin::release_plugin(dv_plugin& plugin) {
if (plugin.m_importer)
plugin.m_importer->cleanup();

if (plugin.m_handle)
release_handle(plugin.m_handle);

plugin.m_handle = nullptr;
plugin.m_importer = nullptr;
void dv_sys_plugin::release() {
release_plugins();
m_systems->model.update_supported_file_types();
}

DV_LOG("Released plugin `{}`", plugin.filename);
void dv_sys_plugin::reload_plugins() {
release_plugins();
prepare_plugins();
m_systems->model.update_supported_file_types();
}

///////////////////////////////////////////////////////////////////////////////
// PRIVATE

void dv_sys_plugin::create_texture_plugins() {
void dv_sys_plugin::prepare_plugins() {
for (const auto& entry : std::filesystem::directory_iterator("./plugins/")) {
// Make sure it's a file
if (!std::filesystem::is_regular_file(entry))
Expand All @@ -70,130 +62,122 @@ void dv_sys_plugin::create_texture_plugins() {
continue;

// Make sure it's a texture plugin
if (!filepath.filename().string().starts_with("dv_plg_tex"))
if (!filepath.filename().string().starts_with("dv_plg_"))
continue;

devue::uuid uuid = dv_util_uuid::create(filepath.string());

if (texture_plugins.contains(uuid))
if (model_plugins.contains(uuid) || texture_plugins.contains(uuid))
continue;

try {
texture_plugins[uuid] = std::move(load_texture_plugin(filepath));
load_plugin(filepath, uuid);
}
catch (const std::exception& e) {
DV_LOG("Failed to load `{}` plugin. | {}", filepath.filename().string(), e.what());
continue;
}
catch (...) {
DV_LOG("Failed to load `{}` texture plugin.", filepath.filename().string());
DV_LOG("Failed to load `{}` plugin.", filepath.filename().string());
continue;
}

DV_LOG("Loaded texture plugin `{}` from `{}`.", texture_plugins[uuid].name, texture_plugins[uuid].filename);
}
}

void dv_sys_plugin::create_model_plugins() {
for (const auto& entry : std::filesystem::directory_iterator("./plugins/")) {
// Make sure it's a file
if (!std::filesystem::is_regular_file(entry))
continue;

std::filesystem::path filepath = entry.path();

// Make sure it's a dll
if (filepath.extension() != ".dll")
continue;
void dv_sys_plugin::release_plugins() {
for (auto& [uuid, plugin] : model_plugins)
release_plugin(plugin);

// Make sure it's a texture plugin
if (!filepath.filename().string().starts_with("dv_plg_mod"))
continue;
for (auto& [uuid, plugin] : texture_plugins)
release_plugin(plugin);
}

devue::uuid uuid = dv_util_uuid::create(filepath.string());
void dv_sys_plugin::release_plugin(dv_plugin& plugin) {
if (plugin.m_importer)
plugin.m_importer->cleanup();

if (model_plugins.contains(uuid))
continue;
if (plugin.m_handle)
release_handle(plugin.m_handle);

try {
model_plugins[uuid] = std::move(load_model_plugin(filepath));
}
catch (...) {
DV_LOG("Failed to load `{}` model plugin.", filepath.filename().string());
continue;
}
plugin.m_handle = nullptr;
plugin.m_importer = nullptr;

DV_LOG("Loaded model plugin `{}` from `{}`.", model_plugins[uuid].name, model_plugins[uuid].filename);
}
DV_LOG("Released plugin `{}`", plugin.filename);
}

dv_texture_plugin dv_sys_plugin::load_texture_plugin(const std::filesystem::path& path) {
void dv_sys_plugin::load_plugin(const std::filesystem::path& path, devue::uuid uuid) {
auto phandle = create_handle(path.string().c_str());

dv_texture_plugin plugin;
plugin.m_handle = phandle.handle;
plugin.m_importer = phandle.importer;
plugin.filename = path.filename().string();
if (phandle.type == plugins::dv_plugin_importer::plugin_type::undefined)
throw dv_exception("Failed to determine plugin type.");

plugin.prepare();
return plugin;
}
if (phandle.type == plugins::dv_plugin_importer::plugin_type::model) {
dv_model_plugin plugin;
plugin.m_handle = phandle.handle;
plugin.m_importer = phandle.importer;
plugin.filename = path.filename().string();

dv_model_plugin dv_sys_plugin::load_model_plugin(const std::filesystem::path& path) {
auto phandle = create_handle(path.string().c_str());
plugin.prepare();

dv_model_plugin plugin;
plugin.m_handle = phandle.handle;
plugin.m_importer = phandle.importer;
plugin.filename = path.filename().string();
model_plugins[uuid] = std::move(plugin);

DV_LOG("Loaded texture plugin `{}` from `{}`.", model_plugins[uuid].name, model_plugins[uuid].filename);
}
else if (phandle.type == plugins::dv_plugin_importer::plugin_type::texture) {
dv_texture_plugin plugin;
plugin.m_handle = phandle.handle;
plugin.m_importer = phandle.importer;
plugin.filename = path.filename().string();

plugin.prepare();
return plugin;
plugin.prepare();

texture_plugins[uuid] = std::move(plugin);

DV_LOG("Loaded texture plugin `{}` from `{}`.", texture_plugins[uuid].name, texture_plugins[uuid].filename);
}
}

///////////////////////////////////////////////////////////////////////////////
// INTERNAL

plugin_handle create_handle(const char* path) {
typedef devue::plugins::dv_plugin_importer* fn_create();
typedef uint8_t fn_plugin_type();

HMODULE handle = LoadLibrary(path);
if (!handle)
throw dv_exception("");

auto create_fn_addr = GetProcAddress(handle, "create");
if (!create_fn_addr)
throw dv_exception("");
auto create_fn_addr = GetProcAddress(handle, "create");
fn_create* create_fn = (fn_create*)create_fn_addr;

auto plugin_type_fn_addr = GetProcAddress(handle, "plugin_type");
if (!plugin_type_fn_addr)
if (!create_fn_addr || !create_fn)
throw dv_exception("");

typedef devue::plugins::dv_plugin_importer* create_fn();
create_fn* create = (create_fn*)create_fn_addr;
if (!create)
throw dv_exception("");
auto plugin_type_fn_addr = GetProcAddress(handle, "plugin_type");
fn_plugin_type* plugin_type_fn = (fn_plugin_type*)plugin_type_fn_addr;

devue::plugins::dv_plugin_importer* importer = create();
if (!importer)
if (!plugin_type_fn_addr || !plugin_type_fn)
throw dv_exception("");

typedef uint8_t plugin_type_fn();
plugin_type_fn* plugin_type = (plugin_type_fn*)plugin_type_fn_addr;
if (!plugin_type)
devue::plugins::dv_plugin_importer* importer = create_fn();
if (!importer)
throw dv_exception("");

devue::plugins::dv_plugin_importer::plugin_type type =
(devue::plugins::dv_plugin_importer::plugin_type)plugin_type();
auto plugin_type = (devue::plugins::dv_plugin_importer::plugin_type)plugin_type_fn();

return { handle, importer, type };
return { handle, importer, plugin_type };
}

void release_handle(HMODULE handle) {
auto release_fn_addr = GetProcAddress(handle, "release");
if (!release_fn_addr)
throw dv_exception("");
typedef void fn_release();

typedef void release_fn();
release_fn* release = (release_fn*)release_fn_addr;
if (!release)
throw dv_exception("");
auto release_fn_addr = GetProcAddress(handle, "release");
fn_release* release_fn = (fn_release*)release_fn_addr;

release();
if (!release_fn_addr || !release_fn)
throw dv_exception("");

release_fn();
FreeLibrary(handle);
}

0 comments on commit fe3bbe0

Please sign in to comment.