Skip to content

C ABI negotiation

The stable C interface is major 1, minor 0. Treat the major version as the compatibility boundary: request the major you were compiled for, inspect the reported major and minor, and refuse to use a table that does not meet your contract.

Link the core target from the installed package and include the forwarding ABI headers:

find_package(TreefallSDK 0.9.0 EXACT REQUIRED CONFIG)
add_executable(c-abi-consumer main.c)
target_link_libraries(c-abi-consumer PRIVATE Treefall::core)

A minimal negotiation checks both the compile-time contract and the runtime response:

#include <treefall/abi.h>
#include <stddef.h>
#include <stdint.h>
uint32_t got_major = 0;
uint32_t got_minor = 0;
const treefall_session_api_v1* api =
treefall_session_abi_v1(TREEFALL_ABI_MAJOR, &got_major, &got_minor);
if (api == NULL || got_major != TREEFALL_ABI_MAJOR || got_minor != TREEFALL_ABI_MINOR ||
TREEFALL_ABI_MAJOR != 1 || TREEFALL_ABI_MINOR != 0) {
/* Do not call function-table entries. */
return 1;
}

The table pointer is the capability result. A null pointer or a major mismatch is a negotiation failure. A minor mismatch must be evaluated against the consumer’s compatibility policy before calling optional capabilities; the pinned 1.0 contract reports minor 0.

The bundle’s C smoke artifact requests TREEFALL_ABI_MAJOR, checks the returned table and reported 1.0 values, and prints exactly the success line. It uses the same installed prefix as the C++ examples, so this check covers package discovery and the C target rather than a header-only compile.

example.c-abi-smoke · Product 0.9.0 · Unreleased preview
Source revision: 0238eac1721d820d16ba5390e0e4641391be1d59
/* SPDX-License-Identifier: MIT */
#include <treefall/abi.h>
#include <treefall/abi_version.h>

#include <stdint.h>
#include <stdio.h>

int main(void) {
  uint32_t got_major = 0;
  uint32_t got_minor = 0;
  const treefall_session_api_v1* api =
      treefall_session_abi_v1(TREEFALL_ABI_MAJOR, &got_major, &got_minor);
  if (api == NULL || !TREEFALL_ABI_EXPECT(got_major) || got_major != 1 || got_minor != 0 ||
      TREEFALL_ABI_MAJOR != 1 || TREEFALL_ABI_MINOR != 0) {
    fputs("Treefall C ABI negotiation failed\n", stderr);
    return 1;
  }
  puts("Treefall C ABI 1.0 available");
  return 0;
}
Treefall C ABI 1.0 available
Source and producer-reported verification
Source-relative path
examples/c-abi-smoke.c
SHA-256
89d7dd07165b888c72e3de61b91fa90f263601f53fd81878a5de4c02d2008ca6
Producer-reported verification
executed
Environment
os=darwin/arm64; cmake=cmake version 4.1.0; compiler=Apple clang version 21.0.0 (clang-2100.0.123.102)
Command
./examples-build/c-abi-smoke

The artifact metadata identifies the exact source and executable command. If negotiation fails, the program prints an error to stderr and exits nonzero; it does not call through an unverified table.

The forwarding declarations and version macros are defined in the pinned ABI header and ABI version header. The package-level C negotiation is exercised by the pinned C package source.