Practical Example

Example Plugin Walkthrough

Line-by-line practical reference from example_plugin.cpp.

  • plugins/example_plugin.cpp

Full source: github.com/TamKungZ/VLiva

Section 1

Plugin Name

Provide a lightweight static name function that host can display.

  • Returned string should remain valid throughout process lifetime.
  • Name can be used in logs, UI list, and diagnostics.

cpp

const char* pluginName()
{
    return "Example UDP Bridge Plugin";
}

Section 2

Load / Unload Hooks

Store host pointer, configure host UDP bridge, and emit diagnostics during load/unload.

  • onLoad caches host API and initializes per-plugin runtime state.
  • Optional udp_configure() can be called to set target host/port.
  • onUnload emits final log and clears shared host pointer safely.

cpp

void onLoad(const VlivaHostApi* host)
{
    g_host = host;
    g_lastSendTime = 0.0;

    int udpConfigured = 0;
    if (g_host && g_host->udp_configure)
    {
        udpConfigured = g_host->udp_configure("127.0.0.1", 11573, 1);
    }

    pluginLog(
        udpConfigured
            ? "Example UDP Bridge Plugin loaded (configured host UDP sender)"
            : "Example UDP Bridge Plugin loaded");
}

void onUnload()
{
    pluginLog("Example UDP Bridge Plugin unloaded");
    g_host = nullptr;
}

Section 3

Frame Callback

Example plugin samples tracking data and sends a compact UDP payload at throttled rate.

  • Callback gates on get_tracking_frame()/udp_send availability.
  • Frame sending is throttled (~60 FPS) with time-based interval guard.
  • Only valid tracking frames are serialized and sent.

cpp

void onFrame(double timeSeconds, float /*deltaSeconds*/)
{
    if (!g_host || !g_host->get_tracking_frame || !g_host->udp_send) {
        return;
    }

    if ((timeSeconds - g_lastSendTime) < kSendIntervalSeconds) {
        return; // throttle to ~60 FPS
    }

    VlivaTrackingFrame frame{};
    frame.struct_size = sizeof(VlivaTrackingFrame);
    if (!g_host->get_tracking_frame(&frame) || !frame.has_valid_parameters) {
        return;
    }

    char payload[512] = {0};
    std::snprintf(payload, sizeof(payload), "VLIVA1 %d %.5f %.5f %.5f", frame.has_face, frame.angle_x, frame.angle_y, frame.angle_z);

    if (g_host->udp_send(payload)) {
        g_lastSendTime = timeSeconds;
    }
}

Section 4

Exported create_plugin

Export C ABI symbol returning a static VlivaPluginApi table.

  • extern "C" prevents C++ name mangling.
  • Static table keeps function pointers stable.
  • Host can call this once and retain the pointer.

cpp

extern "C" const VlivaPluginApi* create_plugin(void)
{
    static VlivaPluginApi api = {
        VLIVA_PLUGIN_API_VERSION,
        &pluginName,
        &onLoad,
        &onUnload,
        &onFrame
    };
    return &api;
}