chore: import upstream snapshot with attribution
cffconvert / validate (push) Has been skipped
License Check / license-check (push) Failing after 2s

This commit is contained in:
wehub-resource-sync
2026-07-13 12:14:16 +08:00
commit 8a852e4b4e
36502 changed files with 9277225 additions and 0 deletions
+483
View File
@@ -0,0 +1,483 @@
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_cc//cc:cc_test.bzl", "cc_test")
load("//tensorflow:tensorflow.default.bzl", "get_compatible_with_portable")
load(
"//tensorflow/lite:build_def.bzl",
"tflite_cc_library_with_c_headers_test",
"tflite_cc_shared_object",
"tflite_copts",
"tflite_copts_warnings",
"tflite_custom_c_library",
"tflite_linkopts_no_undefined",
"tflite_self_contained_libs_test_suite",
)
load("//tensorflow/lite:special_rules.bzl", "c_api_opaque_internal_visibility_allowlist", "tflite_portable_test_suite")
load("//tensorflow/lite/core/shims:cc_library_with_tflite.bzl", "cc_library_with_tflite_with_c_headers_test")
package(
# copybara:uncomment default_applicable_licenses = ["//tensorflow:LICENSE"],
default_visibility = ["//visibility:public"],
licenses = ["notice"],
)
# Generates a platform-specific shared library containing the TensorFlow Lite C
# API implementation as define in `c_api.h`. The exact output library name
# is platform dependent:
# - Linux/Android: `libtensorflowlite_c.so`
# - Mac: `libtensorflowlite_c.dylib`
# - Windows: `tensorflowlite_c.dll`
tflite_cc_shared_object(
name = "tensorflowlite_c",
linkopts = tflite_linkopts_no_undefined() + select({
"//tensorflow:ios": [
"-Wl,-exported_symbols_list,$(location //tensorflow/lite/c:exported_symbols.lds)",
],
"//tensorflow:macos": [
"-Wl,-exported_symbols_list,$(location //tensorflow/lite/c:exported_symbols.lds)",
],
"//tensorflow:windows": [],
"//conditions:default": [
"-Wl,--version-script,$(location //tensorflow/lite/c:version_script.lds)",
],
}),
per_os_targets = True,
deps = [
":c_api",
":c_api_experimental",
":exported_symbols.lds",
":version_script.lds",
],
)
cc_library_with_tflite_with_c_headers_test(
name = "c_api",
hdrs = [
"c_api.h",
],
compatible_with = get_compatible_with_portable(),
copts = tflite_copts(),
generate_opaque_delegate_target = True,
deps = [
":c_api_without_op_resolver",
"//tensorflow/lite/core/async/c:types",
"//tensorflow/lite/core/c:c_api",
],
)
tflite_cc_library_with_c_headers_test(
name = "c_api_for_testing",
testonly = True,
srcs = ["c_api_for_testing.cc"],
hdrs = ["c_api_for_testing.h"],
deps = [
":c_api",
":c_api_internal",
"//tensorflow/lite/core/c:c_api",
],
)
# TODO(b/248514738): Deprecate this target in favour
# of //third_party/tensorflow/lite/core/c:c_api_without_op_resolver after all known existing uses of
# those targets have been changed to instead refer to the new target.
# Same as ":c_api", but doesn't link in the default CreateOpResolver implementation.
cc_library_with_tflite_with_c_headers_test(
name = "c_api_without_op_resolver",
hdrs = ["c_api.h"],
compatible_with = get_compatible_with_portable(),
copts = tflite_copts(),
tags = ["allow_undefined_symbols"], # For tflite::CreateOpResolver().
deps = [
":c_api_types",
"//tensorflow/lite/core/c:c_api_without_op_resolver",
],
)
# TODO(b/248514738): Deprecate this target in favour
# of //third_party/tensorflow/lite/core/c:c_api_without_op_resolver_without_alwayslink after all
# known existing uses of those targets have been changed to instead refer to the new target.
# Same as ":c_api_without_op_resolver", but without alwayslink=1.
cc_library_with_tflite_with_c_headers_test(
name = "c_api_without_op_resolver_without_alwayslink",
hdrs = ["c_api.h"],
compatible_with = get_compatible_with_portable(),
copts = tflite_copts(),
tags = ["allow_undefined_symbols"], # For tflite::CreateOpResolver().
deps = ["//tensorflow/lite/core/c:c_api_without_op_resolver_without_alwayslink"],
)
cc_library_with_tflite_with_c_headers_test(
name = "c_api_experimental",
hdrs = [
"c_api_experimental.h",
# ':c_api_opaque' was promoted to the 'mostly stable' API.
# Please explicitly add a dependency on ':c_api_opaque' if your target
# needs both ':c_api_experimental' and ':c_api_opaque' dependencies.
# We plan to remove 'c_api_opaque.h' from the list of exposed headers and
# will remove the dependency from this target on ':c_api_opaque' in the future.
"c_api_opaque.h",
],
copts = tflite_copts() + tflite_copts_warnings(),
generate_opaque_delegate_target = True,
tflite_deps = [
":c_api",
],
deps = [
"//tensorflow/lite/core/c:c_api_experimental",
"//tensorflow/lite/core/c:c_api_opaque",
],
)
# Same as ":c_api_experimental", but without linking in the default CreateOpResolver implementation.
cc_library_with_tflite_with_c_headers_test(
name = "c_api_experimental_without_op_resolver",
hdrs = [
"c_api_experimental.h",
# DEPRECATED
# ':c_api_opaque_without_op_resolver' was promoted to the 'mostly stable' API.
# Please explicitly add a dependency on ':c_api_opaque_without_op_resolver' if your target
# needs both ':c_api_experimental_without_op_resolver' and ':c_api_opaque_without_op_resolver' dependencies.
# We plan to remove 'c_api_opaque.h' from the list of exposed headers and
# will remove the dependency from this target on ':c_api_opaque_without_op_resolver' in the future.
"c_api_opaque.h",
],
copts = tflite_copts() + tflite_copts_warnings(),
tags = ["allow_undefined_symbols"], # For tflite::CreateOpResolver().
tflite_deps = [
":c_api_without_op_resolver",
],
deps = [
"//tensorflow/lite/core/c:c_api_experimental_without_op_resolver",
"//tensorflow/lite/core/c:c_api_opaque_without_op_resolver",
],
)
# Same as ":c_api_experimental", but without linking in the default CreateOpResolver implementation,
# and without depending on targets that use alwayslink=1.
cc_library_with_tflite_with_c_headers_test(
name = "c_api_experimental_without_op_resolver_without_alwayslink",
hdrs = [
"c_api_experimental.h",
# DEPRECATED
# ':c_api_opaque_without_op_resolver_without_alwayslink' was promoted to the 'mostly stable' API.
# Please explicitly add a dependency on ':c_api_opaque_without_op_resolver_without_alwayslink'
# if your target needs both ':c_api_experimental_without_op_resolver_without_alwayslink' and
# ':c_api_opaque_without_op_resolver_without_alwayslink' dependencies.
# We plan to remove 'c_api_opaque.h' from the list of exposed headers and
# will remove the dependency from this target on
# ':c_api_opaque_without_op_resolver_without_alwayslink' in the future.
"c_api_opaque.h",
],
copts = tflite_copts() + tflite_copts_warnings(),
tags = ["allow_undefined_symbols"], # For tflite::CreateOpResolver().
tflite_deps = [":c_api_without_op_resolver_without_alwayslink"],
deps = [
"//tensorflow/lite/core/c:c_api_experimental_without_op_resolver_without_alwayslink",
"//tensorflow/lite/core/c:c_api_opaque_without_op_resolver_without_alwayslink",
],
)
cc_library_with_tflite_with_c_headers_test(
name = "c_api_opaque",
hdrs = [
"c_api_opaque.h",
],
compatible_with = get_compatible_with_portable(),
copts = tflite_copts() + tflite_copts_warnings(),
generate_opaque_delegate_target = True,
tflite_deps = [":c_api"],
deps = ["//tensorflow/lite/core/c:c_api_opaque"],
)
cc_library_with_tflite_with_c_headers_test(
name = "c_api_opaque_without_op_resolver",
hdrs = [
"c_api_opaque.h",
],
compatible_with = get_compatible_with_portable(),
copts = tflite_copts() + tflite_copts_warnings(),
tags = ["allow_undefined_symbols"], # For tflite::CreateOpResolver().
tflite_deps = [":c_api_without_op_resolver"],
deps = ["//tensorflow/lite/core/c:c_api_opaque_without_op_resolver"],
)
cc_library_with_tflite_with_c_headers_test(
name = "c_api_opaque_without_op_resolver_without_alwayslink",
hdrs = [
"c_api_opaque.h",
],
compatible_with = get_compatible_with_portable(),
copts = tflite_copts() + tflite_copts_warnings(),
tags = ["allow_undefined_symbols"], # For tflite::CreateOpResolver().
tflite_deps = [
":c_api_without_op_resolver_without_alwayslink",
],
deps = ["//tensorflow/lite/core/c:c_api_opaque_without_op_resolver_without_alwayslink"],
)
cc_library_with_tflite_with_c_headers_test(
name = "c_api_types",
hdrs = ["c_api_types.h"],
compatible_with = get_compatible_with_portable(),
copts = tflite_copts() + tflite_copts_warnings(),
generate_opaque_delegate_target = True,
deps = ["//tensorflow/lite/core/c:c_api_types"],
)
cc_library(
name = "c_api_internal",
hdrs = ["c_api_internal.h"],
compatible_with = get_compatible_with_portable(),
copts = tflite_copts(),
visibility = [
"//tensorflow/lite/core/async/c:__subpackages__",
"//tensorflow/lite/core/c:__subpackages__",
],
deps = [
":common_internal",
"//tensorflow/lite:builtin_ops",
"//tensorflow/lite:framework",
"//tensorflow/lite/core:framework",
"//tensorflow/lite/core/api",
"//tensorflow/lite/core/c:common",
"//tensorflow/lite/profiling/telemetry/c:profiler",
],
)
filegroup(
name = "c_api_test_builtin_op_models",
testonly = 1,
srcs = [
"//tensorflow/lite:testdata/add.bin",
"//tensorflow/lite:testdata/add_quantized.bin",
],
)
# TODO(b/248514738): Deprecate this target in favour
# of //third_party/tensorflow/lite/core/c:c_api_test after all known existing uses of those targets
# have been changed to instead refer to the new target.
test_suite(
name = "c_api_test",
tests = [
"//tensorflow/lite/core/c:c_api_test",
],
)
tflite_custom_c_library(
name = "selectively_built_c_api_test_lib",
testonly = 1,
experimental = True,
models = [":c_api_test_builtin_op_models"],
visibility = [
"//tensorflow/lite/core/c:__subpackages__",
],
)
# TODO(b/248514738): Deprecate this target in favour
# of //third_party/tensorflow/lite/core/c:selectively_built_c_api_test after all known existing uses
# of those targets have been changed to instead refer to the new target.
test_suite(
name = "selectively_built_c_api_test",
tests = [
"//tensorflow/lite/core/c:selectively_built_c_api_test",
],
)
test_suite(
name = "c_api_experimental_test",
tests = [
"//tensorflow/lite/core/c:c_api_experimental_test",
],
)
cc_test(
name = "c_api_signature_runner_test",
size = "small",
srcs = ["c_api_signature_runner_test.cc"],
copts = tflite_copts(),
data = [
"//tensorflow/lite:testdata/multi_signatures.bin",
"//tensorflow/lite:testdata/no_signatures.bin",
],
deps = [
":c_api",
"//tensorflow/lite/core/c:c_api",
"//tensorflow/lite/core/c:common",
"@com_google_googletest//:gtest_main",
],
)
cc_library_with_tflite_with_c_headers_test(
name = "common",
hdrs = [
"builtin_op_data.h",
"common.h",
],
compatible_with = get_compatible_with_portable(),
copts = tflite_copts() + tflite_copts_warnings(),
generate_opaque_delegate_target = True,
tflite_deps = [
":c_api_types",
],
deps = [
"//tensorflow/lite:tflite_kernel_use_xnnpack_optional",
"//tensorflow/lite/core/c:c_api_types",
"//tensorflow/lite/core/c:common",
] + select({
"//tensorflow/lite:tensorflow_profiler_config": [
"//tensorflow/lite:macros",
"//tensorflow/lite:tensorflow_profiler_logger_shim",
],
"//conditions:default": [],
}),
)
cc_library(
name = "common_internal",
srcs = ["common_internal.cc"],
hdrs = ["common_internal.h"],
compatible_with = get_compatible_with_portable(),
copts = tflite_copts(),
visibility = [
"//tensorflow/lite:__subpackages__",
],
deps = [
"//tensorflow/lite/core/c:c_api_types",
"//tensorflow/lite/core/c:common",
],
)
cc_library(
name = "c_api_opaque_internal",
srcs = ["c_api_opaque_internal.cc"],
hdrs = ["c_api_opaque_internal.h"],
compatible_with = get_compatible_with_portable(),
tags = ["allow_undefined_symbols"], # For tflite::CreateOpResolver().
visibility = [
"//tensorflow/lite:__subpackages__",
] + c_api_opaque_internal_visibility_allowlist(),
deps = [
":c_api_types",
"//tensorflow/lite:framework",
"//tensorflow/lite/c:c_api_internal",
"//tensorflow/lite/core/api:op_resolver",
"//tensorflow/lite/core/c:common",
"//tensorflow/lite/core/c:operator",
],
)
cc_test(
name = "c_api_opaque_internal_test",
srcs = ["c_api_opaque_internal_test.cc"],
data = [
"//tensorflow/lite:testdata/add.bin",
],
deps = [
":c_api_internal",
":c_api_opaque_internal",
"//tensorflow/lite:builtin_ops",
"//tensorflow/lite:framework",
"//tensorflow/lite/kernels:builtin_ops",
"@com_google_googletest//:gtest_main",
],
)
# Same as c_api_opaque_internal, but depends on the
# '_without_alwayslink' variant of ':c_api_without_op_resolver'.
cc_library(
name = "c_api_opaque_internal_without_alwayslink",
srcs = ["c_api_opaque_internal.cc"],
hdrs = ["c_api_opaque_internal.h"],
compatible_with = get_compatible_with_portable(),
tags = ["allow_undefined_symbols"], # For tflite::CreateOpResolver().
visibility = [
"//tensorflow/lite:__subpackages__",
],
deps = [
":c_api_types",
"//tensorflow/lite:framework",
"//tensorflow/lite/c:c_api_internal",
"//tensorflow/lite/core/api:op_resolver",
"//tensorflow/lite/core/c:common",
"//tensorflow/lite/core/c:operator_without_alwayslink",
],
)
# For use with library targets that can't use relative paths.
# LINT.IfChange(exported_headers)
exports_files([
"builtin_op_data.h",
"c_api.h",
"c_api_experimental.h",
"c_api_opaque.h",
"c_api_types.h",
"common.h",
])
filegroup(
name = "tensorflowlite_c_api_hdrs_filegroup",
srcs = [
"builtin_op_data.h",
"c_api.h",
"c_api_types.h",
"common.h",
],
)
alias(
name = "tensorflowlite_c_impl_hdrs_filegroup",
actual = "//tensorflow/lite/core/c:headers_filegroup",
)
# LINT.ThenChange(../java/BUILD:TFLITE_HEADERS)
# Test the C extension API code.
test_suite(
name = "common_test",
tests = [
"//tensorflow/lite/core/c:common_test",
],
)
test_suite(
name = "builtin_op_data_test",
tests = [
"//tensorflow/lite/core/c:builtin_op_data_test",
],
)
cc_test(
name = "c_test",
size = "small",
srcs = ["c_test.c"],
copts = tflite_copts(),
data = [
"//tensorflow/lite:testdata/add.bin",
"//tensorflow/lite:testdata/multi_signatures.bin",
],
tags = [
# Testing on Android uses "--gunit_output=xml:test.xml" runtime flag,
# but this test is C code, not C++, and hence doesn't use GUnit,
# so doesn't support that flag.
"tflite_not_portable_android",
],
deps = [
":c_api",
":c_api_experimental",
"//tensorflow/lite/core/c:c_api",
"//tensorflow/lite/core/c:c_api_experimental",
"//tensorflow/lite/core/c:c_api_opaque",
"//tensorflow/lite/core/c:c_api_types",
"//tensorflow/lite/core/c:common",
],
)
cc_library_with_tflite_with_c_headers_test(
name = "test_util",
testonly = True,
srcs = ["test_util.cc"],
hdrs = ["test_util.h"],
generate_opaque_delegate_target = True,
)
tflite_self_contained_libs_test_suite(name = "self_contained_libs_test_suite")
tflite_portable_test_suite()
+92
View File
@@ -0,0 +1,92 @@
#
# Copyright 2021 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
#
# https://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.
cmake_minimum_required(VERSION 3.16)
project(tensorflow-lite-c C CXX)
option(TFLITE_C_BUILD_SHARED_LIBS "Build shared libraries" ON)
set(TF_SOURCE_DIR "" CACHE PATH
"Directory that contains the TensorFlow project"
)
if (NOT TF_SOURCE_DIR)
get_filename_component(TF_SOURCE_DIR
"${CMAKE_CURRENT_LIST_DIR}/../../../"
ABSOLUTE
)
endif()
set(TFLITE_SOURCE_DIR "${TF_SOURCE_DIR}/tensorflow/lite")
add_subdirectory(
"${TFLITE_SOURCE_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}/tensorflow-lite"
EXCLUDE_FROM_ALL
)
set(CMAKE_CXX_STANDARD 20)
if(CMAKE_SYSTEM_NAME MATCHES "Windows"
AND (MSVC AND (CMAKE_SIZEOF_VOID_P EQUAL 4)))
message("Disabling MSVC /O2 optimization for Win32")
set(CompFlags
CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL
CMAKE_CXX_FLAGS_RELWITHDEBINFO
CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_MINSIZEREL
CMAKE_C_FLAGS_RELWITHDEBINFO
)
foreach (CompFlag ${CompFlags})
string(REGEX REPLACE "(\/Ob. )" "" ${CompFlag} "${${CompFlag}}")
string(REPLACE "/O2" "/O1" ${CompFlag} "${${CompFlag}}")
list(REMOVE_DUPLICATES ${CompFlag})
set(${CompFlag} "${${CompFlag}}" CACHE INTERNAL "")
endforeach()
endif()
set(TFLITE_C_LIBTYPE STATIC)
if (TFLITE_C_BUILD_SHARED_LIBS)
set(TFLITE_C_LIBTYPE SHARED)
endif()
add_library(tensorflowlite_c ${TFLITE_C_LIBTYPE}
${TFLITE_SOURCE_DIR}/core/c/c_api.cc
${TFLITE_SOURCE_DIR}/core/c/c_api_experimental.cc
${TFLITE_SOURCE_DIR}/core/c/common.cc
${TFLITE_SOURCE_DIR}/core/c/operator.cc
${TF_SOURCE_DIR}/tensorflow/compiler/mlir/lite/core/c/tflite_types.h
builtin_op_data.h
c_api.h
c_api_experimental.h
c_api_internal.h
c_api_types.h
common.h
)
if (TFLITE_C_BUILD_SHARED_LIBS)
if (WIN32)
target_compile_definitions(tensorflowlite_c PRIVATE TFL_COMPILE_LIBRARY)
target_compile_definitions(tensorflow-lite PRIVATE TFL_COMPILE_LIBRARY)
elseif (APPLE)
target_link_options(tensorflowlite_c PRIVATE "-Wl,-exported_symbols_list,${TFLITE_SOURCE_DIR}/c/exported_symbols.lds")
else ()
target_link_options(tensorflowlite_c PRIVATE "-Wl,--version-script,${TFLITE_SOURCE_DIR}/c/version_script.lds")
endif()
endif()
target_link_libraries(tensorflowlite_c
tensorflow-lite
)
+49
View File
@@ -0,0 +1,49 @@
# TensorFlow Lite C API
This directory contains C APIs for TensorFlow Lite. This includes C APIs
for common types, like kernels and delegates, as well as an explicit C API
for inference.
## Header summary
Each public C header contains types and methods for specific uses:
* `common.h` - Contains common C enums, types and methods used throughout
TensorFlow Lite. This includes everything from error codes, to the kernel
and delegate APIs.
* `builtin_op_data.h` - Contains op-specific data that is used for builtin
kernels. This should only be used when (re)implementing a builtin operator.
* `c_api.h` - Contains the TensorFlow Lite C API for inference. The
functionality here is largely equivalent (though a strict subset of) the
functionality provided by the C++ `Interpreter` API.
* `c_api_experimental.h` - Contains experimental C API methods for inference.
These methods are useful and usable, but aren't yet part of the stable API.
## Using the C API
See the [`c_api.h`](c_api.h) header for API usage details.
## Building the C API
A native shared library target that contains the C API for inference has been
provided. Assuming a working [bazel](https://bazel.build/versions/master/docs/install.html)
configuration, this can be built as follows:
```sh
bazel build -c opt //tensorflow/lite/c:tensorflowlite_c
```
and for Android (replace `android_arm` with `android_arm64` for 64-bit),
assuming you've
[configured your project for Android builds](../g3doc/android/lite_build.md):
```sh
bazel build -c opt --cxxopt=--std=c++11 --config=android_arm \
//tensorflow/lite/c:tensorflowlite_c
```
The generated shared library will be available in your
`bazel-bin/tensorflow/lite/c` directory. A target which packages the shared
library together with the necessary headers (`c_api.h`, `c_api_experimental.h`
and `common.h`) will be available soon, and will also be released as a prebuilt
archive (together with existing prebuilt packages for Android/iOS).
+23
View File
@@ -0,0 +1,23 @@
/* Copyright 2020 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_BUILTIN_OP_DATA_H_
#define TENSORFLOW_LITE_C_BUILTIN_OP_DATA_H_
/// For documentation, see
/// third_party/tensorflow/lite/core/c/builtin_op_data.h
#include "tensorflow/lite/core/c/builtin_op_data.h"
#endif // TENSORFLOW_LITE_C_BUILTIN_OP_DATA_H_
+58
View File
@@ -0,0 +1,58 @@
/* Copyright 2020 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_H_
#define TENSORFLOW_LITE_C_C_API_H_
/// \file
///
/// C API for TensorFlow Lite.
///
/// For documentation, see tensorflow/lite/core/c/c_api.h
#include "tensorflow/lite/core/c/c_api.h"
#ifndef DOYXGEN_SKIP
// For backwards compatibility.
// Deprecated. Use the names starting with TfLiteOperator instead.
#ifdef __cplusplus
using TfLiteRegistrationExternal = TfLiteOperator;
// NOLINTBEGIN
const auto TfLiteRegistrationExternalCreate = TfLiteOperatorCreate;
const auto TfLiteRegistrationExternalGetBuiltInCode =
TfLiteOperatorGetBuiltInCode;
const auto TfLiteRegistrationExternalGetVersion = TfLiteOperatorGetVersion;
const auto TfLiteRegistrationExternalDelete = TfLiteOperatorDelete;
const auto TfLiteRegistrationExternalSetInit = TfLiteOperatorSetInit;
const auto TfLiteRegistrationExternalSetFree = TfLiteOperatorSetFree;
const auto TfLiteRegistrationExternalSetPrepare = TfLiteOperatorSetPrepare;
const auto TfLiteRegistrationExternalSetInvoke = TfLiteOperatorSetInvoke;
const auto TfLiteRegistrationExternalGetCustomName =
TfLiteOperatorGetCustomName;
// NOLINTEND
#else
typedef TfLiteOperator TfLiteRegistrationExternal;
#define TfLiteRegistrationExternalCreate TfLiteOperatorCreate
#define TfLiteRegistrationExternalGetBuiltInCode TfLiteOperatorGetBuiltInCode
#define TfLiteRegistrationExternalGetVersion TfLiteOperatorGetVersion
#define TfLiteRegistrationExternalDelete TfLiteOperatorDelete
#define TfLiteRegistrationExternalSetInit TfLiteOperatorSetInit
#define TfLiteRegistrationExternalSetFree TfLiteOperatorSetFree
#define TfLiteRegistrationExternalSetPrepare TfLiteOperatorSetPrepare
#define TfLiteRegistrationExternalSetInvoke TfLiteOperatorSetInvoke
#define TfLiteRegistrationExternalGetCustomName TfLiteOperatorGetCustomName
#endif // __cplusplus
#endif // DOYXGEN_SKIP
#endif // TENSORFLOW_LITE_C_C_API_H_
+23
View File
@@ -0,0 +1,23 @@
/* Copyright 2020 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_EXPERIMENTAL_H_
#define TENSORFLOW_LITE_C_C_API_EXPERIMENTAL_H_
/// For documentation, see
/// third_party/tensorflow/lite/core/c/c_api_experimental.h
#include "tensorflow/lite/core/c/c_api_experimental.h"
#endif // TENSORFLOW_LITE_C_C_API_EXPERIMENTAL_H_
+28
View File
@@ -0,0 +1,28 @@
/* Copyright 2021 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.
==============================================================================*/
#include "tensorflow/lite/c/c_api_for_testing.h"
#include <cstdint>
#include "tensorflow/lite/c/c_api_internal.h"
extern "C" {
int32_t TfLiteInterpreterOptionsGetNumThreads(
TfLiteInterpreterOptions* options) {
return options->num_threads;
}
} // extern "C"
+32
View File
@@ -0,0 +1,32 @@
/* Copyright 2021 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_FOR_TESTING_H_
#define TENSORFLOW_LITE_C_C_API_FOR_TESTING_H_
#include "tensorflow/lite/core/c/c_api.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// Gets the number of CPU threads to use for the interpreter.
TFL_CAPI_EXPORT extern int32_t TfLiteInterpreterOptionsGetNumThreads(
TfLiteInterpreterOptions* options);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // TENSORFLOW_LITE_C_C_API_FOR_TESTING_H_
+299
View File
@@ -0,0 +1,299 @@
/* 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 <stdarg.h>
#include <functional>
#include <memory>
#include <mutex> // NOLINT
#include <vector>
#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<const tflite::impl::FlatBufferModel> 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<const TfLiteRegistration*(
void* user_data, TfLiteBuiltinOperator op, int version)>
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<const TfLiteRegistration*(void* user_data, const char* op,
int version)>
find_custom_op;
// Variant of `find_builtin_op` which returns `TfLiteRegistration_V3`.
std::function<const TfLiteRegistration_V3*(
void* user_data, TfLiteBuiltinOperator op, int version)>
find_builtin_op_v3;
// Variant of `find_custom_op` which returns `TfLiteRegistration_V3`.
std::function<const TfLiteRegistration_V3*(void* user_data, const char* op,
int version)>
find_custom_op_v3;
// Variant of `find_builtin_op` which returns `TfLiteRegistration_V2`.
std::function<const TfLiteRegistration_V2*(
void* user_data, TfLiteBuiltinOperator op, int version)>
find_builtin_op_v2;
// Variant of `find_custom_op` which returns `TfLiteRegistration_V2`.
std::function<const TfLiteRegistration_V2*(void* user_data, const char* op,
int version)>
find_custom_op_v2;
// Varant of `find_builtin_op` which returns `TfLiteRegistration_V1`.
std::function<const TfLiteRegistration_V1*(
void* user_data, TfLiteBuiltinOperator op, int version)>
find_builtin_op_v1;
// Varant of `find_custom_op` which returns `TfLiteRegistration_V1`.
std::function<const TfLiteRegistration_V1*(void* user_data, const char* op,
int version)>
find_custom_op_v1;
// Variant of `find_builtin_op` which returns `TfLiteOperator`.
std::function<const TfLiteOperator*(void* user_data, TfLiteBuiltinOperator op,
int version)>
find_builtin_op_external;
// Variant of `find_custom_op` which returns `TfLiteOperator`.
std::function<const TfLiteOperator*(void* user_data, const char* op,
int version)>
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<TfLiteDelegate*> 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<TfLiteOperator*> 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<const tflite::impl::FlatBufferModel> 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<tflite::ErrorReporter> optional_error_reporter;
std::unique_ptr<tflite::Interpreter> 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 <class LegacyRegistrationT>
TfLiteRegistration* BuildBuiltinOpFromLegacyRegistration(
tflite::BuiltinOperator op, int version,
std::function<const LegacyRegistrationT*(
void* user_data, TfLiteBuiltinOperator op, int version)>
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<TfLiteBuiltinOperator>(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<TfLiteRegistration>(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 <class LegacyRegistrationT>
TfLiteRegistration* BuildCustomOpFromLegacyRegistration(
const char* op, int version,
std::function<const LegacyRegistrationT*(void* user_data, const char* op,
int version)>
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<TfLiteRegistration>(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<std::unique_ptr<TfLiteRegistration>>
temporary_builtin_registrations_; // GUARDED_BY(mutex_)
mutable std::vector<std::unique_ptr<TfLiteRegistration>>
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_
+23
View File
@@ -0,0 +1,23 @@
/* Copyright 2020 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_OPAQUE_H_
#define TENSORFLOW_LITE_C_C_API_OPAQUE_H_
/// For documentation, see
/// third_party/tensorflow/lite/core/c/c_api_opaque.h
#include "tensorflow/lite/core/c/c_api_opaque.h"
#endif // TENSORFLOW_LITE_C_C_API_OPAQUE_H_
@@ -0,0 +1,78 @@
/* Copyright 2022 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.
==============================================================================*/
#include "tensorflow/lite/c/c_api_opaque_internal.h"
#include <memory>
#include <unordered_map>
#include <utility>
#include "tensorflow/lite/core/api/op_resolver.h"
#include "tensorflow/lite/core/c/common.h"
#include "tensorflow/lite/core/c/operator.h"
#include "tensorflow/lite/core/subgraph.h"
namespace tflite {
namespace internal {
namespace {
// Returns a dynamically allocated object; the caller is responsible for
// deallocating it using TfLiteOperatorDelete.
TfLiteOperator* MakeOperator(const TfLiteRegistration* registration,
int node_index) {
// We need to allocate a new TfLiteOperator object and then
// populate its state correctly, based on the contents in 'registration'.
auto* registration_external = TfLiteOperatorCreate(
static_cast<TfLiteBuiltinOperator>(registration->builtin_code),
registration->custom_name, registration->version,
/*user_data=*/nullptr);
registration_external->node_index = node_index;
return registration_external;
}
} // anonymous namespace
TfLiteOperator* CommonOpaqueConversionUtil::CachedObtainOperator(
OperatorsCache* registration_externals_cache,
const TfLiteRegistration* registration, int node_index) {
OpResolver::OpId op_id{registration->builtin_code, registration->custom_name,
registration->version};
auto it = registration_externals_cache->find(op_id);
if (it != registration_externals_cache->end()) {
return it->second.get();
}
auto* registration_external = MakeOperator(registration, node_index);
registration_externals_cache->insert(
it, std::make_pair(op_id, registration_external));
return registration_external;
}
TfLiteOperator* CommonOpaqueConversionUtil::ObtainOperator(
TfLiteContext* context, const TfLiteRegistration* registration,
int node_index) {
auto* subgraph = static_cast<tflite::Subgraph*>(context->impl_);
if (!subgraph->registration_externals_) {
subgraph->registration_externals_ = std::make_shared<OperatorsCache>();
}
return CachedObtainOperator(subgraph->registration_externals_.get(),
registration, node_index);
}
} // namespace internal
} // namespace tflite
+64
View File
@@ -0,0 +1,64 @@
/* Copyright 2022 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_OPAQUE_INTERNAL_H_
#define TENSORFLOW_LITE_C_C_API_OPAQUE_INTERNAL_H_
#include "tensorflow/lite/core/api/op_resolver.h"
#include "tensorflow/lite/core/c/common.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.
namespace tflite {
namespace internal {
class CommonOpaqueConversionUtil {
public:
CommonOpaqueConversionUtil() = delete;
// Obtain (or create) a 'TfLiteOperator' object that corresponds
// to the provided 'registration' argument, and return the address of the
// external registration. We loosely define that a
// 'TfLiteOperator' object "corresponds" to a 'TfLiteRegistration'
// object when calling any function pointer (like 'prepare') on the
// 'TfLiteOperator' object calls into the corresponding function
// pointer of the 'TfLiteRegistration' object.
//
// The specified 'context' or 'op_resolver' object is used to store the
// 'TfLiteOperator*' pointers. The 'TfLiteOperator*'
// pointer will be deallocated when that object gets destroyed. I.e., the
// caller of this function should not deallocate the object pointed to by the
// return value of 'ObtainOperator'.
//
// We also need to provide the 'node_index' that the 'registration'
// corresponds to, so that the 'TfLiteOperator' can store that
// index within its fields. If the registration does not yet correspond
// to a specific node index, then 'node_index' should be -1.
static TfLiteOperator* ObtainOperator(TfLiteContext* context,
const TfLiteRegistration* registration,
int node_index);
private:
static TfLiteOperator* CachedObtainOperator(
::tflite::internal::OperatorsCache* registration_externals_cache,
const TfLiteRegistration* registration, int node_index);
};
} // namespace internal
} // namespace tflite
#endif // TENSORFLOW_LITE_C_C_API_OPAQUE_INTERNAL_H_
@@ -0,0 +1,73 @@
/* Copyright 2022 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.
==============================================================================*/
#include "tensorflow/lite/c/c_api_opaque_internal.h"
#include <memory>
#include <gtest/gtest.h>
#include "tensorflow/lite/builtin_ops.h"
#include "tensorflow/lite/core/subgraph.h"
#include "tensorflow/lite/interpreter.h"
#include "tensorflow/lite/interpreter_builder.h"
#include "tensorflow/lite/kernels/builtin_op_kernels.h"
#include "tensorflow/lite/kernels/register.h"
#include "tensorflow/lite/model_builder.h"
using tflite::FlatBufferModel;
using tflite::Interpreter;
using tflite::InterpreterBuilder;
using tflite::internal::CommonOpaqueConversionUtil;
using tflite::ops::builtin::BuiltinOpResolver;
TEST(ObtainRegistrationFromContext, ProducesValidResult) {
BuiltinOpResolver op_resolver;
std::unique_ptr<Interpreter> interpreter;
std::unique_ptr<FlatBufferModel> model = FlatBufferModel::BuildFromFile(
"tensorflow/lite/testdata/add.bin");
ASSERT_NE(model, nullptr);
InterpreterBuilder builder(*model, op_resolver);
ASSERT_EQ(builder(&interpreter), kTfLiteOk);
ASSERT_NE(interpreter, nullptr);
TfLiteContext* context = interpreter->primary_subgraph().context();
const TfLiteRegistration* registration = tflite::ops::builtin::Register_ADD();
TfLiteOperator* registration_external =
CommonOpaqueConversionUtil::ObtainOperator(context, registration, 42);
ASSERT_EQ(registration_external->builtin_code, kTfLiteBuiltinAdd);
ASSERT_EQ(registration_external->version, registration->version);
ASSERT_EQ(registration_external->custom_name, registration->custom_name);
ASSERT_EQ(registration_external->node_index, 42);
}
TEST(ObtainRegistrationFromContext, CachingWorks) {
BuiltinOpResolver op_resolver;
std::unique_ptr<Interpreter> interpreter;
std::unique_ptr<FlatBufferModel> model = FlatBufferModel::BuildFromFile(
"tensorflow/lite/testdata/add.bin");
ASSERT_NE(model, nullptr);
InterpreterBuilder builder(*model, op_resolver);
ASSERT_EQ(builder(&interpreter), kTfLiteOk);
ASSERT_NE(interpreter, nullptr);
TfLiteContext* context = interpreter->primary_subgraph().context();
const TfLiteRegistration* registration = tflite::ops::builtin::Register_ADD();
// Call it twice, and verify that we get the same result back.
TfLiteOperator* registration_external1 =
CommonOpaqueConversionUtil::ObtainOperator(context, registration, 0);
TfLiteOperator* registration_external2 =
CommonOpaqueConversionUtil::ObtainOperator(context, registration, 1);
ASSERT_EQ(registration_external1, registration_external2);
}
@@ -0,0 +1,229 @@
/* Copyright 2022 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.
==============================================================================*/
#include <array>
#include <string>
#include <vector>
#include <gtest/gtest.h>
#include "tensorflow/lite/core/c/c_api.h"
#include "tensorflow/lite/core/c/common.h"
namespace tflite {
namespace {
TEST(SignatureRunnerTest, TestNoSignatures) {
TfLiteModel* model = TfLiteModelCreateFromFile(
"tensorflow/lite/testdata/no_signatures.bin");
ASSERT_NE(model, nullptr);
TfLiteInterpreter* interpreter =
TfLiteInterpreterCreate(model, /*optional_options=*/nullptr);
ASSERT_NE(interpreter, nullptr);
int nun_signatures = TfLiteInterpreterGetSignatureCount(interpreter);
ASSERT_EQ(nun_signatures, 0);
ASSERT_EQ(TfLiteInterpreterGetSignatureRunner(interpreter, "foo"), nullptr);
TfLiteSignatureRunner* runner =
TfLiteInterpreterGetSignatureRunner(interpreter, nullptr);
ASSERT_NE(runner, nullptr);
int num_interpreter_inputs =
TfLiteInterpreterGetInputTensorCount(interpreter);
int num_runner_inputs = TfLiteSignatureRunnerGetInputCount(runner);
ASSERT_EQ(num_runner_inputs, num_interpreter_inputs);
for (int i = 0; i < num_interpreter_inputs; ++i) {
auto* interpreter_input_tensor =
TfLiteInterpreterGetInputTensor(interpreter, i);
ASSERT_NE(interpreter_input_tensor, nullptr);
auto* interpreter_input_name = TfLiteTensorName(interpreter_input_tensor);
ASSERT_NE(interpreter_input_name, nullptr);
auto* runner_input_name = TfLiteSignatureRunnerGetInputName(runner, i);
ASSERT_NE(runner_input_name, nullptr);
EXPECT_STREQ(runner_input_name, interpreter_input_name);
auto* runner_input_tensor =
TfLiteSignatureRunnerGetInputTensor(runner, interpreter_input_name);
ASSERT_NE(runner_input_tensor, nullptr);
ASSERT_EQ(runner_input_tensor, interpreter_input_tensor);
}
int num_interpreter_outputs =
TfLiteInterpreterGetOutputTensorCount(interpreter);
int num_runner_outputs = TfLiteSignatureRunnerGetOutputCount(runner);
ASSERT_EQ(num_runner_outputs, num_interpreter_outputs);
for (int i = 0; i < num_interpreter_outputs; ++i) {
auto* interpreter_output_tensor =
TfLiteInterpreterGetOutputTensor(interpreter, i);
ASSERT_NE(interpreter_output_tensor, nullptr);
auto* interpreter_output_name = TfLiteTensorName(interpreter_output_tensor);
ASSERT_NE(interpreter_output_name, nullptr);
auto* runner_output_name = TfLiteSignatureRunnerGetOutputName(runner, i);
ASSERT_NE(runner_output_name, nullptr);
EXPECT_STREQ(runner_output_name, interpreter_output_name);
auto* runner_output_tensor =
TfLiteSignatureRunnerGetOutputTensor(runner, interpreter_output_name);
ASSERT_NE(runner_output_tensor, nullptr);
ASSERT_EQ(runner_output_tensor, interpreter_output_tensor);
}
std::array<int, 1> input_dims{2};
ASSERT_EQ(TfLiteSignatureRunnerResizeInputTensor(
runner, "x1", input_dims.data(), input_dims.size()),
kTfLiteOk);
ASSERT_EQ(TfLiteSignatureRunnerResizeInputTensor(
runner, "x2", input_dims.data(), input_dims.size()),
kTfLiteOk);
ASSERT_EQ(TfLiteSignatureRunnerAllocateTensors(runner), kTfLiteOk);
TfLiteTensor* input1 = TfLiteSignatureRunnerGetInputTensor(runner, "x1");
ASSERT_NE(input1, nullptr);
TfLiteTensor* input2 = TfLiteSignatureRunnerGetInputTensor(runner, "x2");
ASSERT_NE(input2, nullptr);
ASSERT_EQ(TfLiteSignatureRunnerGetInputTensor(runner, "foo"), nullptr);
const TfLiteTensor* output =
TfLiteSignatureRunnerGetOutputTensor(runner, "Identity");
ASSERT_NE(output, nullptr);
ASSERT_EQ(TfLiteSignatureRunnerGetOutputTensor(runner, "foo"), nullptr);
input1->data.f[0] = -8;
input1->data.f[1] = 0.5;
input2->data.f[0] = -1;
input2->data.f[1] = 1.5;
ASSERT_EQ(TfLiteSignatureRunnerInvoke(runner), kTfLiteOk);
ASSERT_EQ(output->data.f[0], 0);
ASSERT_EQ(output->data.f[1], 2);
TfLiteSignatureRunnerDelete(runner);
TfLiteInterpreterDelete(interpreter);
TfLiteModelDelete(model);
}
TEST(SignatureRunnerTest, TestMultiSignatures) {
TfLiteModel* model = TfLiteModelCreateFromFile(
"tensorflow/lite/testdata/multi_signatures.bin");
ASSERT_NE(model, nullptr);
TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
ASSERT_NE(options, nullptr);
TfLiteInterpreterOptionsSetNumThreads(options, 2);
TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);
ASSERT_NE(interpreter, nullptr);
// The options can be deleted immediately after interpreter creation.
TfLiteInterpreterOptionsDelete(options);
std::vector<std::string> signature_defs;
for (int i = 0; i < TfLiteInterpreterGetSignatureCount(interpreter); i++) {
signature_defs.push_back(TfLiteInterpreterGetSignatureKey(interpreter, i));
}
ASSERT_EQ(signature_defs.size(), 2);
ASSERT_EQ(signature_defs[0], "add");
ASSERT_EQ(signature_defs[1], "sub");
ASSERT_EQ(TfLiteInterpreterGetSignatureRunner(interpreter, "foo"), nullptr);
// Test out-of-range values.
ASSERT_EQ(TfLiteInterpreterGetSignatureKey(interpreter, 2), nullptr);
ASSERT_EQ(TfLiteInterpreterGetSignatureKey(interpreter, -1), nullptr);
TfLiteSignatureRunner* add_runner = TfLiteInterpreterGetSignatureRunner(
interpreter, signature_defs[0].c_str());
ASSERT_NE(add_runner, nullptr);
std::vector<const char*> input_names;
for (int i = 0; i < TfLiteSignatureRunnerGetInputCount(add_runner); i++) {
input_names.push_back(TfLiteSignatureRunnerGetInputName(add_runner, i));
}
std::vector<const char*> output_names;
for (int i = 0; i < TfLiteSignatureRunnerGetOutputCount(add_runner); i++) {
output_names.push_back(TfLiteSignatureRunnerGetOutputName(add_runner, i));
}
ASSERT_EQ(input_names.size(), 1);
ASSERT_EQ(std::string(input_names[0]), "x");
ASSERT_EQ(output_names.size(), 1);
ASSERT_EQ(std::string(output_names[0]), "output_0");
std::array<int, 1> add_runner_input_dims{2};
ASSERT_EQ(TfLiteSignatureRunnerResizeInputTensor(
add_runner, "x", add_runner_input_dims.data(),
add_runner_input_dims.size()),
kTfLiteOk);
ASSERT_EQ(TfLiteSignatureRunnerAllocateTensors(add_runner), kTfLiteOk);
TfLiteTensor* add_input =
TfLiteSignatureRunnerGetInputTensor(add_runner, "x");
ASSERT_EQ(TfLiteSignatureRunnerGetInputTensor(add_runner, "foo"), nullptr);
const TfLiteTensor* add_output =
TfLiteSignatureRunnerGetOutputTensor(add_runner, "output_0");
ASSERT_EQ(TfLiteSignatureRunnerGetOutputTensor(add_runner, "foo"), nullptr);
ASSERT_NE(add_input, nullptr);
ASSERT_NE(add_output, nullptr);
add_input->data.f[0] = 2;
add_input->data.f[1] = 4;
ASSERT_EQ(TfLiteSignatureRunnerInvoke(add_runner), kTfLiteOk);
ASSERT_EQ(add_output->data.f[0], 4);
ASSERT_EQ(add_output->data.f[1], 6);
// Test out-of-range values.
ASSERT_EQ(TfLiteSignatureRunnerGetInputName(add_runner, 1), nullptr);
ASSERT_EQ(TfLiteSignatureRunnerGetInputName(add_runner, -1), nullptr);
ASSERT_EQ(TfLiteSignatureRunnerGetOutputName(add_runner, 1), nullptr);
ASSERT_EQ(TfLiteSignatureRunnerGetOutputName(add_runner, -1), nullptr);
TfLiteSignatureRunnerDelete(add_runner);
TfLiteSignatureRunner* sub_runner =
TfLiteInterpreterGetSignatureRunner(interpreter, "sub");
ASSERT_NE(sub_runner, nullptr);
std::vector<const char*> input_names2;
for (int i = 0; i < TfLiteSignatureRunnerGetInputCount(sub_runner); i++) {
input_names2.push_back(TfLiteSignatureRunnerGetInputName(sub_runner, i));
}
std::vector<const char*> output_names2;
for (int i = 0; i < TfLiteSignatureRunnerGetOutputCount(sub_runner); i++) {
output_names2.push_back(TfLiteSignatureRunnerGetOutputName(sub_runner, i));
}
ASSERT_EQ(input_names2.size(), 1);
ASSERT_EQ(std::string(input_names2[0]), "x");
ASSERT_EQ(output_names2.size(), 1);
ASSERT_EQ(std::string(output_names2[0]), "output_0");
std::array<int, 1> sub_runner_input_dims{3};
ASSERT_EQ(TfLiteSignatureRunnerResizeInputTensor(
sub_runner, "x", sub_runner_input_dims.data(),
sub_runner_input_dims.size()),
kTfLiteOk);
ASSERT_EQ(TfLiteSignatureRunnerAllocateTensors(sub_runner), kTfLiteOk);
TfLiteTensor* sub_input =
TfLiteSignatureRunnerGetInputTensor(sub_runner, "x");
ASSERT_EQ(TfLiteSignatureRunnerGetInputTensor(sub_runner, "foo"), nullptr);
const TfLiteTensor* sub_output =
TfLiteSignatureRunnerGetOutputTensor(sub_runner, "output_0");
ASSERT_EQ(TfLiteSignatureRunnerGetOutputTensor(sub_runner, "foo"), nullptr);
ASSERT_NE(sub_input, nullptr);
ASSERT_NE(sub_output, nullptr);
sub_input->data.f[0] = 2;
sub_input->data.f[1] = 4;
sub_input->data.f[2] = 6;
ASSERT_EQ(TfLiteSignatureRunnerInvoke(sub_runner), kTfLiteOk);
ASSERT_EQ(sub_output->data.f[0], -1);
ASSERT_EQ(sub_output->data.f[1], 1);
ASSERT_EQ(sub_output->data.f[2], 3);
TfLiteSignatureRunnerDelete(sub_runner);
TfLiteInterpreterDelete(interpreter);
TfLiteModelDelete(model);
}
} // namespace
} // namespace tflite
+26
View File
@@ -0,0 +1,26 @@
/* Copyright 2022 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_TYPES_H_
#define TENSORFLOW_LITE_C_C_API_TYPES_H_
/// \file
///
/// C API types for TensorFlow Lite.
///
/// For documentation, see tensorflow/lite/core/c/c_api_types.h
#include "tensorflow/lite/core/c/c_api_types.h"
#endif // TENSORFLOW_LITE_C_C_API_TYPES_H_
+441
View File
@@ -0,0 +1,441 @@
/* Copyright 2020 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.
==============================================================================*/
#include "tensorflow/lite/core/c/builtin_op_data.h"
#include "tensorflow/lite/core/c/c_api.h"
#include "tensorflow/lite/core/c/c_api_experimental.h"
#include "tensorflow/lite/core/c/c_api_opaque.h"
#include "tensorflow/lite/core/c/c_api_types.h"
#include "tensorflow/lite/core/c/common.h"
// This file exists just to verify that the above header files above can build,
// link, and run as "C" code.
#ifdef __cplusplus
#error "This file should be compiled as C code, not as C++."
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdbool.h>
static void CheckFailed(const char *expression, const char *filename,
int line_number) {
fprintf(stderr, "ERROR: CHECK failed: %s:%d: %s\n", filename, line_number,
expression);
fflush(stderr);
abort();
}
// We use an extra level of macro indirection here to ensure that the
// macro arguments get evaluated, so that in a call to CHECK(foo),
// the call to STRINGIZE(condition) in the definition of the CHECK
// macro results in the string "foo" rather than the string "condition".
#define STRINGIZE(expression) STRINGIZE2(expression)
#define STRINGIZE2(expression) #expression
// Like assert(), but not dependent on NDEBUG.
#define CHECK(condition) \
((condition) ? (void)0 \
: CheckFailed(STRINGIZE(condition), __FILE__, __LINE__))
#define ASSERT_EQ(expected, actual) CHECK((expected) == (actual))
#define ASSERT_NE(expected, actual) CHECK((expected) != (actual))
#define ASSERT_STREQ(expected, actual) \
ASSERT_EQ(0, strcmp((expected), (actual)))
// Test the TfLiteVersion function.
static void TestVersion(void) {
const char *version = TfLiteVersion();
printf("Version = %s\n", version);
CHECK(version[0] != '\0');
}
static void TestInferenceUsingSignature(void) {
TfLiteModel* model = TfLiteModelCreateFromFile(
"tensorflow/lite/testdata/multi_signatures.bin");
ASSERT_NE(model, NULL);
TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
ASSERT_NE(options, NULL);
TfLiteInterpreterOptionsSetNumThreads(options, 2);
TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);
ASSERT_NE(interpreter, NULL);
// The options can be deleted immediately after interpreter creation.
TfLiteInterpreterOptionsDelete(options);
// (optional) Validate signatures
ASSERT_EQ(TfLiteInterpreterGetSignatureCount(interpreter), 2);
ASSERT_STREQ(TfLiteInterpreterGetSignatureKey(interpreter, 0), "add");
ASSERT_STREQ(TfLiteInterpreterGetSignatureKey(interpreter, 1), "sub");
// Validate signature "add"
TfLiteSignatureRunner* add_runner =
TfLiteInterpreterGetSignatureRunner(interpreter, "add");
ASSERT_NE(add_runner, NULL);
ASSERT_EQ(TfLiteSignatureRunnerGetInputCount(add_runner), 1);
ASSERT_STREQ(TfLiteSignatureRunnerGetInputName(add_runner, 0), "x");
ASSERT_EQ(TfLiteSignatureRunnerGetOutputCount(add_runner), 1);
ASSERT_STREQ(TfLiteSignatureRunnerGetOutputName(add_runner, 0), "output_0");
// Resize signature "add" input tensor "x"
int input_dims[1] = {2};
ASSERT_EQ(
TfLiteSignatureRunnerResizeInputTensor(add_runner, "x", input_dims, 1),
kTfLiteOk);
// Allocate tensors for signature "add"
ASSERT_EQ(TfLiteSignatureRunnerAllocateTensors(add_runner), kTfLiteOk);
// Validate signature "add" input tensor "x"
TfLiteTensor* input_tensor =
TfLiteSignatureRunnerGetInputTensor(add_runner, "x");
ASSERT_NE(input_tensor, NULL);
ASSERT_EQ(TfLiteTensorType(input_tensor), kTfLiteFloat32);
ASSERT_EQ(TfLiteTensorNumDims(input_tensor), 1);
ASSERT_EQ(TfLiteTensorDim(input_tensor, 0), 2);
ASSERT_EQ(TfLiteTensorByteSize(input_tensor), sizeof(float) * 2);
ASSERT_NE(TfLiteTensorData(input_tensor), NULL);
TfLiteQuantizationParams input_params =
TfLiteTensorQuantizationParams(input_tensor);
ASSERT_EQ(input_params.scale, 0.f);
ASSERT_EQ(input_params.zero_point, 0);
float input[2] = {2.f, 4.f};
ASSERT_EQ(TfLiteTensorCopyFromBuffer(input_tensor, input, 2 * sizeof(float)),
kTfLiteOk);
ASSERT_EQ(TfLiteSignatureRunnerInvoke(add_runner), kTfLiteOk);
const TfLiteTensor* output_tensor =
TfLiteSignatureRunnerGetOutputTensor(add_runner, "output_0");
ASSERT_NE(output_tensor, NULL);
ASSERT_EQ(TfLiteTensorType(output_tensor), kTfLiteFloat32);
ASSERT_EQ(TfLiteTensorNumDims(output_tensor), 1);
ASSERT_EQ(TfLiteTensorDim(output_tensor, 0), 2);
ASSERT_EQ(TfLiteTensorByteSize(output_tensor), sizeof(float) * 2);
ASSERT_NE(TfLiteTensorData(output_tensor), NULL);
TfLiteQuantizationParams output_params =
TfLiteTensorQuantizationParams(output_tensor);
ASSERT_EQ(output_params.scale, 0.f);
ASSERT_EQ(output_params.zero_point, 0);
float output[2];
ASSERT_EQ(TfLiteTensorCopyToBuffer(output_tensor, output, 2 * sizeof(float)),
kTfLiteOk);
// Verify the result
ASSERT_EQ(output[0], input[0] + 2.f);
ASSERT_EQ(output[1], input[1] + 2.f);
// The signature runner should be deleted before interpreter deletion.
TfLiteSignatureRunnerDelete(add_runner);
TfLiteInterpreterDelete(interpreter);
// The model should only be deleted after destroying the interpreter.
TfLiteModelDelete(model);
}
// This test checks if resizing the input (decreasing or increasing it's size)
// would invalidate input/output tensors.
static void TestRepeatResizeInputTensor(void) {
TfLiteModel* model = TfLiteModelCreateFromFile(
"tensorflow/lite/testdata/multi_signatures.bin");
ASSERT_NE(model, NULL);
TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
ASSERT_NE(options, NULL);
TfLiteInterpreterOptionsSetNumThreads(options, 2);
TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);
ASSERT_NE(interpreter, NULL);
TfLiteInterpreterOptionsDelete(options);
ASSERT_EQ(TfLiteInterpreterGetSignatureCount(interpreter), 2);
ASSERT_STREQ(TfLiteInterpreterGetSignatureKey(interpreter, 0), "add");
ASSERT_STREQ(TfLiteInterpreterGetSignatureKey(interpreter, 1), "sub");
TfLiteSignatureRunner* add_runner =
TfLiteInterpreterGetSignatureRunner(interpreter, "add");
ASSERT_NE(add_runner, NULL);
ASSERT_EQ(TfLiteSignatureRunnerGetInputCount(add_runner), 1);
ASSERT_STREQ(TfLiteSignatureRunnerGetInputName(add_runner, 0), "x");
ASSERT_EQ(TfLiteSignatureRunnerGetOutputCount(add_runner), 1);
ASSERT_STREQ(TfLiteSignatureRunnerGetOutputName(add_runner, 0), "output_0");
TfLiteTensor* input_tensor =
TfLiteSignatureRunnerGetInputTensor(add_runner, "x");
const TfLiteTensor* output_tensor =
TfLiteSignatureRunnerGetOutputTensor(add_runner, "output_0");
// For different input sizes, resize the input/output tensors and check if
// inferences runs as expected.
int sizes[] = {3, 1, 5};
float inputs_1[] = {3.f, 6.f, 11.f};
float inputs_2[] = {4.f};
float inputs_3[] = {5.f, 8.f, 11.f, 12.f, 20.f};
float* all_inputs[] = {inputs_1, inputs_2, inputs_3};
float actual_outputs1[] = {0.f, 0.f, 0.f};
float actual_outputs2[] = {0.f};
float actual_outputs3[] = {0.f, 0.f, 0.f, 0.f, 0.f};
float* all_actual_outputs[] = {actual_outputs1, actual_outputs2,
actual_outputs3};
for (int i = 0; i < 3; i++) {
int input_dims[] = {sizes[i]};
float* inputs = all_inputs[i];
ASSERT_EQ(
TfLiteSignatureRunnerResizeInputTensor(add_runner, "x", input_dims, 1),
kTfLiteOk);
ASSERT_EQ(TfLiteSignatureRunnerAllocateTensors(add_runner), kTfLiteOk);
ASSERT_NE(input_tensor, NULL);
ASSERT_EQ(TfLiteTensorType(input_tensor), kTfLiteFloat32);
ASSERT_EQ(TfLiteTensorNumDims(input_tensor), 1);
ASSERT_EQ(TfLiteTensorDim(input_tensor, 0), sizes[i]);
ASSERT_EQ(TfLiteTensorByteSize(input_tensor), sizes[i] * sizeof(float));
ASSERT_NE(TfLiteTensorData(input_tensor), NULL);
ASSERT_EQ(TfLiteTensorCopyFromBuffer(input_tensor, inputs,
sizes[i] * sizeof(float)),
kTfLiteOk);
ASSERT_EQ(TfLiteSignatureRunnerInvoke(add_runner), kTfLiteOk);
ASSERT_NE(output_tensor, NULL);
ASSERT_EQ(TfLiteTensorType(output_tensor), kTfLiteFloat32);
ASSERT_EQ(TfLiteTensorNumDims(output_tensor), 1);
ASSERT_EQ(TfLiteTensorDim(output_tensor, 0), sizes[i]);
ASSERT_EQ(TfLiteTensorByteSize(output_tensor), sizes[i] * sizeof(float));
ASSERT_NE(TfLiteTensorData(output_tensor), NULL);
float* actual_outputs = all_actual_outputs[i];
ASSERT_EQ(TfLiteTensorCopyToBuffer(output_tensor, actual_outputs,
sizes[i] * sizeof(float)),
kTfLiteOk);
for (int j = 0; j < sizes[i]; j++) {
ASSERT_EQ(actual_outputs[j], inputs[j] + 2);
}
}
TfLiteSignatureRunnerDelete(add_runner);
TfLiteInterpreterDelete(interpreter);
TfLiteModelDelete(model);
}
static void TestInferenceUsingInterpreter(void) {
TfLiteModel* model =
TfLiteModelCreateFromFile("tensorflow/lite/testdata/add.bin");
ASSERT_NE(model, NULL);
TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
ASSERT_NE(options, NULL);
TfLiteInterpreterOptionsSetNumThreads(options, 2);
TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);
ASSERT_NE(interpreter, NULL);
// The options can be deleted immediately after interpreter creation.
TfLiteInterpreterOptionsDelete(options);
ASSERT_EQ(TfLiteInterpreterAllocateTensors(interpreter), kTfLiteOk);
ASSERT_EQ(TfLiteInterpreterGetInputTensorCount(interpreter), 1);
ASSERT_EQ(TfLiteInterpreterGetOutputTensorCount(interpreter), 1);
int input_dims[1] = {2};
ASSERT_EQ(TfLiteInterpreterResizeInputTensor(interpreter, 0, input_dims, 1),
kTfLiteOk);
ASSERT_EQ(TfLiteInterpreterAllocateTensors(interpreter), kTfLiteOk);
TfLiteTensor* input_tensor = TfLiteInterpreterGetInputTensor(interpreter, 0);
ASSERT_NE(input_tensor, NULL);
ASSERT_EQ(TfLiteTensorType(input_tensor), kTfLiteFloat32);
ASSERT_EQ(TfLiteTensorNumDims(input_tensor), 1);
ASSERT_EQ(TfLiteTensorDim(input_tensor, 0), 2);
ASSERT_EQ(TfLiteTensorByteSize(input_tensor), sizeof(float) * 2);
ASSERT_NE(TfLiteTensorData(input_tensor), NULL);
ASSERT_STREQ(TfLiteTensorName(input_tensor), "input");
TfLiteQuantizationParams input_params =
TfLiteTensorQuantizationParams(input_tensor);
ASSERT_EQ(input_params.scale, 0.f);
ASSERT_EQ(input_params.zero_point, 0);
float input[2] = {1.f, 3.f};
ASSERT_EQ(TfLiteTensorCopyFromBuffer(input_tensor, input, 2 * sizeof(float)),
kTfLiteOk);
ASSERT_EQ(TfLiteInterpreterInvoke(interpreter), kTfLiteOk);
const TfLiteTensor* output_tensor =
TfLiteInterpreterGetOutputTensor(interpreter, 0);
ASSERT_NE(output_tensor, NULL);
ASSERT_EQ(TfLiteTensorType(output_tensor), kTfLiteFloat32);
ASSERT_EQ(TfLiteTensorNumDims(output_tensor), 1);
ASSERT_EQ(TfLiteTensorDim(output_tensor, 0), 2);
ASSERT_EQ(TfLiteTensorByteSize(output_tensor), sizeof(float) * 2);
ASSERT_NE(TfLiteTensorData(output_tensor), NULL);
ASSERT_STREQ(TfLiteTensorName(output_tensor), "output");
TfLiteQuantizationParams output_params =
TfLiteTensorQuantizationParams(output_tensor);
ASSERT_EQ(output_params.scale, 0.f);
ASSERT_EQ(output_params.zero_point, 0);
float output[2];
ASSERT_EQ(TfLiteTensorCopyToBuffer(output_tensor, output, 2 * sizeof(float)),
kTfLiteOk);
ASSERT_EQ(output[0], 3.f);
ASSERT_EQ(output[1], 9.f);
TfLiteInterpreterDelete(interpreter);
// The model should only be deleted after destroying the interpreter.
TfLiteModelDelete(model);
}
TfLiteStatus PrepareThatChecksExecutionPlanSizeEqualsTwo(
TfLiteOpaqueContext* context,
TfLiteOpaqueDelegate* opaque_delegate, void* data) {
bool* delegate_prepared = (bool*)data;
*delegate_prepared = true;
TfLiteIntArray* execution_plan;
ASSERT_EQ(kTfLiteOk,
TfLiteOpaqueContextGetExecutionPlan(context, &execution_plan));
ASSERT_EQ(2, execution_plan->size);
return kTfLiteOk;
}
static void TestTfLiteOpaqueContextGetExecutionPlan(void) {
TfLiteModel* model =
TfLiteModelCreateFromFile("tensorflow/lite/testdata/add.bin");
// Create and install a delegate instance.
bool delegate_prepared = false;
TfLiteOpaqueDelegateBuilder opaque_delegate_builder = { NULL };
opaque_delegate_builder.data = &delegate_prepared;
opaque_delegate_builder.Prepare = PrepareThatChecksExecutionPlanSizeEqualsTwo;
TfLiteOpaqueDelegate* opaque_delegate =
TfLiteOpaqueDelegateCreate(&opaque_delegate_builder);
TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
TfLiteInterpreterOptionsAddDelegate(options, opaque_delegate);
TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);
// The delegate should have been applied.
CHECK(delegate_prepared);
TfLiteInterpreterOptionsDelete(options);
TfLiteInterpreterDelete(interpreter);
TfLiteModelDelete(model);
TfLiteOpaqueDelegateDelete(opaque_delegate);
}
static void TestTfLiteOpaqueContextReportErrorMacros(
TfLiteStatus (*Prepare)(TfLiteOpaqueContext* context,
TfLiteOpaqueDelegate* delegate, void* data)) {
TfLiteModel* model =
TfLiteModelCreateFromFile("tensorflow/lite/testdata/add.bin");
// Create and install a delegate instance.
bool delegate_prepared_called = false;
TfLiteOpaqueDelegateBuilder opaque_delegate_builder = { NULL };
opaque_delegate_builder.data = &delegate_prepared_called;
opaque_delegate_builder.Prepare = Prepare;
TfLiteOpaqueDelegate* opaque_delegate =
TfLiteOpaqueDelegateCreate(&opaque_delegate_builder);
TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
TfLiteInterpreterOptionsAddDelegate(options, opaque_delegate);
TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);
// The delegate's prepare function should have been called, even though it
// returned an error code.
CHECK(delegate_prepared_called);
TfLiteInterpreterOptionsDelete(options);
TfLiteInterpreterDelete(interpreter);
TfLiteModelDelete(model);
TfLiteOpaqueDelegateDelete(opaque_delegate);
}
TfLiteStatus TfLiteOpaqueContextReportErrorMacros_EnsureMsg_Prepare(
TfLiteOpaqueContext* context,
TfLiteOpaqueDelegate* opaque_delegate, void* data) {
bool* delegate_prepared = (bool*) data;
*delegate_prepared = true;
TF_LITE_OPAQUE_ENSURE_MSG(context, false, "false was not true!!!");
return kTfLiteOk;
}
TfLiteStatus TfLiteOpaqueContextReportErrorMacros_Ensure_Prepare(
TfLiteOpaqueContext* context,
TfLiteOpaqueDelegate* opaque_delegate, void* data) {
bool* delegate_prepared = (bool*) data;
*delegate_prepared = true;
TF_LITE_OPAQUE_ENSURE(context, false);
return kTfLiteOk;
}
TfLiteStatus TfLiteOpaqueContextReportErrorMacros_EnsureEq_Prepare(
TfLiteOpaqueContext* context,
TfLiteOpaqueDelegate* opaque_delegate, void* data) {
bool* delegate_prepared = (bool*) data;
*delegate_prepared = true;
TF_LITE_OPAQUE_ENSURE_EQ(context, 1, 2);
return kTfLiteOk;
}
TfLiteStatus TfLiteOpaqueContextReportErrorMacros_EnsureTypesEq_Prepare(
TfLiteOpaqueContext* context,
TfLiteOpaqueDelegate* opaque_delegate, void* data) {
bool* delegate_prepared = (bool*) data;
*delegate_prepared = true;
TF_LITE_OPAQUE_ENSURE_TYPES_EQ(context, '1', 2);
return kTfLiteOk;
}
TfLiteStatus TfLiteOpaqueContextReportErrorMacros_EnsureNear_Prepare(
TfLiteOpaqueContext* context,
TfLiteOpaqueDelegate* opaque_delegate, void* data) {
bool* delegate_prepared = (bool*) data;
*delegate_prepared = true;
TF_LITE_OPAQUE_ENSURE_NEAR(context, 3, 10, 1);
return kTfLiteOk;
}
static void RunTests(void) {
TestVersion();
TestInferenceUsingSignature();
TestRepeatResizeInputTensor();
TestInferenceUsingInterpreter();
TestTfLiteOpaqueContextGetExecutionPlan();
TestTfLiteOpaqueContextReportErrorMacros(
TfLiteOpaqueContextReportErrorMacros_Ensure_Prepare);
TestTfLiteOpaqueContextReportErrorMacros(
TfLiteOpaqueContextReportErrorMacros_EnsureMsg_Prepare);
TestTfLiteOpaqueContextReportErrorMacros(
TfLiteOpaqueContextReportErrorMacros_EnsureEq_Prepare);
TestTfLiteOpaqueContextReportErrorMacros(
TfLiteOpaqueContextReportErrorMacros_EnsureTypesEq_Prepare);
TestTfLiteOpaqueContextReportErrorMacros(
TfLiteOpaqueContextReportErrorMacros_EnsureNear_Prepare);
}
int main(void) {
RunTests();
return 0;
}
+33
View File
@@ -0,0 +1,33 @@
/* Copyright 2019 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.
==============================================================================*/
/// \file
///
/// This file defines common C types and APIs for implementing operations,
/// delegates and other constructs in TensorFlow Lite. The actual operations and
/// delegates can be defined using C++, but the interface between the
/// interpreter and the operations are C.
///
/// For documentation, see tensorflow/lite/core/c/common.h.
///
/// See also c_api_opaque.h which has more ABI-stable variants of some of these
/// APIs.
#ifndef TENSORFLOW_LITE_C_COMMON_H_
#define TENSORFLOW_LITE_C_COMMON_H_
#include "tensorflow/lite/core/c/common.h"
#endif // TENSORFLOW_LITE_C_COMMON_H_
+98
View File
@@ -0,0 +1,98 @@
/* Copyright 2022 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.
==============================================================================*/
#include "tensorflow/lite/c/common_internal.h"
#include <cstdint>
#include "tensorflow/lite/core/c/c_api_types.h"
#include "tensorflow/lite/core/c/common.h"
bool TfLiteDelegateIsOpaque(const TfLiteDelegate* delegate) {
return delegate != nullptr && delegate->Prepare == nullptr &&
delegate->CopyFromBufferHandle == nullptr &&
delegate->FreeBufferHandle == nullptr &&
delegate->opaque_delegate_builder != nullptr;
}
TfLiteStatus TfLiteDelegatePrepareInternal(TfLiteContext* context,
TfLiteDelegate* delegate) {
TfLiteStatus status = kTfLiteOk;
// The following casts are safe only because this code is part of the
// TF Lite runtime implementation. Apps using TF Lite should not rely on
// TfLiteOpaqueContext and TfLiteContext being equivalent, or on
// TfLiteOpaqueDelegate and TfLiteDelegate being equivalent.
if (TfLiteDelegateIsOpaque(delegate) &&
delegate->opaque_delegate_builder->Prepare) {
status = delegate->opaque_delegate_builder->Prepare(
reinterpret_cast<TfLiteOpaqueContext*>(context),
reinterpret_cast<TfLiteOpaqueDelegate*>(delegate),
delegate->opaque_delegate_builder->data);
} else {
status = delegate->Prepare(context, delegate);
}
return status;
}
TfLiteStatus TfLiteDelegateCopyFromBufferHandleInternal(
TfLiteContext* context, TfLiteDelegate* delegate,
TfLiteBufferHandle buffer_handle, TfLiteTensor* tensor) {
// The following casts are safe only because this code is part of the
// TF Lite runtime implementation. Apps using TF Lite should not rely on
// TfLiteOpaqueContext and TfLiteContext being equivalent, or on
// TfLiteOpaqueDelegate and TfLiteDelegate being equivalent.
if (TfLiteDelegateIsOpaque(delegate) &&
delegate->opaque_delegate_builder->CopyFromBufferHandle) {
return delegate->opaque_delegate_builder->CopyFromBufferHandle(
reinterpret_cast<TfLiteOpaqueContext*>(context),
reinterpret_cast<TfLiteOpaqueDelegate*>(delegate),
delegate->opaque_delegate_builder->data, tensor->buffer_handle,
reinterpret_cast<TfLiteOpaqueTensor*>(tensor));
} else {
TF_LITE_ENSURE(context, delegate->CopyFromBufferHandle != nullptr);
return delegate->CopyFromBufferHandle(context, delegate,
tensor->buffer_handle, tensor);
}
}
TfLiteStatus TfLiteDelegateFreeBufferHandleInternal(
TfLiteContext* context, TfLiteDelegate* delegate,
TfLiteBufferHandle* buffer_handle) {
// The following casts are safe only because this code is part of the
// TF Lite runtime implementation. Apps using TF Lite should not rely on
// TfLiteOpaqueContext and TfLiteContext being equivalent, or on
// TfLiteOpaqueDelegate and TfLiteDelegate being equivalent.
if (TfLiteDelegateIsOpaque(delegate) &&
delegate->opaque_delegate_builder->FreeBufferHandle) {
delegate->opaque_delegate_builder->FreeBufferHandle(
reinterpret_cast<TfLiteOpaqueContext*>(context),
reinterpret_cast<TfLiteOpaqueDelegate*>(delegate),
delegate->opaque_delegate_builder->data, buffer_handle);
return kTfLiteOk;
} else if (delegate->FreeBufferHandle != nullptr) {
delegate->FreeBufferHandle(context, delegate, buffer_handle);
return kTfLiteOk;
}
// We failed to free the buffer handle.
return kTfLiteError;
}
int64_t TfLiteDelegateGetFlagsInternal(TfLiteDelegate* delegate) {
if (TfLiteDelegateIsOpaque(delegate)) {
return delegate->opaque_delegate_builder->flags;
}
return delegate->flags;
}
+148
View File
@@ -0,0 +1,148 @@
/* Copyright 2022 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_COMMON_INTERNAL_H_
#define TENSORFLOW_LITE_C_COMMON_INTERNAL_H_
#include <stddef.h>
#include <stdint.h>
#include "tensorflow/lite/core/c/c_api_types.h"
#include "tensorflow/lite/core/c/common.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.
// `TfLiteOperator` is an external version of `TfLiteRegistration`
// for C API which doesn't use internal types (such as `TfLiteContext`) but only
// uses stable API types (such as `TfLiteOpaqueContext`). The purpose of each
// field is the exactly the same as with `TfLiteRegistration`.
typedef struct TfLiteOperator {
// Custom op name. This should be non-null iff the op is a custom op,
// i.e. iff builtin_code is kTfLiteBuiltinCustom.
const char* custom_name;
// The version of the op. The version should be higher than 0.
int version;
// Initializes the op from serialized data.
void* (*init)(TfLiteOpaqueContext* context, const char* buffer,
size_t length);
// Deallocates the op.
// The pointer `buffer` is the data previously returned by an init invocation.
void (*free)(TfLiteOpaqueContext* context, void* buffer);
// Called when the inputs that this node depends on have been resized.
TfLiteStatus (*prepare)(TfLiteOpaqueContext* context, TfLiteOpaqueNode* node);
// Called when the node is executed. (Should read node inputs and write to
// node outputs).
TfLiteStatus (*invoke)(TfLiteOpaqueContext* context, TfLiteOpaqueNode* node);
// Retrieves the async kernel. The functor is nullptr if the node / backend
// does not support asynchronous execution.
struct TfLiteAsyncKernel* (*async_kernel)(TfLiteOpaqueContext* context,
TfLiteOpaqueNode* node);
// Builtin op code.
// The values stored in this field should be enum constants from the
// TfLiteBuiltinOperator enum.
// For custom ops, this should be the value kTfLiteBuiltinCustom.
int32_t builtin_code;
// The default value of this field is supposed to be '-1'.
// The default value indicates to the TF Lite runtime that this registration
// should be used through its callbacks, i.e. 'init', 'free' etc.
//
// This would be the case when a delegate implementation supplies an opaque
// delegate kernel to the runtime to claim the execution for a subset of
// nodes. This would also be the case when an application defines a custom OP.
//
// However, users might also iterate over the execution plan to visit the
// nodes and registrations associated with an opaque context. In this
// scenario, due to ABI stability reasons, we provide them with a registration
// external object, that internally delegates execution to a corresponding
// regular TfLiteRegistration. In such a case the 'node_index' field should
// store the index of that corresponding node (and registration).
int node_index;
// Indicates if an operator's output can safely overwrite its input.
// See the comments in `TfLiteInPlaceOp`.
uint64_t inplace_operator;
// Data supplied by the user in the `TfLiteOperatorCreate` call and then
// returned back to the user in the `TfLiteOperator` callbacks listed below.
// The user is expected to manage the memory pointed by this field and the
// lifetime of that memory should extend at least from the call to
// `TfLiteOperatorCreate` to the invocation of the callback set with
// `TfLiteOperatorSetFreeWithData`.
void* user_data;
// The following callbacks can be set with the `TfLiteOperatorSetXXXWithData`
// functions and if, so set, will pass back the value of the user_data field
// above as first argument.
//
// TODO(b/339641079): Remove the legacy callbacks listed above and rename
// these below without the `_with_data` suffix.
void* (*init_with_data)(void* user_data, TfLiteOpaqueContext* context,
const char* buffer, size_t length);
void (*free_with_data)(void* user_data, TfLiteOpaqueContext* context,
void* buffer);
TfLiteStatus (*prepare_with_data)(void* user_data,
TfLiteOpaqueContext* context,
TfLiteOpaqueNode* node);
TfLiteStatus (*invoke_with_data)(void* user_data,
TfLiteOpaqueContext* context,
TfLiteOpaqueNode* node);
struct TfLiteAsyncKernel* (*async_kernel_with_data)(
void* user_data, TfLiteOpaqueContext* context, TfLiteOpaqueNode* node);
} TfLiteOperator;
// Returns true iff the delegate is a well-formed opaque delegate, i.e. none of
// the fields that are part of the legacy 'TfLiteDelegate' interface are set.
bool TfLiteDelegateIsOpaque(const TfLiteDelegate* delegate);
// Invokes 'Prepare' on the provided 'delegate', giving the 'delegate' a view
// of the current graph through the provided 'context'. Returns the delegate's
// 'Prepare' return value.
TfLiteStatus TfLiteDelegatePrepareInternal(TfLiteContext* context,
TfLiteDelegate* delegate);
// Invokes 'CopyFromBufferHandle' on the provided 'delegate', supplying the
// provided 'buffer_handle' and 'tensor' as arguments. The provided
// 'buffer_handle' must have a non-null buffer handle value (i.e., not
// 'kTfLiteNullBufferHandle'). Returns the delegate's 'CopyFromBufferHandle'
// return value.
TfLiteStatus TfLiteDelegateCopyFromBufferHandleInternal(
TfLiteContext* context, TfLiteDelegate* delegate,
TfLiteBufferHandle buffer_handle, TfLiteTensor* tensor);
// Invokes 'FreeBufferHandle' on the provided 'delegate', supplying the provided
// 'buffer_handle' as an argument. The '*buffer_handle' must have a non-null
// buffer handle value (i.e., not 'kTfLiteNullBufferHandle'). Returns
// 'kTfLiteOk' if 'FreeBufferHandle' was called, or 'kTfLiteError' if the
// callback is not available.
TfLiteStatus TfLiteDelegateFreeBufferHandleInternal(
TfLiteContext* context, TfLiteDelegate* delegate,
TfLiteBufferHandle* buffer_handle);
// Returns the 'delegate' flags value. Note, if the delegate contains a valid
// opaque_delegate_builder field, then the flags of the delegate external are
// returned. Otherwise, the flags field inside `TfLiteDelegate` is returned.
int64_t TfLiteDelegateGetFlagsInternal(TfLiteDelegate* delegate);
#endif // TENSORFLOW_LITE_C_COMMON_INTERNAL_H_
+1
View File
@@ -0,0 +1 @@
_TfLite*
+22
View File
@@ -0,0 +1,22 @@
load("//tensorflow/lite:special_rules.bzl", "tflite_portable_test_suite")
load("//tensorflow/lite/core/shims:cc_library_with_tflite.bzl", "cc_library_with_tflite_with_c_headers_test")
package(
# copybara:uncomment default_applicable_licenses = ["//tensorflow:LICENSE"],
licenses = ["notice"],
)
#------------------------------------------------------------------------------
# Utilities for use in JNI Bindings (e.g. Java API and Java Tasks library).
cc_library_with_tflite_with_c_headers_test(
name = "jni_utils",
srcs = ["jni_utils.cc"],
hdrs = ["jni_utils.h"],
visibility = ["//visibility:public"],
deps = [
"//tensorflow/lite/java/jni",
],
)
tflite_portable_test_suite()
+20
View File
@@ -0,0 +1,20 @@
/* Copyright 2021 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.
==============================================================================*/
#include "tensorflow/lite/c/jni/jni_utils.h"
bool TfLiteCheckInitializedOrThrow(JNIEnv* env) {
// No additional initialization is required.
return true;
}
+39
View File
@@ -0,0 +1,39 @@
/* Copyright 2021 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_JNI_JNI_UTILS_H_
#define TENSORFLOW_LITE_JNI_JNI_UTILS_H_
#include <jni.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/// Checks whether the TFLite API has been initialized, throwing a Java exception
/// otherwise.
///
/// @param env The JNIEnv for the current thread (which has to be attached to the
/// JVM).
/// @return Whether or not the TFLite API has been initialized. If this method
/// returns false, no other JNI method should be called until the pending
/// exception has been handled (typically by returning to Java).
bool TfLiteCheckInitializedOrThrow(JNIEnv* env);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // TENSORFLOW_LITE_JNI_JNI_UTILS_H_
+19
View File
@@ -0,0 +1,19 @@
/* Copyright 2020 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.
==============================================================================*/
#include "tensorflow/lite/c/test_util.h"
int TfLiteInitializeShimsForTest() {
return 0;
}
+32
View File
@@ -0,0 +1,32 @@
/* Copyright 2020 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_TEST_UTIL_H_
#define TENSORFLOW_LITE_C_TEST_UTIL_H_
#ifdef __cplusplus
extern "C" {
#endif
// Initialize TF Lite shims, in a manner appropriate for running unit tests.
// Returns zero on success, or an implementation-defined error code on failure.
// This should be called before calling any other shims functions or methods
// in unit tests.
int TfLiteInitializeShimsForTest(void);
#ifdef __cplusplus
}
#endif
#endif // TENSORFLOW_LITE_C_TEST_UTIL_H_
+9
View File
@@ -0,0 +1,9 @@
VERS_1.0 {
# Export symbols in c_api.h.
global:
TfLite*;
# Hide everything else.
local:
*;
};