/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ #ifndef TENSORFLOW_LITE_C_C_API_INTERNAL_H_ #define TENSORFLOW_LITE_C_C_API_INTERNAL_H_ #include #include #include #include // NOLINT #include #include "tensorflow/lite/builtin_ops.h" #include "tensorflow/lite/core/api/error_reporter.h" #include "tensorflow/lite/core/api/op_resolver.h" #include "tensorflow/lite/core/interpreter.h" #include "tensorflow/lite/core/model_builder.h" #include "tensorflow/lite/mutable_op_resolver.h" #include "tensorflow/lite/profiling/telemetry/c/profiler.h" #include "tensorflow/lite/signature_runner.h" // Internal structures and subroutines used by the C API. These are likely to // change and should not be depended on directly by any C API clients. // // NOTE: This header does not follow C conventions and does not define a C API. // It is effectively an (internal) implementation detail of the C API. struct TfLiteModel { // Sharing is safe as FlatBufferModel is const. std::shared_ptr impl; }; // The `TfLiteOpResolver` struct is an abstract callback interface that // contains function pointers for callbacks that return a // `TfLiteRegistration` given an op code or custom op name. This mechanism is // used to map ops referenced in the flatbuffer model to executable function // pointers (`TfLiteRegistration`s). // This struct mirrors the tflite::OpResolver C++ abstract base class. struct TfLiteOpResolverCallbacks { // Opaque data that gets passed down to the callback functions. void* user_data = nullptr; // Callback that finds the op registration for a builtin operator by enum // code. The `user_data` parameter will be set to the // `op_resolver_user_data` value that was passed to // `TfLiteInterpreterOptionsSetOpResolver`. std::function find_builtin_op; // Callback that finds the op registration of a custom operator by op name. // The `user_data` parameter will be set to the `op_resolver_user_data` value // that was passed to `TfLiteInterpreterOptionsSetOpResolver`. std::function find_custom_op; // Variant of `find_builtin_op` which returns `TfLiteRegistration_V3`. std::function find_builtin_op_v3; // Variant of `find_custom_op` which returns `TfLiteRegistration_V3`. std::function find_custom_op_v3; // Variant of `find_builtin_op` which returns `TfLiteRegistration_V2`. std::function find_builtin_op_v2; // Variant of `find_custom_op` which returns `TfLiteRegistration_V2`. std::function find_custom_op_v2; // Varant of `find_builtin_op` which returns `TfLiteRegistration_V1`. std::function find_builtin_op_v1; // Varant of `find_custom_op` which returns `TfLiteRegistration_V1`. std::function find_custom_op_v1; // Variant of `find_builtin_op` which returns `TfLiteOperator`. std::function find_builtin_op_external; // Variant of `find_custom_op` which returns `TfLiteOperator`. std::function find_custom_op_external; }; // This struct mirrors the tflite::ErrorResolver C++ abstract base class. struct TfLiteErrorReporterCallback { // Opaque data that gets passed down to the callback function. void* user_data = nullptr; // Callback function that reports an error. void (*error_reporter)(void* user_data, const char* format, va_list args) = nullptr; }; struct TfLiteInterpreterOptions { enum { kDefaultNumThreads = -1, }; int num_threads = kDefaultNumThreads; tflite::MutableOpResolver mutable_op_resolver; TfLiteOpResolverCallbacks op_resolver_callbacks = {}; std::vector delegates; TfLiteErrorReporterCallback error_reporter_callback; bool use_nnapi = false; // Determines whether to allow automatic fallback to CPU. // If true, and if one or more delegates were set, // then if Invoke with delegates fails, it will be // automatically retried without delegates. bool enable_delegate_fallback = false; // TfLiteOperator objects owned by caller of // `TfLiteInterpreterOptionsAddOperator` API. std::vector op_registrations; // Determines whether to allow to cancel invocations with // `Interpreter::Cancel` or `SignatureRunner::Cancel`. bool enable_cancellation = false; // If not nullptr, report telemetry metrics to profiler. TfLiteTelemetryProfilerStruct* telemetry_profiler = nullptr; }; struct TfLiteInterpreter { // Taking a reference to the (const) model data avoids lifetime-related issues // and complexity with the TfLiteModel's existence. std::shared_ptr model; // The interpreter does not take ownership of the provided ErrorReporter // instance, so we ensure its validity here. Note that the interpreter may use // the reporter in its destructor, so the reporter should be declared first. std::unique_ptr optional_error_reporter; std::unique_ptr impl; bool enable_delegate_fallback; }; struct TfLiteSignatureRunner { // The tflite::SignatureRunner runner object that this points to is owned by // the interpreter. So this pointer will become invalid when the interpreter // is destroyed. tflite::SignatureRunner* impl; }; namespace tflite { namespace internal { /// `CallbackOpResolver` is a (C++) `tflite::OpResolver` that forwards the /// methods to (C ABI) callback functions from a `TfLiteOpResolverCallbacks` /// struct. /// /// The SetCallbacks method must be called before calling any of the FindOp /// methods. class CallbackOpResolver : public ::tflite::OpResolver { public: CallbackOpResolver() = default; void SetCallbacks( const struct TfLiteOpResolverCallbacks& op_resolver_callbacks) { op_resolver_callbacks_ = op_resolver_callbacks; } const TfLiteRegistration* FindOp(tflite::BuiltinOperator op, int version) const override; const TfLiteRegistration* FindOp(const char* op, int version) const override; private: CallbackOpResolver(const CallbackOpResolver&) = delete; CallbackOpResolver& operator=(const CallbackOpResolver&) = delete; // Builds a builtin op TfLiteRegistration from a legacy registration // (e.g. TfLiteRegistration_V1). // The legacy registration type must be a POD struct type whose field types // must be a prefix of the field types in TfLiteRegistration, and offset of // the first field in TfLiteRegistration that is not present in the legacy // registration type must be greater than or equal to the size of the legacy // registration type. // `legacy_find_builtin_op` is a callback that finds the // legacy registration for a builtin operator by enum code. The caller owns // the returned registration. template TfLiteRegistration* BuildBuiltinOpFromLegacyRegistration( tflite::BuiltinOperator op, int version, std::function legacy_find_builtin_op) const { if (legacy_find_builtin_op) { // Get a deprecated Registration object to create a Registration. const LegacyRegistrationT* legacy_registration = legacy_find_builtin_op( op_resolver_callbacks_.user_data, static_cast(op), version); if (legacy_registration) { TfLiteRegistration* new_registration = new TfLiteRegistration(); memcpy(new_registration, legacy_registration, sizeof(LegacyRegistrationT)); new_registration->registration_external = nullptr; temporary_builtin_registrations_.push_back( std::unique_ptr(new_registration)); return new_registration; } } return nullptr; } // Builds a custom op TfLiteRegistration from a legacy registration // (e.g. TfLiteRegistration_V1). // The legacy registration type must be a POD struct type whose field types // must be a prefix of the field types in TfLiteRegistration, and offset of // the first field in TfLiteRegistration that is not present in the legacy // registration type must be greater than or equal to the size of the legacy // registration type. // `legacy_find_custom_op` is a callback that finds the legacy registration // for a builtin operator by op name. // The caller owns the returned registration. template TfLiteRegistration* BuildCustomOpFromLegacyRegistration( const char* op, int version, std::function legacy_find_custom_op) const { if (legacy_find_custom_op) { // Get a deprecated Registration object to create a Registration. const LegacyRegistrationT* legacy_registration = legacy_find_custom_op(op_resolver_callbacks_.user_data, op, version); if (legacy_registration) { TfLiteRegistration* new_registration = new TfLiteRegistration(); memcpy(new_registration, legacy_registration, sizeof(LegacyRegistrationT)); new_registration->registration_external = nullptr; temporary_custom_registrations_.push_back( std::unique_ptr(new_registration)); return new_registration; } } return nullptr; } struct TfLiteOpResolverCallbacks op_resolver_callbacks_ = {}; // mutable objects to store temporary `TfLiteRegistration`. mutable std::mutex mutex_; mutable std::vector> temporary_builtin_registrations_; // GUARDED_BY(mutex_) mutable std::vector> temporary_custom_registrations_; // GUARDED_BY(mutex_) }; // This adds the builtin and/or custom operators specified in options in // `optional_options` (if any) to `mutable_resolver`, and then returns a newly // created TfLiteInterpreter using `mutable_op_resolver` as the default // OpResolver, and using any other options in `optional_options`, and using // the provided `model`. // // * `model` must be a valid model instance. The caller retains ownership of the // object, and can destroy it immediately after creating the interpreter; the // interpreter will maintain its own reference to the underlying model data. // * `optional_options` may be null. The caller retains ownership of the object, // and can safely destroy it immediately after creating the interpreter. // * `mutable_resolver` must not be null. The caller retains ownership of the // MutableOpResolver object, and can safely destroy it immediately after // creating the interpreter. // // NOTE: The client *must* explicitly allocate tensors before attempting to // access input tensor data or invoke the interpreter. TfLiteInterpreter* InterpreterCreateWithOpResolver( const TfLiteModel* model, const TfLiteInterpreterOptions* optional_options, tflite::MutableOpResolver* mutable_resolver); } // namespace internal } // namespace tflite #endif // TENSORFLOW_LITE_C_C_API_INTERNAL_H_