Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

C ABI

powerio-capi exports ABI 7 through powerio-capi/include/powerio.h. The header is generated from the Rust declarations and checked in. Regenerate it with:

cbindgen --config powerio-capi/cbindgen.toml --crate powerio-capi \
  --output powerio-capi/include/powerio.h

scripts/capi-header-parity.sh compares the exported symbols with the header in every CI feature job, and scripts/capi-header-regen.sh regenerates the header with cbindgen and diffs it once. Do not edit the header by hand.

ABI 7 is the only C API in PowerIO 0.11; symbols from ABI 4, 5, and 6 are not exported and have no aliases. Compare pio_abi_version() with PIO_ABI_VERSION before you use the library.

The exported symbol set is fixed. The gridfm cargo feature adds GridFM Parquet parsing and emission behind the same entry points, and the arrow, matrix, dist, and prob feature names are still accepted by the build but gate nothing. pio_schema_report returns a JSON document with the release (powerio_version), the ABI (abi), the PowerIO IR schema name and generation (powerio_ir with schema and version), the BMOPF schema version, the compiled features, and the diagnostic namespaces and error categories.

Parse and inspect a module

PioError *error = NULL;
PioSource *source = pio_source_open("case9.m", 7, &error);
PioModule *module = pio_parse(source, NULL, 0, &error);
PioValueHandle *value = pio_module_value(module);

if (!pio_value_is_type(value, "powerio.BalancedNetwork", 23)) {
    /* handle an unexpected PowerIO type */
}

PioBalancedNetwork *network = pio_value_balanced_network(value, &error);
size_t buses = pio_balanced_network_bus_count(network);

PioDiagnostics *diagnostics = pio_module_diagnostics(module);
for (size_t i = 0; i < pio_diagnostics_len(diagnostics); i++) {
    PioStringView code = pio_diagnostic_code(diagnostics, i);
    /* code.data has code.len bytes and is not NUL terminated */
}

pio_diagnostics_release(diagnostics);
pio_balanced_network_release(network);
pio_value_release(value);
pio_module_release(module);
pio_source_release(source);

Use pio_source_from_memory for text or binary bytes you already hold in memory; both source constructors feed the same pio_parse. pio_geo_layer_parse reads a geographic layer straight from text, with no source object, for callers that have the layer document in memory.

pio_module_value returns an owner rooted value handle, and the exact typed accessors return owner rooted views without serializing or copying the module value. Releasing a module does not invalidate a child you have retained. Every opaque handle has matching retain and release functions, and release(NULL) is a no-op.

Structural type names have replaced ordinal kind integers. Check the type with pio_value_type_name or pio_value_is_type, then call the exact typed accessor for the type you handle.

Diagnostics and errors

Fallible functions take one PioError ** output and signal failure with a null return or a documented failure value. Inspect pio_error_code, pio_error_message, and pio_error_diagnostics, and branch on the stable code rather than the message text. If you pass a null error output the error is discarded.

Every string and buffer comes with an explicit length. PioStringView, PioByteView, PioSizeView, and PioF64View borrow their data from an owning handle and need not end in NUL.

Emit and serialize

pio_emit writes a grid exchange format. With a memory destination the artifact bytes stay in the returned PioEmitResult; with a path destination the artifacts are written to disk and the result holds the same list of artifacts and the same diagnostics.

PioDestination *destination = pio_destination_memory("case", 4, &error);
PioEmitResult *result = pio_emit(module, "matpower", 8, destination, &error);

for (size_t i = 0; i < pio_emit_result_artifact_count(result); i++) {
    PioArtifact *artifact = pio_emit_result_artifact(result, i, &error);
    PioStringView name = pio_artifact_name(artifact);
    PioByteView bytes = pio_artifact_bytes(artifact);
    /* consume name and bytes before releasing artifact */
    pio_artifact_release(artifact);
}

pio_emit_result_release(result);
pio_destination_release(destination);

pio_module_serialize writes PowerIO IR and pio_module_deserialize reads it. The IR header is "schema": "pio-ir" with integer "version": 2, and pio_schema_report reports both; the producer record names the PowerIO release separately. pio_module_deserialize refuses an unsupported schema name or generation and tells you what it found. ABI 7 has no reader for earlier generations and no module JSON aliases.

Collections, updates, and calculations

Time series and scenario set handles give you the length and owner rooted access to each element. Positions are zero based in C, and scenario sets can also be looked up by scenario ID.

Typed update constructors produce PioOperatingPointUpdate, PioNetworkUpdate, and PioCalculationUpdate. pio_apply_updates validates the whole batch before it applies anything and returns a PioUpdateReport listing the exact component IDs and fields it changed, and whether energized connectivity changed.

Named matrix and vector functions expose the public DC calculations directly:

pio_calc_incidence_matrix
pio_calc_branch_susceptances
pio_calc_bus_susceptance_matrix
pio_calc_branch_flow_matrix
pio_calc_branch_phase_shift_injection
pio_calc_bus_phase_shift_injection
pio_calc_branch_flow_dc
pio_calc_bus_injection_dc

Sparse matrices come back as owned CSR arrays and vectors as owned double arrays. The C API has no public DC data bundle.