Core API
Lifecycle and Call Order
Execution flow managed by PluginManager from plugin discovery to per-frame callbacks and unload.
include/vliva/plugins/plugin_api.hinclude/vliva/plugins/plugin_manager.hppplugins/example_plugin.cpp
Full source: github.com/TamKungZ/VLiva
Section 1
Lifecycle Flow
PluginManager drives plugin lifecycle in a strict order. Each callback has a clear responsibility.
- Load *.so plugins from a directory and resolve create_plugin symbol.
- Read returned API table and verify api_version before activation.
- Call on_load(host) once to provide host services.
- Update tracking snapshot and call on_frame(time_seconds, delta_seconds) each frame.
- Call on_unload() and unload every plugin during shutdown.
text
Host start
-> PluginManager::loadFromDirectory("plugins")
-> dlopen each shared library (.so)
-> lookup create_plugin symbol
-> validate VlivaPluginApi and call on_load(host)
-> update tracking snapshot and call on_frame(time, delta)
-> call on_unload() + dlclose() during shutdown
Section 2
PluginManager Host Bridge
PluginManager owns loaded plugin handles and bridges host services through static callbacks.
- setTrackingFrame()/clearTrackingFrame() control what get_tracking_frame() returns.
- setUdpSender() connects udp_configure()/udp_send() to host UDP implementation.
- Mutex-protected state keeps shared plugin services safe across calls.
cpp
class PluginManager {
public:
int loadFromDirectory(const std::string& directoryPath);
void onFrame(double timeSeconds, float deltaSeconds);
void setUdpSender(UdpSender* sender);
void setTrackingFrame(const VlivaTrackingFrame& frame);
void clearTrackingFrame();
void unloadAll();
private:
static void hostLog(const char* message);
static int hostGetTrackingFrame(VlivaTrackingFrame* outFrame);
static int hostUdpConfigure(const char* host, int port, int enabled);
static int hostUdpSend(const char* payload);
};
Section 3
Implementation Guidelines
Keep plugin runtime stable and fail-safe across all callbacks.
- Never assume host callback pointers are always available.
- Avoid heavy work inside on_frame without throttling.
- Keep initialization and shutdown idempotent where possible.
- Preserve ABI safety: no exceptions across C ABI boundary.