improve plugin facing api with c++ helpers

This commit is contained in:
Green Sky 2024-01-18 18:23:24 +01:00
parent 87b3d15a2b
commit 9c54a50810
No known key found for this signature in database
3 changed files with 90 additions and 23 deletions

View File

@ -21,29 +21,7 @@ void g_provideInstance__internal(const char* id, const char* version, const char
} // extern C
namespace internal {
template<typename T>
class g_type_version {
typedef char yes[1];
typedef char no [2];
template<typename C> static yes& test_version(decltype(&C::version));
template<typename C> static no& test_version(...);
static bool const has_version = sizeof(test_version<T>(nullptr)) == sizeof(yes);
static constexpr const char* get_version(void) {
if constexpr (has_version) {
return T::version;
} else {
return "UNK"; // default version
}
}
public:
static constexpr const char* version = get_version();
};
} // internal
#include "./version_helper.inl"
// templated helper, use or make sure vtable is right
template<typename T>

View File

@ -51,6 +51,7 @@ SOLANA_PLUGIN_EXPORT void solana_plugin_stop(void);
// ---------- called periodically ----------
// rendering needs to be called in a different interval AND needs to be garantied from mainthread
// the functions return the minimum time in seconds until the update should be called next
// the interval is not garantied. in fact, clients can call them with a much longer interval
// for compute tasks
SOLANA_PLUGIN_EXPORT float solana_plugin_tick(float delta);
@ -59,6 +60,69 @@ SOLANA_PLUGIN_EXPORT float solana_plugin_render(float delta);
#ifdef __cplusplus
}
// in c++ we can provide generic helpers
#include "./version_helper.inl"
#include <string>
// templated helper, use or make sure vtable is right
// versioned means explicitly provided
// ---------- provide ----------
template<typename T>
static void plug_provideInstance(const SolanaAPI* solana_api, const char* id, const char* version, const char* plugin_name, T* instance) {
solana_api->provideInstance(id, version, plugin_name, instance);
}
template<typename T>
static void plug_provideInstance(const SolanaAPI* solana_api, const char* id, const char* plugin_name, T* instance) {
plug_provideInstance<T>(solana_api, id, internal::g_type_version<T>::version, plugin_name, instance);
}
#define PLUG_PROVIDE_INSTANCE_VERSIONED(x, ver, p, i) plug_provideInstance(solana_api, #x, ver, p, i)
#define PLUG_PROVIDE_INSTANCE(x, p, i) plug_provideInstance(solana_api, #x, p, i)
// ---------- resolve optional ----------
template<typename T>
static T* plug_resolveInstanceOptional(const SolanaAPI* solana_api, const char* id, const char* version) {
return static_cast<T*>(solana_api->resolveInstance(id, version));
}
template<typename T>
static T* plug_resolveInstanceOptional(const SolanaAPI* solana_api, const char* id) {
return plug_resolveInstanceOptional<T>(solana_api, id, internal::g_type_version<T>::version);
}
// ---------- resolve require ----------
// throws if id+version is not found
struct ResolveException {
std::string what;
};
template<typename T>
static T* plug_resolveInstance(const SolanaAPI* solana_api, const char* id, const char* version) {
T* res = plug_resolveInstanceOptional<T>(solana_api, id, version);
if (res == nullptr) {
throw ResolveException{"missing " + std::string{id} + " " + version};
}
return res;
}
template<typename T>
static T* plug_resolveInstance(const SolanaAPI* solana_api, const char* id) {
return plug_resolveInstance<T>(solana_api, id, internal::g_type_version<T>::version);
}
#define PLUG_RESOLVE_INSTANCE_VERSIONED(x, ver) plug_resolveInstance<x>(solana_api, #x, ver)
#define PLUG_RESOLVE_INSTANCE(x) plug_resolveInstance<x>(solana_api, #x)
// optional variants dont error
#define PLUG_RESOLVE_INSTANCE_VERSIONED_OPT(x, ver) plug_resolveInstanceOptional<x>(solana_api, #x, ver)
#define PLUG_RESOLVE_INSTANCE_OPT(x) plug_resolveInstanceOptional<x>(solana_api, #x)
#endif
#endif // SOLANA_PLUGIN__H

View File

@ -0,0 +1,25 @@
#pragma once
namespace internal {
template<typename T>
class g_type_version {
typedef char yes[1];
typedef char no [2];
template<typename C> static yes& test_version(decltype(&C::version));
template<typename C> static no& test_version(...);
static bool const has_version = sizeof(test_version<T>(nullptr)) == sizeof(yes);
static constexpr const char* get_version(void) {
if constexpr (has_version) {
return T::version;
} else {
return "UNK"; // default version
}
}
public:
static constexpr const char* version = get_version();
};
} // internal