Skip to content

Lua sections need revision: This page contains removed v5 APIs or old runtime examples. Do not use its Lua examples for current development. Start with Platform v1.

C++ Native Binding & Lua Export Guide

This guide describes the standard workflow for C++ engine contributors to bind internal classes, structs, and methods via Sol2 and safely export them to the CCB Lua 0.1 runtime.


1. Architectural Rules & Safety Model

In the CCB engine, native bindings must adhere to 3 strict rules: 1. Generation-Safe Handles: - Raw C++ pointers (Character*, item*, monster*) must never be held indefinitely in Lua. - Dynamic entities must be wrapped in a game_handle that verifies generation counters (runtime_generation, world_generation) upon dereference to prevent dangling pointer crashes. 2. Zero-Copy In-Memory Invocation: - C++ and Lua interact directly through the Sol2 / Lua-C stack in memory. No intermediate JSON serialization is used. 3. 100% Contract Coverage & LuaLS Parity: - Every exported symbol must be paired with complete LuaLS type definitions in data/lua/types/ccb_api_v5.d.lua and pass check_coverage.py.


2. Step 1: Implementing Native Bindings in C++

// src/catalua_ui_weather.cpp
#include "weather.h"
#include "catalua_platform_content.h"
#include <sol/sol.hpp>

namespace catalua {

sol::table get_storm_forecast(
    lua_State *lua,
    const game_handle &target_pos,
    const int forecast_hours )
{
    sol::state_view state( lua );

    // Capability check
    require_capability( state, "game.read", "game.weather.get_storm_forecast" );

    // Native C++ engine invocation
    const weather_forecast forecast = weather_manager::forecast_at( target_pos.pos(), forecast_hours );

    sol::table result = state.create_table();
    result["has_storm"] = forecast.has_storm;
    result["intensity"] = forecast.intensity;
    result["wind_speed"] = forecast.wind_speed;
    result["predicted_turn"] = forecast.predicted_turn;

    return result;
}

void register_weather_bindings( sol::state_view &lua ) {
    sol::table weather_ns = lua["game"]["weather"].get_or_create<sol::table>();
    weather_ns["get_storm_forecast"] = &get_storm_forecast;
}

} // namespace catalua

3. Step 2: Providing LuaLS Type Annotations (.d.lua)

In data/lua/types/ccb_api_v5.d.lua:

---@class WeatherForecast
---@field has_storm boolean Whether a storm is forecasted
---@field intensity number Storm intensity index (0.0 to 1.0)
---@field wind_speed number Forecasted wind speed in km/h
---@field predicted_turn integer Forecasted arrival turn

---Query forecasted severe weather conditions for target coordinates
---@param target_pos Tripoint Target tripoint
---@param forecast_hours integer Forecast window in hours
---@return WeatherForecast Forecast structure
function game.weather.get_storm_forecast(target_pos, forecast_hours) end

4. Step 3: Contract Generation & 100% Coverage Checks

Run local contract validators:

# 1. Regenerate C++ export inventory
python3 tools/lua_api/generate_ccb_inventory.py

# 2. Regenerate public contract & coverage
python3 tools/lua_api/generate_public_contract.py

# 3. Verify coverage & declarations
python3 tools/lua_api/check_coverage.py --require-complete
python3 tools/lua_api/check_luals_declarations.py
python3 -m unittest discover -s tools/lua_api -p 'test_*.py'