Skip to content

Commit

Permalink
refactor: improve plugin interface, ref #177
Browse files Browse the repository at this point in the history
  • Loading branch information
iboB committed Nov 15, 2024
1 parent 36dc596 commit 08640b4
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 55 deletions.
31 changes: 19 additions & 12 deletions cmake/ac_local_plugin_util.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -109,17 +109,19 @@ void add_@nameSym@_to_ac_local_registry(ac::local::ModelLoaderRegistry& registry
#include "@aclpName@-interface.hpp"
#include <ac/local/PluginPlibUtil.inl>

PlibHelper g_helper{ac::@nameSym@::getPluginInterface()};

extern "C"
void add_@nameSym@_to_ac_local_global_registry() {
addLoadersToGlobalRegistry(ac::@nameSym@::getLoaders);
g_helper.addLoadersToGlobalRegistry();
}

void add_@nameSym@_to_ac_local_registry(ac::local::ModelLoaderRegistry& registry) {
addLoadersToRegistry(ac::@nameSym@::getLoaders, registry);
g_helper.addLoadersToRegistry(registry);
}

const std::vector<ac::local::ModelLoaderPtr>& get_@nameSym@_model_loaders() {
return getGLoaders(ac::@nameSym@::getLoaders);
return g_helper.getLoaders();
}
]=]
)
Expand Down Expand Up @@ -156,18 +158,23 @@ const std::vector<ac::local::ModelLoaderPtr>& get_@nameSym@_model_loaders() {
namespace ac::local {

extern "C" SYMBOL_EXPORT
PluginInterface acLocalPluginLoad() {
constexpr astl::version ownVersion(
int aclp_ac_local_version() {
return ac::local::Project_Version.to_int();
}
static_assert(std::is_same_v<decltype(&aclp_ac_local_version), PluginInterface::GetAcLocalVersionFunc>);

extern "C" SYMBOL_EXPORT
int aclp_own_version() {
return astl::version(
ACLP_@nameSym@_VERSION_MAJOR, ACLP_@nameSym@_VERSION_MINOR, ACLP_@nameSym@_VERSION_PATCH
);
).to_int();
}

return {
.acLocalVersion = ac::local::Project_Version,
.pluginVersion = ownVersion,
.getLoaders = ac::@nameSym@::getLoaders,
};
extern "C" SYMBOL_EXPORT
PluginInterface aclp_get_interface() {
return ac::@nameSym@::getPluginInterface();
}
static_assert(std::is_same_v<decltype(&acLocalPluginLoad), PluginInterface::PluginLoadFunc>);
static_assert(std::is_same_v<decltype(&aclp_get_interface), PluginInterface::GetFunc>);

} // namespace ac::local
]=]
Expand Down
17 changes: 17 additions & 0 deletions dummy-plugin/code/ac/dummy/LocalDummy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include "Instance.hpp"
#include "Model.hpp"

#include "aclp-dummy-version.h"

#include <ac/local/Instance.hpp>
#include <ac/local/Model.hpp>
#include <ac/local/ModelLoader.hpp>
Expand Down Expand Up @@ -153,9 +155,24 @@ class DummyModelLoader final : public ModelLoader {
} // namespace ac::local

namespace ac::dummy {

std::vector<ac::local::ModelLoaderPtr> getLoaders() {
std::vector<ac::local::ModelLoaderPtr> ret;
ret.push_back(std::make_unique<local::DummyModelLoader>());
return ret;
}

local::PluginInterface getPluginInterface() {
return {
.label = "ac-local dummy",
.desc = "Dummy plugin for ac-local",
.vendor = "Alpaca Core",
.version = astl::version(
ACLP_dummy_VERSION_MAJOR, ACLP_dummy_VERSION_MINOR, ACLP_dummy_VERSION_PATCH
),
.init = nullptr,
.getLoaders = getLoaders,
};
}

} // namespace ac::dummy
4 changes: 2 additions & 2 deletions dummy-plugin/code/ac/dummy/LocalDummy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
// SPDX-License-Identifier: MIT
//
#pragma once
#include <ac/local/ModelLoaderPtr.hpp>
#include <ac/local/PluginInterface.hpp>
#include <vector>

namespace ac::dummy {
std::vector<ac::local::ModelLoaderPtr> getLoaders();
local::PluginInterface getPluginInterface();
}
9 changes: 7 additions & 2 deletions local/code/ac/local/PluginInfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// SPDX-License-Identifier: MIT
//
#pragma once
#include "Version.hpp"
#include "ModelLoaderPtr.hpp"
#include <astl/version.hpp>
#include <vector>

namespace ac::local {
Expand All @@ -12,9 +12,14 @@ struct PluginInfo {
std::string fullPath;
std::stringView name; // points within fullPath, filename without "aclp-" prefix and extension

// data obtained from loaded plugin

void* nativeHandle; // HGLOBAL on Windows, void* on *nix

Version version;
std::string label;
std::string desc;
std::string vendor;
version version;

std::vector<ModelLoaderPtr> loaders; // provided loaders
};
Expand Down
14 changes: 9 additions & 5 deletions local/code/ac/local/PluginInterface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,21 @@
#include <vector>

namespace ac::local {
class ModelLoaderRegistry;

struct PluginInterface {
using PluginLoadFunc = PluginInterface(*)();
using GetAcLocalVersionFunc = int(*)();
using GetFunc = PluginInterface(*)();

astl::version acLocalVersion; // version of ac-local this plugin was built with
const char* label; // optional own name (not necessarily unique)
const char* desc; // optional short description
const char* vendor; // optional vendor name
astl::version version; // version of the plugin

astl::version pluginVersion; // version of the plugin itself
using InitFunc = void(*)();
InitFunc init; // optional init function

using GetLoadersFunc = std::vector<ModelLoaderPtr>(*)();
GetLoadersFunc getLoaders;
GetLoadersFunc getLoaders; // function to get loaders
};

}
20 changes: 13 additions & 7 deletions local/code/ac/local/PluginLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,34 @@ hplugin load_plugin(const char* filename) {

namespace ac::local {

static const char* PluginLoadFunc_name = "acLocalPluginLoad";
static const char* GetAcLocalVersionFunc = "aclp_ac_local_version";
static const char* PluginLoadFunc_name = "aclp_get_interface";

PluginInterface PluginLoader::loadPlugin(const std::string& filename) {
hplugin h = load_plugin(filename.c_str());
if (!h) {
throw_ex{} << "Failed to load plugin " << filename;
}

auto getVer = (PluginInterface::GetAcLocalVersionFunc)get_proc(h, GetAcLocalVersionFunc);
if (!getVer) {
unload_plugin(h);
throw_ex{} << "Failed to find " << GetAcLocalVersionFunc << " in " << filename;
}

if (getVer() != Project_Version.to_int()) {
unload_plugin(h);
throw_ex{} << "Plugin " << filename << " was built with incompatible ac-local version";
}

auto f = (PluginInterface::PluginLoadFunc)get_proc(h, PluginLoadFunc_name);
auto f = (PluginInterface::GetFunc)get_proc(h, PluginLoadFunc_name);
if (!f) {
unload_plugin(h);
throw_ex{} << "Failed to find " << PluginLoadFunc_name << " in " << filename;
}

auto iface = f();

if (iface.acLocalVersion != Project_Version) {
unload_plugin(h);
throw_ex{} << "Plugin " << filename << " was built with incompatible ac-local version";
}

return iface;
}

Expand Down
63 changes: 36 additions & 27 deletions local/code/ac/local/PluginPlibUtil.inl
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,47 @@
#include <ac/local/PluginInterface.hpp>

namespace {
using GLF = ac::local::PluginInterface::GetLoadersFunc;
std::vector<ac::local::ModelLoaderPtr> g_loaders;
bool g_addedToGlobalRegistry = false;

void fillLoaders(GLF getLoaders) {
if (!g_loaders.empty()) {
// already filled
return;
using namespace ac::local;

struct PlibHelper {
PluginInterface m_pluginInterface;
PlibHelper(const PluginInterface& pluginInterface) : m_pluginInterface(pluginInterface) {}

std::vector<ModelLoaderPtr> m_loaders;
bool m_addedToGlobalRegistry = false;

void fillLoaders() {
if (!m_loaders.empty()) {
// already filled
return;
}
if (m_pluginInterface.init) {
m_pluginInterface.init();
}
m_loaders = m_pluginInterface.getLoaders();
}
g_loaders = getLoaders();
}

void addLoadersToRegistry(GLF getLoaders, ac::local::ModelLoaderRegistry& registry) {
fillLoaders(getLoaders);
for (auto& loader : g_loaders) {
registry.addLoader(*loader);
void addLoadersToRegistry(ac::local::ModelLoaderRegistry& registry) {
fillLoaders();
for (auto& loader : m_loaders) {
registry.addLoader(*loader);
}
}
}

void addLoadersToGlobalRegistry(GLF getLoaders) {
if (g_addedToGlobalRegistry) {
// already added
return;
void addLoadersToGlobalRegistry() {
if (m_addedToGlobalRegistry) {
// already added
return;
}
addLoadersToRegistry(ac::local::Lib::modelLoaderRegistry());
m_addedToGlobalRegistry = true;
}
addLoadersToRegistry(getLoaders, ac::local::Lib::modelLoaderRegistry());
g_addedToGlobalRegistry = true;
}

const auto& getGLoaders(GLF getLoaders) {
fillLoaders(getLoaders);
return g_loaders;
}

const auto& getLoaders() {
fillLoaders();
return m_loaders;
}
};

} // namespace

Expand Down

0 comments on commit 08640b4

Please sign in to comment.