mcap/modules/onnxruntime/include/onnxruntime_experimental_cxx_api.h

187 lines
7.9 KiB
C++

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Experimental C++ API consumer header.
//
// This header provides typed inline accessors in the Ort::Experimental namespace for experimental ORT API functions,
// and any C++ wrapper types associated with the experimental API functions.
//
// It is the C++ companion to onnxruntime_experimental_c_api.h.
//
// IMPORTANT: Experimental functions are NOT part of the stable ABI. They may be added, changed, or removed between
// releases without notice. Anything in this file should be treated as experimental and unstable.
//
// Two accessor flavors are generated for each experimental function:
//
// 1. Get_<NAME>_SinceV<VER>_Fn(api)
// Returns the typed function pointer, or nullptr if the function is not available in this build.
// Use this to check availability at runtime.
//
// 2. Get_<NAME>_SinceV<VER>_FnOrThrow(api)
// Returns the typed function pointer, or throws Ort::Exception (ORT_NOT_IMPLEMENTED) if the function is not
// available in this build.
// Use this when the function is required.
//
// C++ usage (nullable):
// if (auto* fn = Ort::Experimental::Get_OrtApi_ExperimentalApiTest_SinceV28_Fn(api)) {
// Ort::Status status(fn(&result));
// }
//
// C++ usage (throwing):
// auto* fn = Ort::Experimental::Get_OrtApi_ExperimentalApiTest_SinceV28_FnOrThrow(api);
// Ort::Status status(fn(&result));
#pragma once
#include "onnxruntime_experimental_c_api.h"
#include "onnxruntime_cxx_api.h"
namespace Ort {
namespace Experimental {
//
// Nullable typed accessors
//
// For each .inc entry, this generates a typed accessor in Ort::Experimental:
//
// inline OrtExperimental_<NAME>_SinceV<VER>_Fn Get_<NAME>_SinceV<VER>_Fn(const OrtApi* api);
//
// Example: ORT_EXPERIMENTAL_API(28, OrtStatusPtr, OrtApi_ExperimentalApiTest, ...) produces:
// inline OrtExperimental_OrtApi_ExperimentalApiTest_SinceV28_Fn
// Get_OrtApi_ExperimentalApiTest_SinceV28_Fn(const OrtApi* api) {
// return reinterpret_cast<OrtExperimental_OrtApi_ExperimentalApiTest_SinceV28_Fn>(
// api->GetExperimentalFunction(kOrtExperimental_OrtApi_ExperimentalApiTest_SinceV28_FnName));
// }
#define ORT_EXPERIMENTAL_API(VER, RET, NAME, ...) \
inline OrtExperimental_##NAME##_SinceV##VER##_Fn Get_##NAME##_SinceV##VER##_Fn( \
const OrtApi* api) { \
return reinterpret_cast<OrtExperimental_##NAME##_SinceV##VER##_Fn>( \
api->GetExperimentalFunction(kOrtExperimental_##NAME##_SinceV##VER##_FnName)); \
}
#include "onnxruntime_experimental_c_api.inc"
#undef ORT_EXPERIMENTAL_API
//
// Throwing typed accessors
//
// For each .inc entry, this generates a throwing accessor in Ort::Experimental:
//
// inline OrtExperimental_<NAME>_SinceV<VER>_Fn Get_<NAME>_SinceV<VER>_FnOrThrow(const OrtApi* api);
//
// It returns the non-null typed function pointer, or throws Ort::Exception (ORT_NOT_IMPLEMENTED) if the function is
// not available in this build.
//
// Example: ORT_EXPERIMENTAL_API(28, OrtStatusPtr, OrtApi_ExperimentalApiTest, ...) produces:
// inline OrtExperimental_OrtApi_ExperimentalApiTest_SinceV28_Fn
// Get_OrtApi_ExperimentalApiTest_SinceV28_FnOrThrow(const OrtApi* api) {
// auto* fn = Get_OrtApi_ExperimentalApiTest_SinceV28_Fn(api);
// if (fn == nullptr) {
// ORT_CXX_API_THROW(
// "Experimental function OrtApi_ExperimentalApiTest_SinceV28 is not available in this build",
// ORT_NOT_IMPLEMENTED);
// }
// return fn;
// }
#define ORT_EXPERIMENTAL_API(VER, RET, NAME, ...) \
inline OrtExperimental_##NAME##_SinceV##VER##_Fn Get_##NAME##_SinceV##VER##_FnOrThrow( \
const OrtApi* api) { \
auto* fn = Get_##NAME##_SinceV##VER##_Fn(api); \
if (fn == nullptr) { \
ORT_CXX_API_THROW( \
"Experimental function " #NAME "_SinceV" #VER " is not available in this build", \
ORT_NOT_IMPLEMENTED); \
} \
return fn; \
}
#include "onnxruntime_experimental_c_api.inc"
#undef ORT_EXPERIMENTAL_API
//
// Auxiliary types and helpers
//
// C++ wrapper types or helpers go here in the `Ort::Experimental` namespace.
//
// Move-only RAII owner for an OrtEpContextConfig handle, which carries the EPContext read/write callbacks and opaque
// state extracted from an OrtSessionOptions instance. The handle is released via OrtEpApi_ReleaseEpContextConfig when
// the wrapper is destroyed.
//
// Typical EP usage: construct from the session options during CreateEp(), keep the wrapper for the EP's lifetime, and
// query the callbacks via GetReadFunc() / GetWriteFunc().
class EpContextConfig {
public:
explicit EpContextConfig(std::nullptr_t) noexcept {}
explicit EpContextConfig(const SessionOptions& session_options) : EpContextConfig{session_options.GetConst()} {}
// Extracts the EPContext config from `session_options`. Throws Ort::Exception (ORT_NOT_IMPLEMENTED) if the
// experimental functions are not available in this build, or propagates any error from the extraction.
explicit EpContextConfig(ConstSessionOptions session_options) {
const OrtApi* api = &GetApi();
// Ensure the release function is available before creating a handle, so the handle can always be freed.
Get_OrtEpApi_ReleaseEpContextConfig_SinceV28_FnOrThrow(api);
auto* get_config = Get_OrtEpApi_SessionOptions_GetEpContextConfig_SinceV28_FnOrThrow(api);
ThrowOnError(get_config(static_cast<const OrtSessionOptions*>(session_options), &config_));
}
EpContextConfig(EpContextConfig&& other) noexcept : config_{other.config_} { other.config_ = nullptr; }
EpContextConfig& operator=(EpContextConfig&& other) noexcept {
if (this != &other) {
reset();
config_ = other.config_;
other.config_ = nullptr;
}
return *this;
}
EpContextConfig(const EpContextConfig&) = delete;
EpContextConfig& operator=(const EpContextConfig&) = delete;
~EpContextConfig() { reset(); }
OrtEpContextConfig* get() const noexcept { return config_; }
explicit operator bool() const noexcept { return config_ != nullptr; }
// Relinquishes ownership of the handle without releasing it.
OrtEpContextConfig* release() noexcept {
OrtEpContextConfig* released = config_;
config_ = nullptr;
return released;
}
// Releases any owned handle and resets to empty.
void reset() noexcept {
if (config_ != nullptr) {
if (auto* release_fn = Get_OrtEpApi_ReleaseEpContextConfig_SinceV28_Fn(&GetApi())) {
release_fn(config_);
}
config_ = nullptr;
}
}
// Returns the configured read callback and opaque state (both nullptr if none was set). Throws on failure.
void GetReadFunc(OrtReadNamedBufferFunc& read_func, void*& state) const {
auto* get_read_func = Get_OrtEpApi_EpContextConfig_GetEpContextDataReadFunc_SinceV28_FnOrThrow(&GetApi());
ThrowOnError(get_read_func(config_, &read_func, &state));
}
// Returns the configured write callback and opaque state (both nullptr if none was set). Throws on failure.
void GetWriteFunc(OrtWriteNamedBufferFunc& write_func, void*& state) const {
auto* get_write_func = Get_OrtEpApi_EpContextConfig_GetEpContextDataWriteFunc_SinceV28_FnOrThrow(&GetApi());
ThrowOnError(get_write_func(config_, &write_func, &state));
}
private:
OrtEpContextConfig* config_ = nullptr;
};
} // namespace Experimental
} // namespace Ort