Experimental Native C API
The native C library is not consumable at the exact alpha.1 tag. Its headers, implementation, ABI metadata, examples, package rules and verification machinery are checked in, but the final C API implementation target fails a compile-time renderer-identity assertion: the C map has 49 entries while CNA has 50 public renderer identities. NanoVG is the missing C identity.
Tag status and scope
CNA_BUILD_C_API is an opt-in CMake option for a native C linkage layer under CNA/C/. At source level, that layer uses fixed-width values, versioned structures, opaque generation-checked handles, explicit result codes, count/copy string and buffer protocols, and callbacks instead of exposing C++ classes or STL types.
The tag contains 59 public C headers and 2,861 declared cna_* routes. Its checked-in route-name report accounts for all 2,861 declarations. Those facts describe the source surface; they do not prove that a library artifact was produced or that every route executes.
The alpha.1 compile blocker
The public C++ enum and generated registry contain 50 renderer identities. In modules/c-api/src/CnaCApiCoreExt.cpp, the RendererIdentities table contains 49 and the public C renderer enum ends at PIXIJS; there is no NanoVG entry. The same source deliberately checks the table against the canonical C++ count:
static_assert(RendererIdentities.size() == CanonicalRendererCount(),
"A renderer was added to CNA::GraphicsRendererType without a C identity.");
For alpha.1 this assertion is false. An isolated GCC 14.2/Ninja build using Headless platform/renderer, Null audio and the default enabled networking reproduced the compiler diagnostic comparison reduces to (49 == 50). Consequently a configuration may create C API targets and the checked-in reports may look release-ready, but compiling the final native C API implementation cannot complete. Do not publish, install or bind to a self-described alpha.1 C API library without a source correction and a new compatibility decision.
Intended build and package design
The tag's CMake design says that enabling CNA_BUILD_C_API=ON turns on C as a project language, uses C17 for CNA's implementation targets, and checks the public headers against a C99 consumer surface. It also defines a CNACApi install component, a shared CNA::CApi target and an optional static CNA::CApiStatic target. These are intended interfaces, not successfully consumable alpha.1 artifacts.
After the renderer map is fixed in a later release, the declared standalone consumer shape is:
cmake_minimum_required(VERSION 3.20)
project(my_cna_game LANGUAGES C)
find_package(CNA 0.7 CONFIG REQUIRED)
add_executable(my_cna_game main.c)
target_link_libraries(my_cna_game PRIVATE CNA::CApi)
The declared install rules place public headers and CNA-built SDL libraries beside the shared API library; FFmpeg remains a system dependency when selected. None of those rules bypasses the alpha.1 compile assertion.
The C ABI version is not the product version
| Identity | Alpha.1 value | Purpose |
|---|---|---|
| CNA product | 0.1.0-alpha.1 | Which CNA source release is documented. |
| Native C ABI | 0.7.0 | Compatibility of the exported C binary contract. |
#include <CNA/C/cna.h>
if (cna_get_abi_version() != CNA_ABI_VERSION) {
return 1;
}
CNA_ABI_VERSION_MAJOR, _MINOR and _PATCH are fixed-width macros, encoded by CNA_ABI_VERSION_ENCODE. Do not compare them with CNA_VERSION_*; the latter describe the C++ product build.
Programming model
| Concern | C contract |
|---|---|
| Objects | CNA_Handle values are opaque, typed and generation-checked. Release them in documented child-before-parent order. |
| Failures | Fallible calls return CNA_Result; retrieve the recorded diagnostic rather than relying on C++ exceptions. |
| Strings/buffers | Query the required count, then copy into caller-owned storage. Buffer-too-small is a named result. |
| Callbacks | Game lifecycle and events cross the boundary through function pointers and user-data values; thread and reentrancy rules are explicit. |
| Capabilities | Query the selected/active renderer and its capabilities; the C layer does not invent a second renderer-selection system. |
The tag's modules/c-api/examples/c/hello_cna.c documents the intended use: it checks the ABI, creates a callback-driven game, borrows the graphics device only during a legal callback, queries capabilities, exercises diagnostics and shuts down in lifetime order. It is a design reference in alpha.1, not evidence of a runnable installed package.
Measured coverage
The checked-in alpha.1 inventory starts from 421 public C++ headers and 6,712 symbol rows: 6,317 are implemented in C, 15 are approved partial mappings, 380 are not applicable to a C consumer, and internal/detail rows are excluded separately. These numbers describe the checked-in generated inventory; they do not convert partial or not-applicable rows into full C++ parity.
The repository declares separate ABI-baseline, compatibility-matrix, coverage, limitations and release-gate workflows and contains installed-consumer test machinery. Their presence does not override the final source contradiction. In particular, the checked-in generated release report says ready while a workflow label says not ready and the final implementation cannot satisfy its own renderer-count assertion.
Important limitations
- The final C library target is compile-blocked in alpha.1 by the 49-versus-50 renderer map.
CNA_BUILD_C_API=ONwithCNA_ENABLE_NET=OFFis also broken: configuration succeeds, but the C API unconditionally includes GamerServices headers that are then absent. Keep networking enabled merely to reach the renderer assertion.- The declared ABI 0.7.0 is experimental and pre-1.0 even after those defects are corrected.
- Platform substrate interfaces that a C++ implementation would subclass are intentionally not exposed for C callers to implement.
- Some C++ overloads, containers and polymorphic values map to narrower typed routes or snapshots; 15 checked-in rows are explicitly partial.
- Thread, callback-borrow and shutdown rules are part of the intended contract. A numerically valid handle would not permit use on the wrong thread or after its owner shuts down.
Continue with Tutorial 129: Inspect the alpha.1 C API boundary, versioning, or the verification guide.