Scripting Guide

C++/WASM Scripting

Write high-performance scripts using C++ with optional WebAssembly compilation for computationally intensive tasks.

Overview

C++ scripting provides maximum performance for computationally intensive tasks. Scripts can be compiled to WebAssembly for near-native execution speed within FaustBot's sandboxed environment.

Native Performance

Near-native execution speed for heavy computation.

WebAssembly

Compile to WASM for sandboxed, portable execution.

Low-Level Control

Direct memory management when needed.

C Libraries

Access to C/C++ libraries and headers.

Advanced Users

C++ scripting is recommended for experienced developers. For most use cases, Python or Lua provide sufficient performance with easier development.

Setup

C++ scripts require a compiler. For WASM output, you'll need Emscripten.

1

Install Compiler

For native C++, install GCC or Clang. For WASM, install Emscripten.

# Install Emscripten
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
2

Get FaustBot Headers

Copy the FaustBot headers to your project from the installation directory.

# Headers are in the FaustBot install directory
cp -r /path/to/faustbot/include/faustbot ./
3

Compile Your Script

Compile to WASM and place in FaustBot's scripts directory.

# Compile to WASM
emcc script.cpp -o script.wasm \
  -I./faustbot \
  -s EXPORTED_FUNCTIONS='["_Execute"]' \
  -O3

Script Structure

C++ scripts require an Execute() function that returns a boolean.

Basic C++ script structure
#include <faustbot/CPH.h>

bool Execute() {
    // Your code here
    CPH::SendMessage("Hello from C++!");
    return true;
}

Header Reference

The faustbot/CPH.h header provides access to all API functions.

Available CPH functions
// faustbot/CPH.h - Available functions

namespace CPH {
    // Logging
    void LogVerbose(const std::string& message);
    void LogDebug(const std::string& message);
    void LogInfo(const std::string& message);
    void LogWarn(const std::string& message);
    void LogError(const std::string& message);

    // Arguments
    std::string GetArg(const std::string& key);
    template<typename T> T GetArg(const std::string& key, T defaultValue);
    void SetArgument(const std::string& key, const std::string& value);

    // Variables
    template<typename T> T GetGlobalVar(const std::string& name, T defaultValue = T());
    template<typename T> void SetGlobalVar(const std::string& name, T value, bool persist = false);
    template<typename T> T GetUserVar(const std::string& user, const std::string& name, T defaultValue = T());
    template<typename T> void SetUserVar(const std::string& user, const std::string& name, T value, bool persist = false);

    // Chat
    void SendMessage(const std::string& message, bool asBot = false);
    void TwitchAnnounce(const std::string& message, const std::string& color = "");

    // Actions
    bool RunAction(const std::string& name, bool immediate = false);

    // OBS
    void ObsSetScene(const std::string& scene, const std::string& connection = "");
    void ObsShowSource(const std::string& scene, const std::string& source);
    void ObsHideSource(const std::string& scene, const std::string& source);
}

CPH API Access

Access FaustBot functionality through the CPH namespace.

Variables and Arguments

Working with variables
#include <faustbot/CPH.h>
#include <string>

bool Execute() {
    // Get event data
    std::string user = CPH::GetArg("user");
    std::string message = CPH::GetArg("message");

    // Get variables with defaults
    int points = CPH::GetUserVar<int>(user, "points", 0);
    std::string rank = CPH::GetUserVar<std::string>(user, "rank", "Newcomer");

    // Global variables
    int totalSubs = CPH::GetGlobalVar<int>("totalSubs", 0);

    // Set variables
    CPH::SetUserVar(user, "points", points + 100);
    CPH::SetGlobalVar("lastUser", user, true);

    return true;
}

Full API Example

Common API operations
#include <faustbot/CPH.h>
#include <string>
#include <sstream>

bool Execute() {
    // Logging
    CPH::LogInfo("Script started");
    CPH::LogDebug("Debug information");

    // Chat messages
    CPH::SendMessage("Hello, chat!");
    CPH::TwitchAnnounce("Big announcement!", "purple");

    // Actions
    CPH::RunAction("MyAction", true);

    // OBS control
    CPH::ObsSetScene("Gaming");
    CPH::ObsShowSource("Gaming", "Webcam");

    // Set output arguments
    CPH::SetArgument("result", "success");
    CPH::SetArgument("count", 42);

    return true;
}

Memory Management

Use modern C++ memory management practices to avoid leaks and crashes.

Safe memory management
#include <faustbot/CPH.h>
#include <memory>
#include <vector>
#include <string>

bool Execute() {
    // Use smart pointers for automatic cleanup
    auto data = std::make_unique<std::vector<std::string>>();

    // Process data
    data->push_back("item1");
    data->push_back("item2");

    // Use RAII for resource management
    {
        std::vector<int> temp_buffer(1000);
        // Process buffer
        // Automatically freed when scope exits
    }

    // Avoid raw new/delete
    // BAD: int* ptr = new int[100];
    // GOOD: std::vector<int> vec(100);

    CPH::SendMessage("Processed " + std::to_string(data->size()) + " items");
    return true;
}

Memory Best Practices

  • Use std::unique_ptr and std::shared_ptr
  • Prefer stack allocation when possible
  • Use RAII for resource management
  • Avoid raw new/delete
  • Use containers like std::vector

Performance Tips

Maximize performance with these C++ optimization techniques.

Performance optimizations
#include <faustbot/CPH.h>
#include <string>
#include <algorithm>
#include <numeric>
#include <vector>

// Use constexpr for compile-time constants
constexpr int MAX_USERS = 1000;
constexpr double POINT_MULTIPLIER = 1.5;

bool Execute() {
    std::vector<int> scores = {100, 200, 300, 400, 500};

    // Use algorithms instead of loops
    int total = std::accumulate(scores.begin(), scores.end(), 0);

    // Use references to avoid copies
    const std::string& user = CPH::GetArg("user");

    // Use move semantics
    std::string result = BuildResult();
    CPH::SetArgument("output", std::move(result));

    // Parallel processing for heavy computation
    // std::for_each(std::execution::par, ...)

    return true;
}

std::string BuildResult() {
    return "Processed successfully";
}

Do

  • Use const references
  • Use move semantics
  • Prefer algorithms over loops
  • Use constexpr for constants
  • Pre-allocate container capacity

Avoid

  • Passing large objects by value
  • Unnecessary string copies
  • Dynamic allocation in loops
  • Virtual functions in hot paths
  • Excessive exception usage

WebAssembly

Compile to WebAssembly for sandboxed execution with near-native performance.

WASM script structure
// Compile with Emscripten for WASM
// emcc script.cpp -o script.wasm -s EXPORTED_FUNCTIONS='["_Execute"]'

#include <faustbot/CPH.h>

extern "C" {
    // Export function for WASM
    bool Execute() {
        CPH::LogInfo("Running in WebAssembly!");

        // Heavy computation runs at near-native speed
        double result = HeavyCalculation();

        CPH::SetArgument("result", result);
        CPH::SendMessage("Calculation complete!");

        return true;
    }
}

double HeavyCalculation() {
    double sum = 0;
    for (int i = 0; i < 1000000; i++) {
        sum += i * 0.001;
    }
    return sum;
}

Compilation Options

FlagPurpose
-O3Maximum optimization
-OsOptimize for size
-s WASM=1Output WASM (default)
-s EXPORTED_FUNCTIONSFunctions to export
-s ALLOW_MEMORY_GROWTH=1Allow dynamic memory growth
-s STACK_SIZE=1048576Set stack size (1MB)

WASM Limitations

  • No direct file system access
  • Network requests go through CPH API
  • Memory is sandboxed
  • Some C++ features may have limited support