From 15be9fd14320918c92e41949351d7af6d29c5f60 Mon Sep 17 00:00:00 2001 From: Jordan Date: Tue, 27 Oct 2026 12:19:13 -0600 Subject: [PATCH 1/2] fix(linux): keep flutter_onnxruntime off Linux so the app starts again The phone-only onnxruntime plugin also built for Linux and linked relic_app against libonnxruntime.so.1. The bundle shipped only lib/libonnxruntime.so, a symlink to that missing file, so 1.0.60 to 1.0.64 (tarball and AppImage) died at launch on any machine without ONNX Runtime 1.22 installed. Only mobile.dart uses the plugin; the desktop embeds through relic-sift. Drop the Linux platform from the vendored copy, as was done for macOS, and make build_release_linux.sh refuse to pack a bundle with a dangling symlink or a library ldd cannot find. App 1.0.65. Co-Authored-By: Claude Opus 5.5 --- .../flutter/generated_plugin_registrant.cc | 4 - app/linux/flutter/generated_plugins.cmake | 1 - app/pubspec.yaml | 19 +- app/scripts/build_release_linux.sh | 14 + .../flutter_onnxruntime/linux/CMakeLists.txt | 308 ------ .../include/flutter_onnxruntime/export.h | 16 - .../flutter_onnxruntime_plugin.h | 31 - .../linux/src/flutter_onnxruntime_plugin.cc | 900 ------------------ .../linux/src/session_manager.cc | 401 -------- .../linux/src/session_manager.h | 99 -- .../linux/src/tensor_manager.cc | 848 ----------------- .../linux/src/tensor_manager.h | 125 --- .../linux/src/value_conversion.cc | 96 -- .../linux/src/value_conversion.h | 42 - app/vendor/flutter_onnxruntime/pubspec.yaml | 2 - 15 files changed, 25 insertions(+), 2881 deletions(-) delete mode 100644 app/vendor/flutter_onnxruntime/linux/CMakeLists.txt delete mode 100644 app/vendor/flutter_onnxruntime/linux/include/flutter_onnxruntime/export.h delete mode 100644 app/vendor/flutter_onnxruntime/linux/include/flutter_onnxruntime/flutter_onnxruntime_plugin.h delete mode 100644 app/vendor/flutter_onnxruntime/linux/src/flutter_onnxruntime_plugin.cc delete mode 100644 app/vendor/flutter_onnxruntime/linux/src/session_manager.cc delete mode 100644 app/vendor/flutter_onnxruntime/linux/src/session_manager.h delete mode 100644 app/vendor/flutter_onnxruntime/linux/src/tensor_manager.cc delete mode 100644 app/vendor/flutter_onnxruntime/linux/src/tensor_manager.h delete mode 100644 app/vendor/flutter_onnxruntime/linux/src/value_conversion.cc delete mode 100644 app/vendor/flutter_onnxruntime/linux/src/value_conversion.h diff --git a/app/linux/flutter/generated_plugin_registrant.cc b/app/linux/flutter/generated_plugin_registrant.cc index 30dec38..44e9b70 100644 --- a/app/linux/flutter/generated_plugin_registrant.cc +++ b/app/linux/flutter/generated_plugin_registrant.cc @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -33,9 +32,6 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) file_saver_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FileSaverPlugin"); file_saver_plugin_register_with_registrar(file_saver_registrar); - g_autoptr(FlPluginRegistrar) flutter_onnxruntime_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterOnnxruntimePlugin"); - flutter_onnxruntime_plugin_register_with_registrar(flutter_onnxruntime_registrar); g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); diff --git a/app/linux/flutter/generated_plugins.cmake b/app/linux/flutter/generated_plugins.cmake index 42c31e8..ea1b404 100644 --- a/app/linux/flutter/generated_plugins.cmake +++ b/app/linux/flutter/generated_plugins.cmake @@ -6,7 +6,6 @@ list(APPEND FLUTTER_PLUGIN_LIST clipboard_watcher desktop_webview_window file_saver - flutter_onnxruntime flutter_secure_storage_linux gtk hotkey_manager_linux diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 51968e0..a364439 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.64+82 +version: 1.0.65+83 environment: sdk: ^3.12.2 @@ -85,13 +85,16 @@ dependencies: # Wi-Fi gate for the 330 MB model download (data/wifi_watch.dart). connectivity_plus: ^7.3.2 # flutter_onnxruntime is served from app/vendor: the pub.dev copy, minus its -# macOS platform. Only mobile.dart uses it (the phone's query encoder); the -# desktop embeds through relic-sift. Its macOS Swift package requires macOS -# 14, and Relic's Mac floor is 11, so the macOS build fails with the pub -# copy. The vendored copy is byte-identical for the other platforms. To -# upgrade: copy the new pub version over app/vendor/flutter_onnxruntime, -# drop its macos/ folder and the macos: entry under flutter.plugin.platforms, -# and bump the constraint above. +# macOS and Linux platforms. Only mobile.dart uses it (the phone's query +# encoder); the desktop embeds through relic-sift. Its macOS Swift package +# requires macOS 14, and Relic's Mac floor is 11, so the macOS build fails +# with the pub copy. On Linux the plugin linked relic_app against +# libonnxruntime.so.1, which the bundle shipped only as a dangling symlink, +# so 1.0.60 to 1.0.64 would not start on a machine without ONNX Runtime 1.22 +# installed. The vendored copy is byte-identical for the other platforms. To +# upgrade: copy the new pub version over app/vendor/flutter_onnxruntime, drop +# its macos/ and linux/ folders and those entries under +# flutter.plugin.platforms, and bump the constraint above. dependency_overrides: flutter_onnxruntime: path: vendor/flutter_onnxruntime diff --git a/app/scripts/build_release_linux.sh b/app/scripts/build_release_linux.sh index bccaa48..dd1d4b6 100644 --- a/app/scripts/build_release_linux.sh +++ b/app/scripts/build_release_linux.sh @@ -142,6 +142,20 @@ Uninstall: delete this folder, then Your vault lives in ~/.local/share/relic — delete that too if you mean it. EOF +# Refuse to pack a bundle that cannot start. 1.0.60 to 1.0.64 shipped +# lib/libonnxruntime.so pointing at a file that was not there, and relic_app +# needed it, so the app died at launch on any machine without that library. +# The build machine's own libraries hide this, so check the bundle itself: +# no dangling symlinks, and every library the app and its plugins need either +# in the bundle or a normal system package. +echo "==> checking the bundle's libraries" +dangling=$(find "$STAGE" -xtype l) +[[ -z "$dangling" ]] || { echo "dangling symlinks in the bundle:" >&2; echo "$dangling" >&2; exit 1; } +missing=$(for f in "$STAGE/relic_app" "$STAGE"/lib/*.so; do + LD_LIBRARY_PATH="$STAGE/lib" ldd "$f" 2>/dev/null | grep 'not found' | grep -v 'libjvm.so' | sed "s|^|$(basename "$f"): |" +done) +[[ -z "$missing" ]] || { echo "libraries the bundle needs but does not have:" >&2; echo "$missing" >&2; exit 1; } + mkdir -p "$DIST" TARBALL="$DIST/relic-$VER-linux-x64.tar.gz" rm -f "$TARBALL" diff --git a/app/vendor/flutter_onnxruntime/linux/CMakeLists.txt b/app/vendor/flutter_onnxruntime/linux/CMakeLists.txt deleted file mode 100644 index b21af29..0000000 --- a/app/vendor/flutter_onnxruntime/linux/CMakeLists.txt +++ /dev/null @@ -1,308 +0,0 @@ -# The Flutter tooling requires that developers have CMake 3.10 or later installed. You should not increase this version, -# as doing so will cause the plugin to fail to compile for some customers of the plugin. -cmake_minimum_required(VERSION 3.10) - -# Set policy for FetchContent timestamp handling -if(POLICY CMP0135) - cmake_policy(SET CMP0135 NEW) -endif() - -# Project-level configuration. -set(PROJECT_NAME "flutter_onnxruntime") -project(${PROJECT_NAME} LANGUAGES CXX) - -# This value is used when generating builds using this plugin, so it must not be changed. -set(PLUGIN_NAME "flutter_onnxruntime_plugin") - -# === ONNX Runtime Configuration === -# Option 1: Use pre-installed ONNX Runtime (preferred for system packages) -option(USE_SYSTEM_ONNXRUNTIME "Use system-installed ONNX Runtime" ON) - -if(USE_SYSTEM_ONNXRUNTIME) - # Try to find ONNX Runtime using pkg-config - find_package(PkgConfig) - if(PkgConfig_FOUND) - pkg_check_modules(ONNXRUNTIME onnxruntime) - endif() - - # If pkg-config didn't find it, try to find it manually - if(NOT ONNXRUNTIME_FOUND) - # Specify custom paths where ONNX Runtime might be installed - set(ONNXRUNTIME_ROOT_DIR - "" - CACHE PATH "ONNX Runtime root directory") - - # Look for the library - find_library( - ONNXRUNTIME_LIBRARY - NAMES onnxruntime - PATHS ${ONNXRUNTIME_ROOT_DIR}/lib - DOC "ONNX Runtime library") - - # Look for the include directory - find_path( - ONNXRUNTIME_INCLUDE_DIR - NAMES onnxruntime_cxx_api.h - PATHS ${ONNXRUNTIME_ROOT_DIR}/include - DOC "ONNX Runtime include directory") - - if(ONNXRUNTIME_LIBRARY AND ONNXRUNTIME_INCLUDE_DIR) - set(ONNXRUNTIME_FOUND TRUE) - set(ONNXRUNTIME_LIBRARIES ${ONNXRUNTIME_LIBRARY}) - set(ONNXRUNTIME_INCLUDE_DIRS ${ONNXRUNTIME_INCLUDE_DIR}) - message(STATUS "Found ONNX Runtime: ${ONNXRUNTIME_LIBRARY}") - else() - set(ONNXRUNTIME_FOUND FALSE) - endif() - endif() - - if(NOT ONNXRUNTIME_FOUND) - message(STATUS "System ONNX Runtime not found. Falling back to downloaded version.") - set(USE_SYSTEM_ONNXRUNTIME OFF) - endif() -endif() - -# Option 2: Download ONNX Runtime if not using system installed version -if(NOT USE_SYSTEM_ONNXRUNTIME) - include(FetchContent) - - # Set ONNX Runtime version - make sure this is defined Only set if not already defined, to allow the parent project to - # override it - if(NOT DEFINED ONNXRUNTIME_VERSION) - set(ONNXRUNTIME_VERSION - "1.22.0" - CACHE STRING "ONNX Runtime version to use") - endif() - - # Check if version is not empty - if("${ONNXRUNTIME_VERSION}" STREQUAL "") - set(ONNXRUNTIME_VERSION "1.22.0") - message(STATUS "ONNX Runtime version was empty, defaulting to 1.22.0") - endif() - - # Debug output - message(STATUS "ONNX Runtime version set to: ${ONNXRUNTIME_VERSION}") - - # Determine platform and architecture for download URL - if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - set(ONNXRUNTIME_PLATFORM "linux") - if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") - set(ONNXRUNTIME_ARCH "x64") - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") - set(ONNXRUNTIME_ARCH "aarch64") - else() - message(FATAL_ERROR "Unsupported architecture: ${CMAKE_SYSTEM_PROCESSOR}") - endif() - else() - message(FATAL_ERROR "Unsupported platform: ${CMAKE_SYSTEM_NAME}") - endif() - - # Set download URL with correct naming pattern for 1.22.0 Make sure all parts of the version are included - message(STATUS "Using ONNX Runtime version: ${ONNXRUNTIME_VERSION}") - set(ONNXRUNTIME_URL - "https://github.com/microsoft/onnxruntime/releases/download/v${ONNXRUNTIME_VERSION}/onnxruntime-linux-${ONNXRUNTIME_ARCH}-${ONNXRUNTIME_VERSION}.tgz" - ) - - message(STATUS "Downloading ONNX Runtime from: ${ONNXRUNTIME_URL}") - - # Create a directory for the downloaded library - set(ONNXRUNTIME_DOWNLOAD_DIR "${CMAKE_CURRENT_BINARY_DIR}/onnxruntime") - - # Download and extract ONNX Runtime - using file(DOWNLOAD) for more direct control - if(NOT - EXISTS - "${ONNXRUNTIME_DOWNLOAD_DIR}/onnxruntime-linux-${ONNXRUNTIME_ARCH}-${ONNXRUNTIME_VERSION}/include/onnxruntime_cxx_api.h" - ) - message(STATUS "Downloading ONNX Runtime...") - file(MAKE_DIRECTORY ${ONNXRUNTIME_DOWNLOAD_DIR}) - - # Download the tarball - set(ONNXRUNTIME_TARBALL "${ONNXRUNTIME_DOWNLOAD_DIR}/onnxruntime.tgz") - file(DOWNLOAD ${ONNXRUNTIME_URL} ${ONNXRUNTIME_TARBALL} SHOW_PROGRESS) - - # Extract the tarball - message(STATUS "Extracting ONNX Runtime...") - execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf ${ONNXRUNTIME_TARBALL} - WORKING_DIRECTORY ${ONNXRUNTIME_DOWNLOAD_DIR}) - - # Clean up the tarball - file(REMOVE ${ONNXRUNTIME_TARBALL}) - endif() - - # Set paths to the extracted files - set(ONNXRUNTIME_EXTRACT_DIR - "${ONNXRUNTIME_DOWNLOAD_DIR}/onnxruntime-linux-${ONNXRUNTIME_ARCH}-${ONNXRUNTIME_VERSION}") - - # Verify the directory exists - if(NOT EXISTS ${ONNXRUNTIME_EXTRACT_DIR}) - message(FATAL_ERROR "ONNX Runtime extraction directory doesn't exist: ${ONNXRUNTIME_EXTRACT_DIR}") - endif() - - # Set include and library directories - set(ONNXRUNTIME_INCLUDE_DIRS "${ONNXRUNTIME_EXTRACT_DIR}/include") - - # Log directory contents to help with debugging - message(STATUS "ONNX Runtime extract directory: ${ONNXRUNTIME_EXTRACT_DIR}") - file(GLOB_RECURSE ONNXRUNTIME_FILES "${ONNXRUNTIME_EXTRACT_DIR}/*") - foreach(FILE ${ONNXRUNTIME_FILES}) - message(STATUS "Found file: ${FILE}") - endforeach() - - # Find the library files - if(EXISTS "${ONNXRUNTIME_EXTRACT_DIR}/lib/libonnxruntime.so") - set(ONNXRUNTIME_LIBRARY "${ONNXRUNTIME_EXTRACT_DIR}/lib/libonnxruntime.so") - else() - # Try to find the library in case the structure changed - file(GLOB_RECURSE ONNXRUNTIME_LIB_CANDIDATES - "${ONNXRUNTIME_EXTRACT_DIR}/*onnxruntime*${CMAKE_SHARED_LIBRARY_SUFFIX}") - - if(ONNXRUNTIME_LIB_CANDIDATES) - list(GET ONNXRUNTIME_LIB_CANDIDATES 0 ONNXRUNTIME_LIBRARY) - message(STATUS "Found ONNX Runtime library: ${ONNXRUNTIME_LIBRARY}") - else() - message(FATAL_ERROR "Could not find ONNX Runtime library in extracted files") - endif() - endif() - - set(ONNXRUNTIME_LIBRARIES ${ONNXRUNTIME_LIBRARY}) - - # Add to bundled libraries - set(flutter_onnxruntime_bundled_libraries ${ONNXRUNTIME_LIBRARY}) -endif() - -# Any new source files that you add to the plugin should be added here. -list(APPEND PLUGIN_SOURCES "src/flutter_onnxruntime_plugin.cc" "src/session_manager.cc" "src/value_conversion.cc" - "src/tensor_manager.cc") - -# Define the plugin library target. Its name must not be changed (see comment on PLUGIN_NAME above). -add_library(${PLUGIN_NAME} SHARED ${PLUGIN_SOURCES}) - -# Apply a standard set of build settings that are configured in the application-level CMakeLists.txt. This can be -# removed for plugins that want full control over build settings. -apply_standard_settings(${PLUGIN_NAME}) - -# Symbols are hidden by default to reduce the chance of accidental conflicts between plugins. This should not be -# removed; any symbols that should be exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro. -set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) -target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) - -# Enable C++17 features (required for ONNX Runtime 1.22.0+) -target_compile_features(${PLUGIN_NAME} PRIVATE cxx_std_17) - -# Source include directories and library dependencies. Add any plugin-specific dependencies here. -target_include_directories( - ${PLUGIN_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}" "${FLUTTER_EPHEMERAL_DIR}" - "${FLUTTER_EPHEMERAL_DIR}/cpp_client_wrapper/include" "${ONNXRUNTIME_INCLUDE_DIRS}") - -# Install debugging message -message(STATUS "Include directories: ${CMAKE_CURRENT_SOURCE_DIR}/include") -message(STATUS "Binary directory: ${CMAKE_CURRENT_BINARY_DIR}/include") -message(STATUS "This file: ${CMAKE_CURRENT_LIST_FILE}") - -# Install public headers for the plugin -install(FILES "include/flutter_onnxruntime/flutter_onnxruntime_plugin.h" - DESTINATION "${CMAKE_BINARY_DIR}/include/flutter_onnxruntime") - -# Install utility header files with the proper path -install(FILES DESTINATION "${CMAKE_BINARY_DIR}/include") - -# Also create symlinks in the build directory to ensure includes work during build -file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include/flutter_onnxruntime") - -# Copy headers with error handling -file( - COPY "${CMAKE_CURRENT_SOURCE_DIR}/include/flutter_onnxruntime/flutter_onnxruntime_plugin.h" - DESTINATION "${CMAKE_BINARY_DIR}/include/flutter_onnxruntime/" - FOLLOW_SYMLINK_CHAIN) - -file( - COPY "${CMAKE_CURRENT_SOURCE_DIR}/include/flutter_onnxruntime/export.h" - DESTINATION "${CMAKE_BINARY_DIR}/include/flutter_onnxruntime/" - FOLLOW_SYMLINK_CHAIN) - -# Add include directories for the plugin -target_include_directories(${PLUGIN_NAME} PUBLIC $ - $) - -# Add ONNX Runtime include directories -target_include_directories(${PLUGIN_NAME} PRIVATE ${ONNXRUNTIME_INCLUDE_DIRS}) - -target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) -target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) - -# Link against ONNX Runtime -target_link_libraries(${PLUGIN_NAME} PRIVATE ${ONNXRUNTIME_LIBRARIES}) - -# Add a post-build command to copy ONNX Runtime libraries to the build directory -if(NOT USE_SYSTEM_ONNXRUNTIME AND ONNXRUNTIME_LIBRARY) - add_custom_command( - TARGET ${PLUGIN_NAME} - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ONNXRUNTIME_LIBRARY} $ - COMMENT "Copying ONNX Runtime library to build directory") -endif() - -# List of absolute paths to libraries that should be bundled with the plugin. This list could contain prebuilt -# libraries, or libraries created by an external build triggered from this build file. -if(NOT USE_SYSTEM_ONNXRUNTIME AND ONNXRUNTIME_LIBRARY) - # When using the downloaded version, we need to bundle the library - set(bundled_libs ${ONNXRUNTIME_LIBRARY}) -else() - # When using system library, don't bundle it - set(bundled_libs "") -endif() - -set(flutter_onnxruntime_bundled_libraries - ${bundled_libs} - PARENT_SCOPE) - -# === Tests === -# These unit tests can be run from a terminal after building the example. - -# Only enable test builds when building the example (which sets this variable) so that plugin clients aren't building -# the tests. -if(${include_${PROJECT_NAME}_tests}) - if(${CMAKE_VERSION} VERSION_LESS "3.11.0") - message("Unit tests require CMake 3.11.0 or later") - else() - set(TEST_RUNNER "${PROJECT_NAME}_test") - enable_testing() - - # Add the Google Test dependency. - include(FetchContent) - FetchContent_Declare(googletest URL https://github.com/google/googletest/archive/v1.17.0.zip - DOWNLOAD_EXTRACT_TIMESTAMP TRUE) - # Prevent overriding the parent project's compiler/linker settings - set(gtest_force_shared_crt - ON - CACHE BOOL "" FORCE) - # Disable install commands for gtest so it doesn't end up in the bundle. - set(INSTALL_GTEST - OFF - CACHE BOOL "Disable installation of googletest" FORCE) - - FetchContent_MakeAvailable(googletest) - - # The plugin's exported API is not very useful for unit testing, so build the sources directly into the test binary - # rather than using the shared library. - add_executable(${TEST_RUNNER} test/flutter_onnxruntime_plugin_test.cc ${PLUGIN_SOURCES}) - - # Dedicated binary: the issue #73 regression only reproduces before any Ort::Env exists in the process, since the - # ONNX operator schemas holding the affected constants are registered once per process. Compile only the source - # under test so nothing else in this binary can create one first. - set(LOCALE_TEST_RUNNER "${PROJECT_NAME}_locale_test") - add_executable(${LOCALE_TEST_RUNNER} test/session_manager_locale_test.cc src/session_manager.cc) - - foreach(TARGET ${TEST_RUNNER} ${LOCALE_TEST_RUNNER}) - apply_standard_settings(${TARGET}) - target_include_directories(${TARGET} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" ${ONNXRUNTIME_INCLUDE_DIRS}) - target_link_libraries(${TARGET} PRIVATE flutter PkgConfig::GTK ${ONNXRUNTIME_LIBRARIES} gtest_main gmock) - endforeach() - - # Enable automatic test discovery. - include(GoogleTest) - gtest_discover_tests(${TEST_RUNNER}) - gtest_discover_tests(${LOCALE_TEST_RUNNER}) - - endif() # CMake version check -endif() # include_${PROJECT_NAME}_tests diff --git a/app/vendor/flutter_onnxruntime/linux/include/flutter_onnxruntime/export.h b/app/vendor/flutter_onnxruntime/linux/include/flutter_onnxruntime/export.h deleted file mode 100644 index f7c11f6..0000000 --- a/app/vendor/flutter_onnxruntime/linux/include/flutter_onnxruntime/export.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) MASIC AI -// All rights reserved. -// -// This source code is licensed under the license found in the -// LICENSE file in the root directory of this source tree. - -#ifndef FLUTTER_PLUGIN_FLUTTER_ONNXRUNTIME_EXPORT_H_ -#define FLUTTER_PLUGIN_FLUTTER_ONNXRUNTIME_EXPORT_H_ - -#ifdef FLUTTER_PLUGIN_IMPL -#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) -#else -#define FLUTTER_PLUGIN_EXPORT -#endif - -#endif // FLUTTER_PLUGIN_FLUTTER_ONNXRUNTIME_EXPORT_H_ \ No newline at end of file diff --git a/app/vendor/flutter_onnxruntime/linux/include/flutter_onnxruntime/flutter_onnxruntime_plugin.h b/app/vendor/flutter_onnxruntime/linux/include/flutter_onnxruntime/flutter_onnxruntime_plugin.h deleted file mode 100644 index e37d76b..0000000 --- a/app/vendor/flutter_onnxruntime/linux/include/flutter_onnxruntime/flutter_onnxruntime_plugin.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) MASIC AI -// All rights reserved. -// -// This source code is licensed under the license found in the -// LICENSE file in the root directory of this source tree. - -#ifndef FLUTTER_PLUGIN_FLUTTER_ONNXRUNTIME_PLUGIN_H_ -#define FLUTTER_PLUGIN_FLUTTER_ONNXRUNTIME_PLUGIN_H_ - -#include - -G_BEGIN_DECLS - -#ifdef FLUTTER_PLUGIN_IMPL -#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) -#else -#define FLUTTER_PLUGIN_EXPORT -#endif - -typedef struct _FlutterOnnxruntimePlugin FlutterOnnxruntimePlugin; -typedef struct { - GObjectClass parent_class; -} FlutterOnnxruntimePluginClass; - -FLUTTER_PLUGIN_EXPORT GType flutter_onnxruntime_plugin_get_type(); - -FLUTTER_PLUGIN_EXPORT void flutter_onnxruntime_plugin_register_with_registrar(FlPluginRegistrar *registrar); - -G_END_DECLS - -#endif // FLUTTER_PLUGIN_FLUTTER_ONNXRUNTIME_PLUGIN_H_ \ No newline at end of file diff --git a/app/vendor/flutter_onnxruntime/linux/src/flutter_onnxruntime_plugin.cc b/app/vendor/flutter_onnxruntime/linux/src/flutter_onnxruntime_plugin.cc deleted file mode 100644 index 2cd4e40..0000000 --- a/app/vendor/flutter_onnxruntime/linux/src/flutter_onnxruntime_plugin.cc +++ /dev/null @@ -1,900 +0,0 @@ -// Copyright (c) MASIC AI -// All rights reserved. -// -// This source code is licensed under the license found in the -// LICENSE file in the root directory of this source tree. - -#include "include/flutter_onnxruntime/flutter_onnxruntime_plugin.h" - -#include -#include -#include - -#include "session_manager.h" -#include "tensor_manager.h" -#include "value_conversion.h" -#include -#include -#include -#include -#include -#include -#include - -#define FLUTTER_ONNXRUNTIME_PLUGIN(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), flutter_onnxruntime_plugin_get_type(), FlutterOnnxruntimePlugin)) - -struct _FlutterOnnxruntimePlugin { - GObject parent_instance; - - // SessionManager for handling ONNX Runtime sessions - SessionManager *session_manager; - - // TensorManager for handling OrtValue objects - TensorManager *tensor_manager; - - // Maps to store value data - std::map values; - - // Mutex for thread safety - std::mutex mutex; -}; - -G_DEFINE_TYPE(FlutterOnnxruntimePlugin, flutter_onnxruntime_plugin, g_object_get_type()) - -// Method declarations -static void flutter_onnxruntime_plugin_dispose(GObject *object); -static void flutter_onnxruntime_plugin_handle_method_call(FlutterOnnxruntimePlugin *self, FlMethodCall *method_call); -static void method_call_handler(FlMethodChannel *channel, FlMethodCall *method_call, gpointer user_data); - -// Helper function to get platform version -static FlMethodResponse *get_platform_version(); - -// Session management -static FlMethodResponse *create_session(FlutterOnnxruntimePlugin *self, FlValue *args); -static FlMethodResponse *get_available_providers(FlutterOnnxruntimePlugin *self, FlValue *args); -static FlMethodResponse *run_inference(FlutterOnnxruntimePlugin *self, FlValue *args); -static FlMethodResponse *close_session(FlutterOnnxruntimePlugin *self, FlValue *args); -static FlMethodResponse *get_metadata(FlutterOnnxruntimePlugin *self, FlValue *args); -static FlMethodResponse *get_input_info(FlutterOnnxruntimePlugin *self, FlValue *args); -static FlMethodResponse *get_output_info(FlutterOnnxruntimePlugin *self, FlValue *args); - -// OrtValue operations -static FlMethodResponse *create_ort_value(FlutterOnnxruntimePlugin *self, FlValue *args); -static FlMethodResponse *convert_ort_value(FlutterOnnxruntimePlugin *self, FlValue *args); -static FlMethodResponse *get_ort_value_data(FlutterOnnxruntimePlugin *self, FlValue *args); -static FlMethodResponse *release_ort_value(FlutterOnnxruntimePlugin *self, FlValue *args); - -// Helper function to map C++ API provider names to OrtProvider enum names -static std::string mapProviderNameToEnumName(const std::string &providerName) { - // Map from C++ API provider names to OrtProvider enum names - static const std::unordered_map providerNameMap = { - {"CPUExecutionProvider", "CPU"}, - {"CUDAExecutionProvider", "CUDA"}, - {"TensorrtExecutionProvider", "TENSOR_RT"}, - {"MIGraphXExecutionProvider", "MIGRAPHX"}, - {"ROCMExecutionProvider", "ROCM"}, - {"CoreMLExecutionProvider", "CORE_ML"}, - {"DnnlExecutionProvider", "DNNL"}, - {"OpenVINOExecutionProvider", "OPEN_VINO"}, - {"NnapiExecutionProvider", "NNAPI"}, - {"QnnExecutionProvider", "QNN"}, - {"DmlExecutionProvider", "DIRECT_ML"}, - {"ACLExecutionProvider", "ACL"}, - {"ArmNNExecutionProvider", "ARM_NN"}, - {"XnnpackExecutionProvider", "XNNPACK"}}; - - auto it = providerNameMap.find(providerName); - if (it != providerNameMap.end()) { - return it->second; - } - - // Return the original name if no mapping exists - // This handles cases like custom or new providers that aren't in the enum yet - return providerName; -} - -// Plugin class initialization -static void flutter_onnxruntime_plugin_class_init(FlutterOnnxruntimePluginClass *klass) { - G_OBJECT_CLASS(klass)->dispose = flutter_onnxruntime_plugin_dispose; -} - -static void flutter_onnxruntime_plugin_init(FlutterOnnxruntimePlugin *self) { - self->session_manager = new SessionManager(); - self->tensor_manager = new TensorManager(); -} - -static void flutter_onnxruntime_plugin_dispose(GObject *object) { - FlutterOnnxruntimePlugin *self = FLUTTER_ONNXRUNTIME_PLUGIN(object); - - // Clean up session manager, tensor manager and values - delete self->session_manager; - delete self->tensor_manager; - - std::lock_guard lock(self->mutex); - self->values.clear(); - - G_OBJECT_CLASS(flutter_onnxruntime_plugin_parent_class)->dispose(object); -} - -// Plugin registration with Flutter engine -void flutter_onnxruntime_plugin_register_with_registrar(FlPluginRegistrar *registrar) { - FlutterOnnxruntimePlugin *plugin = - FLUTTER_ONNXRUNTIME_PLUGIN(g_object_new(flutter_onnxruntime_plugin_get_type(), nullptr)); - - g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); - g_autoptr(FlMethodChannel) channel = fl_method_channel_new(fl_plugin_registrar_get_messenger(registrar), - "flutter_onnxruntime", FL_METHOD_CODEC(codec)); - - // Setup method call handler - fl_method_channel_set_method_call_handler(channel, method_call_handler, g_object_ref(plugin), g_object_unref); - - g_object_unref(plugin); -} - -// Method call handler function -static void method_call_handler(FlMethodChannel *channel, FlMethodCall *method_call, gpointer user_data) { - FlutterOnnxruntimePlugin *self = FLUTTER_ONNXRUNTIME_PLUGIN(user_data); - flutter_onnxruntime_plugin_handle_method_call(self, method_call); -} - -// Handler for method calls from Dart -static void flutter_onnxruntime_plugin_handle_method_call(FlutterOnnxruntimePlugin *self, FlMethodCall *method_call) { - g_autoptr(FlMethodResponse) response = nullptr; - const gchar *method = fl_method_call_get_name(method_call); - FlValue *args = fl_method_call_get_args(method_call); - - // Dispatch the call to the appropriate handler function. - // Each handler function now directly returns an FlMethodResponse. - if (strcmp(method, "getPlatformVersion") == 0) { - response = get_platform_version(); - } else if (strcmp(method, "createSession") == 0) { - response = create_session(self, args); - } else if (strcmp(method, "getAvailableProviders") == 0) { - response = get_available_providers(self, args); - } else if (strcmp(method, "runInference") == 0) { - response = run_inference(self, args); - } else if (strcmp(method, "closeSession") == 0) { - response = close_session(self, args); - } else if (strcmp(method, "getMetadata") == 0) { - response = get_metadata(self, args); - } else if (strcmp(method, "getInputInfo") == 0) { - response = get_input_info(self, args); - } else if (strcmp(method, "getOutputInfo") == 0) { - response = get_output_info(self, args); - } else if (strcmp(method, "createOrtValue") == 0) { - response = create_ort_value(self, args); - } else if (strcmp(method, "convertOrtValue") == 0) { - response = convert_ort_value(self, args); - } else if (strcmp(method, "getOrtValueData") == 0) { - response = get_ort_value_data(self, args); - } else if (strcmp(method, "releaseOrtValue") == 0) { - response = release_ort_value(self, args); - } else { - response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new()); - } - - if (response != nullptr) { - fl_method_call_respond(method_call, response, nullptr); - } else { - // Fallback if no response was created (should ideally not happen) - response = - FL_METHOD_RESPONSE(fl_method_error_response_new("INTERNAL_ERROR", "Failed to process method call", nullptr)); - fl_method_call_respond(method_call, response, nullptr); - } -} - -// Implementation of method functions -static FlMethodResponse *get_platform_version() { - struct utsname uname_data = {}; - uname(&uname_data); - return FL_METHOD_RESPONSE(fl_method_success_response_new(fl_value_new_string(uname_data.version))); -} - -static FlMethodResponse *create_session(FlutterOnnxruntimePlugin *self, FlValue *args) { - FlValue *model_path_value = fl_value_lookup_string(args, "modelPath"); - - if (model_path_value == nullptr || fl_value_get_type(model_path_value) != FL_VALUE_TYPE_STRING) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("INVALID_ARG", "Model path cannot be null", nullptr)); - } - - const char *model_path = fl_value_get_string(model_path_value); - - FlValue *session_options_value = fl_value_lookup_string(args, "sessionOptions"); - - Ort::SessionOptions session_options; - - // Configure session options if provided - if (session_options_value != nullptr && fl_value_get_type(session_options_value) == FL_VALUE_TYPE_MAP) { - auto options_map = fl_value_to_map(session_options_value); - - // Set threading options - auto intra_threads_val = options_map.find("intraOpNumThreads"); - if (intra_threads_val != options_map.end() && fl_value_get_type(intra_threads_val->second) == FL_VALUE_TYPE_INT) { - session_options.SetIntraOpNumThreads(fl_value_get_int(intra_threads_val->second)); - } - - auto inter_threads_val = options_map.find("interOpNumThreads"); - if (inter_threads_val != options_map.end() && fl_value_get_type(inter_threads_val->second) == FL_VALUE_TYPE_INT) { - session_options.SetInterOpNumThreads(fl_value_get_int(inter_threads_val->second)); - } - - // get the device id, if not provided, set to 0 - int device_id = 0; - auto device_id_val = options_map.find("deviceId"); - if (device_id_val != options_map.end() && fl_value_get_type(device_id_val->second) == FL_VALUE_TYPE_INT) { - device_id = fl_value_get_int(device_id_val->second); - } - - // Convert device_id to string for use with provider options - std::string device_id_str = std::to_string(device_id); - - // Handle providers - auto providers_val = options_map.find("providers"); - std::vector providers; - if (providers_val != options_map.end() && fl_value_get_type(providers_val->second) == FL_VALUE_TYPE_LIST) { - FlValue *providers_list = providers_val->second; - size_t num_providers = fl_value_get_length(providers_list); - for (size_t i = 0; i < num_providers; i++) { - FlValue *provider_value = fl_value_get_list_value(providers_list, i); - if (fl_value_get_type(provider_value) == FL_VALUE_TYPE_STRING) { - providers.push_back(fl_value_get_string(provider_value)); - } - } - } - - // Default to CPU provider if no providers are specified - if (providers.empty()) { - providers.push_back("CPU"); - } - - // Set providers in session options - try { - for (const auto &provider : providers) { - if (provider == "CPU") { - // CPU is implicitly added if no others are, or can be explicitly added. - // No specific options needed here usually. - continue; - } else if (provider == "CUDA") { - OrtCUDAProviderOptionsV2 *cuda_options = nullptr; - OrtStatus *status = Ort::GetApi().CreateCUDAProviderOptions(&cuda_options); - if (status != nullptr) { - std::string error_message = "Failed to create CUDA provider options: "; - error_message += Ort::GetApi().GetErrorMessage(status); - Ort::GetApi().ReleaseStatus(status); - return FL_METHOD_RESPONSE(fl_method_error_response_new("PROVIDER_ERROR", error_message.c_str(), nullptr)); - } - // Use g_autoptr for automatic release - struct CudaOptionsDeleter { - void operator()(OrtCUDAProviderOptionsV2 *p) { Ort::GetApi().ReleaseCUDAProviderOptions(p); } - }; - std::unique_ptr cuda_options_ptr(cuda_options); - - // Follow the example at - // https://onnxruntime.ai/docs/execution-providers/CUDA-ExecutionProvider.html#using-v2-provider-options-struct - std::vector keys{"device_id"}; - std::vector values{device_id_str.c_str()}; - status = - Ort::GetApi().UpdateCUDAProviderOptions(cuda_options_ptr.get(), keys.data(), values.data(), keys.size()); - if (status != nullptr) { - std::string error_message = "Failed to update CUDA provider options: "; - error_message += Ort::GetApi().GetErrorMessage(status); - Ort::GetApi().ReleaseStatus(status); - return FL_METHOD_RESPONSE(fl_method_error_response_new("PROVIDER_ERROR", error_message.c_str(), nullptr)); - } - - // Append CUDA execution provider to session options - session_options.AppendExecutionProvider_CUDA_V2(*cuda_options_ptr); - - } else if (provider == "TENSOR_RT") { - OrtTensorRTProviderOptionsV2 *tensorrt_options = nullptr; - OrtStatus *status = Ort::GetApi().CreateTensorRTProviderOptions(&tensorrt_options); - if (status != nullptr) { - std::string error_message = "Failed to create TensorRT provider options: "; - error_message += Ort::GetApi().GetErrorMessage(status); - Ort::GetApi().ReleaseStatus(status); - return FL_METHOD_RESPONSE(fl_method_error_response_new("PROVIDER_ERROR", error_message.c_str(), nullptr)); - } - struct TensorRTOptionsDeleter { - void operator()(OrtTensorRTProviderOptionsV2 *p) { Ort::GetApi().ReleaseTensorRTProviderOptions(p); } - }; - std::unique_ptr tensorrt_options_ptr(tensorrt_options); - - std::vector keys{"device_id"}; - std::vector values{device_id_str.c_str()}; - status = Ort::GetApi().UpdateTensorRTProviderOptions(tensorrt_options_ptr.get(), keys.data(), values.data(), - keys.size()); - if (status != nullptr) { - std::string error_message = "Failed to update TensorRT provider options: "; - error_message += Ort::GetApi().GetErrorMessage(status); - Ort::GetApi().ReleaseStatus(status); - return FL_METHOD_RESPONSE(fl_method_error_response_new("PROVIDER_ERROR", error_message.c_str(), nullptr)); - } - - session_options.AppendExecutionProvider_TensorRT_V2(*tensorrt_options_ptr); - - } else { - std::string error_message = "Provider is not supported: " + provider; - return FL_METHOD_RESPONSE(fl_method_error_response_new("INVALID_PROVIDER", error_message.c_str(), nullptr)); - } - } - } catch (const Ort::Exception &e) { - // Catch potential exceptions during provider setup (e.g., AppendExecutionProvider) - return FL_METHOD_RESPONSE(fl_method_error_response_new("PROVIDER_ERROR", e.what(), nullptr)); - } catch (const std::exception &e) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("PLUGIN_ERROR", e.what(), nullptr)); - } - } - - try { - std::string session_id = self->session_manager->createSession(model_path, session_options); - - std::vector input_names = self->session_manager->getInputNames(session_id); - std::vector output_names = self->session_manager->getOutputNames(session_id); - - g_autoptr(FlValue) result = fl_value_new_map(); - fl_value_set_string_take(result, "sessionId", fl_value_new_string(session_id.c_str())); - fl_value_set_string_take(result, "inputNames", vector_to_fl_value(input_names)); - fl_value_set_string_take(result, "outputNames", vector_to_fl_value(output_names)); - fl_value_set_string_take(result, "status", fl_value_new_string("success")); // Keep status for compatibility maybe? - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); - } catch (const Ort::Exception &e) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("ORT_ERROR", e.what(), nullptr)); - } catch (const std::exception &e) { - // Catch other potential errors during session creation or name retrieval - return FL_METHOD_RESPONSE(fl_method_error_response_new("PLUGIN_ERROR", e.what(), nullptr)); - } -} - -static FlMethodResponse *get_available_providers(FlutterOnnxruntimePlugin *self, FlValue *args) { - std::vector providers = Ort::GetAvailableProviders(); - - g_autoptr(FlValue) result = fl_value_new_list(); - for (const auto &provider : providers) { - // Map the provider name to the standardized enum name - std::string mappedName = mapProviderNameToEnumName(provider); - fl_value_append_take(result, fl_value_new_string(mappedName.c_str())); - } - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse *run_inference(FlutterOnnxruntimePlugin *self, FlValue *args) { - FlValue *session_id_value = fl_value_lookup_string(args, "sessionId"); - if (session_id_value == nullptr || fl_value_get_type(session_id_value) != FL_VALUE_TYPE_STRING) { - return FL_METHOD_RESPONSE( - fl_method_error_response_new("INVALID_ARG", "Session ID must be a non-null string", nullptr)); - } - const char *session_id = fl_value_get_string(session_id_value); - - FlValue *inputs_value = fl_value_lookup_string(args, "inputs"); - if (inputs_value == nullptr || fl_value_get_type(inputs_value) != FL_VALUE_TYPE_MAP) { // inputs is a map from Dart - return FL_METHOD_RESPONSE(fl_method_error_response_new("INVALID_ARG", "Inputs must be a non-null map", nullptr)); - } - - FlValue *run_options_value = fl_value_lookup_string(args, "runOptions"); - - // Check if session exists - if (!self->session_manager->hasSession(session_id)) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("INVALID_SESSION", "Session not found", nullptr)); - } - - try { - // Get expected input names from the session - std::vector output_names = self->session_manager->getOutputNames(session_id); - - // Prepare input tensors and input names - // Use ClonedTensor to keep backing buffers alive during inference - std::vector cloned_inputs; - std::vector input_names; - - // Iterate through each input - size_t num_inputs = fl_value_get_length(inputs_value); - for (size_t i = 0; i < num_inputs; i++) { - FlValue *key = fl_value_get_map_key(inputs_value, i); - FlValue *value = fl_value_get_map_value(inputs_value, i); - - if (fl_value_get_type(key) != FL_VALUE_TYPE_STRING || fl_value_get_type(value) != FL_VALUE_TYPE_MAP) { - continue; - } - - // Extract the input name from the map key - std::string input_name = fl_value_get_string(key); - - FlValue *tensor_id_map = fl_value_lookup_string(value, "valueId"); - - if (tensor_id_map == nullptr || fl_value_get_type(tensor_id_map) != FL_VALUE_TYPE_STRING) { - continue; - } - - std::string tensor_id = fl_value_get_string(tensor_id_map); - - // Get the tensor value - Ort::Value *tensor_ptr = self->tensor_manager->getTensor(tensor_id); - if (tensor_ptr != nullptr) { - try { - // Clone the tensor — ClonedTensor owns both the Ort::Value and its backing buffer - ClonedTensor cloned = self->tensor_manager->cloneTensor(tensor_id); - cloned_inputs.push_back(std::move(cloned)); - input_names.push_back(input_name); - } catch (const std::exception &e) { - g_warning("Failed to clone tensor %s: %s", tensor_id.c_str(), e.what()); - // Continue with the next tensor - } - } - } - - // Build a vector of Ort::Value references for Session::Run - std::vector input_tensors; - input_tensors.reserve(cloned_inputs.size()); - for (auto &ci : cloned_inputs) { - input_tensors.push_back(std::move(ci.value)); - } - - // Create and configure run options - Ort::RunOptions run_options; - - // Configure run options if provided - if (run_options_value != nullptr && fl_value_get_type(run_options_value) == FL_VALUE_TYPE_MAP) { - // Extract log severity level if provided - FlValue *log_severity_level_value = fl_value_lookup_string(run_options_value, "logSeverityLevel"); - if (log_severity_level_value != nullptr && fl_value_get_type(log_severity_level_value) == FL_VALUE_TYPE_INT) { - run_options.SetRunLogSeverityLevel(fl_value_get_int(log_severity_level_value)); - } - - // Extract log verbosity level if provided - FlValue *log_verbosity_level_value = fl_value_lookup_string(run_options_value, "logVerbosityLevel"); - if (log_verbosity_level_value != nullptr && fl_value_get_type(log_verbosity_level_value) == FL_VALUE_TYPE_INT) { - run_options.SetRunLogVerbosityLevel(fl_value_get_int(log_verbosity_level_value)); - } - - // Extract terminate option if provided - FlValue *terminate_value = fl_value_lookup_string(run_options_value, "terminate"); - if (terminate_value != nullptr && fl_value_get_type(terminate_value) == FL_VALUE_TYPE_BOOL) { - if (fl_value_get_bool(terminate_value)) { - run_options.SetTerminate(); - } - } - } - - // Run inference using SessionManager with input names - // Note: cloned_inputs (with backing buffers) stays alive through this scope - std::vector output_tensors; - if (!input_tensors.empty()) { - output_tensors = self->session_manager->runInference(session_id, input_tensors, input_names, &run_options); - } - - // Process outputs - g_autoptr(FlValue) outputs_map = fl_value_new_map(); - - // For each output tensor, directly store it using TensorManager's storeTensor - for (size_t i = 0; i < output_tensors.size(); i++) { - // Create a tensor ID - std::string value_id = self->tensor_manager->generateTensorId(); - - // Store the tensor directly using storeTensor - this transfers ownership - self->tensor_manager->storeTensor(value_id, std::move(output_tensors[i])); - - // get the tensor type and shape from tensor manager - // Note: only do this after storeTensor get the tensor registered in tensor manager - std::string tensor_type = self->tensor_manager->getTensorType(value_id); - std::vector shape = self->tensor_manager->getTensorShape(value_id); - - // Add the value ID to the outputs map - FlValue *shape_list = fl_value_new_list(); - for (const auto &dim : shape) { - fl_value_append_take(shape_list, fl_value_new_int(dim)); - } - - // Note: Flutter does not allow return a nested map, so we have to use list here to keep the output_info format - FlValue *output_info = fl_value_new_list(); - fl_value_append_take(output_info, fl_value_new_string(value_id.c_str())); - fl_value_append_take(output_info, fl_value_new_string(tensor_type.c_str())); - fl_value_append_take(output_info, shape_list); - - fl_value_set_string_take(outputs_map, output_names[i].c_str(), output_info); - } - return FL_METHOD_RESPONSE(fl_method_success_response_new(outputs_map)); - } catch (const Ort::Exception &e) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("INFERENCE_ERROR", e.what(), nullptr)); - } catch (const std::exception &e) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("PLUGIN_ERROR", e.what(), nullptr)); - } -} - -static FlMethodResponse *close_session(FlutterOnnxruntimePlugin *self, FlValue *args) { - // Get session ID - FlValue *session_id_value = fl_value_lookup_string(args, "sessionId"); - - if (session_id_value == nullptr || fl_value_get_type(session_id_value) != FL_VALUE_TYPE_STRING) { - // Similar to closeSession, return success even if ID is invalid. - // Alternatively, return an error: - return FL_METHOD_RESPONSE( - fl_method_error_response_new("INVALID_ARG", "Session ID must be a non-null string", nullptr)); - } - - const char *session_id = fl_value_get_string(session_id_value); - - self->session_manager->closeSession(session_id); - - return FL_METHOD_RESPONSE(fl_method_success_response_new(fl_value_new_null())); -} - -static FlMethodResponse *get_metadata(FlutterOnnxruntimePlugin *self, FlValue *args) { - FlValue *session_id_value = fl_value_lookup_string(args, "sessionId"); - - if (session_id_value == nullptr || fl_value_get_type(session_id_value) != FL_VALUE_TYPE_STRING) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("INVALID_SESSION", "Invalid session ID", nullptr)); - } - - const char *session_id = fl_value_get_string(session_id_value); - - if (!self->session_manager->hasSession(session_id)) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("INVALID_SESSION", "Session not found", nullptr)); - } - - try { - // Get metadata using the SessionManager - ModelMetadata metadata = self->session_manager->getModelMetadata(session_id); - - // Create empty custom metadata map - FlValue *custom_metadata_map = fl_value_new_map(); - g_autoptr(FlValue) result = fl_value_new_map(); - fl_value_set_string_take(result, "producerName", fl_value_new_string(metadata.producer_name.c_str())); - fl_value_set_string_take(result, "graphName", fl_value_new_string(metadata.graph_name.c_str())); - fl_value_set_string_take(result, "domain", fl_value_new_string(metadata.domain.c_str())); - fl_value_set_string_take(result, "description", fl_value_new_string(metadata.description.c_str())); - fl_value_set_string_take(result, "version", fl_value_new_int(metadata.version)); - fl_value_set_string_take(result, "customMetadataMap", custom_metadata_map); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); - } catch (const Ort::Exception &e) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("ORT_ERROR", e.what(), nullptr)); - } catch (const std::exception &e) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("PLUGIN_ERROR", e.what(), nullptr)); - } -} - -static FlMethodResponse *get_input_info(FlutterOnnxruntimePlugin *self, FlValue *args) { - FlValue *session_id_value = fl_value_lookup_string(args, "sessionId"); - - if (session_id_value == nullptr || fl_value_get_type(session_id_value) != FL_VALUE_TYPE_STRING) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("INVALID_SESSION", "Invalid session ID", nullptr)); - } - - const char *session_id = fl_value_get_string(session_id_value); - - if (!self->session_manager->hasSession(session_id)) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("INVALID_SESSION", "Session not found", nullptr)); - } - - try { - // Get input info from SessionManager - std::vector input_info = self->session_manager->getInputInfo(session_id); - g_autoptr(FlValue) result = fl_value_new_list(); - - for (const auto &info : input_info) { - FlValue *info_map = fl_value_new_map(); - fl_value_set_string_take(info_map, "name", fl_value_new_string(info.name.c_str())); - - // Add shape - FlValue *shape_list = fl_value_new_list(); - for (const auto &dim : info.shape) { - fl_value_append_take(shape_list, fl_value_new_int(dim)); - } - fl_value_set_string_take(info_map, "shape", shape_list); - - // Add type - fl_value_set_string_take(info_map, "type", fl_value_new_string(info.type.c_str())); - - fl_value_append_take(result, info_map); - } - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); - } catch (const Ort::Exception &e) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("ORT_ERROR", e.what(), nullptr)); - } catch (const std::exception &e) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("PLUGIN_ERROR", e.what(), nullptr)); - } -} - -static FlMethodResponse *get_output_info(FlutterOnnxruntimePlugin *self, FlValue *args) { - FlValue *session_id_value = fl_value_lookup_string(args, "sessionId"); - - if (session_id_value == nullptr || fl_value_get_type(session_id_value) != FL_VALUE_TYPE_STRING) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("INVALID_SESSION", "Invalid session ID", nullptr)); - } - - const char *session_id = fl_value_get_string(session_id_value); - - if (!self->session_manager->hasSession(session_id)) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("INVALID_SESSION", "Session not found", nullptr)); - } - - try { - // Get output info from SessionManager - std::vector output_info = self->session_manager->getOutputInfo(session_id); - g_autoptr(FlValue) result = fl_value_new_list(); - - for (const auto &info : output_info) { - FlValue *info_map = fl_value_new_map(); - fl_value_set_string_take(info_map, "name", fl_value_new_string(info.name.c_str())); - - // Add shape - FlValue *shape_list = fl_value_new_list(); - for (const auto &dim : info.shape) { - fl_value_append_take(shape_list, fl_value_new_int(dim)); - } - fl_value_set_string_take(info_map, "shape", shape_list); - - // Add type - fl_value_set_string_take(info_map, "type", fl_value_new_string(info.type.c_str())); - - fl_value_append_take(result, info_map); - } - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); - } catch (const Ort::Exception &e) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("ORT_ERROR", e.what(), nullptr)); - } catch (const std::exception &e) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("PLUGIN_ERROR", e.what(), nullptr)); - } -} - -static FlMethodResponse *create_ort_value(FlutterOnnxruntimePlugin *self, FlValue *args) { - FlValue *source_type_value = fl_value_lookup_string(args, "sourceType"); - FlValue *data_value = fl_value_lookup_string(args, "data"); - FlValue *shape_value = fl_value_lookup_string(args, "shape"); - - // Check if all required arguments are provided - if (source_type_value == nullptr || data_value == nullptr || shape_value == nullptr || - fl_value_get_type(source_type_value) != FL_VALUE_TYPE_STRING || - fl_value_get_type(shape_value) != FL_VALUE_TYPE_LIST) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("INVALID_ARG", "Missing required arguments", nullptr)); - } - - const char *source_type = fl_value_get_string(source_type_value); - - // Convert shape values to vector of int64_t - size_t shape_size = fl_value_get_length(shape_value); - std::vector shape; - for (size_t i = 0; i < shape_size; i++) { - FlValue *dim = fl_value_get_list_value(shape_value, i); - if (fl_value_get_type(dim) != FL_VALUE_TYPE_INT) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("INVALID_ARG", "Shape must contain integers", nullptr)); - } - shape.push_back(fl_value_get_int(dim)); - } - - std::string valueId; - - try { - // Handle data according to source type - if (strcmp(source_type, "float32") == 0) { - std::vector data_vec; - - // Convert data to vector of floats - if (fl_value_get_type(data_value) == FL_VALUE_TYPE_FLOAT32_LIST) { - size_t data_size = fl_value_get_length(data_value); - const float *float_array = fl_value_get_float32_list(data_value); - data_vec.assign(float_array, float_array + data_size); - } else if (fl_value_get_type(data_value) == FL_VALUE_TYPE_LIST) { // regular float list array - size_t length = fl_value_get_length(data_value); - data_vec.reserve(length); - for (size_t i = 0; i < length; i++) { - FlValue *val = fl_value_get_list_value(data_value, i); - // Ensure it's a float or int (can be losslessly converted) - if (fl_value_get_type(val) != FL_VALUE_TYPE_FLOAT && fl_value_get_type(val) != FL_VALUE_TYPE_INT) { - return FL_METHOD_RESPONSE(fl_method_error_response_new( - "INVALID_DATA", "Data must be a list of numbers for float32 type", nullptr)); - } - data_vec.push_back(fl_value_get_float(val)); - } - } else { - return FL_METHOD_RESPONSE( - fl_method_error_response_new("INVALID_DATA", "Data must be a list of numbers for float32 type", nullptr)); - } - valueId = self->tensor_manager->createFloat32Tensor(data_vec, shape); - } else if (strcmp(source_type, "int32") == 0) { - std::vector data_vec; - if (fl_value_get_type(data_value) == FL_VALUE_TYPE_INT32_LIST) { - size_t data_size = fl_value_get_length(data_value); - const int32_t *int_array = fl_value_get_int32_list(data_value); - data_vec.assign(int_array, int_array + data_size); - } else if (fl_value_get_type(data_value) == FL_VALUE_TYPE_LIST) { - size_t length = fl_value_get_length(data_value); - data_vec.reserve(length); - for (size_t i = 0; i < length; i++) { - FlValue *val = fl_value_get_list_value(data_value, i); - if (fl_value_get_type(val) != FL_VALUE_TYPE_INT) { - return FL_METHOD_RESPONSE( - fl_method_error_response_new("INVALID_DATA", "Data must be a list of numbers for int32 type", nullptr)); - } - data_vec.push_back(static_cast(fl_value_get_int(val))); // Explicit cast - } - } else { - return FL_METHOD_RESPONSE( - fl_method_error_response_new("INVALID_DATA", "Data must be a list of numbers for int32 type", nullptr)); - } - valueId = self->tensor_manager->createInt32Tensor(data_vec, shape); - } else if (strcmp(source_type, "int64") == 0) { - std::vector data_vec; - if (fl_value_get_type(data_value) == FL_VALUE_TYPE_INT64_LIST) { - size_t data_size = fl_value_get_length(data_value); - const int64_t *int_array = fl_value_get_int64_list(data_value); - data_vec.assign(int_array, int_array + data_size); - } else if (fl_value_get_type(data_value) == FL_VALUE_TYPE_LIST) { - size_t length = fl_value_get_length(data_value); - data_vec.reserve(length); - for (size_t i = 0; i < length; i++) { - FlValue *val = fl_value_get_list_value(data_value, i); - if (fl_value_get_type(val) != FL_VALUE_TYPE_INT) { - return FL_METHOD_RESPONSE( - fl_method_error_response_new("INVALID_DATA", "Data must be a list of numbers for int64 type", nullptr)); - } - data_vec.push_back(fl_value_get_int(val)); // Direct conversion works for int64 - } - } else { - return FL_METHOD_RESPONSE( - fl_method_error_response_new("INVALID_DATA", "Data must be a list of numbers for int64 type", nullptr)); - } - valueId = self->tensor_manager->createInt64Tensor(data_vec, shape); - } else if (strcmp(source_type, "uint8") == 0) { - std::vector data_vec; - if (fl_value_get_type(data_value) == FL_VALUE_TYPE_UINT8_LIST) { - size_t data_size = fl_value_get_length(data_value); - const uint8_t *uint_array = fl_value_get_uint8_list(data_value); - data_vec.assign(uint_array, uint_array + data_size); - } else if (fl_value_get_type(data_value) == FL_VALUE_TYPE_LIST) { // regular int list array - size_t length = fl_value_get_length(data_value); - data_vec.reserve(length); - for (size_t i = 0; i < length; i++) { - FlValue *val = fl_value_get_list_value(data_value, i); - if (fl_value_get_type(val) != FL_VALUE_TYPE_INT) { - return FL_METHOD_RESPONSE( - fl_method_error_response_new("INVALID_DATA", "Data must be a list of numbers for int8 type", nullptr)); - } - data_vec.push_back(static_cast(fl_value_get_int(val))); // Explicit cast - } - } else { - return FL_METHOD_RESPONSE( - fl_method_error_response_new("INVALID_DATA", "Data must be a list of numbers for int8 type", nullptr)); - } - valueId = self->tensor_manager->createUint8Tensor(data_vec, shape); - } else if (strcmp(source_type, "bool") == 0) { - std::vector data_vec; - if (fl_value_get_type(data_value) == FL_VALUE_TYPE_LIST) { - size_t length = fl_value_get_length(data_value); - data_vec.reserve(length); - for (size_t i = 0; i < length; i++) { - FlValue *val = fl_value_get_list_value(data_value, i); - if (fl_value_get_type(val) != FL_VALUE_TYPE_BOOL) { - return FL_METHOD_RESPONSE( - fl_method_error_response_new("INVALID_DATA", "Data must be a list of booleans for bool type", nullptr)); - } - data_vec.push_back(fl_value_get_bool(val)); - } - } else { - return FL_METHOD_RESPONSE( - fl_method_error_response_new("INVALID_DATA", "Data must be a list of booleans for bool type", nullptr)); - } - valueId = self->tensor_manager->createBoolTensor(data_vec, shape); - } else if (strcmp(source_type, "string") == 0) { - std::vector data_vec; - if (fl_value_get_type(data_value) == FL_VALUE_TYPE_LIST) { - size_t length = fl_value_get_length(data_value); - data_vec.reserve(length); - for (size_t i = 0; i < length; i++) { - FlValue *val = fl_value_get_list_value(data_value, i); - if (fl_value_get_type(val) != FL_VALUE_TYPE_STRING) { - return FL_METHOD_RESPONSE(fl_method_error_response_new( - "INVALID_DATA", "Data must be a list of strings for string type", nullptr)); - } - data_vec.push_back(fl_value_get_string(val)); - } - } else { - return FL_METHOD_RESPONSE( - fl_method_error_response_new("INVALID_DATA", "Data must be a list of strings for string type", nullptr)); - } - valueId = self->tensor_manager->createStringTensor(data_vec, shape); - } else { - std::string error_message = "Unsupported source data type: "; - error_message += source_type; - return FL_METHOD_RESPONSE(fl_method_error_response_new("UNSUPPORTED_TYPE", error_message.c_str(), nullptr)); - } - } catch (const std::exception &e) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("TENSOR_CREATION_ERROR", e.what(), nullptr)); - } - - g_autoptr(FlValue) result = fl_value_new_map(); - fl_value_set_string_take(result, "valueId", fl_value_new_string(valueId.c_str())); - fl_value_set_string_take(result, "dataType", fl_value_new_string(source_type)); - - // Add shape to response - FlValue *shape_list = fl_value_new_list(); - for (const auto &dim : shape) { - fl_value_append_take(shape_list, fl_value_new_int(dim)); - } - fl_value_set_string_take(result, "shape", shape_list); - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse *convert_ort_value(FlutterOnnxruntimePlugin *self, FlValue *args) { - FlValue *value_id_value = fl_value_lookup_string(args, "valueId"); - FlValue *target_type_value = fl_value_lookup_string(args, "targetType"); - - // Check if required arguments are provided - if (value_id_value == nullptr || target_type_value == nullptr || - fl_value_get_type(value_id_value) != FL_VALUE_TYPE_STRING || - fl_value_get_type(target_type_value) != FL_VALUE_TYPE_STRING) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("INVALID_ARG", "Missing required arguments", nullptr)); - } - - // Get valueId and targetType - const char *value_id = fl_value_get_string(value_id_value); - const char *target_type = fl_value_get_string(target_type_value); - - std::string new_tensor_id; - try { - std::lock_guard lock(self->mutex); - - new_tensor_id = self->tensor_manager->convertTensor(value_id, target_type); - } catch (const std::exception &e) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("CONVERSION_ERROR", e.what(), nullptr)); - } - - std::vector shape = self->tensor_manager->getTensorShape(new_tensor_id); - - g_autoptr(FlValue) result = fl_value_new_map(); - fl_value_set_string_take(result, "valueId", fl_value_new_string(new_tensor_id.c_str())); - fl_value_set_string_take(result, "dataType", fl_value_new_string(target_type)); // Use target type - - // Add shape - FlValue *shape_list = fl_value_new_list(); - for (const auto &dim : shape) { - fl_value_append_take(shape_list, fl_value_new_int(dim)); - } - fl_value_set_string_take(result, "shape", shape_list); - - return FL_METHOD_RESPONSE(fl_method_success_response_new(result)); -} - -static FlMethodResponse *get_ort_value_data(FlutterOnnxruntimePlugin *self, FlValue *args) { - FlValue *value_id_value = fl_value_lookup_string(args, "valueId"); - - if (value_id_value == nullptr || fl_value_get_type(value_id_value) != FL_VALUE_TYPE_STRING) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("INVALID_ARG", "Invalid value ID", nullptr)); - } - - const char *value_id = fl_value_get_string(value_id_value); - - FlValue *tensor_data = nullptr; - try { - tensor_data = self->tensor_manager->getTensorData(value_id); - - // If tensor_data is null, it means tensor wasn't found or is invalid - if (tensor_data == nullptr || fl_value_get_type(tensor_data) == FL_VALUE_TYPE_NULL) { - if (tensor_data != nullptr) { - fl_value_unref(tensor_data); - } - return FL_METHOD_RESPONSE( - fl_method_error_response_new("INVALID_VALUE", "Tensor not found or already being disposed", nullptr)); - } - return FL_METHOD_RESPONSE(fl_method_success_response_new(tensor_data)); // tensor_data ownership transferred - } catch (const std::exception &e) { - if (tensor_data != nullptr) { - fl_value_unref(tensor_data); - } - return FL_METHOD_RESPONSE(fl_method_error_response_new("DATA_EXTRACTION_ERROR", e.what(), nullptr)); - } -} - -static FlMethodResponse *release_ort_value(FlutterOnnxruntimePlugin *self, FlValue *args) { - FlValue *value_id_value = fl_value_lookup_string(args, "valueId"); - - if (value_id_value == nullptr || fl_value_get_type(value_id_value) != FL_VALUE_TYPE_STRING) { - return FL_METHOD_RESPONSE(fl_method_error_response_new("INVALID_ARG", "Invalid value ID", nullptr)); - } - - const char *value_id = fl_value_get_string(value_id_value); - - self->tensor_manager->releaseTensor(value_id); - - return FL_METHOD_RESPONSE(fl_method_success_response_new(fl_value_new_null())); -} diff --git a/app/vendor/flutter_onnxruntime/linux/src/session_manager.cc b/app/vendor/flutter_onnxruntime/linux/src/session_manager.cc deleted file mode 100644 index bd17806..0000000 --- a/app/vendor/flutter_onnxruntime/linux/src/session_manager.cc +++ /dev/null @@ -1,401 +0,0 @@ -// Copyright (c) MASIC AI -// All rights reserved. -// -// This source code is licensed under the license found in the -// LICENSE file in the root directory of this source tree. - -#include "session_manager.h" -#include -#include - -namespace { - -// onnx <= 1.22 parses operator function bodies (e.g. HardSwish) from their text form with -// locale-dependent std::stof. GTK sets the process locale from the user's environment, so under -// comma-decimal locales (de_DE, fr_FR, ...) fractional constants such as HardSwish's alpha = 1/6 -// silently parse as 0 and the operator returns all zeros (issue #73, onnx/onnx#8111). Switch -// LC_NUMERIC to "C" around the two calls that trigger that parsing: creation of the process's first -// Ort::Env, which registers the operator schemas, and session construction, where context-dependent -// bodies (LayerNormalization, Gelu, ...) are parsed. uselocale is thread-local, so the host app's -// global locale is untouched. -// -// Only schemas this plugin registers are protected: native code that creates an Ort::Env first must -// be locale-safe on its own. Keep the guard even once onnx ships the upstream fix — -// USE_SYSTEM_ONNXRUNTIME defaults to ON, so the onnx version behind the plugin is not pinned here. -class ScopedCLocale { -public: - ScopedCLocale() : c_locale_(newlocale(LC_NUMERIC_MASK, "C", (locale_t)0)) { - if (c_locale_ != (locale_t)0) { - previous_ = uselocale(c_locale_); - } else { - // A silently degraded guard is indistinguishable from the unfixed build, so leave a trace. - std::cerr << "flutter_onnxruntime: newlocale(\"C\") failed; ONNX operator constants may parse " - "incorrectly under the current locale (issue #73)" - << std::endl; - } - } - ~ScopedCLocale() { - if (previous_ != (locale_t)0) { - uselocale(previous_); - } - if (c_locale_ != (locale_t)0) { - freelocale(c_locale_); - } - } - - // Owns a locale_t; a copy would double-freelocale it. - ScopedCLocale(const ScopedCLocale &) = delete; - ScopedCLocale &operator=(const ScopedCLocale &) = delete; - -private: - locale_t c_locale_; - locale_t previous_ = (locale_t)0; -}; - -Ort::Env createOrtEnv() { - ScopedCLocale locale_guard; - return Ort::Env(ORT_LOGGING_LEVEL_WARNING, "FlutterOnnxRuntime"); -} - -} // namespace - -SessionManager::SessionManager() : next_session_id_(1), env_(createOrtEnv()) { - // Initialize ONNX Runtime environment in constructor -} - -SessionManager::~SessionManager() { - // Clear all sessions - std::lock_guard lock(mutex_); - sessions_.clear(); -} - -std::string SessionManager::createSession(const char *model_path, void *options) { - std::lock_guard lock(mutex_); - - ScopedCLocale locale_guard; - - // Generate a session ID - std::string session_id = generateSessionId(); - - try { - // Create session options - Ort::SessionOptions session_options; - - // If options are provided, use them - if (options != nullptr) { - // Cast the void* to the correct type - Ort::SessionOptions *provided_options = static_cast(options); - - // Directly use the provided options - session_options = std::move(*provided_options); - } else { - // Configure default execution providers - // Default to CPU execution provider - } - - // Create a new session - std::unique_ptr ort_session = std::make_unique(env_, model_path, session_options); - - // Create session info - SessionInfo session_info; - session_info.session = std::move(ort_session); - - // Get input names - Ort::AllocatorWithDefaultOptions allocator; - size_t num_inputs = session_info.session->GetInputCount(); - session_info.input_names.clear(); - - for (size_t i = 0; i < num_inputs; i++) { - auto input_name = session_info.session->GetInputNameAllocated(i, allocator); - session_info.input_names.push_back(std::string(input_name.get())); - } - - // Get output names - size_t num_outputs = session_info.session->GetOutputCount(); - session_info.output_names.clear(); - - for (size_t i = 0; i < num_outputs; i++) { - auto output_name = session_info.session->GetOutputNameAllocated(i, allocator); - session_info.output_names.push_back(std::string(output_name.get())); - } - - // Store the session info - sessions_[session_id] = std::move(session_info); - - return session_id; - } catch (const Ort::Exception &e) { - std::cerr << "ONNX Runtime Error: " << e.what() << std::endl; - throw e; - } catch (const std::exception &e) { - std::cerr << "Error: " << e.what() << std::endl; - throw e; - } -} - -bool SessionManager::closeSession(const std::string &session_id) { - std::lock_guard lock(mutex_); - - auto it = sessions_.find(session_id); - if (it != sessions_.end()) { - sessions_.erase(it); - return true; - } - - return false; -} - -bool SessionManager::hasSession(const std::string &session_id) { - std::lock_guard lock(mutex_); - return sessions_.find(session_id) != sessions_.end(); -} - -std::vector SessionManager::getInputNames(const std::string &session_id) { - std::lock_guard lock(mutex_); - - auto it = sessions_.find(session_id); - if (it != sessions_.end()) { - return it->second.input_names; - } - - return {}; -} - -std::vector SessionManager::getOutputNames(const std::string &session_id) { - std::lock_guard lock(mutex_); - - auto it = sessions_.find(session_id); - if (it != sessions_.end()) { - return it->second.output_names; - } - - return {}; -} - -std::string SessionManager::generateSessionId() { return "session_" + std::to_string(next_session_id_++); } - -// Get element type string helper -const char *SessionManager::getElementTypeString(ONNXTensorElementDataType element_type) { - switch (element_type) { - case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT: - return "float32"; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8: - return "uint8"; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8: - return "int8"; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16: - return "uint16"; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16: - return "int16"; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32: - return "int32"; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64: - return "int64"; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING: - return "string"; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL: - return "bool"; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16: - return "float16"; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE: - return "float64"; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32: - return "uint32"; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64: - return "uint64"; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX64: - return "complex64"; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_COMPLEX128: - return "complex128"; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_BFLOAT16: - return "bfloat16"; - default: - return "unknown"; - } -} - -// Get model metadata -ModelMetadata SessionManager::getModelMetadata(const std::string &session_id) { - std::lock_guard lock(mutex_); - ModelMetadata metadata{}; - - auto it = sessions_.find(session_id); - if (it != sessions_.end()) { - try { - Ort::Session *session = it->second.session.get(); - if (session) { - // Get model metadata - Ort::ModelMetadata model_metadata = session->GetModelMetadata(); - Ort::AllocatorWithDefaultOptions allocator; - - // Extract metadata details - auto producer_name = model_metadata.GetProducerNameAllocated(allocator); - auto graph_name = model_metadata.GetGraphNameAllocated(allocator); - auto domain = model_metadata.GetDomainAllocated(allocator); - auto description = model_metadata.GetDescriptionAllocated(allocator); - - metadata.producer_name = producer_name.get(); - metadata.graph_name = graph_name.get(); - metadata.domain = domain.get(); - metadata.description = description.get(); - metadata.version = model_metadata.GetVersion(); - - // Add custom metadata if needed - // Currently returning an empty map as in the original implementation - } - } catch (const Ort::Exception &e) { - std::cerr << "ONNX Runtime Error: " << e.what() << std::endl; - } catch (const std::exception &e) { - std::cerr << "Error: " << e.what() << std::endl; - } - } - - return metadata; -} - -// Get input info -std::vector SessionManager::getInputInfo(const std::string &session_id) { - std::lock_guard lock(mutex_); - std::vector info_list; - - auto it = sessions_.find(session_id); - if (it != sessions_.end()) { - try { - Ort::Session *session = it->second.session.get(); - if (session) { - size_t num_inputs = session->GetInputCount(); - Ort::AllocatorWithDefaultOptions allocator; - - for (size_t i = 0; i < num_inputs; i++) { - TensorInfo info{}; - - // Get input name - auto input_name = session->GetInputNameAllocated(i, allocator); - info.name = input_name.get(); - - // Get type and shape - auto type_info = session->GetInputTypeInfo(i); - ONNXType onnx_type = type_info.GetONNXType(); - - if (onnx_type == ONNX_TYPE_TENSOR) { - auto tensor_info = type_info.GetTensorTypeAndShapeInfo(); - info.shape = tensor_info.GetShape(); - - // Get element type - ONNXTensorElementDataType element_type = tensor_info.GetElementType(); - info.type = getElementTypeString(element_type); - } else { - // Non-tensor type - info.type = "non-tensor"; - } - - info_list.push_back(info); - } - } - } catch (const Ort::Exception &e) { - std::cerr << "ONNX Runtime Error: " << e.what() << std::endl; - } catch (const std::exception &e) { - std::cerr << "Error: " << e.what() << std::endl; - } - } - - return info_list; -} - -// Get output info -std::vector SessionManager::getOutputInfo(const std::string &session_id) { - std::lock_guard lock(mutex_); - std::vector info_list; - - auto it = sessions_.find(session_id); - if (it != sessions_.end()) { - try { - Ort::Session *session = it->second.session.get(); - if (session) { - size_t num_outputs = session->GetOutputCount(); - Ort::AllocatorWithDefaultOptions allocator; - - for (size_t i = 0; i < num_outputs; i++) { - TensorInfo info{}; - - // Get output name - auto output_name = session->GetOutputNameAllocated(i, allocator); - info.name = output_name.get(); - - // Get type and shape - auto type_info = session->GetOutputTypeInfo(i); - ONNXType onnx_type = type_info.GetONNXType(); - - if (onnx_type == ONNX_TYPE_TENSOR) { - auto tensor_info = type_info.GetTensorTypeAndShapeInfo(); - info.shape = tensor_info.GetShape(); - - // Get element type - ONNXTensorElementDataType element_type = tensor_info.GetElementType(); - info.type = getElementTypeString(element_type); - } else { - // Non-tensor type - info.type = "non-tensor"; - } - - info_list.push_back(info); - } - } - } catch (const Ort::Exception &e) { - std::cerr << "ONNX Runtime Error: " << e.what() << std::endl; - } catch (const std::exception &e) { - std::cerr << "Error: " << e.what() << std::endl; - } - } - - return info_list; -} - -// Run inference with provided input names -std::vector SessionManager::runInference(const std::string &session_id, - const std::vector &input_tensors, - const std::vector &input_names, - Ort::RunOptions *run_options) { - - std::lock_guard lock(mutex_); - std::vector output_tensors; - - auto it = sessions_.find(session_id); - if (it == sessions_.end()) { - throw Ort::Exception("Session not found", ORT_INVALID_ARGUMENT); - } - - Ort::Session *session = it->second.session.get(); - if (!session) { - throw Ort::Exception("Session is invalid", ORT_INVALID_ARGUMENT); - } - - if (input_tensors.empty()) { - throw Ort::Exception("No input tensors provided", ORT_INVALID_ARGUMENT); - } - - if (input_names.size() != input_tensors.size()) { - throw Ort::Exception("Number of input names must match number of input tensors", ORT_INVALID_ARGUMENT); - } - - // Prepare input names - std::vector input_names_char; - for (const auto &name : input_names) { - input_names_char.push_back(name.c_str()); - } - - // Prepare output names - std::vector output_names_char; - for (const auto &name : it->second.output_names) { - output_names_char.push_back(name.c_str()); - } - - // Create default run options if none provided - Ort::RunOptions default_run_options; - Ort::RunOptions *run_opts = run_options ? run_options : &default_run_options; - - // Run inference - let exceptions propagate out - output_tensors = session->Run(*run_opts, input_names_char.data(), input_tensors.data(), input_tensors.size(), - output_names_char.data(), output_names_char.size()); - - return output_tensors; -} \ No newline at end of file diff --git a/app/vendor/flutter_onnxruntime/linux/src/session_manager.h b/app/vendor/flutter_onnxruntime/linux/src/session_manager.h deleted file mode 100644 index 3a1ebd3..0000000 --- a/app/vendor/flutter_onnxruntime/linux/src/session_manager.h +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright (c) MASIC AI -// All rights reserved. -// -// This source code is licensed under the license found in the -// LICENSE file in the root directory of this source tree. - -#ifndef SESSION_MANAGER_H -#define SESSION_MANAGER_H - -#include -#include -#include -#include -#include -#include - -// Forward declaration -class TensorManager; - -// Session information structure -struct SessionInfo { - std::unique_ptr session; - std::vector input_names; - std::vector output_names; -}; - -// Model metadata structure -struct ModelMetadata { - std::string producer_name; - std::string graph_name; - std::string domain; - std::string description; - int64_t version; - std::map custom_metadata; -}; - -// Input/Output tensor info structure -struct TensorInfo { - std::string name; - std::string type; - std::vector shape; -}; - -// Session Manager Class -class SessionManager { -public: - SessionManager(); - ~SessionManager(); - - // Create a new session from a model file path - std::string createSession(const char *model_path, void *options); - - // Close and remove a session - bool closeSession(const std::string &session_id); - - // Get session info - bool hasSession(const std::string &session_id); - - // Get input names for a session - std::vector getInputNames(const std::string &session_id); - - // Get output names for a session - std::vector getOutputNames(const std::string &session_id); - - // Get model metadata for a session - ModelMetadata getModelMetadata(const std::string &session_id); - - // Get input tensor info for a session - std::vector getInputInfo(const std::string &session_id); - - // Get output tensor info for a session - std::vector getOutputInfo(const std::string &session_id); - - // Run inference with a session using provided input names - std::vector runInference(const std::string &session_id, const std::vector &input_tensors, - const std::vector &input_names, - Ort::RunOptions *run_options = nullptr); - - // Helper method to get element type string - static const char *getElementTypeString(ONNXTensorElementDataType element_type); - -private: - // Generate a unique session ID - std::string generateSessionId(); - - // Map of session IDs to session info - std::map sessions_; - - // Counter for generating unique session IDs - int next_session_id_; - - // Mutex for thread safety - std::mutex mutex_; - - // ONNX Runtime environment - Ort::Env env_; -}; - -#endif // SESSION_MANAGER_H \ No newline at end of file diff --git a/app/vendor/flutter_onnxruntime/linux/src/tensor_manager.cc b/app/vendor/flutter_onnxruntime/linux/src/tensor_manager.cc deleted file mode 100644 index 9dab5f7..0000000 --- a/app/vendor/flutter_onnxruntime/linux/src/tensor_manager.cc +++ /dev/null @@ -1,848 +0,0 @@ -// Copyright (c) MASIC AI -// All rights reserved. -// -// This source code is licensed under the license found in the -// LICENSE file in the root directory of this source tree. - -#include "tensor_manager.h" -#include "session_manager.h" -#include "value_conversion.h" - -TensorManager::TensorManager() - : next_tensor_id_(1), memory_info_(Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault)) {} - -TensorManager::~TensorManager() { - std::lock_guard lock(mutex_); - tensors_.clear(); - tensor_types_.clear(); - tensor_shapes_.clear(); - tensor_data_buffers_.clear(); -} - -std::string TensorManager::generateTensorId() { return "tensor_" + std::to_string(next_tensor_id_++); } - -std::string TensorManager::createFloat32Tensor(const std::vector &data, const std::vector &shape) { - std::lock_guard lock(mutex_); - - try { - // Create a unique tensor ID - std::string tensor_id = generateTensorId(); - // Store data in a managed buffer so it is freed when the tensor is released - std::vector buffer(data.size() * sizeof(float)); - std::memcpy(buffer.data(), data.data(), data.size() * sizeof(float)); - float *tensor_data = reinterpret_cast(buffer.data()); - // Create a new tensor with the buffer-backed data - auto tensor = Ort::Value::CreateTensor(memory_info_, tensor_data, data.size(), shape.data(), shape.size()); - // Store the tensor, its type, shape, and backing buffer - tensors_[tensor_id] = std::make_unique(std::move(tensor)); - tensor_data_buffers_[tensor_id] = std::move(buffer); - tensor_types_[tensor_id] = "float32"; - tensor_shapes_[tensor_id] = shape; - - return tensor_id; - } catch (const Ort::Exception &e) { - throw; - } -} - -std::string TensorManager::createInt32Tensor(const std::vector &data, const std::vector &shape) { - std::lock_guard lock(mutex_); - - try { - // Create a unique tensor ID - std::string tensor_id = generateTensorId(); - // Store data in a managed buffer so it is freed when the tensor is released - std::vector buffer(data.size() * sizeof(int32_t)); - std::memcpy(buffer.data(), data.data(), data.size() * sizeof(int32_t)); - int32_t *tensor_data = reinterpret_cast(buffer.data()); - // Create a new tensor with the buffer-backed data - auto tensor = Ort::Value::CreateTensor(memory_info_, tensor_data, data.size(), shape.data(), shape.size()); - // Store the tensor, its type, shape, and backing buffer - tensors_[tensor_id] = std::make_unique(std::move(tensor)); - tensor_data_buffers_[tensor_id] = std::move(buffer); - tensor_types_[tensor_id] = "int32"; - tensor_shapes_[tensor_id] = shape; - - return tensor_id; - } catch (const Ort::Exception &e) { - throw; - } -} - -std::string TensorManager::createInt64Tensor(const std::vector &data, const std::vector &shape) { - std::lock_guard lock(mutex_); - - try { - // Create a unique tensor ID - std::string tensor_id = generateTensorId(); - // Store data in a managed buffer so it is freed when the tensor is released - std::vector buffer(data.size() * sizeof(int64_t)); - std::memcpy(buffer.data(), data.data(), data.size() * sizeof(int64_t)); - int64_t *tensor_data = reinterpret_cast(buffer.data()); - // Create a new tensor with the buffer-backed data - auto tensor = Ort::Value::CreateTensor(memory_info_, tensor_data, data.size(), shape.data(), shape.size()); - // Store the tensor, its type, shape, and backing buffer - tensors_[tensor_id] = std::make_unique(std::move(tensor)); - tensor_data_buffers_[tensor_id] = std::move(buffer); - tensor_types_[tensor_id] = "int64"; - tensor_shapes_[tensor_id] = shape; - - return tensor_id; - } catch (const Ort::Exception &e) { - throw; - } -} - -std::string TensorManager::createUint8Tensor(const std::vector &data, const std::vector &shape) { - std::lock_guard lock(mutex_); - - try { - // Create a unique tensor ID - std::string tensor_id = generateTensorId(); - // Store data in a managed buffer so it is freed when the tensor is released - std::vector buffer(data.size() * sizeof(uint8_t)); - std::memcpy(buffer.data(), data.data(), data.size() * sizeof(uint8_t)); - // Create a new tensor with the buffer-backed data - auto tensor = - Ort::Value::CreateTensor(memory_info_, buffer.data(), data.size(), shape.data(), shape.size()); - // Store the tensor, its type, shape, and backing buffer - tensors_[tensor_id] = std::make_unique(std::move(tensor)); - tensor_data_buffers_[tensor_id] = std::move(buffer); - tensor_types_[tensor_id] = "uint8"; - tensor_shapes_[tensor_id] = shape; - - return tensor_id; - } catch (const Ort::Exception &e) { - throw; - } -} - -std::string TensorManager::createBoolTensor(const std::vector &data, const std::vector &shape) { - std::lock_guard lock(mutex_); - - try { - // Create a unique tensor ID - std::string tensor_id = generateTensorId(); - // Store data in a managed buffer (std::vector is specialized and can't be used directly) - std::vector buffer(data.size() * sizeof(bool)); - bool *tensor_data = reinterpret_cast(buffer.data()); - for (size_t i = 0; i < data.size(); i++) { - tensor_data[i] = data[i]; - } - // Create a new tensor with the buffer-backed data - auto tensor = Ort::Value::CreateTensor(memory_info_, tensor_data, data.size(), shape.data(), shape.size()); - // Store the tensor, its type, shape, and backing buffer - tensors_[tensor_id] = std::make_unique(std::move(tensor)); - tensor_data_buffers_[tensor_id] = std::move(buffer); - tensor_types_[tensor_id] = "bool"; - tensor_shapes_[tensor_id] = shape; - - return tensor_id; - } catch (const Ort::Exception &e) { - throw; - } -} - -std::string TensorManager::createStringTensor(const std::vector &data, const std::vector &shape) { - std::lock_guard lock(mutex_); - - try { - // Create a unique tensor ID - std::string tensor_id = generateTensorId(); - - // Create a C-style array of const char* for ONNX Runtime - const char **tensor_data = new const char *[data.size()]; - for (size_t i = 0; i < data.size(); i++) { - tensor_data[i] = data[i].c_str(); - } - - OrtAllocator *allocator = nullptr; - // Follow the test at: - // https://github.com/microsoft/onnxruntime/blob/4adef01e741b2327188279dcd63bc55c5d2307e9/onnxruntime/test/shared_lib/test_inference.cc#L4278 - // create allocator with default options - Ort::ThrowOnError(Ort::GetApi().GetAllocatorWithDefaultOptions(&allocator)); - auto tensor = Ort::Value::CreateTensor(allocator, shape.data(), shape.size(), ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING); - - // Fill the tensor with string data - Ort::ThrowOnError(Ort::GetApi().FillStringTensor(tensor, tensor_data, data.size())); - - delete[] tensor_data; - - tensors_[tensor_id] = std::make_unique(std::move(tensor)); - tensor_types_[tensor_id] = "string"; - tensor_shapes_[tensor_id] = shape; - - return tensor_id; - } catch (const Ort::Exception &e) { - throw; - } -} - -FlValue *TensorManager::getTensorData(const std::string &tensor_id) { - std::lock_guard lock(mutex_); - - // Check if the tensor exists - auto tensor_it = tensors_.find(tensor_id); - auto type_it = tensor_types_.find(tensor_id); - auto shape_it = tensor_shapes_.find(tensor_id); - - if (tensor_it == tensors_.end() || type_it == tensor_types_.end() || shape_it == tensor_shapes_.end()) { - // Tensor not found - return fl_value_new_null(); - } - - // Create result map - g_autoptr(FlValue) result = fl_value_new_map(); - - try { - // Get tensor type - const std::string &tensor_type = type_it->second; - - // Get tensor shape - const std::vector &shape = shape_it->second; - - // Convert shape to FlValue - FlValue *shape_list = fl_value_new_list(); - for (const auto &dim : shape) { - fl_value_append_take(shape_list, fl_value_new_int(static_cast(dim))); - } - - // Set shape and type in result - fl_value_set_string_take(result, "shape", shape_list); - fl_value_set_string_take(result, "dataType", fl_value_new_string(tensor_type.c_str())); - // Get tensor info - Ort::Value *tensor = tensor_it->second.get(); - Ort::TensorTypeAndShapeInfo tensor_info = tensor->GetTensorTypeAndShapeInfo(); - size_t elem_count = tensor_info.GetElementCount(); - - // Handle different tensor types - if (tensor_type == "float32") { - // Get float data from tensor - float *tensor_data = tensor->GetTensorMutableData(); - - // Create typed data list (Float32List) - FlValue *data_list = fl_value_new_float32_list(tensor_data, elem_count); - - // Set data in result - fl_value_set_string_take(result, "data", data_list); - } else if (tensor_type == "int32") { - // Get int32 data from tensor - int32_t *tensor_data = tensor->GetTensorMutableData(); - - // Create typed data list (Int32List) - FlValue *data_list = fl_value_new_int32_list(tensor_data, elem_count); - - // Set data in result - fl_value_set_string_take(result, "data", data_list); - } else if (tensor_type == "int64") { - // Get int64 data from tensor - int64_t *tensor_data = tensor->GetTensorMutableData(); - - // Create typed data list (Int64List) - FlValue *data_list = fl_value_new_int64_list(tensor_data, elem_count); - - // Set data in result - fl_value_set_string_take(result, "data", data_list); - } else if (tensor_type == "uint8") { - // Get uint8 data from tensor - uint8_t *tensor_data = tensor->GetTensorMutableData(); - - // Create typed data list (Uint8List) - FlValue *data_list = fl_value_new_uint8_list(tensor_data, elem_count); - - // Set data in result - fl_value_set_string_take(result, "data", data_list); - } else if (tensor_type == "bool") { - // Get bool data from tensor - bool *tensor_data = tensor->GetTensorMutableData(); - - // Create data list and copy values - convert bool to int for Flutter compatibility - std::vector data_vec(tensor_data, tensor_data + elem_count); - FlValue *data_list = vector_to_fl_value(data_vec); - - // Set data in result - fl_value_set_string_take(result, "data", data_list); - } else if (tensor_type == "string") { - // Create a list for the strings - FlValue *data_list = fl_value_new_list(); - - // Extract strings from the tensor - for (size_t i = 0; i < elem_count; i++) { - std::string s = tensor->GetStringTensorElement(i); - // Add the string to the list - fl_value_append_take(data_list, fl_value_new_string(s.c_str())); - } - - // Set data in result - fl_value_set_string_take(result, "data", data_list); - } else { - // Unsupported tensor type - throw std::runtime_error("Unsupported tensor type: " + tensor_type); - } - } catch (const Ort::Exception &e) { - throw std::runtime_error(e.what()); - } - - return fl_value_ref(result); -} - -bool TensorManager::releaseTensor(const std::string &tensor_id) { - std::lock_guard lock(mutex_); - - auto tensor_it = tensors_.find(tensor_id); - auto type_it = tensor_types_.find(tensor_id); - auto shape_it = tensor_shapes_.find(tensor_id); - auto buffer_it = tensor_data_buffers_.find(tensor_id); - - if (tensor_it == tensors_.end()) { - return false; - } - - // Remove tensor, type, shape, and buffer - tensors_.erase(tensor_it); - if (type_it != tensor_types_.end()) { - tensor_types_.erase(type_it); - } - if (shape_it != tensor_shapes_.end()) { - tensor_shapes_.erase(shape_it); - } - if (buffer_it != tensor_data_buffers_.end()) { - tensor_data_buffers_.erase(buffer_it); - } - - return true; -} - -Ort::Value *TensorManager::getTensor(const std::string &tensor_id) { - std::lock_guard lock(mutex_); - - auto it = tensors_.find(tensor_id); - if (it == tensors_.end()) { - return nullptr; - } - - return it->second.get(); -} - -void TensorManager::storeTensor(const std::string &tensor_id, Ort::Value &&tensor) { - std::lock_guard lock(mutex_); - - try { - // Store the tensor - tensors_[tensor_id] = std::make_unique(std::move(tensor)); - - // Get tensor info to store type and shape - Ort::TensorTypeAndShapeInfo tensor_info = tensors_[tensor_id]->GetTensorTypeAndShapeInfo(); - - // Get and store the tensor shape - auto shape = tensor_info.GetShape(); - tensor_shapes_[tensor_id] = shape; - - // Get and store the tensor type - ONNXTensorElementDataType element_type = tensor_info.GetElementType(); - tensor_types_[tensor_id] = SessionManager::getElementTypeString(element_type); - } catch (const std::exception &e) { - // Handle exception - maybe log it - } -} - -std::string TensorManager::getTensorType(const std::string &tensor_id) { - std::lock_guard lock(mutex_); - return tensor_types_.at(tensor_id); -} - -std::vector TensorManager::getTensorShape(const std::string &tensor_id) { - std::lock_guard lock(mutex_); - return tensor_shapes_.at(tensor_id); -} - -std::string TensorManager::convertTensor(const std::string &tensor_id, const std::string &target_type) { - - std::lock_guard lock(mutex_); - - // Check if the tensor exists - auto tensor_it = tensors_.find(tensor_id); - auto type_it = tensor_types_.find(tensor_id); - auto shape_it = tensor_shapes_.find(tensor_id); - - if (tensor_it == tensors_.end() || type_it == tensor_types_.end() || shape_it == tensor_shapes_.end()) { - throw std::runtime_error("Tensor not found"); - } - const std::string &source_type = type_it->second; - - // If the target type is the same as the source type, just clone the tensor - if (source_type == target_type) { - - // Clone the tensor (returns ClonedTensor with managed buffer) - auto cloned = cloneTensorLocked(tensor_id); - // Create a new tensor ID - std::string new_tensor_id = generateTensorId(); - tensors_[new_tensor_id] = std::make_unique(std::move(cloned.value)); - if (!cloned.buffer.empty()) { - tensor_data_buffers_[new_tensor_id] = std::move(cloned.buffer); - } - - // Store the type and shape - Ort::Value *tensor = tensor_it->second.get(); - Ort::TensorTypeAndShapeInfo tensor_info = tensor->GetTensorTypeAndShapeInfo(); - std::vector shape = tensor_info.GetShape(); - tensor_types_[new_tensor_id] = source_type; - tensor_shapes_[new_tensor_id] = shape; - - return new_tensor_id; - } - - // Convert based on the source type - if (source_type == "float32") { - return convertFloat32To(tensor_id, target_type); - } else if (source_type == "int32") { - return convertInt32To(tensor_id, target_type); - } else if (source_type == "int64") { - return convertInt64To(tensor_id, target_type); - } else if (source_type == "uint8") { - return convertUint8To(tensor_id, target_type); - } else if (source_type == "bool") { - return convertBoolTo(tensor_id, target_type); - } - - throw std::runtime_error("Unsupported type conversion: " + source_type + " to " + target_type); -} - -std::string TensorManager::convertFloat32To(const std::string &tensor_id, const std::string &target_type) { - // Get the tensor - Ort::Value *tensor = tensors_[tensor_id].get(); - Ort::TensorTypeAndShapeInfo tensor_info = tensor->GetTensorTypeAndShapeInfo(); - size_t elem_count = tensor_info.GetElementCount(); - std::vector shape = tensor_info.GetShape(); - float *data = tensor->GetTensorMutableData(); - - // Create a new tensor ID - std::string new_tensor_id = generateTensorId(); - - // Convert to the target type - if (target_type == "int32") { - // Convert float32 to int32 - std::vector buffer(elem_count * sizeof(int32_t)); - int32_t *new_data = reinterpret_cast(buffer.data()); - for (size_t i = 0; i < elem_count; i++) { - // Round float to int - new_data[i] = static_cast(data[i] + (data[i] >= 0 ? 0.5f : -0.5f)); - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else if (target_type == "int64") { - // Convert float32 to int64 - std::vector buffer(elem_count * sizeof(int64_t)); - int64_t *new_data = reinterpret_cast(buffer.data()); - for (size_t i = 0; i < elem_count; i++) { - // Round float to int64 - new_data[i] = static_cast(data[i] + (data[i] >= 0 ? 0.5f : -0.5f)); - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else if (target_type == "uint8") { - // Convert float32 to uint8 - std::vector buffer(elem_count * sizeof(uint8_t)); - uint8_t *new_data = buffer.data(); - for (size_t i = 0; i < elem_count; i++) { - // Clamp between 0 and 255 - float val = data[i] < 0 ? 0 : (data[i] > 255 ? 255 : data[i] + 0.5f); - new_data[i] = static_cast(val); - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else if (target_type == "bool") { - // Convert float32 to bool - std::vector buffer(elem_count * sizeof(bool)); - bool *new_data = reinterpret_cast(buffer.data()); - for (size_t i = 0; i < elem_count; i++) { - new_data[i] = data[i] != 0.0f; - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else { - throw std::runtime_error("Unsupported type: " + target_type); - } - - // Store the shape - tensor_shapes_[new_tensor_id] = shape; - tensor_types_[new_tensor_id] = target_type; - - return new_tensor_id; -} - -std::string TensorManager::convertInt32To(const std::string &tensor_id, const std::string &target_type) { - // Get the tensor - Ort::Value *tensor = tensors_[tensor_id].get(); - Ort::TensorTypeAndShapeInfo tensor_info = tensor->GetTensorTypeAndShapeInfo(); - size_t elem_count = tensor_info.GetElementCount(); - std::vector shape = tensor_info.GetShape(); - int32_t *data = tensor->GetTensorMutableData(); - - // Create a new tensor ID - std::string new_tensor_id = generateTensorId(); - - // Convert to the target type - if (target_type == "float32") { - // Convert int32 to float32 - std::vector buffer(elem_count * sizeof(float)); - float *new_data = reinterpret_cast(buffer.data()); - for (size_t i = 0; i < elem_count; i++) { - new_data[i] = static_cast(data[i]); - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else if (target_type == "int64") { - // Convert int32 to int64 - std::vector buffer(elem_count * sizeof(int64_t)); - int64_t *new_data = reinterpret_cast(buffer.data()); - for (size_t i = 0; i < elem_count; i++) { - new_data[i] = static_cast(data[i]); - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else if (target_type == "uint8") { - // Convert int32 to uint8 - std::vector buffer(elem_count * sizeof(uint8_t)); - uint8_t *new_data = buffer.data(); - for (size_t i = 0; i < elem_count; i++) { - // Clamp between 0 and 255 - int32_t val = data[i] < 0 ? 0 : (data[i] > 255 ? 255 : data[i]); - new_data[i] = static_cast(val); - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else if (target_type == "bool") { - // Convert int32 to bool - std::vector buffer(elem_count * sizeof(bool)); - bool *new_data = reinterpret_cast(buffer.data()); - for (size_t i = 0; i < elem_count; i++) { - new_data[i] = data[i] != 0; - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else { - throw std::runtime_error("Unsupported type: " + target_type); - } - - // Store the shape - tensor_shapes_[new_tensor_id] = shape; - tensor_types_[new_tensor_id] = target_type; - - return new_tensor_id; -} - -std::string TensorManager::convertInt64To(const std::string &tensor_id, const std::string &target_type) { - // Get the tensor - Ort::Value *tensor = tensors_[tensor_id].get(); - Ort::TensorTypeAndShapeInfo tensor_info = tensor->GetTensorTypeAndShapeInfo(); - size_t elem_count = tensor_info.GetElementCount(); - std::vector shape = tensor_info.GetShape(); - int64_t *data = tensor->GetTensorMutableData(); - - // Create a new tensor ID - std::string new_tensor_id = generateTensorId(); - - // Convert to the target type - if (target_type == "float32") { - // Convert int64 to float32 - std::vector buffer(elem_count * sizeof(float)); - float *new_data = reinterpret_cast(buffer.data()); - for (size_t i = 0; i < elem_count; i++) { - // Note: potential precision loss for large int64 values - new_data[i] = static_cast(data[i]); - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else if (target_type == "int32") { - // Convert int64 to int32 - std::vector buffer(elem_count * sizeof(int32_t)); - int32_t *new_data = reinterpret_cast(buffer.data()); - for (size_t i = 0; i < elem_count; i++) { - // Clamp to int32 range to prevent overflow - int64_t val = data[i]; - if (val > INT32_MAX) - val = INT32_MAX; - if (val < INT32_MIN) - val = INT32_MIN; - new_data[i] = static_cast(val); - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else if (target_type == "uint8") { - // Convert int64 to uint8 - std::vector buffer(elem_count * sizeof(uint8_t)); - uint8_t *new_data = buffer.data(); - for (size_t i = 0; i < elem_count; i++) { - // Clamp between 0 and 255 - int64_t val = data[i] < 0 ? 0 : (data[i] > 255 ? 255 : data[i]); - new_data[i] = static_cast(val); - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else if (target_type == "bool") { - // Convert int64 to bool - std::vector buffer(elem_count * sizeof(bool)); - bool *new_data = reinterpret_cast(buffer.data()); - for (size_t i = 0; i < elem_count; i++) { - new_data[i] = data[i] != 0; - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else { - throw std::runtime_error("Unsupported type: " + target_type); - } - - // Store the shape - tensor_shapes_[new_tensor_id] = shape; - tensor_types_[new_tensor_id] = target_type; - - return new_tensor_id; -} - -std::string TensorManager::convertUint8To(const std::string &tensor_id, const std::string &target_type) { - // Get the tensor - Ort::Value *tensor = tensors_[tensor_id].get(); - Ort::TensorTypeAndShapeInfo tensor_info = tensor->GetTensorTypeAndShapeInfo(); - size_t elem_count = tensor_info.GetElementCount(); - std::vector shape = tensor_info.GetShape(); - uint8_t *data = tensor->GetTensorMutableData(); - - // Create a new tensor ID - std::string new_tensor_id = generateTensorId(); - - // Convert to the target type - if (target_type == "float32") { - // Convert uint8 to float32 - std::vector buffer(elem_count * sizeof(float)); - float *new_data = reinterpret_cast(buffer.data()); - for (size_t i = 0; i < elem_count; i++) { - new_data[i] = static_cast(data[i]); - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else if (target_type == "int32") { - // Convert uint8 to int32 - std::vector buffer(elem_count * sizeof(int32_t)); - int32_t *new_data = reinterpret_cast(buffer.data()); - for (size_t i = 0; i < elem_count; i++) { - new_data[i] = static_cast(data[i]); - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else if (target_type == "int64") { - // Convert uint8 to int64 - std::vector buffer(elem_count * sizeof(int64_t)); - int64_t *new_data = reinterpret_cast(buffer.data()); - for (size_t i = 0; i < elem_count; i++) { - new_data[i] = static_cast(data[i]); - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else if (target_type == "bool") { - // Convert uint8 to bool - std::vector buffer(elem_count * sizeof(bool)); - bool *new_data = reinterpret_cast(buffer.data()); - for (size_t i = 0; i < elem_count; i++) { - new_data[i] = data[i] != 0; - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else { - throw std::runtime_error("Unsupported type: " + target_type); - } - - // Store the shape - tensor_shapes_[new_tensor_id] = shape; - tensor_types_[new_tensor_id] = target_type; - - return new_tensor_id; -} - -std::string TensorManager::convertBoolTo(const std::string &tensor_id, const std::string &target_type) { - // Get the tensor - Ort::Value *tensor = tensors_[tensor_id].get(); - Ort::TensorTypeAndShapeInfo tensor_info = tensor->GetTensorTypeAndShapeInfo(); - size_t elem_count = tensor_info.GetElementCount(); - std::vector shape = tensor_info.GetShape(); - bool *data = tensor->GetTensorMutableData(); - - // Create a new tensor ID - std::string new_tensor_id = generateTensorId(); - - // Convert to the target type - if (target_type == "float32") { - // Convert bool to float32 - std::vector buffer(elem_count * sizeof(float)); - float *new_data = reinterpret_cast(buffer.data()); - for (size_t i = 0; i < elem_count; i++) { - new_data[i] = data[i] ? 1.0f : 0.0f; - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else if (target_type == "int32") { - // Convert bool to int32 - std::vector buffer(elem_count * sizeof(int32_t)); - int32_t *new_data = reinterpret_cast(buffer.data()); - for (size_t i = 0; i < elem_count; i++) { - new_data[i] = data[i] ? 1 : 0; - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else if (target_type == "int64") { - // Convert bool to int64 - std::vector buffer(elem_count * sizeof(int64_t)); - int64_t *new_data = reinterpret_cast(buffer.data()); - for (size_t i = 0; i < elem_count; i++) { - new_data[i] = data[i] ? 1 : 0; - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else if (target_type == "uint8") { - // Convert bool to uint8 - std::vector buffer(elem_count * sizeof(uint8_t)); - uint8_t *new_data = buffer.data(); - for (size_t i = 0; i < elem_count; i++) { - new_data[i] = data[i] ? 1 : 0; - } - auto new_tensor = Ort::Value::CreateTensor(memory_info_, new_data, elem_count, shape.data(), shape.size()); - tensors_[new_tensor_id] = std::make_unique(std::move(new_tensor)); - tensor_data_buffers_[new_tensor_id] = std::move(buffer); - } else { - throw std::runtime_error("Unsupported type: " + target_type); - } - - // Store the shape - tensor_shapes_[new_tensor_id] = shape; - tensor_types_[new_tensor_id] = target_type; - - return new_tensor_id; -} - -ClonedTensor TensorManager::cloneTensor(const std::string &tensor_id) { - std::lock_guard lock(mutex_); - - return cloneTensorLocked(tensor_id); -} - -ClonedTensor TensorManager::cloneTensorLocked(const std::string &tensor_id) { - // Find the tensor - auto tensor_it = tensors_.find(tensor_id); - auto type_it = tensor_types_.find(tensor_id); - auto shape_it = tensor_shapes_.find(tensor_id); - - if (tensor_it == tensors_.end() || type_it == tensor_types_.end() || shape_it == tensor_shapes_.end()) { - throw std::runtime_error("Tensor not found: " + tensor_id); - } - - Ort::Value *tensor_ptr = tensor_it->second.get(); - const std::string &tensor_type = type_it->second; - const std::vector &shape = shape_it->second; - - // Get tensor info - Ort::TensorTypeAndShapeInfo tensor_info = tensor_ptr->GetTensorTypeAndShapeInfo(); - size_t element_count = tensor_info.GetElementCount(); - - // Create a new tensor with the same data as the original, backed by a managed buffer - if (tensor_type == "float32") { - float *data = tensor_ptr->GetTensorMutableData(); - std::vector buffer(element_count * sizeof(float)); - std::memcpy(buffer.data(), data, element_count * sizeof(float)); - float *new_data = reinterpret_cast(buffer.data()); - - ClonedTensor result; - result.value = Ort::Value::CreateTensor(memory_info_, new_data, element_count, shape.data(), shape.size()); - result.buffer = std::move(buffer); - return result; - } else if (tensor_type == "int32") { - int32_t *data = tensor_ptr->GetTensorMutableData(); - std::vector buffer(element_count * sizeof(int32_t)); - std::memcpy(buffer.data(), data, element_count * sizeof(int32_t)); - int32_t *new_data = reinterpret_cast(buffer.data()); - - ClonedTensor result; - result.value = Ort::Value::CreateTensor(memory_info_, new_data, element_count, shape.data(), shape.size()); - result.buffer = std::move(buffer); - return result; - } else if (tensor_type == "int64") { - int64_t *data = tensor_ptr->GetTensorMutableData(); - std::vector buffer(element_count * sizeof(int64_t)); - std::memcpy(buffer.data(), data, element_count * sizeof(int64_t)); - int64_t *new_data = reinterpret_cast(buffer.data()); - - ClonedTensor result; - result.value = Ort::Value::CreateTensor(memory_info_, new_data, element_count, shape.data(), shape.size()); - result.buffer = std::move(buffer); - return result; - } else if (tensor_type == "uint8") { - uint8_t *data = tensor_ptr->GetTensorMutableData(); - std::vector buffer(element_count * sizeof(uint8_t)); - std::memcpy(buffer.data(), data, element_count * sizeof(uint8_t)); - - ClonedTensor result; - result.value = - Ort::Value::CreateTensor(memory_info_, buffer.data(), element_count, shape.data(), shape.size()); - result.buffer = std::move(buffer); - return result; - } else if (tensor_type == "bool") { - bool *data = tensor_ptr->GetTensorMutableData(); - std::vector buffer(element_count * sizeof(bool)); - std::memcpy(buffer.data(), data, element_count * sizeof(bool)); - bool *new_data = reinterpret_cast(buffer.data()); - - ClonedTensor result; - result.value = Ort::Value::CreateTensor(memory_info_, new_data, element_count, shape.data(), shape.size()); - result.buffer = std::move(buffer); - return result; - } else if (tensor_type == "string") { - // Extract strings from the tensor - std::vector data_vec; - data_vec.reserve(element_count); - for (size_t i = 0; i < element_count; i++) { - std::string s = tensor_ptr->GetStringTensorElement(i); - data_vec.push_back(s); - } - - // Create a C-style array of const char* for ONNX Runtime - const char **new_tensor_data = new const char *[data_vec.size()]; - for (size_t i = 0; i < data_vec.size(); i++) { - new_tensor_data[i] = data_vec[i].c_str(); - } - OrtAllocator *allocator = nullptr; - // Follow the test at: - // https://github.com/microsoft/onnxruntime/blob/4adef01e741b2327188279dcd63bc55c5d2307e9/onnxruntime/test/shared_lib/test_inference.cc#L4278 - // create allocator with default options - Ort::ThrowOnError(Ort::GetApi().GetAllocatorWithDefaultOptions(&allocator)); - auto new_tensor = - Ort::Value::CreateTensor(allocator, shape.data(), shape.size(), ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING); - // Fill the tensor with string data - Ort::ThrowOnError(Ort::GetApi().FillStringTensor(new_tensor, new_tensor_data, data_vec.size())); - delete[] new_tensor_data; - - // String tensors use ORT's allocator, no external buffer needed - ClonedTensor result; - result.value = std::move(new_tensor); - return result; - } else { - throw std::runtime_error("Unsupported tensor type: " + tensor_type); - } -} diff --git a/app/vendor/flutter_onnxruntime/linux/src/tensor_manager.h b/app/vendor/flutter_onnxruntime/linux/src/tensor_manager.h deleted file mode 100644 index 9b145b0..0000000 --- a/app/vendor/flutter_onnxruntime/linux/src/tensor_manager.h +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (c) MASIC AI -// All rights reserved. -// -// This source code is licensed under the license found in the -// LICENSE file in the root directory of this source tree. - -#ifndef TENSOR_MANAGER_H -#define TENSOR_MANAGER_H - -#include -#include -#include -#include -#include -#include -#include - -// Forward declare SessionManager -class SessionManager; - -// Holds a cloned Ort::Value together with its backing data buffer. -// When this struct goes out of scope, both the tensor and its memory are freed. -// Field order matters: buffer is declared first so that value (declared second) -// is destroyed first, ensuring the Ort::Value is released before its backing memory. -struct ClonedTensor { - std::vector buffer; - Ort::Value value{nullptr}; -}; - -// Class to manage tensor data -class TensorManager { -public: - TensorManager(); - ~TensorManager(); - - // Disallow copy and assign - TensorManager(const TensorManager &) = delete; - TensorManager &operator=(const TensorManager &) = delete; - - // Create a tensor from Float32List data - std::string createFloat32Tensor(const std::vector &data, const std::vector &shape); - - // Create a tensor from Int32List data - std::string createInt32Tensor(const std::vector &data, const std::vector &shape); - - // Create a tensor from Int64List data - std::string createInt64Tensor(const std::vector &data, const std::vector &shape); - - // Create a tensor from Uint8List data - std::string createUint8Tensor(const std::vector &data, const std::vector &shape); - - // Create a tensor from Boolean data - std::string createBoolTensor(const std::vector &data, const std::vector &shape); - - // Create a tensor from String data - std::string createStringTensor(const std::vector &data, const std::vector &shape); - - // Convert between tensor formats - std::string convertTensor(const std::string &tensor_id, const std::string &target_type); - - // Convert float32 tensor to another type - std::string convertFloat32To(const std::string &tensor_id, const std::string &target_type); - - // Convert int32 tensor to another type - std::string convertInt32To(const std::string &tensor_id, const std::string &target_type); - - // Convert int64 tensor to another type - std::string convertInt64To(const std::string &tensor_id, const std::string &target_type); - - // Convert uint8 tensor to another type - std::string convertUint8To(const std::string &tensor_id, const std::string &target_type); - - // Convert bool tensor to another type - std::string convertBoolTo(const std::string &tensor_id, const std::string &target_type); - - // Store a tensor with a specific ID (used for output tensors) - void storeTensor(const std::string &tensor_id, Ort::Value &&tensor); - - // Get data from a tensor - FlValue *getTensorData(const std::string &tensor_id); - - // Release a tensor - bool releaseTensor(const std::string &tensor_id); - - // Get the OrtValue for a tensor ID - Ort::Value *getTensor(const std::string &tensor_id); - - // Get the type of a tensor - std::string getTensorType(const std::string &tensor_id); - - // Get the shape of a tensor - std::vector getTensorShape(const std::string &tensor_id); - - // Generate a unique tensor ID - std::string generateTensorId(); - - // Clone a tensor, returning both the Ort::Value and its backing buffer - ClonedTensor cloneTensor(const std::string &tensor_id); - -private: - ClonedTensor cloneTensorLocked(const std::string &tensor_id); - - // Map of tensor IDs to OrtValue objects - std::map> tensors_; - - // Map of tensor IDs to their data types - std::map tensor_types_; - - // Map of tensor IDs to their shapes - std::map> tensor_shapes_; - - // Memory for tensor data that needs to persist - std::map> tensor_data_buffers_; - - // Counter for generating unique tensor IDs - int next_tensor_id_; - - // Mutex for thread safety - std::mutex mutex_; - - // Memory info for CPU memory - Ort::MemoryInfo memory_info_{nullptr}; -}; - -#endif // TENSOR_MANAGER_H \ No newline at end of file diff --git a/app/vendor/flutter_onnxruntime/linux/src/value_conversion.cc b/app/vendor/flutter_onnxruntime/linux/src/value_conversion.cc deleted file mode 100644 index fdb5ed1..0000000 --- a/app/vendor/flutter_onnxruntime/linux/src/value_conversion.cc +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) MASIC AI -// All rights reserved. -// -// This source code is licensed under the license found in the -// LICENSE file in the root directory of this source tree. - -#include "value_conversion.h" - -// Implementation of the vector_to_fl_value specialization for strings -template <> FlValue *vector_to_fl_value(const std::vector &vec) { - FlValue *list = fl_value_new_list(); - - for (const auto &str : vec) { - fl_value_append_take(list, fl_value_new_string(str.c_str())); - } - - return list; -} - -// Implementation of the vector_to_fl_value specialization for floats -template <> FlValue *vector_to_fl_value(const std::vector &vec) { - FlValue *list = fl_value_new_list(); - - for (const auto &val : vec) { - fl_value_append_take(list, fl_value_new_float(val)); - } - - return list; -} - -// Implementation of the vector_to_fl_value specialization for int32_t -template <> FlValue *vector_to_fl_value(const std::vector &vec) { - FlValue *list = fl_value_new_list(); - - for (const auto &val : vec) { - fl_value_append_take(list, fl_value_new_int(val)); - } - - return list; -} - -// Implementation of the vector_to_fl_value specialization for int64_t -template <> FlValue *vector_to_fl_value(const std::vector &vec) { - FlValue *list = fl_value_new_list(); - - for (const auto &val : vec) { - fl_value_append_take(list, fl_value_new_int(val)); - } - - return list; -} - -// Implementation of the vector_to_fl_value specialization for uint8_t -template <> FlValue *vector_to_fl_value(const std::vector &vec) { - FlValue *list = fl_value_new_list(); - - for (const auto &val : vec) { - fl_value_append_take(list, fl_value_new_int(val)); - } - - return list; -} - -// Implementation of the vector_to_fl_value specialization for bool -template <> FlValue *vector_to_fl_value(const std::vector &vec) { - FlValue *list = fl_value_new_list(); - - for (size_t i = 0; i < vec.size(); i++) { - // Convert bool to int as Flutter expects - fl_value_append_take(list, fl_value_new_int(vec[i] ? 1 : 0)); - } - - return list; -} - -// Implementation of fl_value_to_map -std::map fl_value_to_map(FlValue *map_value) { - std::map result; - - if (map_value == nullptr || fl_value_get_type(map_value) != FL_VALUE_TYPE_MAP) { - return result; - } - - size_t size = fl_value_get_length(map_value); - - for (size_t i = 0; i < size; i++) { - FlValue *key = fl_value_get_map_key(map_value, i); - FlValue *value = fl_value_get_map_value(map_value, i); - - if (fl_value_get_type(key) == FL_VALUE_TYPE_STRING) { - result[fl_value_get_string(key)] = value; - } - } - - return result; -} \ No newline at end of file diff --git a/app/vendor/flutter_onnxruntime/linux/src/value_conversion.h b/app/vendor/flutter_onnxruntime/linux/src/value_conversion.h deleted file mode 100644 index 72ca620..0000000 --- a/app/vendor/flutter_onnxruntime/linux/src/value_conversion.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) MASIC AI -// All rights reserved. -// -// This source code is licensed under the license found in the -// LICENSE file in the root directory of this source tree. - -#ifndef VALUE_CONVERSION_H -#define VALUE_CONVERSION_H - -#include -#include -#include -#include - -// Convert a C++ vector to a FlValue -template FlValue *vector_to_fl_value(const std::vector &vec); - -// Specialization for string vectors -template <> FlValue *vector_to_fl_value(const std::vector &vec); - -// Specialization for int vectors -template <> FlValue *vector_to_fl_value(const std::vector &vec); - -// Specialization for float vectors -template <> FlValue *vector_to_fl_value(const std::vector &vec); - -// Specialization for int32_t vectors -template <> FlValue *vector_to_fl_value(const std::vector &vec); - -// Specialization for int64_t vectors -template <> FlValue *vector_to_fl_value(const std::vector &vec); - -// Specialization for uint8_t vectors -template <> FlValue *vector_to_fl_value(const std::vector &vec); - -// Specialization for bool vectors -template <> FlValue *vector_to_fl_value(const std::vector &vec); - -// Convert a FlValue map to a C++ map -std::map fl_value_to_map(FlValue *map_value); - -#endif // VALUE_CONVERSION_H \ No newline at end of file diff --git a/app/vendor/flutter_onnxruntime/pubspec.yaml b/app/vendor/flutter_onnxruntime/pubspec.yaml index cbdadc9..5dbc1d8 100644 --- a/app/vendor/flutter_onnxruntime/pubspec.yaml +++ b/app/vendor/flutter_onnxruntime/pubspec.yaml @@ -34,8 +34,6 @@ flutter: pluginClass: FlutterOnnxruntimePlugin ios: pluginClass: FlutterOnnxruntimePlugin - linux: - pluginClass: FlutterOnnxruntimePlugin web: pluginClass: FlutterOnnxruntimeWebPlugin fileName: web/flutter_onnxruntime_web_plugin.dart From 9f3fd4a02191d229d1ed757e875f4696f161c147 Mon Sep 17 00:00:00 2001 From: Jordan Date: Tue, 27 Oct 2026 12:23:22 -0600 Subject: [PATCH 2/2] build(linux): the library check must not trip pipefail when nothing is missing Co-Authored-By: Claude Opus 5.5 --- app/scripts/build_release_linux.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/scripts/build_release_linux.sh b/app/scripts/build_release_linux.sh index dd1d4b6..72cb9e3 100644 --- a/app/scripts/build_release_linux.sh +++ b/app/scripts/build_release_linux.sh @@ -152,7 +152,7 @@ echo "==> checking the bundle's libraries" dangling=$(find "$STAGE" -xtype l) [[ -z "$dangling" ]] || { echo "dangling symlinks in the bundle:" >&2; echo "$dangling" >&2; exit 1; } missing=$(for f in "$STAGE/relic_app" "$STAGE"/lib/*.so; do - LD_LIBRARY_PATH="$STAGE/lib" ldd "$f" 2>/dev/null | grep 'not found' | grep -v 'libjvm.so' | sed "s|^|$(basename "$f"): |" + LD_LIBRARY_PATH="$STAGE/lib" ldd "$f" 2>/dev/null | grep 'not found' | grep -v 'libjvm.so' | sed "s|^|$(basename "$f"): |" || true done) [[ -z "$missing" ]] || { echo "libraries the bundle needs but does not have:" >&2; echo "$missing" >&2; exit 1; }