Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
89d414f
[Plugin EP] Add C APIs to add OpSchemas for custom ops, get opschema …
adrianlizarraga Mar 17, 2026
c57cc57
Add OpSchema APIs to get SinceVersion, NumInputs, and NumOutputs
adrianlizarraga Mar 17, 2026
df4058a
CXX apis
adrianlizarraga Mar 17, 2026
c79cad5
Add unit tests
adrianlizarraga Mar 17, 2026
a052871
null checks
adrianlizarraga Mar 17, 2026
183ea29
Update OpSchema_HasTypeConstraint to return a status
adrianlizarraga Mar 17, 2026
a05ade9
Update C++ API to return std::string
adrianlizarraga Mar 17, 2026
5b64fec
Remove unnecessary forward declaration
adrianlizarraga Mar 17, 2026
bfe6853
Review comments
adrianlizarraga Mar 17, 2026
b2b67f9
Merge branch 'main' into adrianl/PluginEp_Kernels_GetOpSchema
adrianlizarraga Mar 24, 2026
b0491bb
Merge branch 'main' into adrianl/PluginEp_Kernels_GetOpSchema
adrianlizarraga Mar 27, 2026
419735c
Add static_assert for ep_api
adrianlizarraga Mar 27, 2026
4f58b99
First attempt at getting more info about type constraints
adrianlizarraga Mar 27, 2026
29f1f7b
Remove HasTypeConstraint
adrianlizarraga Mar 28, 2026
0b71072
Refactor OrtOpSchema from reinterpret_cast to opaque owning struct
adrianlizarraga Mar 30, 2026
d5642a2
Refactor type constraints to per-entity OrtOpSchemaTypeConstraint API
adrianlizarraga Mar 30, 2026
09d5ecd
Rename OpSchemaTypeConstraint_GetName to GetTypeParamName
adrianlizarraga Mar 30, 2026
87dc453
Mention domains and handle 'ai.onnx' alias
adrianlizarraga Mar 30, 2026
50a6541
Update docs and move ReleaseOpSchema
adrianlizarraga Mar 30, 2026
742fd26
Add comment about there only being one type param per input or output
adrianlizarraga Mar 30, 2026
061b39c
Add doc comment about use of OpSchema_GetTypeConstraint
adrianlizarraga Mar 30, 2026
2cf04fc
Merge branch 'main' into adrianl/PluginEp_Kernels_GetOpSchema
adrianlizarraga Mar 30, 2026
8437870
Review comments
adrianlizarraga Mar 30, 2026
a195d9a
Make tests test what comments say
adrianlizarraga Mar 30, 2026
82d5322
Consolidate tests
adrianlizarraga Mar 30, 2026
a3a60fb
Address review comments
adrianlizarraga Mar 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/onnxruntime/core/session/onnxruntime_c_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ ORT_RUNTIME_CLASS(ExternalSemaphoreHandle); // EP-imported view of shared exte
ORT_RUNTIME_CLASS(DeviceEpIncompatibilityDetails);
ORT_RUNTIME_CLASS(EpAssignedSubgraph);
ORT_RUNTIME_CLASS(EpAssignedNode);
ORT_RUNTIME_CLASS(OpSchema);

#ifdef _MSC_VER
typedef _Return_type_success_(return == 0) OrtStatus* OrtStatusPtr;
Expand Down
46 changes: 46 additions & 0 deletions include/onnxruntime/core/session/onnxruntime_cxx_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -3515,6 +3515,52 @@ struct KernelRegistry : detail::Base<OrtKernelRegistry> {
void* kernel_create_func_state);
};

namespace detail {
/** \brief Non-owning wrapper around a `const OrtOpSchema*` from the ONNX schema registry.
*
* Provides access to operator schema metadata such as version, input/output names,
* and type constraints. The underlying pointer is owned by the global ONNX schema registry
* and must not be released by the caller.
*/
template <typename T>
struct ConstOpSchemaImpl : Base<T> {
using B = Base<T>;
using B::B;

///< Wraps OrtEpApi::OpSchema_GetSinceVersion
int GetSinceVersion() const;

///< Wraps OrtEpApi::OpSchema_GetNumInputs
size_t GetNumInputs() const;

///< Wraps OrtEpApi::OpSchema_GetInputName
std::string GetInputName(size_t index) const;

///< Wraps OrtEpApi::OpSchema_GetInputTypeStr
std::string GetInputTypeStr(size_t index) const;

///< Wraps OrtEpApi::OpSchema_GetNumOutputs
size_t GetNumOutputs() const;

///< Wraps OrtEpApi::OpSchema_GetOutputName
std::string GetOutputName(size_t index) const;

///< Wraps OrtEpApi::OpSchema_GetOutputTypeStr
std::string GetOutputTypeStr(size_t index) const;

///< Wraps OrtEpApi::OpSchema_HasTypeConstraint
bool HasTypeConstraint(const char* type_str) const;
Comment thread
adrianlizarraga marked this conversation as resolved.
Outdated
};
} // namespace detail

/// Non-owning wrapper around a `const OrtOpSchema*` from the ONNX schema registry.
using ConstOpSchema = detail::ConstOpSchemaImpl<detail::Unowned<const OrtOpSchema>>;

/// \brief Get an ONNX operator schema from the global registry.
///
/// Wraps OrtEpApi::GetOpSchema. Returns a ConstOpSchema that may wrap nullptr if the schema is not found.
ConstOpSchema GetOpSchema(const char* name, int max_inclusive_version, const char* domain);

namespace detail {
template <typename T>
struct SharedPrePackedWeightCacheImpl : Ort::detail::Base<T> {
Expand Down
64 changes: 64 additions & 0 deletions include/onnxruntime/core/session/onnxruntime_cxx_inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -3941,4 +3941,68 @@ inline Ort::KeyValuePairs GetEnvConfigEntries() {

return Ort::KeyValuePairs{entries};
}

namespace detail {
template <typename T>
inline int ConstOpSchemaImpl<T>::GetSinceVersion() const {
int version = 0;
ThrowOnError(GetEpApi().OpSchema_GetSinceVersion(this->p_, &version));
return version;
}

template <typename T>
inline size_t ConstOpSchemaImpl<T>::GetNumInputs() const {
size_t num = 0;
ThrowOnError(GetEpApi().OpSchema_GetNumInputs(this->p_, &num));
return num;
}

template <typename T>
inline std::string ConstOpSchemaImpl<T>::GetInputName(size_t index) const {
const char* name = nullptr;
ThrowOnError(GetEpApi().OpSchema_GetInputName(this->p_, index, &name));
return std::string(name);
}

template <typename T>
inline std::string ConstOpSchemaImpl<T>::GetInputTypeStr(size_t index) const {
const char* type_str = nullptr;
ThrowOnError(GetEpApi().OpSchema_GetInputTypeStr(this->p_, index, &type_str));
return std::string(type_str);
}

template <typename T>
inline size_t ConstOpSchemaImpl<T>::GetNumOutputs() const {
size_t num = 0;
ThrowOnError(GetEpApi().OpSchema_GetNumOutputs(this->p_, &num));
return num;
}

template <typename T>
inline std::string ConstOpSchemaImpl<T>::GetOutputName(size_t index) const {
const char* name = nullptr;
ThrowOnError(GetEpApi().OpSchema_GetOutputName(this->p_, index, &name));
return std::string(name);
}

template <typename T>
inline std::string ConstOpSchemaImpl<T>::GetOutputTypeStr(size_t index) const {
const char* type_str = nullptr;
ThrowOnError(GetEpApi().OpSchema_GetOutputTypeStr(this->p_, index, &type_str));
return std::string(type_str);
}

template <typename T>
inline bool ConstOpSchemaImpl<T>::HasTypeConstraint(const char* type_str) const {
bool result = false;
ThrowOnError(GetEpApi().OpSchema_HasTypeConstraint(this->p_, type_str, &result));
return result;
}
} // namespace detail

inline ConstOpSchema GetOpSchema(const char* name, int max_inclusive_version, const char* domain) {
const OrtOpSchema* schema = nullptr;
ThrowOnError(GetEpApi().GetOpSchema(name, max_inclusive_version, domain, &schema));
return ConstOpSchema{schema};
}
} // namespace Ort
125 changes: 125 additions & 0 deletions include/onnxruntime/core/session/onnxruntime_ep_c_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -1444,6 +1444,131 @@ struct OrtEpApi {
* \since Version 1.24
*/
ORT_API2_STATUS(GetEnvConfigEntries, _Outptr_ OrtKeyValuePairs** config_entries);

/** \brief Get an ONNX operator schema from the global registry.
Comment thread
edgchen1 marked this conversation as resolved.
Outdated
*
* Looks up a schema by name, maximum inclusive version, and domain.
* The returned pointer is non-owning and must not be freed by the caller.
* It is valid as long as the schema remains registered.
*
* \param[in] name A null-terminated string for the operator name.
* \param[in] max_inclusive_version The maximum inclusive opset version.
* \param[in] domain A null-terminated string for the operator domain.
* \param[out] out_schema Output parameter set to the schema pointer, or nullptr if not found.
*
* \snippet{doc} snippets.dox OrtStatus Return Value
*
* \since Version 1.25.
*/
ORT_API2_STATUS(GetOpSchema, _In_ const char* name, _In_ int max_inclusive_version,
_In_ const char* domain, _Outptr_result_maybenull_ const OrtOpSchema** out_schema);

/** \brief Get the first ONNX opset version that introduced this operator schema.
*
* If an operator has had no changes that break backwards compatibility, the `since_version` is
* just the first opset version that introduced the operator. However, if the operator has had breaking changes,
* then `since_version` corresponds to the opset version that introduced the breaking change.
*
* For example, suppose operator "Foo" was added in version 3 and had a breaking change in version 6.
* Then, there will be an operator schema entry for "Foo" with a since_version of 3 and another updated
* operator schema entry for "Foo" with a since_version of 6.
*
* \param[in] schema The OrtOpSchema instance.
* \param[out] out The ONNX opset version.
*
* \snippet{doc} snippets.dox OrtStatus Return Value
*
* \since Version 1.25.
*/
ORT_API2_STATUS(OpSchema_GetSinceVersion, _In_ const OrtOpSchema* schema, _Out_ int* out);

/** \brief Get the number of inputs defined by the operator schema.
*
* \param[in] schema The OrtOpSchema instance.
* \param[out] out The number of inputs.
*
* \snippet{doc} snippets.dox OrtStatus Return Value
*
* \since Version 1.25.
*/
ORT_API2_STATUS(OpSchema_GetNumInputs, _In_ const OrtOpSchema* schema, _Out_ size_t* out);

/** \brief Get the name of the i-th input formal parameter from an operator schema.
*
* \param[in] schema The OrtOpSchema instance.
* \param[in] index Zero-based index of the input parameter.
* \param[out] out The name of the input parameter. Valid as long as the schema is registered.
*
* \snippet{doc} snippets.dox OrtStatus Return Value
*
* \since Version 1.25.
*/
ORT_API2_STATUS(OpSchema_GetInputName, _In_ const OrtOpSchema* schema, _In_ size_t index,
_Outptr_ const char** out);

/** \brief Get the type constraint string of the i-th input formal parameter from an operator schema.
*
* \param[in] schema The OrtOpSchema instance.
* \param[in] index Zero-based index of the input parameter.
* \param[out] out The type constraint string (e.g., "T"). Valid as long as the schema is registered.
*
* \snippet{doc} snippets.dox OrtStatus Return Value
*
* \since Version 1.25.
*/
ORT_API2_STATUS(OpSchema_GetInputTypeStr, _In_ const OrtOpSchema* schema, _In_ size_t index,
_Outptr_ const char** out);

/** \brief Get the number of outputs defined by the operator schema.
*
* \param[in] schema The OrtOpSchema instance.
* \param[out] out The number of outputs.
*
* \snippet{doc} snippets.dox OrtStatus Return Value
*
* \since Version 1.25.
*/
ORT_API2_STATUS(OpSchema_GetNumOutputs, _In_ const OrtOpSchema* schema, _Out_ size_t* out);

/** \brief Get the name of the i-th output formal parameter from an operator schema.
*
* \param[in] schema The OrtOpSchema instance.
* \param[in] index Zero-based index of the output parameter.
* \param[out] out The name of the output parameter. Valid as long as the schema is registered.
*
* \snippet{doc} snippets.dox OrtStatus Return Value
*
* \since Version 1.25.
*/
ORT_API2_STATUS(OpSchema_GetOutputName, _In_ const OrtOpSchema* schema, _In_ size_t index,
_Outptr_ const char** out);

/** \brief Get the type constraint string of the i-th output formal parameter from an operator schema.
*
* \param[in] schema The OrtOpSchema instance.
* \param[in] index Zero-based index of the output parameter.
* \param[out] out The type constraint string (e.g., "T"). Valid as long as the schema is registered.
*
* \snippet{doc} snippets.dox OrtStatus Return Value
*
* \since Version 1.25.
*/
ORT_API2_STATUS(OpSchema_GetOutputTypeStr, _In_ const OrtOpSchema* schema, _In_ size_t index,
_Outptr_ const char** out);

/** \brief Check if a type constraint name exists in the schema's type constraint map.
*
* This is used to determine whether a formal parameter name or its type string should be used
* as the type constraint identifier when building kernel definitions.
*
* \param[in] schema The OrtOpSchema instance.
* \param[in] type_str A null-terminated string for the type constraint name to look up.
* \param[out] out Set to true if the type constraint exists in the schema's type constraint map, false otherwise.
*
* \since Version 1.25.
*/
ORT_API2_STATUS(OpSchema_HasTypeConstraint, _In_ const OrtOpSchema* schema, _In_ const char* type_str,
_Out_ bool* out);
};

/**
Expand Down
9 changes: 9 additions & 0 deletions onnxruntime/core/framework/error_code_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "core/common/status.h"
#include "core/common/exceptions.h"
#include "core/common/make_string.h"
#include "core/session/onnxruntime_c_api.h"

namespace onnxruntime {
Expand Down Expand Up @@ -39,6 +40,14 @@ Status ToStatusAndRelease(OrtStatus* ort_status,
#define API_IMPL_END }
#endif

// Check condition. If met, return an OrtStatus* error with the given OrtErrorCode.
#define ORT_API_RETURN_IF(condition, ort_error_code, ...) \
do { \
if (condition) { \
return OrtApis::CreateStatus(ort_error_code, ::onnxruntime::MakeString(__VA_ARGS__).c_str()); \
} \
} while (false)
Comment thread
adrianlizarraga marked this conversation as resolved.

// Return the OrtStatus if it indicates an error
#define ORT_API_RETURN_IF_ERROR(expr) \
do { \
Expand Down
Loading
Loading