diff --git a/include/onnxruntime/core/session/onnxruntime_c_api.h b/include/onnxruntime/core/session/onnxruntime_c_api.h index 23309b7d5d..838d202c28 100644 --- a/include/onnxruntime/core/session/onnxruntime_c_api.h +++ b/include/onnxruntime/core/session/onnxruntime_c_api.h @@ -507,7 +507,8 @@ struct OrtApi { _Outptr_ OrtTypeInfo** type_info); /** - * \param value is set to a null terminated string allocated using 'allocator'. The caller is responsible for freeing it. + * \param value is set to a null terminated UTF-8 encoded string allocated using 'allocator'. + * The caller is responsible for freeing it. */ ORT_API2_STATUS(SessionGetInputName, _In_ const OrtSession* sess, size_t index, _Inout_ OrtAllocator* allocator, _Outptr_ char** value); diff --git a/objectivec/include/ort_session.h b/objectivec/include/ort_session.h index 08a24e5cc3..950cae5fb2 100644 --- a/objectivec/include/ort_session.h +++ b/objectivec/include/ort_session.h @@ -64,6 +64,30 @@ NS_ASSUME_NONNULL_BEGIN runOptions:(nullable ORTRunOptions*)runOptions error:(NSError**)error; +/** + * Gets the model's input names. + * + * @param[out] error Optional error information set if an error occurs. + * @return An array of input names, or nil if an error occurs. + */ +- (nullable NSArray*)inputNamesWithError:(NSError**)error; + +/** + * Gets the model's overridable initializer names. + * + * @param[out] error Optional error information set if an error occurs. + * @return An array of overridable initializer names, or nil if an error occurs. + */ +- (nullable NSArray*)overridableInitializerNamesWithError:(NSError**)error; + +/** + * Gets the model's output names. + * + * @param[out] error Optional error information set if an error occurs. + * @return An array of output names, or nil if an error occurs. + */ +- (nullable NSArray*)outputNamesWithError:(NSError**)error; + @end /** diff --git a/objectivec/src/ort_session.mm b/objectivec/src/ort_session.mm index b3be3bcf6a..08d140ff77 100644 --- a/objectivec/src/ort_session.mm +++ b/objectivec/src/ort_session.mm @@ -13,12 +13,22 @@ #import "src/ort_env_internal.h" #import "src/ort_value_internal.h" +namespace { +enum class NamedValueType { + Input, + OverridableInitializer, + Output, +}; +} // namespace + NS_ASSUME_NONNULL_BEGIN @implementation ORTSession { std::optional _session; } +#pragma mark - Public + - (nullable instancetype)initWithEnv:(ORTEnv*)env modelPath:(NSString*)path sessionOptions:(nullable ORTSessionOptions*)sessionOptions @@ -130,6 +140,62 @@ NS_ASSUME_NONNULL_BEGIN ORT_OBJC_API_IMPL_CATCH_RETURNING_NULLABLE(error) } +- (nullable NSArray*)inputNamesWithError:(NSError**)error { + return [self namesWithType:NamedValueType::Input error:error]; +} + +- (nullable NSArray*)overridableInitializerNamesWithError:(NSError**)error { + return [self namesWithType:NamedValueType::OverridableInitializer error:error]; +} + +- (nullable NSArray*)outputNamesWithError:(NSError**)error { + return [self namesWithType:NamedValueType::Output error:error]; +} + +#pragma mark - Private + +- (nullable NSArray*)namesWithType:(NamedValueType)namedValueType + error:(NSError**)error { + try { + auto getCount = [&session = *_session, namedValueType]() { + if (namedValueType == NamedValueType::Input) { + return session.GetInputCount(); + } else if (namedValueType == NamedValueType::OverridableInitializer) { + return session.GetOverridableInitializerCount(); + } else { + return session.GetOutputCount(); + } + }; + + auto getName = [&session = *_session, namedValueType](size_t i, OrtAllocator* allocator) { + if (namedValueType == NamedValueType::Input) { + return session.GetInputName(i, allocator); + } else if (namedValueType == NamedValueType::OverridableInitializer) { + return session.GetOverridableInitializerName(i, allocator); + } else { + return session.GetOutputName(i, allocator); + } + }; + + const size_t nameCount = getCount(); + + Ort::AllocatorWithDefaultOptions allocator; + auto deleter = [ortAllocator = static_cast(allocator)](void* p) { + ortAllocator->Free(ortAllocator, p); + }; + + NSMutableArray* result = [NSMutableArray arrayWithCapacity:nameCount]; + + for (size_t i = 0; i < nameCount; ++i) { + auto name = std::unique_ptr{getName(i, allocator), deleter}; + [result addObject:[NSString stringWithUTF8String:name.get()]]; + } + + return result; + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_NULLABLE(error) +} + @end @implementation ORTSessionOptions { diff --git a/objectivec/test/ort_session_test.mm b/objectivec/test/ort_session_test.mm index ef4c434a28..621d3f4303 100644 --- a/objectivec/test/ort_session_test.mm +++ b/objectivec/test/ort_session_test.mm @@ -147,6 +147,31 @@ NS_ASSUME_NONNULL_BEGIN XCTAssertEqual(cActual, cExpected); } +- (void)testGetNamesOk { + NSError* err = nil; + ORTSession* session = [[ORTSession alloc] initWithEnv:self.ortEnv + modelPath:[ORTSessionTest getAddModelPath] + sessionOptions:[ORTSessionTest makeSessionOptions] + error:&err]; + XCTAssertNotNil(session); + XCTAssertNil(err); + + NSArray* inputNames = [session inputNamesWithError:&err]; + XCTAssertNotNil(inputNames); + XCTAssertNil(err); + XCTAssertEqualObjects(inputNames, (@[ @"A", @"B" ])); + + NSArray* overridableInitializerNames = [session overridableInitializerNamesWithError:&err]; + XCTAssertNotNil(overridableInitializerNames); + XCTAssertNil(err); + XCTAssertEqualObjects(overridableInitializerNames, (@[])); + + NSArray* outputNames = [session outputNamesWithError:&err]; + XCTAssertNotNil(outputNames); + XCTAssertNil(err); + XCTAssertEqualObjects(outputNames, (@[ @"C" ])); +} + - (void)testInitFailsWithInvalidPath { NSString* invalidModelPath = [ORTSessionTest getTestDataWithRelativePath:@"/invalid/path/to/model.onnx"]; NSError* err = nil;