Experimental C API support#28746
Conversation
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
… .inc - Use ExpSinceV<version>_<TargetStruct>_<Name> naming convention - Version prefix guarantees uniqueness, eliminating need for retired .inc - Merge C and C++ headers into single file with #ifdef __cplusplus guard - C++ accessors reuse C typedefs directly (no duplicate typedef) - Add SinceVersion as first X-macro argument for mechanical name construction Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Implement a single stable OrtApi entry point (GetExperimentalFunction) that retrieves experimental function pointers by name. This allows new APIs to be iterated on before promotion to the stable ABI surface, with minimal stable API cost (one slot). - Add OrtExperimentalFnPtr typedef and GetExperimentalFunction slot to OrtApi - Add X-macro .inc file as single source of truth for experimental functions - Add consumer header with C typedefs, name constants, and C++ typed accessors - Add runtime registration table with linear scan lookup in experimental_c_api.cc - Add test-only OrtApi_ExperimentalApiTest function to exercise the mechanism - Add shared_lib tests for lookup (null/unknown/known name, typed call, consistency) - Wire new public headers into CMake packaging (onnxruntime.cmake) - Wire test file into onnxruntime_unittests.cmake Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Align file names, _FnName suffix, and namespace syntax in code examples with the actual implementation. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
The macro name now matches the naming convention used by the generated symbols (which all use Fn/FnName suffixes to describe what they are, while the macro describes an API entry). Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…_c_api.cc Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Introduces a name-based experimental C API mechanism for ONNX Runtime. A single new stable OrtApi::GetExperimentalFunction(name) slot is added; experimental functions are declared centrally in an X-macro .inc file that is expanded by a consumer header (to produce C typedefs/name constants and C++ typed accessors) and by the runtime registration table. A test-only experimental function plus design doc and unit tests are included.
Changes:
- New stable API entry
GetExperimentalFunctionplusOrtExperimentalFnPtrtypedef; runtime implementation with a name-keyed lookup table populated fromonnxruntime_experimental_c_api.inc. - Generated consumer header
onnxruntime_experimental_c_api.hproviding C typedefs/name constants andOrt::Experimental::Get_*C++ accessors via X-macro expansion. - Design doc, build/install plumbing for the new headers, and a shared-lib gtest suite exercising null/unknown/empty/known lookups and end-to-end call.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| docs/design/Experimental_C_API.md | New design document explaining motivation, alternatives, and lifecycle rules. |
| docs/design/readme.md | Brief readme describing the design docs directory. |
| include/onnxruntime/core/session/onnxruntime_c_api.h | Adds OrtExperimentalFnPtr typedef and GetExperimentalFunction slot to OrtApi. |
| include/onnxruntime/core/session/onnxruntime_experimental_c_api.h | New consumer header expanding the X-macro into typedefs/name constants and C++ accessors. |
| include/onnxruntime/core/session/onnxruntime_experimental_c_api.inc | Central X-macro declaration list with one test-only experimental entry. |
| onnxruntime/core/session/ort_apis.h | Declares OrtApis::GetExperimentalFunction. |
| onnxruntime/core/session/onnxruntime_c_api.cc | Wires GetExperimentalFunction into the ort_api_1_to_27 table. |
| onnxruntime/core/session/experimental_c_api.cc | Implements the registration table, lookup function, and the test experimental function. |
| onnxruntime/test/shared_lib/test_experimental_api.cc | New gtest suite for null/unknown/empty/known lookup and end-to-end call. |
| cmake/onnxruntime.cmake | Installs the new experimental headers (.h and .inc) as public API. |
| cmake/onnxruntime_unittests.cmake | Adds test_experimental_api.cc to the shared-lib test sources. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Will we enable other language bindings on demand? There's a few things to consider for C# to make this more usable if we want to enable that now. e.g. the native handle for ORT types exposed in the C# bindings is internal, so there's no way to pass one of those objects in to an experimental function. if I had a C# OrtValue instance I couldn't use that as an arg to the experimental function as you'd need to pass the IntPtr for the handle in. The helper to check an OrtStatus was successful is also internal. |
- Shorten generated names: ExpSinceV<ver> -> V<ver> throughout - Reorder ORT_EXPERIMENTAL_API macro params: (VER, NAME, RET, ...) -> (VER, RET, NAME, ...) to match ORT_API_T convention - Add comment on OrtExperimentalFnPtr explaining why it is a function pointer rather than void* (casting between function pointers and void* is UB) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Link to AGENTS.md for codebase conventions and document that ORT_API_VERSION bumps, new ort_api tables, and static_assert updates happen only during release preparation, not when individual APIs are added. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Change the version suffix in experimental API names from _V<ver> to _SinceV<ver> to avoid ambiguity (_V27 could be misread as version 2 of function 7). The _SinceV suffix clearly conveys 'introduced in API version N'. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
ORT_API_VERSION was bumped to 28 in main. Update the experimental API test function and all comments/examples from SinceV27 to SinceV28. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
- Add warning that SinceVersion must be a numeric literal, not a macro - Add lifecycle note: test function is kept permanently for regression coverage - Add comment noting C++ accessor nullptr path is covered by C-side test - Use ORT_API_T macro for GetExperimentalFunction declaration Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
I think other language bindings can be enabled later, on demand. is there anything with the existing setup that would make things more difficult for supporting C# later? |
Move the model package C surface off the stable OrtApi onto the experimental name-based lookup added in #28746. Each function is registered individually in onnxruntime_experimental_c_api.inc with the OrtModelPackageApi_ prefix and the _SinceV28 version suffix, matching the lifecycle rules in docs/design/Experimental_C_API.md. - Drop the OrtModelPackageApi struct, OrtApi::GetModelPackageApi, the OrtModelPackageAPI namespace, model_package_api.h, and the C++ wrappers/release glue in onnxruntime_cxx_api.h. - Move the OrtModelPackageOptions/Context/ComponentContext opaque handle decls into onnxruntime_experimental_c_api.h. - Add forward decls in experimental_c_api.cc so the registration table can take addresses of bodies defined in model_package_api.cc. - Rename impls into namespace OrtExperimentalApis with the _SinceV28 suffix; bodies unchanged. - Drop the Python bindings; per the design doc we start the experimental API in C/C++ only and prove it out before exposing it to Python. - Update the autoep gtest to use a local ModelPackageFns struct populated through Ort::Experimental::Get_*_Fn lookups. - Rewrite onnxruntime/core/session/model_package/README.md for the experimental API surface. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Convert the six EPContext read/write callback C APIs from stable APIs to experimental APIs using the mechanism introduced in PR #28746: - OrtApi_SessionOptions_SetEpContextDataReadFunc - OrtCompileApi_ModelCompilationOptions_SetEpContextDataWriteFunc - OrtEpApi_SessionOptions_GetEpContextConfig - OrtEpApi_ReleaseEpContextConfig - OrtEpApi_EpContextConfig_GetEpContextDataReadFunc - OrtEpApi_EpContextConfig_GetEpContextDataWriteFunc Remove the C++ convenience wrappers and move the auxiliary types (OrtEpContextConfig, OrtReadNamedBufferFunc, OrtWriteNamedBufferFunc) into onnxruntime_experimental_c_api.h. Update the example plugin EP, sample helper utilities, and tests to use the generated experimental accessors.
Convert the six EPContext read/write callback C APIs from stable APIs to experimental APIs using the mechanism introduced in PR #28746: - OrtApi_SessionOptions_SetEpContextDataReadFunc - OrtCompileApi_ModelCompilationOptions_SetEpContextDataWriteFunc - OrtEpApi_SessionOptions_GetEpContextConfig - OrtEpApi_ReleaseEpContextConfig - OrtEpApi_EpContextConfig_GetEpContextDataReadFunc - OrtEpApi_EpContextConfig_GetEpContextDataWriteFunc Remove the C++ convenience wrappers and move the auxiliary types (OrtEpContextConfig, OrtReadNamedBufferFunc, OrtWriteNamedBufferFunc) into onnxruntime_experimental_c_api.h. Update the example plugin EP, sample helper utilities, and tests to use the generated experimental accessors.
### Description Move the existing model package C API off the stable `OrtApi` onto the experimental name-based lookup mechanism added in #28746. Each model package function is registered individually in `include/onnxruntime/core/session/onnxruntime_experimental_c_api.inc` with the `OrtModelPackageApi_` prefix and the `_SinceV28` version suffix, following the lifecycle rules in `docs/design/Experimental_C_API.md`. Headline changes: - `OrtApi::GetModelPackageApi`, the `OrtModelPackageApi` struct, `OrtApis::GetModelPackageApi`, the `OrtModelPackageAPI` namespace, `onnxruntime/core/session/model_package_api.h`, and the C++ wrappers (`Ort::GetModelPackageApi`, `ORT_DEFINE_RELEASE_FROM_API_STRUCT(ModelPackage*)`, `ModelPackageOptions/Context/ComponentContext`) are removed. - Opaque handle types (`OrtModelPackageOptions`, `OrtModelPackageContext`, `OrtModelPackageComponentContext`) move into `onnxruntime_experimental_c_api.h`. - All 15 model package functions are registered in `onnxruntime_experimental_c_api.inc`. Impls move into `namespace OrtExperimentalApis` with `_SinceV28`-suffixed names in `model_package_api.cc`; bodies are unchanged. - `experimental_c_api.cc` gains a forward-decl block (driven by the same `.inc` X-macro) so the auto-generated registration table can take the address of every entry, even those defined in `model_package_api.cc`. - The Python bindings (`PyModelPackageContext` / `PyModelPackageOptions` / `PyModelPackageComponentContext` and their `onnxruntime.__init__` exports) are removed. Per the design doc we start the experimental API in C/C++ only. - `onnxruntime/test/autoep/test_model_package.cc` switches to a local `ModelPackageFns` struct populated through the `Ort::Experimental::Get_OrtModelPackageApi_*_Fn(api)` typed accessors. Consumer usage going forward, in C++: ```cpp #include "onnxruntime_c_api.h" #include "onnxruntime_experimental_c_api.h" const OrtApi* ort = OrtGetApiBase()->GetApi(ORT_API_VERSION); if (auto* fn = Ort::Experimental::Get_OrtModelPackageApi_CreateModelPackageContext_SinceV28_Fn(ort)) { OrtModelPackageContext* ctx = nullptr; Ort::ThrowOnError(fn(ORT_TSTR("/path/to/pkg"), &ctx)); // ... } ``` ### Motivation and Context The model package API was added to the stable `OrtApi` in 1.27 but has not shipped in a release yet. Now that #28746 has landed the experimental C API framework, the right home for an iterating preview surface like model package is behind `OrtApi::GetExperimentalFunction`, not on the stable struct. Moving it to experimental: - frees us to change signatures (each name is uniquely versioned) without breaking the stable ABI; - gives consumers a clear "is this specific thing available?" contract instead of a struct that *looks* stable but isn't; - lets the surface be promoted to stable cleanly later (move entries to `OrtApi`, drop the `_SinceV<N>` suffix, remove the experimental entries). --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Convert the six EPContext read/write callback C APIs from stable APIs to experimental APIs using the mechanism introduced in PR #28746: - OrtApi_SessionOptions_SetEpContextDataReadFunc - OrtCompileApi_ModelCompilationOptions_SetEpContextDataWriteFunc - OrtEpApi_SessionOptions_GetEpContextConfig - OrtEpApi_ReleaseEpContextConfig - OrtEpApi_EpContextConfig_GetEpContextDataReadFunc - OrtEpApi_EpContextConfig_GetEpContextDataWriteFunc Remove the C++ convenience wrappers and move the auxiliary types (OrtEpContextConfig, OrtReadNamedBufferFunc, OrtWriteNamedBufferFunc) into onnxruntime_experimental_c_api.h. Update the example plugin EP, sample helper utilities, and tests to use the generated experimental accessors.
Description
This pull request introduces a mechanism for exposing experimental C API functions in ONNX Runtime. The new system enables the addition, iteration, and eventual promotion of experimental APIs without impacting the stable ABI, using a name-based function pointer lookup and a generated header for type safety and ergonomics. The changes include documentation, build integration, header generation, implementation, and test coverage for the new experimental API flow.
Experimental C API Framework
Experimental_C_API.md) detailing the motivation, design decisions, and usage patterns for the experimental C API mechanism.onnxruntime_experimental_c_api.inc) using X-macros to define experimental API functions and their lifecycle rules. The X-macro signature usesORT_EXPERIMENTAL_API(VER, RET, NAME, ...)ordering (return type before name) to match the convention used byORT_API_Tin the stable API.onnxruntime_experimental_c_api.h) that provides C typedefs, name constants, and C++ typed accessors for experimental functions. Experimental function names follow the pattern<TargetStruct>_<Name>_SinceV<APIVersion>to unambiguously convey availability and avoid collision.OrtApiinonnxruntime_c_api.h) to include a single function pointer,GetExperimentalFunction, for name-based experimental function lookup. TheOrtExperimentalFnPtrgeneric function pointer type (rather thanvoid*) is used as the return type to avoid undefined behavior when casting between function pointers.Implementation and Test Coverage
experimental_c_api.cc), including a test-only function (OrtApi_ExperimentalApiTest) to exercise the mechanism end-to-end.onnxruntime_c_api.cc).Motivation and Context
Enable support for experimental C APIs.