Merge pull request #545 from dart-lang/merge-jnigen
Merge `package:jnigen` and `package:jni` into dart-lang/native.
diff --git a/.github/workflows/jnigen.yaml b/.github/workflows/jnigen.yaml
new file mode 100644
index 0000000..2deae7f
--- /dev/null
+++ b/.github/workflows/jnigen.yaml
@@ -0,0 +1,428 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# Note: There's a script under `jnigen/tool` which runs a subset of these
+# tests on local machine. It's a useful little script for checking the
+# code before making a PR. If you add a task here, you might want to add
+# the equivalent in that script as well.
+
+name: Dart CI
+
+on:
+ # Run on PRs and pushes to the default branch.
+ push:
+ branches: [main]
+ paths:
+ - '.github/workflows/jnigen.yaml'
+ - 'pkgs/jnigen/**'
+ - 'pkgs/jni/**'
+ pull_request:
+ branches: [main]
+ paths:
+ - '.github/workflows/jnigen.yaml'
+ - 'pkgs/jnigen/**'
+ - 'pkgs/jni/**'
+ schedule:
+ - cron: '0 0 * * 0'
+
+env:
+ PUB_ENVIRONMENT: bot.github
+
+jobs:
+ analyze_jnigen:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: ./pkgs/jnigen
+ strategy:
+ fail-fast: false
+ matrix:
+ sdk: [stable]
+ steps:
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
+ - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225
+ with:
+ channel: ${{ matrix.sdk }}
+ cache: true
+ cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
+ - uses: axel-op/googlejavaformat-action@fe78db8a90171b6a836449f8d0e982d5d71e5c5a
+ name: 'Check Java formatting with google-java-format'
+ with:
+ args: '--set-exit-if-changed'
+ - id: install
+ name: Install dependencies
+ run: dart pub get
+ - name: install dependencies for android test runner
+ run: flutter pub get
+ working-directory: ./pkgs/jnigen/android_test_runner
+ - name: Check formatting
+ run: dart format --output=none --set-exit-if-changed .
+ if: always() && steps.install.outcome == 'success'
+ - name: Analyze code
+ run: flutter analyze --fatal-infos
+ if: always() && steps.install.outcome == 'success'
+
+ test_jnigen:
+ needs: [analyze_jnigen]
+ runs-on: ${{ matrix.os }}
+ defaults:
+ run:
+ working-directory: ./pkgs/jnigen
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-latest]
+ sdk: [stable, beta]
+ steps:
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
+ - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225
+ with:
+ channel: ${{ matrix.sdk }}
+ cache: true
+ cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
+ - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0
+ with:
+ distribution: 'zulu'
+ java-version: '11'
+ cache: maven
+ ## Committed bindings are formatted with clang-format.
+ ## So this is required to format generated bindings identically
+ - name: install clang tools
+ run: |
+ sudo apt-get update -y
+ sudo apt-get install -y clang-format
+ - name: Install dependencies
+ run: dart pub get
+ - name: build in_app_java APK
+ run: flutter build apk --target-platform=android-arm64
+ working-directory: ./pkgs/jnigen/example/in_app_java
+ - name: build notification_plugin example APK
+ run: flutter build apk --target-platform=android-arm64
+ working-directory: ./pkgs/jnigen/example/notification_plugin/example
+ - name: Run summarizer tests
+ run: mvn surefire:test
+ working-directory: ./pkgs/jnigen/java
+ - name: Build summarizer
+ run: dart run jnigen:setup
+ - name: Generate runtime tests
+ run: dart run tool/generate_runtime_tests.dart
+ - name: Run VM tests
+ run: dart test --test-randomize-ordering-seed random
+ - name: Install coverage
+ run: dart pub global activate coverage
+ - name: Collect coverage
+ run: dart pub global run coverage:test_with_coverage
+ - name: Upload coverage
+ uses: coverallsapp/github-action@3dfc5567390f6fa9267c0ee9c251e4c8c3f18949
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ flag-name: jnigen_tests
+ parallel: true
+ path-to-lcov: ./pkgs/jnigen/coverage/lcov.info
+ if: ${{ matrix.sdk == 'stable' }}
+
+ analyze_jni:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: ./pkgs/jni
+ steps:
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
+ - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225
+ with:
+ channel: 'stable'
+ cache: true
+ cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
+ - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0
+ with:
+ distribution: 'zulu'
+ java-version: '11'
+ - uses: axel-op/googlejavaformat-action@fe78db8a90171b6a836449f8d0e982d5d71e5c5a
+ name: 'Check Java formatting with google-java-format'
+ with:
+ args: '--set-exit-if-changed'
+ - name: install clang tools & CMake
+ run: |
+ sudo apt-get update -y
+ sudo apt-get install -y clang-format build-essential cmake
+ - run: flutter pub get
+ - name: Check formatting
+ run: dart format --output=none --set-exit-if-changed .
+ - name: Run lints
+ run: flutter analyze --fatal-infos
+ - name: Check C code formatting using clang-format
+ run: clang-format --dry-run -Werror dartjni.c dartjni.h third_party/*.c third_party/*.h
+ working-directory: ./pkgs/jni/src
+ - name: verify that tool/generate_ide_files.dart generates a file
+ run: |
+ dart run tool/generate_ide_files.dart
+ ls src/compile_commands.json
+
+ test_jni:
+ runs-on: ubuntu-latest
+ needs: [analyze_jni]
+ defaults:
+ run:
+ working-directory: ./pkgs/jni
+ steps:
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
+ - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225
+ with:
+ channel: 'stable'
+ cache: true
+ cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
+ - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0
+ with:
+ distribution: 'zulu'
+ java-version: '11'
+ - run: |
+ sudo apt-get update -y
+ sudo apt-get install -y ninja-build libgtk-3-dev libclang-dev
+ - run: dart pub get
+ - run: dart run jni:setup
+ - name: Get dependencies
+ run: dart pub get
+ - name: Run tests
+ run: dart test --test-randomize-ordering-seed random
+ - name: Install coverage
+ run: dart pub global activate coverage
+ - name: Collect coverage
+ run: dart pub global run coverage:test_with_coverage
+ - name: Upload coverage
+ uses: coverallsapp/github-action@3dfc5567390f6fa9267c0ee9c251e4c8c3f18949
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ flag-name: jni_tests
+ parallel: true
+ path-to-lcov: ./pkgs/jni/coverage/lcov.info
+ # TODO(https://github.com/dart-lang/ffigen/issues/555): Ffigen generated
+ # on my machine has macOS specific stuff and CI does not.
+ # We should just generate the struct as opaque, but we currently can't.
+ #
+ # - name: regenerate & compare ffigen bindings
+ # ## Use git to verify no source files have changed
+ # run: |
+ # dart run tool/generate_ffi_bindings.dart
+ # git diff --exit-code -- lib/src/third_party src/third_party
+
+ ## Run tests for package:jni on windows, just to confirm it works.
+ ## Do not, for example, collect coverage or check formatting.
+ test_jni_windows_minimal:
+ needs: [analyze_jni]
+ runs-on: windows-latest
+ defaults:
+ run:
+ working-directory: ./pkgs/jni
+ steps:
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
+ - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225
+ with:
+ channel: 'stable'
+ cache: true
+ cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
+ - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0
+ with:
+ distribution: 'zulu'
+ java-version: '11'
+ - run: Add-Content $env:GITHUB_PATH "$env:JAVA_HOME\bin\server"
+ - run: dart pub get
+ - run: dart run jni:setup
+ - run: dart test --test-randomize-ordering-seed random
+
+ test_jnigen_windows_minimal:
+ needs: [analyze_jnigen]
+ runs-on: windows-latest
+ defaults:
+ run:
+ working-directory: ./pkgs/jnigen
+ steps:
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
+ - name: Setup clang
+ uses: egor-tensin/setup-clang@ef434b41eb33a70396fb336b1bae39c76d740c3d
+ with:
+ version: latest
+ platform: x64
+ - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225
+ with:
+ channel: 'stable'
+ cache: true
+ cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
+ - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0
+ with:
+ distribution: 'zulu'
+ java-version: '11'
+ - run: git config --global core.autocrlf true
+ - run: Add-Content $env:GITHUB_PATH "$env:JAVA_HOME\bin\server"
+ - run: dart pub get
+ - run: dart run jnigen:setup
+ - name: Build summarizer
+ run: dart run jnigen:setup
+ - name: Generate runtime tests
+ run: dart run tool/generate_runtime_tests.dart
+ - name: Run tests
+ run: dart test --test-randomize-ordering-seed random
+
+ test_jni_macos_minimal:
+ needs: [analyze_jni]
+ runs-on: macos-latest
+ defaults:
+ run:
+ working-directory: ./pkgs/jni
+ steps:
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
+ - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225
+ with:
+ channel: 'stable'
+ cache: true
+ cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
+ - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0
+ with:
+ distribution: 'temurin'
+ java-version: '11'
+ - run: dart pub get
+ - run: dart run jni:setup
+ - run: dart test --test-randomize-ordering-seed random
+
+ test_jnigen_macos_minimal:
+ needs: [analyze_jnigen]
+ runs-on: macos-latest
+ defaults:
+ run:
+ working-directory: ./pkgs/jnigen
+ steps:
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
+ - name: Setup clang format
+ uses: ConorMacBride/install-package@3e7ad059e07782ee54fa35f827df52aae0626f30
+ with:
+ brew: clang-format
+ - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225
+ with:
+ channel: 'stable'
+ cache: true
+ cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
+ - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0
+ with:
+ distribution: 'temurin'
+ java-version: '11'
+ - run: git config --global core.autocrlf true
+ - run: dart pub get
+ - name: Build summarizer
+ run: dart run jnigen:setup
+ - name: Generate runtime tests
+ run: dart run tool/generate_runtime_tests.dart
+ - name: Run tests
+ run: dart test --test-randomize-ordering-seed random
+
+ build_jni_example_linux:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: ./pkgs/jni/example
+ steps:
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
+ - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225
+ with:
+ channel: 'stable'
+ cache: true
+ cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
+ - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0
+ with:
+ distribution: 'zulu'
+ java-version: '11'
+ - run: |
+ sudo apt-get update -y
+ sudo apt-get install -y ninja-build libgtk-3-dev
+ - run: flutter config --enable-linux-desktop
+ - run: flutter pub get
+ - run: dart run jni:setup
+ - run: flutter build linux
+
+ build_jni_example_windows:
+ runs-on: windows-latest
+ defaults:
+ run:
+ working-directory: ./pkgs/jni/example
+ steps:
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
+ - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225
+ with:
+ channel: 'stable'
+ cache: true
+ cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
+ - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0
+ with:
+ distribution: 'zulu'
+ java-version: '11'
+ - run: flutter config --enable-windows-desktop
+ - run: flutter pub get
+ - run: flutter build windows
+
+ build_jni_example_android:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: ./pkgs/jni/example
+ steps:
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
+ - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0
+ with:
+ distribution: 'zulu'
+ java-version: '11'
+ - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225
+ with:
+ channel: 'stable'
+ cache: true
+ cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
+ - run: flutter pub get
+ - run: flutter build apk
+
+ run_pdfbox_example_linux:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: ./pkgs/jnigen/example/pdfbox_plugin
+ steps:
+ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
+ - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225
+ with:
+ channel: 'stable'
+ cache: true
+ cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
+ - uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0
+ with:
+ distribution: 'zulu'
+ java-version: '11'
+ - run: |
+ sudo apt-get update -y
+ sudo apt-get install -y ninja-build libgtk-3-dev clang-format
+ - run: flutter config --enable-linux-desktop
+ - run: dart pub get
+ - name: Generate full bindings
+ run: dart run jnigen --config jnigen.yaml --override classes="org.apache.pdfbox"
+ - name: Analyze generated bindings
+ run: |
+ flutter pub get # dart-analyze errors on flutter example
+ flutter analyze
+ - name: Run standalone example
+ run: |
+ dart pub get
+ dart run jni:setup
+ wget 'https://dart.dev/guides/language/specifications/DartLangSpec-v2.2.pdf'
+ dart run bin/pdf_info.dart DartLangSpec-v2.2.pdf
+ working-directory: ./pkgs/jnigen/example/pdfbox_plugin/dart_example
+ - name: Build flutter example for pdfbox_plugin
+ run: |
+ flutter pub get
+ flutter build linux
+ working-directory: ./pkgs/jnigen/example/pdfbox_plugin/example
+
+ coveralls_finish:
+ needs: [test_jnigen, test_jni]
+ runs-on: ubuntu-latest
+ steps:
+ - name: Coveralls finished
+ uses: coverallsapp/github-action@3dfc5567390f6fa9267c0ee9c251e4c8c3f18949
+ with:
+ github-token: ${{ secrets.github_token }}
+ parallel-finished: true
diff --git a/pkgs/jni/.gitignore b/pkgs/jni/.gitignore
new file mode 100644
index 0000000..ae8c6c2
--- /dev/null
+++ b/pkgs/jni/.gitignore
@@ -0,0 +1,32 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
+/pubspec.lock
+**/doc/api/
+.dart_tool/
+.packages
+build/
+
+.vscode/
\ No newline at end of file
diff --git a/pkgs/jni/.metadata b/pkgs/jni/.metadata
new file mode 100644
index 0000000..26fc23f
--- /dev/null
+++ b/pkgs/jni/.metadata
@@ -0,0 +1,39 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled.
+
+version:
+ revision: 676cefaaff197f27424942307668886253e1ec35
+ channel: stable
+
+project_type: plugin_ffi
+
+# Tracks metadata for the flutter migrate command
+migration:
+ platforms:
+ - platform: root
+ create_revision: 676cefaaff197f27424942307668886253e1ec35
+ base_revision: 676cefaaff197f27424942307668886253e1ec35
+ - platform: android
+ create_revision: 676cefaaff197f27424942307668886253e1ec35
+ base_revision: 676cefaaff197f27424942307668886253e1ec35
+ - platform: linux
+ create_revision: 676cefaaff197f27424942307668886253e1ec35
+ base_revision: 676cefaaff197f27424942307668886253e1ec35
+ - platform: macos
+ create_revision: 676cefaaff197f27424942307668886253e1ec35
+ base_revision: 676cefaaff197f27424942307668886253e1ec35
+ - platform: windows
+ create_revision: 676cefaaff197f27424942307668886253e1ec35
+ base_revision: 676cefaaff197f27424942307668886253e1ec35
+
+ # User provided section
+
+ # List of Local paths (relative to this file) that should be
+ # ignored by the migrate tool.
+ #
+ # Files that are not part of the templates will be ignored by default.
+ unmanaged_files:
+ - 'lib/main.dart'
+ - 'ios/Runner.xcodeproj/project.pbxproj'
diff --git a/pkgs/jni/CHANGELOG.md b/pkgs/jni/CHANGELOG.md
new file mode 100644
index 0000000..2065bb1
--- /dev/null
+++ b/pkgs/jni/CHANGELOG.md
@@ -0,0 +1,84 @@
+## 0.8.0-wip
+
+- **Breaking Change** ([#394](https://github.com/dart-lang/jnigen/issues/394)):
+ Converted various `Exception`s into `Error`s:
+ - `UseAfterReleaseException` -> `UseAfterReleaseError`
+ - `DoubleReleaseException` -> `DoubleReleaseError`
+ - `SpawnException` -> `JniError` (It's now a `sealed class`)
+ - `JNullException` -> `JNullError`
+ - `InvalidCallTypeException` -> `InvalidCallTypeError`
+ - `HelperNotFoundException` -> `HelperNotFoundError`
+ - `JvmExistsException` -> `JniVmExistsError`
+ - `NoJvmInstanceException` -> `NoJvmInstanceError`
+- **Breaking Change**: Removed `InvalidJStringException`.
+- **Breaking Change**: The default return `callType` of type parameter `int` for
+ methods such as `JObject.callMethodByName<int>` is now Java's `long` instead
+ of `int` to be consistent with the way arguments work.
+- **Breaking Change**: `JType` is now `sealed`.
+- **Breaking Change**: Primitive types and their type classes are now `final`.
+- **Breaking Change**: `JArray.filled` now uses the generated type class of the
+ `fill` object and not its Java runtime type.
+
+## 0.7.2
+- Fixed a bug where reading non-null terminated strings would overflow.
+
+## 0.7.1
+- Removed macOS Flutter plugin until package:jni supports it ([#41](https://github.com/dart-lang/jnigen/issues/41)).
+
+## 0.7.0
+
+- **Breaking Change** ([#387](https://github.com/dart-lang/jnigen/issues/387)):
+ Added `JBuffer` and `JByteBuffer` classes as default classes for
+ `java.nio.Buffer` and `java.nio.ByteBuffer` respectively.
+- **Breaking Change**: Made the type classes `final`.
+- Fixed a bug where `addAll`, `removeAll` and `retainAll` in `JSet` would run
+ their respective operation twice.
+- Fixed a bug where `JList.insertAll` would not throw the potentially thrown
+ Java exception.
+
+## 0.6.1
+
+- Depend on the stable version of Dart 3.1.
+
+## 0.6.0
+
+- **Breaking Change** ([#131](https://github.com/dart-lang/jnigen/issues/131)):
+ Renamed `delete*` to `release*`.
+- Added `PortProxy` and related methods used for interface implementation.
+- Added the missing binding for `java.lang.Character`.
+
+## 0.5.0
+
+- **Breaking Change** ([#137](https://github.com/dart-lang/jnigen/issues/137)):
+ Java primitive types are now all lowercase like `jint`, `jshort`, ...
+- The bindings for `java.util.Set`, `java.util.Map`, `java.util.List` and the
+ numeric types like `java.lang.Integer`, `java.lang.Boolean`, ... are now
+ included in `package:jni`.
+
+## 0.4.0
+
+- Type classes now have `superCount` and `superType` getters used for type
+ inference.
+
+## 0.3.0
+
+- Added `PortContinuation` used for `suspend fun` in Kotlin.
+- `dartjni` now depends on `dart_api_dl.h`.
+
+## 0.2.1
+
+- Added `.clang-format` to pub.
+
+## 0.2.0
+
+- Added array support
+- Added generic support
+- `JniX` turned into `JX` for a more terse code.
+
+## 0.1.1
+
+- Windows support for running tests and examples on development machines.
+
+## 0.1.0
+
+- Initial version: Android and Linux support, JObject API
diff --git a/pkgs/jni/LICENSE b/pkgs/jni/LICENSE
new file mode 100644
index 0000000..33474aa
--- /dev/null
+++ b/pkgs/jni/LICENSE
@@ -0,0 +1,27 @@
+Copyright 2022, the Dart project authors.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of Google LLC nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkgs/jni/README.md b/pkgs/jni/README.md
new file mode 100644
index 0000000..37f5b36
--- /dev/null
+++ b/pkgs/jni/README.md
@@ -0,0 +1,18 @@
+# jni
+
+This is a support library to access JNI from Dart / Flutter code. This provides the common infrastructure to bindings generated by [jnigen](https://pub.dev/packages/jnigen), as well as some utility methods.
+
+This library contains:
+
+* Functions to access the JNIEnv and JavaVM variables from JNI, and wrapper functions to those provided by JNI. JNIEnv is exposed via `GlobalJniEnv` type which provides a thin abstraction over JNIEnv, so that it can be used from multiple threads.
+* Functions to spawn a JVM on desktop platforms (`Jni.spawn`).
+* Some Android-specific helpers (get application context and current activity references).
+* `JObject` class, which provides base class for classes generated by jnigen.
+* Commonly used Java classes like `JList`, `JMap`, `JInteger`, ...
+
+Apart from being the base library for code generated by `jnigen` this can also be used for one-off uses of the JNI and debugging. __To generate type-safe bindings from Java libraries, use `jnigen`.__
+
+## Documentation
+The test/ directory contains files with comments explaining the basics of this module, and the example/ directory contains a flutter example which also touches some Android-specifics.
+
+Using this library assumes some familiarity with JNI - it's threading model and object references, among other things.
diff --git a/pkgs/jni/analysis_options.yaml b/pkgs/jni/analysis_options.yaml
new file mode 100644
index 0000000..e591be8
--- /dev/null
+++ b/pkgs/jni/analysis_options.yaml
@@ -0,0 +1,13 @@
+include: package:flutter_lints/flutter.yaml
+
+analyzer:
+ exclude: [build/**, third_party/**]
+ language:
+ strict-raw-types: true
+
+linter:
+ rules:
+ - prefer_final_locals
+ - prefer_const_declarations
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/pkgs/jni/android/.gitignore b/pkgs/jni/android/.gitignore
new file mode 100644
index 0000000..161bdcd
--- /dev/null
+++ b/pkgs/jni/android/.gitignore
@@ -0,0 +1,9 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+.cxx
diff --git a/pkgs/jni/android/README.md b/pkgs/jni/android/README.md
new file mode 100644
index 0000000..7d56c69
--- /dev/null
+++ b/pkgs/jni/android/README.md
@@ -0,0 +1 @@
+This folder contains the [Android plugin class](src/main/java/com/github/dart_lang/jni/JniPlugin.java) which takes care of initializing JNI on Android.
diff --git a/pkgs/jni/android/build.gradle b/pkgs/jni/android/build.gradle
new file mode 100644
index 0000000..3f650e8
--- /dev/null
+++ b/pkgs/jni/android/build.gradle
@@ -0,0 +1,89 @@
+// The Android Gradle Plugin builds the native code with the Android NDK.
+
+group 'com.github.dart_lang.jni'
+version '1.0'
+
+buildscript {
+ ext.kotlin_version = '1.6.10'
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ // The Android Gradle Plugin knows how to build native code with the NDK.
+ classpath 'com.android.tools.build:gradle:7.1.2'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+rootProject.allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+apply plugin: 'com.android.library'
+
+android {
+ // Keeping the classes from being removed by proguard.
+ defaultConfig {
+ consumerProguardFiles 'consumer-rules.pro'
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ }
+ }
+
+ // Condition for namespace compatibility in AGP 8
+ if (project.android.hasProperty("namespace")) {
+ namespace 'com.github.dart_lang.jni'
+ }
+
+ // Adding [PortContinuation] and [PortProxy] classes shared between Flutter and
+ // Dart-standalone versions of package:jni.
+ sourceSets {
+ main {
+ java {
+ srcDirs '../java/src/main/java'
+ }
+ }
+ }
+
+ // Bumping the plugin compileSdkVersion requires all clients of this plugin
+ // to bump the version in their app.
+ compileSdkVersion 31
+
+ // Bumping the plugin ndkVersion requires all clients of this plugin to bump
+ // the version in their app and to download a newer version of the NDK.
+ // Note(MaheshH) - Flutter seems to download minimum NDK of flutter when
+ // below line is commented out.
+ // How about leaving it?
+ // ndkVersion "21.1.6352462"
+
+ // Invoke the shared CMake build with the Android Gradle Plugin.
+ externalNativeBuild {
+ cmake {
+ path "../src/CMakeLists.txt"
+
+ // The default CMake version for the Android Gradle Plugin is 3.10.2.
+ // https://developer.android.com/studio/projects/install-ndk#vanilla_cmake
+ //
+ // 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.
+ // version "3.10.2"
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ defaultConfig {
+ minSdkVersion 16
+ }
+}
diff --git a/pkgs/jni/android/consumer-rules.pro b/pkgs/jni/android/consumer-rules.pro
new file mode 100644
index 0000000..269e421
--- /dev/null
+++ b/pkgs/jni/android/consumer-rules.pro
@@ -0,0 +1 @@
+-keep class com.github.dart_lang.jni.** { *; }
diff --git a/pkgs/jni/android/settings.gradle b/pkgs/jni/android/settings.gradle
new file mode 100644
index 0000000..ac55455
--- /dev/null
+++ b/pkgs/jni/android/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'jni'
diff --git a/pkgs/jni/android/src/main/AndroidManifest.xml b/pkgs/jni/android/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..9a6646f
--- /dev/null
+++ b/pkgs/jni/android/src/main/AndroidManifest.xml
@@ -0,0 +1,3 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.github.dart_lang.jni">
+</manifest>
diff --git a/pkgs/jni/android/src/main/java/com/github/dart_lang/jni/JniPlugin.java b/pkgs/jni/android/src/main/java/com/github/dart_lang/jni/JniPlugin.java
new file mode 100644
index 0000000..d3a1ebe
--- /dev/null
+++ b/pkgs/jni/android/src/main/java/com/github/dart_lang/jni/JniPlugin.java
@@ -0,0 +1,60 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jni;
+
+import android.app.Activity;
+import android.content.Context;
+import androidx.annotation.NonNull;
+import io.flutter.embedding.engine.plugins.FlutterPlugin;
+import io.flutter.embedding.engine.plugins.activity.ActivityAware;
+import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
+import io.flutter.plugin.common.PluginRegistry.Registrar;
+
+public class JniPlugin implements FlutterPlugin, ActivityAware {
+
+ @Override
+ public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
+ setup(binding.getApplicationContext());
+ }
+
+ public static void registerWith(Registrar registrar) {
+ JniPlugin plugin = new JniPlugin();
+ plugin.setup(registrar.activeContext());
+ }
+
+ private void setup(Context context) {
+ initializeJni(context, getClass().getClassLoader());
+ }
+
+ @Override
+ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {}
+
+ // Activity handling methods
+ @Override
+ public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
+ Activity activity = binding.getActivity();
+ setJniActivity(activity, activity.getApplicationContext());
+ }
+
+ @Override
+ public void onDetachedFromActivityForConfigChanges() {}
+
+ @Override
+ public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
+ Activity activity = binding.getActivity();
+ setJniActivity(activity, activity.getApplicationContext());
+ }
+
+ @Override
+ public void onDetachedFromActivity() {}
+
+ native void initializeJni(Context context, ClassLoader classLoader);
+
+ native void setJniActivity(Activity activity, Context context);
+
+ static {
+ System.loadLibrary("dartjni");
+ }
+}
diff --git a/pkgs/jni/bin/setup.dart b/pkgs/jni/bin/setup.dart
new file mode 100644
index 0000000..7727cc1
--- /dev/null
+++ b/pkgs/jni/bin/setup.dart
@@ -0,0 +1,262 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:args/args.dart';
+import 'package:package_config/package_config.dart';
+
+import 'package:jni/src/build_util/build_util.dart';
+
+const jniNativeBuildDirective =
+ '# jni_native_build (Build with jni:setup. Do not delete this line.)';
+
+// When changing this constant here, also change corresponding path in
+// test/test_util.
+const _defaultRelativeBuildPath = "build/jni_libs";
+
+const _buildPath = "build-path";
+const _srcPath = "add-source";
+const _packageName = 'add-package';
+const _verbose = "verbose";
+const _cmakeArgs = "cmake-args";
+
+Future<void> runCommand(
+ String exec, List<String> args, String workingDir) async {
+ // For printing relative path always.
+ var current = Directory.current.path;
+ if (!current.endsWith(Platform.pathSeparator)) {
+ current += Platform.pathSeparator;
+ }
+ if (workingDir.startsWith(current)) {
+ workingDir.replaceFirst(current, "");
+ }
+
+ final cmd = "$exec ${args.join(" ")}";
+ stderr.writeln("+ [$workingDir] $cmd");
+ int status;
+ if (options.verbose) {
+ final process = await Process.start(
+ exec, args,
+ workingDirectory: workingDir,
+ mode: ProcessStartMode.inheritStdio,
+ // without `runInShell`, sometimes cmake doesn't run on windows.
+ runInShell: true,
+ );
+ status = await process.exitCode;
+ if (status != 0) {
+ exitCode = status;
+ }
+ } else {
+ // ProcessStartMode.normal sometimes hangs on windows. No idea why.
+ final process = await Process.run(exec, args,
+ runInShell: true, workingDirectory: workingDir);
+ status = process.exitCode;
+ if (status != 0) {
+ exitCode = status;
+ var out = process.stdout;
+ var err = process.stderr;
+ if (stdout.supportsAnsiEscapes) {
+ out = "$ansiRed$out$ansiDefault";
+ err = "$ansiRed$err$ansiDefault";
+ }
+ stdout.writeln(out);
+ stderr.writeln(err);
+ }
+ }
+ if (status != 0) {
+ stderr.writeln('Command exited with status code $status');
+ }
+}
+
+class Options {
+ Options(ArgResults arg)
+ : buildPath = arg[_buildPath],
+ sources = arg[_srcPath],
+ packages = arg[_packageName],
+ cmakeArgs = arg[_cmakeArgs],
+ verbose = arg[_verbose] ?? false;
+
+ String? buildPath;
+ List<String> sources;
+ List<String> packages;
+ List<String> cmakeArgs;
+ bool verbose;
+}
+
+late Options options;
+
+void verboseLog(String msg) {
+ if (options.verbose) {
+ stderr.writeln(msg);
+ }
+}
+
+/// Find path to C or Java sources in pub cache for package specified by
+/// [packageName].
+///
+/// If package cannot be found, null is returned.
+Future<String> findSources(String packageName, String subDirectory) async {
+ final packageConfig = await findPackageConfig(Directory.current);
+ if (packageConfig == null) {
+ throw UnsupportedError("Please run from project root.");
+ }
+ final package = packageConfig[packageName];
+ if (package == null) {
+ throw UnsupportedError("Cannot find package: $packageName");
+ }
+ return package.root.resolve(subDirectory).toFilePath();
+}
+
+/// Return '/src' directories of all dependencies which has a CMakeLists.txt
+/// file.
+Future<Map<String, String>> findDependencySources() async {
+ final packageConfig = await findPackageConfig(Directory.current);
+ if (packageConfig == null) {
+ throw UnsupportedError("Please run the command from project root.");
+ }
+ final sources = <String, String>{};
+ for (var package in packageConfig.packages) {
+ final src = package.root.resolve("src/");
+ final cmakeLists = src.resolve("CMakeLists.txt");
+ final cmakeListsFile = File.fromUri(cmakeLists);
+ if (cmakeListsFile.existsSync()) {
+ final firstLine = cmakeListsFile.readAsLinesSync().first;
+ if (firstLine == jniNativeBuildDirective) {
+ sources[package.name] = src.toFilePath();
+ }
+ }
+ }
+ return sources;
+}
+
+/// Returns the name of file built using sources in [cDir]
+String getTargetName(Directory cDir) {
+ for (final file in cDir.listSync(recursive: true)) {
+ if (file.path.endsWith(".c")) {
+ final cFileName = file.uri.pathSegments.last;
+ final librarySuffix = Platform.isWindows ? "dll" : "so";
+ return cFileName.substring(0, cFileName.length - 1) + librarySuffix;
+ }
+ }
+ throw Exception("Could not find a C file in ${cDir.path}");
+}
+
+void main(List<String> arguments) async {
+ final parser = ArgParser()
+ ..addOption(_buildPath,
+ abbr: 'b', help: 'Directory to place built artifacts')
+ ..addMultiOption(_srcPath,
+ abbr: 's', help: 'alternative path to package:jni sources')
+ ..addMultiOption(_packageName,
+ abbr: 'p',
+ help: 'package for which native'
+ 'library should be built')
+ ..addFlag(_verbose, abbr: 'v', help: 'Enable verbose output')
+ ..addMultiOption(_cmakeArgs,
+ abbr: 'm', help: 'Pass additional argument to CMake');
+ final argResults = parser.parse(arguments);
+ options = Options(argResults);
+ final rest = argResults.rest;
+
+ if (rest.isNotEmpty) {
+ stderr.writeln("one or more unrecognized arguments: $rest");
+ stderr.writeln("usage: dart run jni:setup <options>");
+ stderr.writeln(parser.usage);
+ exitCode = 1;
+ return;
+ }
+
+ final sources = options.sources;
+ for (var packageName in options.packages) {
+ // It's assumed C FFI sources are in "src/" relative to package root.
+ sources.add(await findSources(packageName, 'src'));
+ }
+ if (sources.isEmpty) {
+ final dependencySources = await findDependencySources();
+ stderr.writeln("selecting source directories for dependencies: "
+ "${dependencySources.keys}");
+ sources.addAll(dependencySources.values);
+ } else {
+ stderr.writeln("selecting source directories: $sources");
+ }
+ if (sources.isEmpty) {
+ stderr.writeln('No source paths to build!');
+ exitCode = 1;
+ return;
+ }
+
+ final currentDirUri = Uri.directory(".");
+ final buildPath = options.buildPath ??
+ currentDirUri.resolve(_defaultRelativeBuildPath).toFilePath();
+ final buildDir = Directory(buildPath);
+ await buildDir.create(recursive: true);
+
+ final javaSrc = await findSources('jni', 'java');
+ final targetJar = File.fromUri(buildDir.uri.resolve('jni.jar'));
+ if (!needsBuild(targetJar, Directory.fromUri(Uri.directory(javaSrc)))) {
+ verboseLog('Last modified of ${targetJar.path}: '
+ '${targetJar.lastModifiedSync()}.');
+ stderr.writeln('Target newer than source, skipping build.');
+ } else {
+ verboseLog('Running mvn package for jni java sources to $buildPath.');
+ await runCommand(
+ 'mvn',
+ ['package', '-Dtarget=${buildDir.absolute.path}'],
+ await findSources('jni', 'java'),
+ );
+ }
+
+ for (var srcPath in sources) {
+ final srcDir = Directory(srcPath);
+ if (!srcDir.existsSync()) {
+ stderr.writeln('Directory $srcPath does not exist');
+ exitCode = 1;
+ return;
+ }
+
+ verboseLog("srcPath: $srcPath");
+ verboseLog("buildPath: $buildPath");
+
+ final targetFileUri = buildDir.uri.resolve(getTargetName(srcDir));
+ final targetFile = File.fromUri(targetFileUri);
+ if (!needsBuild(targetFile, srcDir)) {
+ verboseLog("Last modified of ${targetFile.path}: "
+ "${targetFile.lastModifiedSync()}.");
+ stderr.writeln('Target newer than source, skipping build.');
+ continue;
+ }
+
+ // Note: creating temp dir in .dart_tool/jni instead of SystemTemp
+ // because latter can fail tests on Windows CI, when system temp is on
+ // separate drive or something.
+ final jniDirUri = Uri.directory(".dart_tool").resolve("jni");
+ final jniDir = Directory.fromUri(jniDirUri);
+ await jniDir.create(recursive: true);
+ final tempDir = await jniDir.createTemp("jni_native_build_");
+ final cmakeArgs = <String>[];
+ cmakeArgs.addAll(options.cmakeArgs);
+ // Pass absolute path of srcDir because cmake command is run in temp dir
+ cmakeArgs.add(srcDir.absolute.path);
+ await runCommand("cmake", cmakeArgs, tempDir.path);
+ await runCommand("cmake", ["--build", "."], tempDir.path);
+ final dllDirUri =
+ Platform.isWindows ? tempDir.uri.resolve("Debug") : tempDir.uri;
+ final dllDir = Directory.fromUri(dllDirUri);
+ for (var entry in dllDir.listSync()) {
+ verboseLog(entry.toString());
+ final dllSuffix = Platform.isWindows
+ ? "dll"
+ : Platform.isMacOS
+ ? "dylib"
+ : "so";
+ if (entry.path.endsWith(dllSuffix)) {
+ final dllName = entry.uri.pathSegments.last;
+ final target = buildDir.uri.resolve(dllName);
+ entry.renameSync(target.toFilePath());
+ }
+ }
+ await tempDir.delete(recursive: true);
+ }
+}
diff --git a/pkgs/jni/dart_test.yaml b/pkgs/jni/dart_test.yaml
new file mode 100644
index 0000000..361ada4
--- /dev/null
+++ b/pkgs/jni/dart_test.yaml
@@ -0,0 +1,7 @@
+## Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+## for details. All rights reserved. Use of this source code is governed by a
+## BSD-style license that can be found in the LICENSE file.
+
+tags:
+ load_test:
+ timeout: 10x
diff --git a/pkgs/jni/example/.gitignore b/pkgs/jni/example/.gitignore
new file mode 100644
index 0000000..a8e938c
--- /dev/null
+++ b/pkgs/jni/example/.gitignore
@@ -0,0 +1,47 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Web related
+lib/generated_plugin_registrant.dart
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
diff --git a/pkgs/jni/example/README.md b/pkgs/jni/example/README.md
new file mode 100644
index 0000000..583f960
--- /dev/null
+++ b/pkgs/jni/example/README.md
@@ -0,0 +1,3 @@
+# jni_example
+Demonstrates how to use the jni plugin.
+
diff --git a/pkgs/jni/example/analysis_options.yaml b/pkgs/jni/example/analysis_options.yaml
new file mode 100644
index 0000000..7f0b15f
--- /dev/null
+++ b/pkgs/jni/example/analysis_options.yaml
@@ -0,0 +1,36 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+analyzer:
+ exclude: [build/**]
+ language:
+ strict-raw-types: true
+
+linter:
+ # The lint rules applied to this project can be customized in the
+ # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+ # included above or to enable additional rules. A list of all available lints
+ # and their documentation is published at
+ # https://dart-lang.github.io/linter/lints/index.html.
+ #
+ # Instead of disabling a lint rule for the entire project in the
+ # section below, it can also be suppressed for a single line of code
+ # or a specific dart file by using the `// ignore: name_of_lint` and
+ # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+ # producing the lint.
+ rules:
+ - prefer_final_locals
+ - prefer_const_declarations
+ # avoid_print: false # Uncomment to disable the `avoid_print` rule
+ # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/pkgs/jni/example/android/.gitignore b/pkgs/jni/example/android/.gitignore
new file mode 100644
index 0000000..6f56801
--- /dev/null
+++ b/pkgs/jni/example/android/.gitignore
@@ -0,0 +1,13 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/pkgs/jni/example/android/app/build.gradle b/pkgs/jni/example/android/app/build.gradle
new file mode 100644
index 0000000..fbcc356
--- /dev/null
+++ b/pkgs/jni/example/android/app/build.gradle
@@ -0,0 +1,70 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+ localPropertiesFile.withReader('UTF-8') { reader ->
+ localProperties.load(reader)
+ }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+ throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+ flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+ flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+ compileSdkVersion flutter.compileSdkVersion
+ ndkVersion flutter.ndkVersion
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+
+ defaultConfig {
+ applicationId "com.github.dart_lang.jni_example"
+ // You can update the following values to match your application needs.
+ // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
+ minSdkVersion flutter.minSdkVersion
+ targetSdkVersion flutter.targetSdkVersion
+ versionCode flutterVersionCode.toInteger()
+ versionName flutterVersionName
+ }
+
+ buildTypes {
+ release {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig signingConfigs.debug
+ }
+ }
+}
+
+flutter {
+ source '../..'
+}
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
diff --git a/pkgs/jni/example/android/app/src/debug/AndroidManifest.xml b/pkgs/jni/example/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..1a2af73
--- /dev/null
+++ b/pkgs/jni/example/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.github.dart_lang.jni_example">
+ <!-- The INTERNET permission is required for development. Specifically,
+ the Flutter tool needs it to communicate with the running application
+ to allow setting breakpoints, to provide hot reload, etc.
+ -->
+ <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/pkgs/jni/example/android/app/src/main/AndroidManifest.xml b/pkgs/jni/example/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..5a849fc
--- /dev/null
+++ b/pkgs/jni/example/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.github.dart_lang.jni_example">
+ <application
+ android:label="jni_example"
+ android:name="${applicationName}"
+ android:icon="@mipmap/ic_launcher">
+ <activity
+ android:name=".MainActivity"
+ android:exported="true"
+ android:launchMode="singleTop"
+ android:theme="@style/LaunchTheme"
+ android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
+ android:hardwareAccelerated="true"
+ android:windowSoftInputMode="adjustResize">
+ <!-- Specifies an Android theme to apply to this Activity as soon as
+ the Android process has started. This theme is visible to the user
+ while the Flutter UI initializes. After that, this theme continues
+ to determine the Window background behind the Flutter UI. -->
+ <meta-data
+ android:name="io.flutter.embedding.android.NormalTheme"
+ android:resource="@style/NormalTheme"
+ />
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <!-- Don't delete the meta-data below.
+ This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
+ <meta-data
+ android:name="flutterEmbedding"
+ android:value="2" />
+ </application>
+</manifest>
diff --git a/pkgs/jni/example/android/app/src/main/java/com/github/dart_lang/jni_example/Toaster.java b/pkgs/jni/example/android/app/src/main/java/com/github/dart_lang/jni_example/Toaster.java
new file mode 100644
index 0000000..ec61c8a
--- /dev/null
+++ b/pkgs/jni/example/android/app/src/main/java/com/github/dart_lang/jni_example/Toaster.java
@@ -0,0 +1,31 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jni_example;
+
+import android.app.Activity;
+import android.content.Context;
+import android.widget.Toast;
+import androidx.annotation.Keep;
+
+@Keep
+class Toaster {
+ static Toaster makeText(Activity mainActivity, Context context, CharSequence text, int duration) {
+ Toaster toast = new Toaster();
+ toast.mainActivity = mainActivity;
+ toast.context = context;
+ toast.text = text;
+ toast.duration = duration;
+ return toast;
+ }
+
+ void show() {
+ mainActivity.runOnUiThread(() -> Toast.makeText(context, text, duration).show());
+ }
+
+ Activity mainActivity;
+ Context context;
+ CharSequence text;
+ int duration;
+}
diff --git a/pkgs/jni/example/android/app/src/main/kotlin/dev/dart/jni_example/MainActivity.kt b/pkgs/jni/example/android/app/src/main/kotlin/dev/dart/jni_example/MainActivity.kt
new file mode 100644
index 0000000..2aa0914
--- /dev/null
+++ b/pkgs/jni/example/android/app/src/main/kotlin/dev/dart/jni_example/MainActivity.kt
@@ -0,0 +1,6 @@
+package com.github.dart_lang.jni_example
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}
diff --git a/pkgs/jni/example/android/app/src/main/res/drawable-v21/launch_background.xml b/pkgs/jni/example/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/pkgs/jni/example/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="?android:colorBackground" />
+
+ <!-- You can insert your own image assets here -->
+ <!-- <item>
+ <bitmap
+ android:gravity="center"
+ android:src="@mipmap/launch_image" />
+ </item> -->
+</layer-list>
diff --git a/pkgs/jni/example/android/app/src/main/res/drawable/launch_background.xml b/pkgs/jni/example/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..304732f
--- /dev/null
+++ b/pkgs/jni/example/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@android:color/white" />
+
+ <!-- You can insert your own image assets here -->
+ <!-- <item>
+ <bitmap
+ android:gravity="center"
+ android:src="@mipmap/launch_image" />
+ </item> -->
+</layer-list>
diff --git a/pkgs/jni/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/pkgs/jni/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..db77bb4
--- /dev/null
+++ b/pkgs/jni/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jni/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/pkgs/jni/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..17987b7
--- /dev/null
+++ b/pkgs/jni/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jni/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/pkgs/jni/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..09d4391
--- /dev/null
+++ b/pkgs/jni/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jni/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/pkgs/jni/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d5f1c8d
--- /dev/null
+++ b/pkgs/jni/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jni/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/pkgs/jni/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d6372e
--- /dev/null
+++ b/pkgs/jni/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jni/example/android/app/src/main/res/values-night/styles.xml b/pkgs/jni/example/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..06952be
--- /dev/null
+++ b/pkgs/jni/example/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
+ <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
+ <!-- Show a splash screen on the activity. Automatically removed when
+ the Flutter engine draws its first frame -->
+ <item name="android:windowBackground">@drawable/launch_background</item>
+ </style>
+ <!-- Theme applied to the Android Window as soon as the process has started.
+ This theme determines the color of the Android Window while your
+ Flutter UI initializes, as well as behind your Flutter UI while its
+ running.
+
+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
+ <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
+ <item name="android:windowBackground">?android:colorBackground</item>
+ </style>
+</resources>
diff --git a/pkgs/jni/example/android/app/src/main/res/values/styles.xml b/pkgs/jni/example/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..cb1ef88
--- /dev/null
+++ b/pkgs/jni/example/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
+ <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
+ <!-- Show a splash screen on the activity. Automatically removed when
+ the Flutter engine draws its first frame -->
+ <item name="android:windowBackground">@drawable/launch_background</item>
+ </style>
+ <!-- Theme applied to the Android Window as soon as the process has started.
+ This theme determines the color of the Android Window while your
+ Flutter UI initializes, as well as behind your Flutter UI while its
+ running.
+
+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
+ <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
+ <item name="android:windowBackground">?android:colorBackground</item>
+ </style>
+</resources>
diff --git a/pkgs/jni/example/android/app/src/profile/AndroidManifest.xml b/pkgs/jni/example/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..1a2af73
--- /dev/null
+++ b/pkgs/jni/example/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.github.dart_lang.jni_example">
+ <!-- The INTERNET permission is required for development. Specifically,
+ the Flutter tool needs it to communicate with the running application
+ to allow setting breakpoints, to provide hot reload, etc.
+ -->
+ <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/pkgs/jni/example/android/build.gradle b/pkgs/jni/example/android/build.gradle
new file mode 100644
index 0000000..3cdaac9
--- /dev/null
+++ b/pkgs/jni/example/android/build.gradle
@@ -0,0 +1,31 @@
+buildscript {
+ ext.kotlin_version = '1.6.10'
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:7.1.2'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+ project.evaluationDependsOn(':app')
+}
+
+tasks.register("clean", Delete) {
+ delete rootProject.buildDir
+}
diff --git a/pkgs/jni/example/android/gradle.properties b/pkgs/jni/example/android/gradle.properties
new file mode 100644
index 0000000..94adc3a
--- /dev/null
+++ b/pkgs/jni/example/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/pkgs/jni/example/android/gradle/wrapper/gradle-wrapper.properties b/pkgs/jni/example/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..cc5527d
--- /dev/null
+++ b/pkgs/jni/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jun 23 08:50:38 CEST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
diff --git a/pkgs/jni/example/android/settings.gradle b/pkgs/jni/example/android/settings.gradle
new file mode 100644
index 0000000..44e62bc
--- /dev/null
+++ b/pkgs/jni/example/android/settings.gradle
@@ -0,0 +1,11 @@
+include ':app'
+
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
+
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/pkgs/jni/example/integration_test/on_device_jni_test.dart b/pkgs/jni/example/integration_test/on_device_jni_test.dart
new file mode 100644
index 0000000..cdc7296
--- /dev/null
+++ b/pkgs/jni/example/integration_test/on_device_jni_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:flutter_test/flutter_test.dart';
+
+import '../../test/global_env_test.dart' as global_env_test;
+import '../../test/exception_test.dart' as exception_test;
+import '../../test/jlist_test.dart' as jlist_test;
+import '../../test/jmap_test.dart' as jmap_test;
+import '../../test/jobject_test.dart' as jobject_test;
+import '../../test/jstring_test.dart' as jstring_test;
+import '../../test/jset_test.dart' as jset_test;
+import '../../test/jarray_test.dart' as jarray_test;
+import '../../test/boxed_test.dart' as boxed_test;
+import '../../test/type_test.dart' as type_test;
+import '../../test/load_test.dart' as load_test;
+
+void integrationTestRunner(String description, void Function() testCallback) {
+ testWidgets(description, (widgetTester) async => testCallback());
+}
+
+void main() {
+ final testSuites = [
+ global_env_test.run,
+ exception_test.run,
+ jlist_test.run,
+ jmap_test.run,
+ jobject_test.run,
+ jstring_test.run,
+ jset_test.run,
+ jarray_test.run,
+ boxed_test.run,
+ type_test.run,
+ load_test.run,
+ ];
+ for (var testSuite in testSuites) {
+ testSuite(testRunner: integrationTestRunner);
+ }
+}
diff --git a/pkgs/jni/example/lib/main.dart b/pkgs/jni/example/lib/main.dart
new file mode 100644
index 0000000..4c73693
--- /dev/null
+++ b/pkgs/jni/example/lib/main.dart
@@ -0,0 +1,224 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// ignore_for_file: library_private_types_in_public_api
+
+import 'package:flutter/material.dart';
+
+import 'dart:io';
+import 'dart:ffi';
+
+import 'package:jni/jni.dart';
+
+// An example of calling JNI methods using low level primitives.
+// GlobalJniEnv is a thin abstraction over JNIEnv in JNI C API.
+//
+// For a more ergonomic API for common use cases of calling methods and
+// accessing fields, see next examples using JObject and JClass.
+String toJavaStringUsingEnv(int n) => using((arena) {
+ final env = Jni.env;
+ final cls = env.FindClass("java/lang/String".toNativeChars(arena));
+ final mId = env.GetStaticMethodID(cls, "valueOf".toNativeChars(),
+ "(I)Ljava/lang/String;".toNativeChars(arena));
+ final i = arena<JValue>();
+ i.ref.i = n;
+ final res = env.CallStaticObjectMethodA(cls, mId, i);
+ final str = env.toDartString(res);
+ env.deleteAllRefs([res, cls]);
+ return str;
+ });
+
+int randomUsingEnv(int n) => using((arena) {
+ final env = Jni.env;
+ final randomCls = env.FindClass("java/util/Random".toNativeChars(arena));
+ final ctor = env.GetMethodID(
+ randomCls, "<init>".toNativeChars(arena), "()V".toNativeChars(arena));
+ final random = env.NewObject(randomCls, ctor);
+ final nextInt = env.GetMethodID(randomCls, "nextInt".toNativeChars(arena),
+ "(I)I".toNativeChars(arena));
+ final res = env.CallIntMethodA(random, nextInt, Jni.jvalues([n]));
+ env.deleteAllRefs([randomCls, random]);
+ return res;
+ });
+double randomDouble() {
+ final math = Jni.findJClass("java/lang/Math");
+ final random = math.callStaticMethodByName<double>("random", "()D", []);
+ math.release();
+ return random;
+}
+
+int uptime() {
+ return Jni.findJClass("android/os/SystemClock").use(
+ (systemClock) => systemClock.callStaticMethodByName<int>(
+ "uptimeMillis", "()J", [], JniCallType.longType),
+ );
+}
+
+String backAndForth() {
+ final jstring = '🪓'.toJString();
+ final dartString = jstring.toDartString(releaseOriginal: true);
+ return dartString;
+}
+
+void quit() {
+ JObject.fromRef(Jni.getCurrentActivity())
+ .use((ac) => ac.callMethodByName<void>("finish", "()V", []));
+}
+
+void showToast(String text) {
+ // This is example for calling your app's custom java code.
+ // Place the Toaster class in the app's android/ source Folder, with a Keep
+ // annotation or appropriate proguard rules to retain classes in release mode.
+ //
+ // In this example, Toaster class wraps android.widget.Toast so that it
+ // can be called from any thread. See
+ // android/app/src/main/java/com/github/dart_lang/jni_example/Toaster.java
+ Jni.invokeStaticMethod<JObject>(
+ "com/github/dart_lang/jni_example/Toaster",
+ "makeText",
+ "(Landroid/app/Activity;Landroid/content/Context;"
+ "Ljava/lang/CharSequence;I)"
+ "Lcom/github/dart_lang/jni_example/Toaster;",
+ [
+ Jni.getCurrentActivity(),
+ Jni.getCachedApplicationContext(),
+ "😀",
+ 0,
+ ]).callMethodByName<void>("show", "()V", []);
+}
+
+void main() {
+ if (!Platform.isAndroid) {
+ Jni.spawn();
+ }
+ final examples = [
+ Example("String.valueOf(1332)", () => toJavaStringUsingEnv(1332)),
+ Example("Generate random number", () => randomUsingEnv(180),
+ runInitially: false),
+ Example("Math.random()", () => randomDouble(), runInitially: false),
+ if (Platform.isAndroid) ...[
+ Example("Minutes of usage since reboot",
+ () => (uptime() / (60 * 1000)).floor()),
+ Example("Back and forth string conversion", () => backAndForth()),
+ Example(
+ "Device name",
+ () => Jni.retrieveStaticField<String>(
+ "android/os/Build", "DEVICE", "Ljava/lang/String;")),
+ Example(
+ "Package name",
+ () => JObject.fromRef(Jni.getCurrentActivity()).use((activity) =>
+ activity.callMethodByName<String>(
+ "getPackageName", "()Ljava/lang/String;", [])),
+ ),
+ Example("Show toast", () => showToast("Hello from JNI!"),
+ runInitially: false),
+ Example(
+ "Quit",
+ quit,
+ runInitially: false,
+ ),
+ ]
+ ];
+ runApp(MyApp(examples));
+}
+
+class Example {
+ String title;
+ dynamic Function() callback;
+ bool runInitially;
+ Example(this.title, this.callback, {this.runInitially = true});
+}
+
+class MyApp extends StatefulWidget {
+ const MyApp(this.examples, {Key? key}) : super(key: key);
+ final List<Example> examples;
+
+ @override
+ _MyAppState createState() => _MyAppState();
+}
+
+class _MyAppState extends State<MyApp> {
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ home: Scaffold(
+ appBar: AppBar(
+ title: const Text('JNI Examples'),
+ ),
+ body: ListView.builder(
+ itemCount: widget.examples.length,
+ itemBuilder: (context, i) {
+ final eg = widget.examples[i];
+ return ExampleCard(eg);
+ }),
+ ),
+ );
+ }
+}
+
+class ExampleCard extends StatefulWidget {
+ const ExampleCard(this.example, {Key? key}) : super(key: key);
+ final Example example;
+
+ @override
+ _ExampleCardState createState() => _ExampleCardState();
+}
+
+class _ExampleCardState extends State<ExampleCard> {
+ Widget _pad(Widget w, double h, double v) {
+ return Padding(
+ padding: EdgeInsets.symmetric(horizontal: h, vertical: v), child: w);
+ }
+
+ bool _run = false;
+
+ @override
+ void initState() {
+ super.initState();
+ _run = widget.example.runInitially;
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final eg = widget.example;
+ var result = "";
+ var hasError = false;
+ if (_run) {
+ try {
+ result = eg.callback().toString();
+ } on Exception catch (e) {
+ hasError = true;
+ result = e.toString();
+ } on Error catch (e) {
+ hasError = true;
+ result = e.toString();
+ }
+ }
+ var resultStyle = const TextStyle(fontFamily: "Monospace");
+ if (hasError) {
+ resultStyle = const TextStyle(fontFamily: "Monospace", color: Colors.red);
+ }
+ return Card(
+ child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
+ Text(eg.title,
+ softWrap: true,
+ style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600)),
+ _pad(
+ Text(result.toString(), softWrap: true, style: resultStyle), 8, 16),
+ _pad(
+ ElevatedButton(
+ child: Text(_run ? "Run again" : "Run"),
+ onPressed: () => setState(() => _run = true),
+ ),
+ 8,
+ 8),
+ ]),
+ );
+ }
+}
diff --git a/pkgs/jni/example/linux/.gitignore b/pkgs/jni/example/linux/.gitignore
new file mode 100644
index 0000000..d3896c9
--- /dev/null
+++ b/pkgs/jni/example/linux/.gitignore
@@ -0,0 +1 @@
+flutter/ephemeral
diff --git a/pkgs/jni/example/linux/CMakeLists.txt b/pkgs/jni/example/linux/CMakeLists.txt
new file mode 100644
index 0000000..8df6c44
--- /dev/null
+++ b/pkgs/jni/example/linux/CMakeLists.txt
@@ -0,0 +1,138 @@
+# Project-level configuration.
+cmake_minimum_required(VERSION 3.10)
+project(runner LANGUAGES CXX)
+
+# The name of the executable created for the application. Change this to change
+# the on-disk name of your application.
+set(BINARY_NAME "jni_example")
+# The unique GTK application identifier for this application. See:
+# https://wiki.gnome.org/HowDoI/ChooseApplicationID
+set(APPLICATION_ID "com.github.dart_lang.jni")
+
+# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
+# versions of CMake.
+cmake_policy(SET CMP0063 NEW)
+
+# Load bundled libraries from the lib/ directory relative to the binary.
+set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
+
+# Root filesystem for cross-building.
+if(FLUTTER_TARGET_PLATFORM_SYSROOT)
+ set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
+ set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
+ set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+endif()
+
+# Define build configuration options.
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+ set(CMAKE_BUILD_TYPE "Debug" CACHE
+ STRING "Flutter build mode" FORCE)
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+ "Debug" "Profile" "Release")
+endif()
+
+# Compilation settings that should be applied to most targets.
+#
+# Be cautious about adding new options here, as plugins use this function by
+# default. In most cases, you should add new options to specific targets instead
+# of modifying this function.
+function(APPLY_STANDARD_SETTINGS TARGET)
+ target_compile_features(${TARGET} PUBLIC cxx_std_14)
+ target_compile_options(${TARGET} PRIVATE -Wall -Werror)
+ target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
+ target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
+endfunction()
+
+# Flutter library and tool build rules.
+set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
+add_subdirectory(${FLUTTER_MANAGED_DIR})
+
+# System-level dependencies.
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
+
+add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
+
+# Define the application target. To change its name, change BINARY_NAME above,
+# not the value here, or `flutter run` will no longer work.
+#
+# Any new source files that you add to the application should be added here.
+add_executable(${BINARY_NAME}
+ "main.cc"
+ "my_application.cc"
+ "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
+)
+
+# Apply the standard set of build settings. This can be removed for applications
+# that need different build settings.
+apply_standard_settings(${BINARY_NAME})
+
+# Add dependency libraries. Add any application-specific dependencies here.
+target_link_libraries(${BINARY_NAME} PRIVATE flutter)
+target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
+
+# Run the Flutter tool portions of the build. This must not be removed.
+add_dependencies(${BINARY_NAME} flutter_assemble)
+
+# Only the install-generated bundle's copy of the executable will launch
+# correctly, since the resources must in the right relative locations. To avoid
+# people trying to run the unbundled copy, put it in a subdirectory instead of
+# the default top-level location.
+set_target_properties(${BINARY_NAME}
+ PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
+)
+
+# Generated plugin build rules, which manage building the plugins and adding
+# them to the application.
+include(flutter/generated_plugins.cmake)
+
+
+# === Installation ===
+# By default, "installing" just makes a relocatable bundle in the build
+# directory.
+set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
+endif()
+
+# Start with a clean build bundle directory every time.
+install(CODE "
+ file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
+ " COMPONENT Runtime)
+
+set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
+set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
+
+install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
+ COMPONENT Runtime)
+
+install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
+ COMPONENT Runtime)
+
+install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+
+foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
+ install(FILES "${bundled_library}"
+ DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+endforeach(bundled_library)
+
+# Fully re-copy the assets directory on each build to avoid having stale files
+# from a previous install.
+set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
+install(CODE "
+ file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
+ " COMPONENT Runtime)
+install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
+ DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
+
+# Install the AOT library on non-Debug builds only.
+if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
+ install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+endif()
diff --git a/pkgs/jni/example/linux/flutter/CMakeLists.txt b/pkgs/jni/example/linux/flutter/CMakeLists.txt
new file mode 100644
index 0000000..d5bd016
--- /dev/null
+++ b/pkgs/jni/example/linux/flutter/CMakeLists.txt
@@ -0,0 +1,88 @@
+# This file controls Flutter-level build steps. It should not be edited.
+cmake_minimum_required(VERSION 3.10)
+
+set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
+
+# Configuration provided via flutter tool.
+include(${EPHEMERAL_DIR}/generated_config.cmake)
+
+# TODO: Move the rest of this into files in ephemeral. See
+# https://github.com/flutter/flutter/issues/57146.
+
+# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
+# which isn't available in 3.10.
+function(list_prepend LIST_NAME PREFIX)
+ set(NEW_LIST "")
+ foreach(element ${${LIST_NAME}})
+ list(APPEND NEW_LIST "${PREFIX}${element}")
+ endforeach(element)
+ set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
+endfunction()
+
+# === Flutter Library ===
+# System-level dependencies.
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
+pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
+pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
+
+set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
+
+# Published to parent scope for install step.
+set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
+set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
+set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
+set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
+
+list(APPEND FLUTTER_LIBRARY_HEADERS
+ "fl_basic_message_channel.h"
+ "fl_binary_codec.h"
+ "fl_binary_messenger.h"
+ "fl_dart_project.h"
+ "fl_engine.h"
+ "fl_json_message_codec.h"
+ "fl_json_method_codec.h"
+ "fl_message_codec.h"
+ "fl_method_call.h"
+ "fl_method_channel.h"
+ "fl_method_codec.h"
+ "fl_method_response.h"
+ "fl_plugin_registrar.h"
+ "fl_plugin_registry.h"
+ "fl_standard_message_codec.h"
+ "fl_standard_method_codec.h"
+ "fl_string_codec.h"
+ "fl_value.h"
+ "fl_view.h"
+ "flutter_linux.h"
+)
+list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
+add_library(flutter INTERFACE)
+target_include_directories(flutter INTERFACE
+ "${EPHEMERAL_DIR}"
+)
+target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
+target_link_libraries(flutter INTERFACE
+ PkgConfig::GTK
+ PkgConfig::GLIB
+ PkgConfig::GIO
+)
+add_dependencies(flutter flutter_assemble)
+
+# === Flutter tool backend ===
+# _phony_ is a non-existent file to force this command to run every time,
+# since currently there's no way to get a full input/output list from the
+# flutter tool.
+add_custom_command(
+ OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
+ ${CMAKE_CURRENT_BINARY_DIR}/_phony_
+ COMMAND ${CMAKE_COMMAND} -E env
+ ${FLUTTER_TOOL_ENVIRONMENT}
+ "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
+ ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
+ VERBATIM
+)
+add_custom_target(flutter_assemble DEPENDS
+ "${FLUTTER_LIBRARY}"
+ ${FLUTTER_LIBRARY_HEADERS}
+)
diff --git a/pkgs/jni/example/linux/flutter/generated_plugin_registrant.cc b/pkgs/jni/example/linux/flutter/generated_plugin_registrant.cc
new file mode 100644
index 0000000..e71a16d
--- /dev/null
+++ b/pkgs/jni/example/linux/flutter/generated_plugin_registrant.cc
@@ -0,0 +1,11 @@
+//
+// Generated file. Do not edit.
+//
+
+// clang-format off
+
+#include "generated_plugin_registrant.h"
+
+
+void fl_register_plugins(FlPluginRegistry* registry) {
+}
diff --git a/pkgs/jni/example/linux/flutter/generated_plugin_registrant.h b/pkgs/jni/example/linux/flutter/generated_plugin_registrant.h
new file mode 100644
index 0000000..e0f0a47
--- /dev/null
+++ b/pkgs/jni/example/linux/flutter/generated_plugin_registrant.h
@@ -0,0 +1,15 @@
+//
+// Generated file. Do not edit.
+//
+
+// clang-format off
+
+#ifndef GENERATED_PLUGIN_REGISTRANT_
+#define GENERATED_PLUGIN_REGISTRANT_
+
+#include <flutter_linux/flutter_linux.h>
+
+// Registers Flutter plugins.
+void fl_register_plugins(FlPluginRegistry* registry);
+
+#endif // GENERATED_PLUGIN_REGISTRANT_
diff --git a/pkgs/jni/example/linux/flutter/generated_plugins.cmake b/pkgs/jni/example/linux/flutter/generated_plugins.cmake
new file mode 100644
index 0000000..be1ee3e
--- /dev/null
+++ b/pkgs/jni/example/linux/flutter/generated_plugins.cmake
@@ -0,0 +1,24 @@
+#
+# Generated file, do not edit.
+#
+
+list(APPEND FLUTTER_PLUGIN_LIST
+)
+
+list(APPEND FLUTTER_FFI_PLUGIN_LIST
+ jni
+)
+
+set(PLUGIN_BUNDLED_LIBRARIES)
+
+foreach(plugin ${FLUTTER_PLUGIN_LIST})
+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
+ target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
+endforeach(plugin)
+
+foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
+endforeach(ffi_plugin)
diff --git a/pkgs/jni/example/linux/main.cc b/pkgs/jni/example/linux/main.cc
new file mode 100644
index 0000000..e7c5c54
--- /dev/null
+++ b/pkgs/jni/example/linux/main.cc
@@ -0,0 +1,6 @@
+#include "my_application.h"
+
+int main(int argc, char** argv) {
+ g_autoptr(MyApplication) app = my_application_new();
+ return g_application_run(G_APPLICATION(app), argc, argv);
+}
diff --git a/pkgs/jni/example/linux/my_application.cc b/pkgs/jni/example/linux/my_application.cc
new file mode 100644
index 0000000..3420542
--- /dev/null
+++ b/pkgs/jni/example/linux/my_application.cc
@@ -0,0 +1,104 @@
+#include "my_application.h"
+
+#include <flutter_linux/flutter_linux.h>
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#endif
+
+#include "flutter/generated_plugin_registrant.h"
+
+struct _MyApplication {
+ GtkApplication parent_instance;
+ char** dart_entrypoint_arguments;
+};
+
+G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
+
+// Implements GApplication::activate.
+static void my_application_activate(GApplication* application) {
+ MyApplication* self = MY_APPLICATION(application);
+ GtkWindow* window =
+ GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
+
+ // Use a header bar when running in GNOME as this is the common style used
+ // by applications and is the setup most users will be using (e.g. Ubuntu
+ // desktop).
+ // If running on X and not using GNOME then just use a traditional title bar
+ // in case the window manager does more exotic layout, e.g. tiling.
+ // If running on Wayland assume the header bar will work (may need changing
+ // if future cases occur).
+ gboolean use_header_bar = TRUE;
+#ifdef GDK_WINDOWING_X11
+ GdkScreen* screen = gtk_window_get_screen(window);
+ if (GDK_IS_X11_SCREEN(screen)) {
+ const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
+ if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
+ use_header_bar = FALSE;
+ }
+ }
+#endif
+ if (use_header_bar) {
+ GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
+ gtk_widget_show(GTK_WIDGET(header_bar));
+ gtk_header_bar_set_title(header_bar, "jni_example");
+ gtk_header_bar_set_show_close_button(header_bar, TRUE);
+ gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
+ } else {
+ gtk_window_set_title(window, "jni_example");
+ }
+
+ gtk_window_set_default_size(window, 1280, 720);
+ gtk_widget_show(GTK_WIDGET(window));
+
+ g_autoptr(FlDartProject) project = fl_dart_project_new();
+ fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
+
+ FlView* view = fl_view_new(project);
+ gtk_widget_show(GTK_WIDGET(view));
+ gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
+
+ fl_register_plugins(FL_PLUGIN_REGISTRY(view));
+
+ gtk_widget_grab_focus(GTK_WIDGET(view));
+}
+
+// Implements GApplication::local_command_line.
+static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
+ MyApplication* self = MY_APPLICATION(application);
+ // Strip out the first argument as it is the binary name.
+ self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
+
+ g_autoptr(GError) error = nullptr;
+ if (!g_application_register(application, nullptr, &error)) {
+ g_warning("Failed to register: %s", error->message);
+ *exit_status = 1;
+ return TRUE;
+ }
+
+ g_application_activate(application);
+ *exit_status = 0;
+
+ return TRUE;
+}
+
+// Implements GObject::dispose.
+static void my_application_dispose(GObject* object) {
+ MyApplication* self = MY_APPLICATION(object);
+ g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
+ G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
+}
+
+static void my_application_class_init(MyApplicationClass* klass) {
+ G_APPLICATION_CLASS(klass)->activate = my_application_activate;
+ G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
+ G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
+}
+
+static void my_application_init(MyApplication* self) {}
+
+MyApplication* my_application_new() {
+ return MY_APPLICATION(g_object_new(my_application_get_type(),
+ "application-id", APPLICATION_ID,
+ "flags", G_APPLICATION_NON_UNIQUE,
+ nullptr));
+}
diff --git a/pkgs/jni/example/linux/my_application.h b/pkgs/jni/example/linux/my_application.h
new file mode 100644
index 0000000..72271d5
--- /dev/null
+++ b/pkgs/jni/example/linux/my_application.h
@@ -0,0 +1,18 @@
+#ifndef FLUTTER_MY_APPLICATION_H_
+#define FLUTTER_MY_APPLICATION_H_
+
+#include <gtk/gtk.h>
+
+G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
+ GtkApplication)
+
+/**
+ * my_application_new:
+ *
+ * Creates a new Flutter-based application.
+ *
+ * Returns: a new #MyApplication.
+ */
+MyApplication* my_application_new();
+
+#endif // FLUTTER_MY_APPLICATION_H_
diff --git a/pkgs/jni/example/macos/.gitignore b/pkgs/jni/example/macos/.gitignore
new file mode 100644
index 0000000..746adbb
--- /dev/null
+++ b/pkgs/jni/example/macos/.gitignore
@@ -0,0 +1,7 @@
+# Flutter-related
+**/Flutter/ephemeral/
+**/Pods/
+
+# Xcode-related
+**/dgph
+**/xcuserdata/
diff --git a/pkgs/jni/example/macos/Flutter/Flutter-Debug.xcconfig b/pkgs/jni/example/macos/Flutter/Flutter-Debug.xcconfig
new file mode 100644
index 0000000..4b81f9b
--- /dev/null
+++ b/pkgs/jni/example/macos/Flutter/Flutter-Debug.xcconfig
@@ -0,0 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
+#include "ephemeral/Flutter-Generated.xcconfig"
diff --git a/pkgs/jni/example/macos/Flutter/Flutter-Release.xcconfig b/pkgs/jni/example/macos/Flutter/Flutter-Release.xcconfig
new file mode 100644
index 0000000..5caa9d1
--- /dev/null
+++ b/pkgs/jni/example/macos/Flutter/Flutter-Release.xcconfig
@@ -0,0 +1,2 @@
+#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
+#include "ephemeral/Flutter-Generated.xcconfig"
diff --git a/pkgs/jni/example/macos/Flutter/GeneratedPluginRegistrant.swift b/pkgs/jni/example/macos/Flutter/GeneratedPluginRegistrant.swift
new file mode 100644
index 0000000..cccf817
--- /dev/null
+++ b/pkgs/jni/example/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -0,0 +1,10 @@
+//
+// Generated file. Do not edit.
+//
+
+import FlutterMacOS
+import Foundation
+
+
+func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
+}
diff --git a/pkgs/jni/example/macos/Podfile b/pkgs/jni/example/macos/Podfile
new file mode 100644
index 0000000..dade8df
--- /dev/null
+++ b/pkgs/jni/example/macos/Podfile
@@ -0,0 +1,40 @@
+platform :osx, '10.11'
+
+# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
+ENV['COCOAPODS_DISABLE_STATS'] = 'true'
+
+project 'Runner', {
+ 'Debug' => :debug,
+ 'Profile' => :release,
+ 'Release' => :release,
+}
+
+def flutter_root
+ generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
+ unless File.exist?(generated_xcode_build_settings_path)
+ raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
+ end
+
+ File.foreach(generated_xcode_build_settings_path) do |line|
+ matches = line.match(/FLUTTER_ROOT\=(.*)/)
+ return matches[1].strip if matches
+ end
+ raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
+end
+
+require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
+
+flutter_macos_podfile_setup
+
+target 'Runner' do
+ use_frameworks!
+ use_modular_headers!
+
+ flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
+end
+
+post_install do |installer|
+ installer.pods_project.targets.each do |target|
+ flutter_additional_macos_build_settings(target)
+ end
+end
diff --git a/pkgs/jni/example/macos/Runner.xcodeproj/project.pbxproj b/pkgs/jni/example/macos/Runner.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..79f7a20
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner.xcodeproj/project.pbxproj
@@ -0,0 +1,572 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 51;
+ objects = {
+
+/* Begin PBXAggregateTarget section */
+ 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */;
+ buildPhases = (
+ 33CC111E2044C6BF0003C045 /* ShellScript */,
+ );
+ dependencies = (
+ );
+ name = "Flutter Assemble";
+ productName = FLX;
+ };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+ 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
+ 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
+ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
+ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
+ 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 33CC111A2044C6BA0003C045;
+ remoteInfo = FLX;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 33CC110E2044A8840003C045 /* Bundle Framework */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ );
+ name = "Bundle Framework";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
+ 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
+ 33CC10ED2044A3C60003C045 /* jni_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "jni_example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
+ 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
+ 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
+ 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = "<group>"; };
+ 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = "<group>"; };
+ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = "<group>"; };
+ 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = "<group>"; };
+ 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = "<group>"; };
+ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
+ 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
+ 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 33CC10EA2044A3C60003C045 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 33BA886A226E78AF003329D5 /* Configs */ = {
+ isa = PBXGroup;
+ children = (
+ 33E5194F232828860026EE4D /* AppInfo.xcconfig */,
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */,
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
+ 333000ED22D3DE5D00554162 /* Warnings.xcconfig */,
+ );
+ path = Configs;
+ sourceTree = "<group>";
+ };
+ 33CC10E42044A3C60003C045 = {
+ isa = PBXGroup;
+ children = (
+ 33FAB671232836740065AC1E /* Runner */,
+ 33CEB47122A05771004F2AC0 /* Flutter */,
+ 33CC10EE2044A3C60003C045 /* Products */,
+ D73912EC22F37F3D000D13A0 /* Frameworks */,
+ );
+ sourceTree = "<group>";
+ };
+ 33CC10EE2044A3C60003C045 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10ED2044A3C60003C045 /* jni_example.app */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 33CC11242044D66E0003C045 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10F22044A3C60003C045 /* Assets.xcassets */,
+ 33CC10F42044A3C60003C045 /* MainMenu.xib */,
+ 33CC10F72044A3C60003C045 /* Info.plist */,
+ );
+ name = Resources;
+ path = ..;
+ sourceTree = "<group>";
+ };
+ 33CEB47122A05771004F2AC0 /* Flutter */ = {
+ isa = PBXGroup;
+ children = (
+ 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */,
+ 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */,
+ 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */,
+ 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */,
+ );
+ path = Flutter;
+ sourceTree = "<group>";
+ };
+ 33FAB671232836740065AC1E /* Runner */ = {
+ isa = PBXGroup;
+ children = (
+ 33CC10F02044A3C60003C045 /* AppDelegate.swift */,
+ 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */,
+ 33E51913231747F40026EE4D /* DebugProfile.entitlements */,
+ 33E51914231749380026EE4D /* Release.entitlements */,
+ 33CC11242044D66E0003C045 /* Resources */,
+ 33BA886A226E78AF003329D5 /* Configs */,
+ );
+ path = Runner;
+ sourceTree = "<group>";
+ };
+ D73912EC22F37F3D000D13A0 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 33CC10EC2044A3C60003C045 /* Runner */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
+ buildPhases = (
+ 33CC10E92044A3C60003C045 /* Sources */,
+ 33CC10EA2044A3C60003C045 /* Frameworks */,
+ 33CC10EB2044A3C60003C045 /* Resources */,
+ 33CC110E2044A8840003C045 /* Bundle Framework */,
+ 3399D490228B24CF009A79C7 /* ShellScript */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 33CC11202044C79F0003C045 /* PBXTargetDependency */,
+ );
+ name = Runner;
+ productName = Runner;
+ productReference = 33CC10ED2044A3C60003C045 /* jni_example.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 33CC10E52044A3C60003C045 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 0920;
+ LastUpgradeCheck = 1300;
+ ORGANIZATIONNAME = "";
+ TargetAttributes = {
+ 33CC10EC2044A3C60003C045 = {
+ CreatedOnToolsVersion = 9.2;
+ LastSwiftMigration = 1100;
+ ProvisioningStyle = Automatic;
+ SystemCapabilities = {
+ com.apple.Sandbox = {
+ enabled = 1;
+ };
+ };
+ };
+ 33CC111A2044C6BA0003C045 = {
+ CreatedOnToolsVersion = 9.2;
+ ProvisioningStyle = Manual;
+ };
+ };
+ };
+ buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 33CC10E42044A3C60003C045;
+ productRefGroup = 33CC10EE2044A3C60003C045 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 33CC10EC2044A3C60003C045 /* Runner */,
+ 33CC111A2044C6BA0003C045 /* Flutter Assemble */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 33CC10EB2044A3C60003C045 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,
+ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 3399D490228B24CF009A79C7 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
+ };
+ 33CC111E2044C6BF0003C045 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ Flutter/ephemeral/FlutterInputs.xcfilelist,
+ );
+ inputPaths = (
+ Flutter/ephemeral/tripwire,
+ );
+ outputFileListPaths = (
+ Flutter/ephemeral/FlutterOutputs.xcfilelist,
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 33CC10E92044A3C60003C045 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */,
+ 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */,
+ 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 33CC11202044C79F0003C045 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;
+ targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 33CC10F42044A3C60003C045 /* MainMenu.xib */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 33CC10F52044A3C60003C045 /* Base */,
+ );
+ name = MainMenu.xib;
+ path = Runner;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 338D0CE9231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ };
+ name = Profile;
+ };
+ 338D0CEA231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Profile;
+ };
+ 338D0CEB231458BD00FA5F75 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Manual;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Profile;
+ };
+ 33CC10F92044A3C60003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ 33CC10FA2044A3C60003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.11;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = macosx;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ };
+ name = Release;
+ };
+ 33CC10FC2044A3C60003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Debug;
+ };
+ 33CC10FD2044A3C60003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
+ CODE_SIGN_STYLE = Automatic;
+ COMBINE_HIDPI_IMAGES = YES;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/../Frameworks",
+ );
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Release;
+ };
+ 33CC111C2044C6BA0003C045 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Manual;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 33CC111D2044C6BA0003C045 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC10F92044A3C60003C045 /* Debug */,
+ 33CC10FA2044A3C60003C045 /* Release */,
+ 338D0CE9231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC10FC2044A3C60003C045 /* Debug */,
+ 33CC10FD2044A3C60003C045 /* Release */,
+ 338D0CEA231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 33CC111C2044C6BA0003C045 /* Debug */,
+ 33CC111D2044C6BA0003C045 /* Release */,
+ 338D0CEB231458BD00FA5F75 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 33CC10E52044A3C60003C045 /* Project object */;
+}
diff --git a/pkgs/jni/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/pkgs/jni/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IDEDidComputeMac32BitWarning</key>
+ <true/>
+</dict>
+</plist>
diff --git a/pkgs/jni/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/pkgs/jni/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
new file mode 100644
index 0000000..2b12d61
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "1300"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "33CC10EC2044A3C60003C045"
+ BuildableName = "jni_example.app"
+ BlueprintName = "Runner"
+ ReferencedContainer = "container:Runner.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "33CC10EC2044A3C60003C045"
+ BuildableName = "jni_example.app"
+ BlueprintName = "Runner"
+ ReferencedContainer = "container:Runner.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <Testables>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Debug"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "33CC10EC2044A3C60003C045"
+ BuildableName = "jni_example.app"
+ BlueprintName = "Runner"
+ ReferencedContainer = "container:Runner.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Profile"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "33CC10EC2044A3C60003C045"
+ BuildableName = "jni_example.app"
+ BlueprintName = "Runner"
+ ReferencedContainer = "container:Runner.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/pkgs/jni/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/pkgs/jni/example/macos/Runner.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..1d526a1
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "group:Runner.xcodeproj">
+ </FileRef>
+</Workspace>
diff --git a/pkgs/jni/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/pkgs/jni/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IDEDidComputeMac32BitWarning</key>
+ <true/>
+</dict>
+</plist>
diff --git a/pkgs/jni/example/macos/Runner/AppDelegate.swift b/pkgs/jni/example/macos/Runner/AppDelegate.swift
new file mode 100644
index 0000000..d53ef64
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/AppDelegate.swift
@@ -0,0 +1,9 @@
+import Cocoa
+import FlutterMacOS
+
+@NSApplicationMain
+class AppDelegate: FlutterAppDelegate {
+ override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
+ return true
+ }
+}
diff --git a/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..a2ec33f
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,68 @@
+{
+ "images" : [
+ {
+ "size" : "16x16",
+ "idiom" : "mac",
+ "filename" : "app_icon_16.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "16x16",
+ "idiom" : "mac",
+ "filename" : "app_icon_32.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "32x32",
+ "idiom" : "mac",
+ "filename" : "app_icon_32.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "32x32",
+ "idiom" : "mac",
+ "filename" : "app_icon_64.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "128x128",
+ "idiom" : "mac",
+ "filename" : "app_icon_128.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "128x128",
+ "idiom" : "mac",
+ "filename" : "app_icon_256.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "256x256",
+ "idiom" : "mac",
+ "filename" : "app_icon_256.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "256x256",
+ "idiom" : "mac",
+ "filename" : "app_icon_512.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "512x512",
+ "idiom" : "mac",
+ "filename" : "app_icon_512.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "512x512",
+ "idiom" : "mac",
+ "filename" : "app_icon_1024.png",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
new file mode 100644
index 0000000..3c4935a
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
Binary files differ
diff --git a/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
new file mode 100644
index 0000000..ed4cc16
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
Binary files differ
diff --git a/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
new file mode 100644
index 0000000..483be61
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
Binary files differ
diff --git a/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
new file mode 100644
index 0000000..bcbf36d
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
Binary files differ
diff --git a/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
new file mode 100644
index 0000000..9c0a652
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
Binary files differ
diff --git a/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
new file mode 100644
index 0000000..e71a726
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
Binary files differ
diff --git a/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
new file mode 100644
index 0000000..8a31fe2
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
Binary files differ
diff --git a/pkgs/jni/example/macos/Runner/Base.lproj/MainMenu.xib b/pkgs/jni/example/macos/Runner/Base.lproj/MainMenu.xib
new file mode 100644
index 0000000..80e867a
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/Base.lproj/MainMenu.xib
@@ -0,0 +1,343 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+ <dependencies>
+ <deployment identifier="macosx"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14490.70"/>
+ <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+ </dependencies>
+ <objects>
+ <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
+ <connections>
+ <outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
+ </connections>
+ </customObject>
+ <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+ <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+ <customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="Runner" customModuleProvider="target">
+ <connections>
+ <outlet property="applicationMenu" destination="uQy-DD-JDr" id="XBo-yE-nKs"/>
+ <outlet property="mainFlutterWindow" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/>
+ </connections>
+ </customObject>
+ <customObject id="YLy-65-1bz" customClass="NSFontManager"/>
+ <menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
+ <items>
+ <menuItem title="APP_NAME" id="1Xt-HY-uBw">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="APP_NAME" systemMenu="apple" id="uQy-DD-JDr">
+ <items>
+ <menuItem title="About APP_NAME" id="5kV-Vb-QxS">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
+ <menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/>
+ <menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
+ <menuItem title="Services" id="NMo-om-nkz">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
+ <menuItem title="Hide APP_NAME" keyEquivalent="h" id="Olw-nP-bQN">
+ <connections>
+ <action selector="hide:" target="-1" id="PnN-Uc-m68"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
+ <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+ <connections>
+ <action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Show All" id="Kd2-mp-pUS">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
+ <menuItem title="Quit APP_NAME" keyEquivalent="q" id="4sb-4s-VLi">
+ <connections>
+ <action selector="terminate:" target="-1" id="Te7-pn-YzF"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Edit" id="5QF-Oa-p0T">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Edit" id="W48-6f-4Dl">
+ <items>
+ <menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg">
+ <connections>
+ <action selector="undo:" target="-1" id="M6e-cu-g7V"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam">
+ <connections>
+ <action selector="redo:" target="-1" id="oIA-Rs-6OD"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/>
+ <menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG">
+ <connections>
+ <action selector="cut:" target="-1" id="YJe-68-I9s"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU">
+ <connections>
+ <action selector="copy:" target="-1" id="G1f-GL-Joy"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL">
+ <connections>
+ <action selector="paste:" target="-1" id="UvS-8e-Qdg"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk">
+ <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+ <connections>
+ <action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Delete" id="pa3-QI-u2k">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="delete:" target="-1" id="0Mk-Ml-PaM"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m">
+ <connections>
+ <action selector="selectAll:" target="-1" id="VNm-Mi-diN"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/>
+ <menuItem title="Find" id="4EN-yA-p0u">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Find" id="1b7-l0-nxx">
+ <items>
+ <menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W">
+ <connections>
+ <action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz">
+ <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
+ <connections>
+ <action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye">
+ <connections>
+ <action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV">
+ <connections>
+ <action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt">
+ <connections>
+ <action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd">
+ <connections>
+ <action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Spelling and Grammar" id="Dv1-io-Yv7">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Spelling" id="3IN-sU-3Bg">
+ <items>
+ <menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI">
+ <connections>
+ <action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7">
+ <connections>
+ <action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="bNw-od-mp5"/>
+ <menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Correct Spelling Automatically" id="78Y-hA-62v">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Substitutions" id="9ic-FL-obx">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Substitutions" id="FeM-D8-WVr">
+ <items>
+ <menuItem title="Show Substitutions" id="z6F-FW-3nz">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/>
+ <menuItem title="Smart Copy/Paste" id="9yt-4B-nSM">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Smart Quotes" id="hQb-2v-fYv">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Smart Dashes" id="rgM-f4-ycn">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Smart Links" id="cwL-P1-jid">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Data Detectors" id="tRr-pd-1PS">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Text Replacement" id="HFQ-gK-NFA">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Transformations" id="2oI-Rn-ZJC">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Transformations" id="c8a-y6-VQd">
+ <items>
+ <menuItem title="Make Upper Case" id="vmV-6d-7jI">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Make Lower Case" id="d9M-CD-aMd">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Capitalize" id="UEZ-Bs-lqG">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Speech" id="xrE-MZ-jX0">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Speech" id="3rS-ZA-NoH">
+ <items>
+ <menuItem title="Start Speaking" id="Ynk-f8-cLZ">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Stop Speaking" id="Oyz-dy-DGm">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="View" id="H8h-7b-M4v">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="View" id="HyV-fh-RgO">
+ <items>
+ <menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
+ <modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
+ <connections>
+ <action selector="toggleFullScreen:" target="-1" id="dU3-MA-1Rq"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Window" id="aUF-d1-5bR">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
+ <items>
+ <menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
+ <connections>
+ <action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Zoom" id="R4o-n2-Eq4">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
+ <menuItem title="Bring All to Front" id="LE2-aR-0XJ">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem title="Help" id="EPT-qC-fAb">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Help" systemMenu="help" id="rJ0-wn-3NY"/>
+ </menuItem>
+ </items>
+ <point key="canvasLocation" x="142" y="-258"/>
+ </menu>
+ <window title="APP_NAME" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g" customClass="MainFlutterWindow" customModule="Runner" customModuleProvider="target">
+ <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
+ <rect key="contentRect" x="335" y="390" width="800" height="600"/>
+ <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1577"/>
+ <view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ">
+ <rect key="frame" x="0.0" y="0.0" width="800" height="600"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </view>
+ </window>
+ </objects>
+</document>
diff --git a/pkgs/jni/example/macos/Runner/Configs/AppInfo.xcconfig b/pkgs/jni/example/macos/Runner/Configs/AppInfo.xcconfig
new file mode 100644
index 0000000..acda531
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/Configs/AppInfo.xcconfig
@@ -0,0 +1,14 @@
+// Application-level settings for the Runner target.
+//
+// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
+// future. If not, the values below would default to using the project name when this becomes a
+// 'flutter create' template.
+
+// The application's name. By default this is also the title of the Flutter window.
+PRODUCT_NAME = jni_example
+
+// The application's bundle identifier
+PRODUCT_BUNDLE_IDENTIFIER = com.github.dart_lang.jniExample
+
+// The copyright displayed in application information
+PRODUCT_COPYRIGHT = Copyright © 2022 com.github.dart_lang. All rights reserved.
diff --git a/pkgs/jni/example/macos/Runner/Configs/Debug.xcconfig b/pkgs/jni/example/macos/Runner/Configs/Debug.xcconfig
new file mode 100644
index 0000000..36b0fd9
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/Configs/Debug.xcconfig
@@ -0,0 +1,2 @@
+#include "../../Flutter/Flutter-Debug.xcconfig"
+#include "Warnings.xcconfig"
diff --git a/pkgs/jni/example/macos/Runner/Configs/Release.xcconfig b/pkgs/jni/example/macos/Runner/Configs/Release.xcconfig
new file mode 100644
index 0000000..dff4f49
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/Configs/Release.xcconfig
@@ -0,0 +1,2 @@
+#include "../../Flutter/Flutter-Release.xcconfig"
+#include "Warnings.xcconfig"
diff --git a/pkgs/jni/example/macos/Runner/Configs/Warnings.xcconfig b/pkgs/jni/example/macos/Runner/Configs/Warnings.xcconfig
new file mode 100644
index 0000000..42bcbf4
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/Configs/Warnings.xcconfig
@@ -0,0 +1,13 @@
+WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
+GCC_WARN_UNDECLARED_SELECTOR = YES
+CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
+CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
+CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
+CLANG_WARN_PRAGMA_PACK = YES
+CLANG_WARN_STRICT_PROTOTYPES = YES
+CLANG_WARN_COMMA = YES
+GCC_WARN_STRICT_SELECTOR_MATCH = YES
+CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
+CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
+GCC_WARN_SHADOW = YES
+CLANG_WARN_UNREACHABLE_CODE = YES
diff --git a/pkgs/jni/example/macos/Runner/DebugProfile.entitlements b/pkgs/jni/example/macos/Runner/DebugProfile.entitlements
new file mode 100644
index 0000000..dddb8a3
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/DebugProfile.entitlements
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>com.apple.security.app-sandbox</key>
+ <true/>
+ <key>com.apple.security.cs.allow-jit</key>
+ <true/>
+ <key>com.apple.security.network.server</key>
+ <true/>
+</dict>
+</plist>
diff --git a/pkgs/jni/example/macos/Runner/Info.plist b/pkgs/jni/example/macos/Runner/Info.plist
new file mode 100644
index 0000000..4789daa
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/Info.plist
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
+ <key>CFBundleExecutable</key>
+ <string>$(EXECUTABLE_NAME)</string>
+ <key>CFBundleIconFile</key>
+ <string></string>
+ <key>CFBundleIdentifier</key>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>$(PRODUCT_NAME)</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>$(FLUTTER_BUILD_NAME)</string>
+ <key>CFBundleVersion</key>
+ <string>$(FLUTTER_BUILD_NUMBER)</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>$(MACOSX_DEPLOYMENT_TARGET)</string>
+ <key>NSHumanReadableCopyright</key>
+ <string>$(PRODUCT_COPYRIGHT)</string>
+ <key>NSMainNibFile</key>
+ <string>MainMenu</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
diff --git a/pkgs/jni/example/macos/Runner/MainFlutterWindow.swift b/pkgs/jni/example/macos/Runner/MainFlutterWindow.swift
new file mode 100644
index 0000000..2722837
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/MainFlutterWindow.swift
@@ -0,0 +1,15 @@
+import Cocoa
+import FlutterMacOS
+
+class MainFlutterWindow: NSWindow {
+ override func awakeFromNib() {
+ let flutterViewController = FlutterViewController.init()
+ let windowFrame = self.frame
+ self.contentViewController = flutterViewController
+ self.setFrame(windowFrame, display: true)
+
+ RegisterGeneratedPlugins(registry: flutterViewController)
+
+ super.awakeFromNib()
+ }
+}
diff --git a/pkgs/jni/example/macos/Runner/Release.entitlements b/pkgs/jni/example/macos/Runner/Release.entitlements
new file mode 100644
index 0000000..852fa1a
--- /dev/null
+++ b/pkgs/jni/example/macos/Runner/Release.entitlements
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>com.apple.security.app-sandbox</key>
+ <true/>
+</dict>
+</plist>
diff --git a/pkgs/jni/example/pubspec.lock b/pkgs/jni/example/pubspec.lock
new file mode 100644
index 0000000..0da0519
--- /dev/null
+++ b/pkgs/jni/example/pubspec.lock
@@ -0,0 +1,523 @@
+# Generated by pub
+# See https://dart.dev/tools/pub/glossary#lockfile
+packages:
+ _fe_analyzer_shared:
+ dependency: transitive
+ description:
+ name: _fe_analyzer_shared
+ sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a
+ url: "https://pub.dev"
+ source: hosted
+ version: "61.0.0"
+ analyzer:
+ dependency: transitive
+ description:
+ name: analyzer
+ sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.13.0"
+ args:
+ dependency: transitive
+ description:
+ name: args
+ sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.2"
+ async:
+ dependency: transitive
+ description:
+ name: async
+ sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.11.0"
+ boolean_selector:
+ dependency: transitive
+ description:
+ name: boolean_selector
+ sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.1"
+ characters:
+ dependency: transitive
+ description:
+ name: characters
+ sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.0"
+ clock:
+ dependency: transitive
+ description:
+ name: clock
+ sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.1"
+ collection:
+ dependency: transitive
+ description:
+ name: collection
+ sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.17.2"
+ convert:
+ dependency: transitive
+ description:
+ name: convert
+ sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.1"
+ coverage:
+ dependency: transitive
+ description:
+ name: coverage
+ sha256: "2fb815080e44a09b85e0f2ca8a820b15053982b2e714b59267719e8a9ff17097"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.6.3"
+ crypto:
+ dependency: transitive
+ description:
+ name: crypto
+ sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.3"
+ cupertino_icons:
+ dependency: "direct main"
+ description:
+ name: cupertino_icons
+ sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.5"
+ fake_async:
+ dependency: transitive
+ description:
+ name: fake_async
+ sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.1"
+ ffi:
+ dependency: "direct main"
+ description:
+ name: ffi
+ sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.0"
+ file:
+ dependency: transitive
+ description:
+ name: file
+ sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.1.4"
+ flutter:
+ dependency: "direct main"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_driver:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_lints:
+ dependency: "direct dev"
+ description:
+ name: flutter_lints
+ sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.2"
+ flutter_test:
+ dependency: "direct dev"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ frontend_server_client:
+ dependency: transitive
+ description:
+ name: frontend_server_client
+ sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.2.0"
+ fuchsia_remote_debug_protocol:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ glob:
+ dependency: transitive
+ description:
+ name: glob
+ sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.2"
+ http_multi_server:
+ dependency: transitive
+ description:
+ name: http_multi_server
+ sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.2.1"
+ http_parser:
+ dependency: transitive
+ description:
+ name: http_parser
+ sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.0.2"
+ integration_test:
+ dependency: "direct dev"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ io:
+ dependency: transitive
+ description:
+ name: io
+ sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.4"
+ jni:
+ dependency: "direct main"
+ description:
+ path: ".."
+ relative: true
+ source: path
+ version: "0.6.1"
+ js:
+ dependency: transitive
+ description:
+ name: js
+ sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.6.7"
+ lints:
+ dependency: transitive
+ description:
+ name: lints
+ sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.1"
+ logging:
+ dependency: transitive
+ description:
+ name: logging
+ sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.0"
+ matcher:
+ dependency: transitive
+ description:
+ name: matcher
+ sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.12.16"
+ material_color_utilities:
+ dependency: transitive
+ description:
+ name: material_color_utilities
+ sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.5.0"
+ meta:
+ dependency: transitive
+ description:
+ name: meta
+ sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.9.1"
+ mime:
+ dependency: transitive
+ description:
+ name: mime
+ sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.4"
+ node_preamble:
+ dependency: transitive
+ description:
+ name: node_preamble
+ sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.2"
+ package_config:
+ dependency: transitive
+ description:
+ name: package_config
+ sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.0"
+ path:
+ dependency: transitive
+ description:
+ name: path
+ sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.8.3"
+ platform:
+ dependency: transitive
+ description:
+ name: platform
+ sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.0"
+ plugin_platform_interface:
+ dependency: transitive
+ description:
+ name: plugin_platform_interface
+ sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.5"
+ pool:
+ dependency: transitive
+ description:
+ name: pool
+ sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.5.1"
+ process:
+ dependency: transitive
+ description:
+ name: process
+ sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.2.4"
+ pub_semver:
+ dependency: transitive
+ description:
+ name: pub_semver
+ sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.4"
+ shelf:
+ dependency: transitive
+ description:
+ name: shelf
+ sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.4.1"
+ shelf_packages_handler:
+ dependency: transitive
+ description:
+ name: shelf_packages_handler
+ sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.2"
+ shelf_static:
+ dependency: transitive
+ description:
+ name: shelf_static
+ sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.2"
+ shelf_web_socket:
+ dependency: transitive
+ description:
+ name: shelf_web_socket
+ sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.4"
+ sky_engine:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.99"
+ source_map_stack_trace:
+ dependency: transitive
+ description:
+ name: source_map_stack_trace
+ sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.1"
+ source_maps:
+ dependency: transitive
+ description:
+ name: source_maps
+ sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.10.12"
+ source_span:
+ dependency: transitive
+ description:
+ name: source_span
+ sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.10.0"
+ stack_trace:
+ dependency: transitive
+ description:
+ name: stack_trace
+ sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.11.0"
+ stream_channel:
+ dependency: transitive
+ description:
+ name: stream_channel
+ sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.1"
+ string_scanner:
+ dependency: transitive
+ description:
+ name: string_scanner
+ sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.0"
+ sync_http:
+ dependency: transitive
+ description:
+ name: sync_http
+ sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.3.1"
+ term_glyph:
+ dependency: transitive
+ description:
+ name: term_glyph
+ sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.1"
+ test:
+ dependency: "direct dev"
+ description:
+ name: test
+ sha256: "13b41f318e2a5751c3169137103b60c584297353d4b1761b66029bae6411fe46"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.24.3"
+ test_api:
+ dependency: transitive
+ description:
+ name: test_api
+ sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.6.0"
+ test_core:
+ dependency: transitive
+ description:
+ name: test_core
+ sha256: "99806e9e6d95c7b059b7a0fc08f07fc53fabe54a829497f0d9676299f1e8637e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.5.3"
+ typed_data:
+ dependency: transitive
+ description:
+ name: typed_data
+ sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.2"
+ vector_math:
+ dependency: transitive
+ description:
+ name: vector_math
+ sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.4"
+ vm_service:
+ dependency: transitive
+ description:
+ name: vm_service
+ sha256: c620a6f783fa22436da68e42db7ebbf18b8c44b9a46ab911f666ff09ffd9153f
+ url: "https://pub.dev"
+ source: hosted
+ version: "11.7.1"
+ watcher:
+ dependency: transitive
+ description:
+ name: watcher
+ sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.1.0"
+ web:
+ dependency: transitive
+ description:
+ name: web
+ sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.1.4-beta"
+ web_socket_channel:
+ dependency: transitive
+ description:
+ name: web_socket_channel
+ sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.0"
+ webdriver:
+ dependency: transitive
+ description:
+ name: webdriver
+ sha256: "3c923e918918feeb90c4c9fdf1fe39220fa4c0e8e2c0fffaded174498ef86c49"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.2"
+ webkit_inspection_protocol:
+ dependency: transitive
+ description:
+ name: webkit_inspection_protocol
+ sha256: "67d3a8b6c79e1987d19d848b0892e582dbb0c66c57cc1fef58a177dd2aa2823d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.2.0"
+ yaml:
+ dependency: transitive
+ description:
+ name: yaml
+ sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.2"
+sdks:
+ dart: ">=3.1.0 <4.0.0"
+ flutter: ">=2.11.0"
diff --git a/pkgs/jni/example/pubspec.yaml b/pkgs/jni/example/pubspec.yaml
new file mode 100644
index 0000000..ce06464
--- /dev/null
+++ b/pkgs/jni/example/pubspec.yaml
@@ -0,0 +1,100 @@
+name: jni_example
+description: Demonstrates how to use the jni plugin.
+
+# The following line prevents the package from being accidentally published to
+# pub.dev using `flutter pub publish`. This is preferred for private packages.
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+# The following defines the version and build number for your application.
+# A version number is three numbers separated by dots, like 1.2.43
+# followed by an optional build number separated by a +.
+# Both the version and the builder number may be overridden in flutter
+# build by specifying --build-name and --build-number, respectively.
+# In Android, build-name is used as versionName while build-number used as versionCode.
+# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
+# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
+# Read more about iOS versioning at
+# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
+version: 1.0.0+1
+
+environment:
+ sdk: '>=3.1.0 <4.0.0'
+
+# Dependencies specify other packages that your package needs in order to work.
+# To automatically upgrade your package dependencies to the latest versions
+# consider running `flutter pub upgrade --major-versions`. Alternatively,
+# dependencies can be manually updated by changing the version numbers below to
+# the latest version available on pub.dev. To see which dependencies have newer
+# versions available, run `flutter pub outdated`.
+dependencies:
+ flutter:
+ sdk: flutter
+
+ ffi: ^2.0.0
+
+ jni:
+ # When depending on this package from a real application you should use:
+ # jni: ^x.y.z
+ # See https://dart.dev/tools/pub/dependencies#version-constraints
+ # The example app is bundled with the plugin so we use a path dependency on
+ # the parent directory to use the current plugin's version.
+ path: ../
+
+ # The following adds the Cupertino Icons font to your application.
+ # Use with the CupertinoIcons class for iOS style icons.
+ cupertino_icons: ^1.0.2
+
+dev_dependencies:
+ test: any
+ flutter_test:
+ sdk: flutter
+ integration_test:
+ sdk: flutter
+
+ # The "flutter_lints" package below contains a set of recommended lints to
+ # encourage good coding practices. The lint set provided by the package is
+ # activated in the `analysis_options.yaml` file located at the root of your
+ # package. See that file for information about deactivating specific lint
+ # rules and activating additional ones.
+ flutter_lints: ^2.0.0
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter packages.
+flutter:
+ # The following line ensures that the Material Icons font is
+ # included with your application, so that you can use the icons in
+ # the material Icons class.
+ uses-material-design: true
+
+ # To add assets to your application, add an assets section, like this:
+ # assets:
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
+
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/assets-and-images/#resolution-aware
+
+ # For details regarding adding assets from package dependencies, see
+ # https://flutter.dev/assets-and-images/#from-packages
+
+ # To add custom fonts to your application, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts from package dependencies,
+ # see https://flutter.dev/custom-fonts/#from-packages
diff --git a/pkgs/jni/example/windows/.gitignore b/pkgs/jni/example/windows/.gitignore
new file mode 100644
index 0000000..d492d0d
--- /dev/null
+++ b/pkgs/jni/example/windows/.gitignore
@@ -0,0 +1,17 @@
+flutter/ephemeral/
+
+# Visual Studio user-specific files.
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# Visual Studio build-related files.
+x64/
+x86/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
diff --git a/pkgs/jni/example/windows/CMakeLists.txt b/pkgs/jni/example/windows/CMakeLists.txt
new file mode 100644
index 0000000..1948892
--- /dev/null
+++ b/pkgs/jni/example/windows/CMakeLists.txt
@@ -0,0 +1,101 @@
+# Project-level configuration.
+cmake_minimum_required(VERSION 3.14)
+project(jni_example LANGUAGES CXX)
+
+# The name of the executable created for the application. Change this to change
+# the on-disk name of your application.
+set(BINARY_NAME "jni_example")
+
+# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
+# versions of CMake.
+cmake_policy(SET CMP0063 NEW)
+
+# Define build configuration option.
+get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(IS_MULTICONFIG)
+ set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
+ CACHE STRING "" FORCE)
+else()
+ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+ set(CMAKE_BUILD_TYPE "Debug" CACHE
+ STRING "Flutter build mode" FORCE)
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+ "Debug" "Profile" "Release")
+ endif()
+endif()
+# Define settings for the Profile build mode.
+set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
+set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
+set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
+set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
+
+# Use Unicode for all projects.
+add_definitions(-DUNICODE -D_UNICODE)
+
+# Compilation settings that should be applied to most targets.
+#
+# Be cautious about adding new options here, as plugins use this function by
+# default. In most cases, you should add new options to specific targets instead
+# of modifying this function.
+function(APPLY_STANDARD_SETTINGS TARGET)
+ target_compile_features(${TARGET} PUBLIC cxx_std_17)
+ target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
+ target_compile_options(${TARGET} PRIVATE /EHsc)
+ target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
+ target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>")
+endfunction()
+
+# Flutter library and tool build rules.
+set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
+add_subdirectory(${FLUTTER_MANAGED_DIR})
+
+# Application build; see runner/CMakeLists.txt.
+add_subdirectory("runner")
+
+# Generated plugin build rules, which manage building the plugins and adding
+# them to the application.
+include(flutter/generated_plugins.cmake)
+
+
+# === Installation ===
+# Support files are copied into place next to the executable, so that it can
+# run in place. This is done instead of making a separate bundle (as on Linux)
+# so that building and running from within Visual Studio will work.
+set(BUILD_BUNDLE_DIR "$<TARGET_FILE_DIR:${BINARY_NAME}>")
+# Make the "install" step default, as it's required to run.
+set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
+endif()
+
+set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
+set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
+
+install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
+ COMPONENT Runtime)
+
+install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
+ COMPONENT Runtime)
+
+install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+
+if(PLUGIN_BUNDLED_LIBRARIES)
+ install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
+ DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+endif()
+
+# Fully re-copy the assets directory on each build to avoid having stale files
+# from a previous install.
+set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
+install(CODE "
+ file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
+ " COMPONENT Runtime)
+install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
+ DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
+
+# Install the AOT library on non-Debug builds only.
+install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
+ CONFIGURATIONS Profile;Release
+ COMPONENT Runtime)
diff --git a/pkgs/jni/example/windows/flutter/CMakeLists.txt b/pkgs/jni/example/windows/flutter/CMakeLists.txt
new file mode 100644
index 0000000..930d207
--- /dev/null
+++ b/pkgs/jni/example/windows/flutter/CMakeLists.txt
@@ -0,0 +1,104 @@
+# This file controls Flutter-level build steps. It should not be edited.
+cmake_minimum_required(VERSION 3.14)
+
+set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
+
+# Configuration provided via flutter tool.
+include(${EPHEMERAL_DIR}/generated_config.cmake)
+
+# TODO: Move the rest of this into files in ephemeral. See
+# https://github.com/flutter/flutter/issues/57146.
+set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
+
+# === Flutter Library ===
+set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
+
+# Published to parent scope for install step.
+set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
+set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
+set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
+set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE)
+
+list(APPEND FLUTTER_LIBRARY_HEADERS
+ "flutter_export.h"
+ "flutter_windows.h"
+ "flutter_messenger.h"
+ "flutter_plugin_registrar.h"
+ "flutter_texture_registrar.h"
+)
+list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
+add_library(flutter INTERFACE)
+target_include_directories(flutter INTERFACE
+ "${EPHEMERAL_DIR}"
+)
+target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib")
+add_dependencies(flutter flutter_assemble)
+
+# === Wrapper ===
+list(APPEND CPP_WRAPPER_SOURCES_CORE
+ "core_implementations.cc"
+ "standard_codec.cc"
+)
+list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/")
+list(APPEND CPP_WRAPPER_SOURCES_PLUGIN
+ "plugin_registrar.cc"
+)
+list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/")
+list(APPEND CPP_WRAPPER_SOURCES_APP
+ "flutter_engine.cc"
+ "flutter_view_controller.cc"
+)
+list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/")
+
+# Wrapper sources needed for a plugin.
+add_library(flutter_wrapper_plugin STATIC
+ ${CPP_WRAPPER_SOURCES_CORE}
+ ${CPP_WRAPPER_SOURCES_PLUGIN}
+)
+apply_standard_settings(flutter_wrapper_plugin)
+set_target_properties(flutter_wrapper_plugin PROPERTIES
+ POSITION_INDEPENDENT_CODE ON)
+set_target_properties(flutter_wrapper_plugin PROPERTIES
+ CXX_VISIBILITY_PRESET hidden)
+target_link_libraries(flutter_wrapper_plugin PUBLIC flutter)
+target_include_directories(flutter_wrapper_plugin PUBLIC
+ "${WRAPPER_ROOT}/include"
+)
+add_dependencies(flutter_wrapper_plugin flutter_assemble)
+
+# Wrapper sources needed for the runner.
+add_library(flutter_wrapper_app STATIC
+ ${CPP_WRAPPER_SOURCES_CORE}
+ ${CPP_WRAPPER_SOURCES_APP}
+)
+apply_standard_settings(flutter_wrapper_app)
+target_link_libraries(flutter_wrapper_app PUBLIC flutter)
+target_include_directories(flutter_wrapper_app PUBLIC
+ "${WRAPPER_ROOT}/include"
+)
+add_dependencies(flutter_wrapper_app flutter_assemble)
+
+# === Flutter tool backend ===
+# _phony_ is a non-existent file to force this command to run every time,
+# since currently there's no way to get a full input/output list from the
+# flutter tool.
+set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
+set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
+add_custom_command(
+ OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
+ ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
+ ${CPP_WRAPPER_SOURCES_APP}
+ ${PHONY_OUTPUT}
+ COMMAND ${CMAKE_COMMAND} -E env
+ ${FLUTTER_TOOL_ENVIRONMENT}
+ "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
+ windows-x64 $<CONFIG>
+ VERBATIM
+)
+add_custom_target(flutter_assemble DEPENDS
+ "${FLUTTER_LIBRARY}"
+ ${FLUTTER_LIBRARY_HEADERS}
+ ${CPP_WRAPPER_SOURCES_CORE}
+ ${CPP_WRAPPER_SOURCES_PLUGIN}
+ ${CPP_WRAPPER_SOURCES_APP}
+)
diff --git a/pkgs/jni/example/windows/flutter/generated_plugin_registrant.cc b/pkgs/jni/example/windows/flutter/generated_plugin_registrant.cc
new file mode 100644
index 0000000..8b6d468
--- /dev/null
+++ b/pkgs/jni/example/windows/flutter/generated_plugin_registrant.cc
@@ -0,0 +1,11 @@
+//
+// Generated file. Do not edit.
+//
+
+// clang-format off
+
+#include "generated_plugin_registrant.h"
+
+
+void RegisterPlugins(flutter::PluginRegistry* registry) {
+}
diff --git a/pkgs/jni/example/windows/flutter/generated_plugin_registrant.h b/pkgs/jni/example/windows/flutter/generated_plugin_registrant.h
new file mode 100644
index 0000000..dc139d8
--- /dev/null
+++ b/pkgs/jni/example/windows/flutter/generated_plugin_registrant.h
@@ -0,0 +1,15 @@
+//
+// Generated file. Do not edit.
+//
+
+// clang-format off
+
+#ifndef GENERATED_PLUGIN_REGISTRANT_
+#define GENERATED_PLUGIN_REGISTRANT_
+
+#include <flutter/plugin_registry.h>
+
+// Registers Flutter plugins.
+void RegisterPlugins(flutter::PluginRegistry* registry);
+
+#endif // GENERATED_PLUGIN_REGISTRANT_
diff --git a/pkgs/jni/example/windows/flutter/generated_plugins.cmake b/pkgs/jni/example/windows/flutter/generated_plugins.cmake
new file mode 100644
index 0000000..3ad69c6
--- /dev/null
+++ b/pkgs/jni/example/windows/flutter/generated_plugins.cmake
@@ -0,0 +1,24 @@
+#
+# Generated file, do not edit.
+#
+
+list(APPEND FLUTTER_PLUGIN_LIST
+)
+
+list(APPEND FLUTTER_FFI_PLUGIN_LIST
+ jni
+)
+
+set(PLUGIN_BUNDLED_LIBRARIES)
+
+foreach(plugin ${FLUTTER_PLUGIN_LIST})
+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
+ target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
+endforeach(plugin)
+
+foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
+endforeach(ffi_plugin)
diff --git a/pkgs/jni/example/windows/runner/CMakeLists.txt b/pkgs/jni/example/windows/runner/CMakeLists.txt
new file mode 100644
index 0000000..b9e550f
--- /dev/null
+++ b/pkgs/jni/example/windows/runner/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.14)
+project(runner LANGUAGES CXX)
+
+# Define the application target. To change its name, change BINARY_NAME in the
+# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
+# work.
+#
+# Any new source files that you add to the application should be added here.
+add_executable(${BINARY_NAME} WIN32
+ "flutter_window.cpp"
+ "main.cpp"
+ "utils.cpp"
+ "win32_window.cpp"
+ "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
+ "Runner.rc"
+ "runner.exe.manifest"
+)
+
+# Apply the standard set of build settings. This can be removed for applications
+# that need different build settings.
+apply_standard_settings(${BINARY_NAME})
+
+# Disable Windows macros that collide with C++ standard library functions.
+target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
+
+# Add dependency libraries and include directories. Add any application-specific
+# dependencies here.
+target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
+target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
+
+# Run the Flutter tool portions of the build. This must not be removed.
+add_dependencies(${BINARY_NAME} flutter_assemble)
diff --git a/pkgs/jni/example/windows/runner/Runner.rc b/pkgs/jni/example/windows/runner/Runner.rc
new file mode 100644
index 0000000..79c3952
--- /dev/null
+++ b/pkgs/jni/example/windows/runner/Runner.rc
@@ -0,0 +1,121 @@
+// Microsoft Visual C++ generated resource script.
+//
+#pragma code_page(65001)
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_APP_ICON ICON "resources\\app_icon.ico"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+#ifdef FLUTTER_BUILD_NUMBER
+#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER
+#else
+#define VERSION_AS_NUMBER 1,0,0
+#endif
+
+#ifdef FLUTTER_BUILD_NAME
+#define VERSION_AS_STRING #FLUTTER_BUILD_NAME
+#else
+#define VERSION_AS_STRING "1.0.0"
+#endif
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION VERSION_AS_NUMBER
+ PRODUCTVERSION VERSION_AS_NUMBER
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#ifdef _DEBUG
+ FILEFLAGS VS_FF_DEBUG
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_APP
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "CompanyName", "com.github.dart_lang" "\0"
+ VALUE "FileDescription", "jni_example" "\0"
+ VALUE "FileVersion", VERSION_AS_STRING "\0"
+ VALUE "InternalName", "jni_example" "\0"
+ VALUE "LegalCopyright", "Copyright (C) 2022 Dart Project Authors. All rights reserved." "\0"
+ VALUE "OriginalFilename", "jni_example.exe" "\0"
+ VALUE "ProductName", "jni_example" "\0"
+ VALUE "ProductVersion", VERSION_AS_STRING "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
diff --git a/pkgs/jni/example/windows/runner/flutter_window.cpp b/pkgs/jni/example/windows/runner/flutter_window.cpp
new file mode 100644
index 0000000..b43b909
--- /dev/null
+++ b/pkgs/jni/example/windows/runner/flutter_window.cpp
@@ -0,0 +1,61 @@
+#include "flutter_window.h"
+
+#include <optional>
+
+#include "flutter/generated_plugin_registrant.h"
+
+FlutterWindow::FlutterWindow(const flutter::DartProject& project)
+ : project_(project) {}
+
+FlutterWindow::~FlutterWindow() {}
+
+bool FlutterWindow::OnCreate() {
+ if (!Win32Window::OnCreate()) {
+ return false;
+ }
+
+ RECT frame = GetClientArea();
+
+ // The size here must match the window dimensions to avoid unnecessary surface
+ // creation / destruction in the startup path.
+ flutter_controller_ = std::make_unique<flutter::FlutterViewController>(
+ frame.right - frame.left, frame.bottom - frame.top, project_);
+ // Ensure that basic setup of the controller was successful.
+ if (!flutter_controller_->engine() || !flutter_controller_->view()) {
+ return false;
+ }
+ RegisterPlugins(flutter_controller_->engine());
+ SetChildContent(flutter_controller_->view()->GetNativeWindow());
+ return true;
+}
+
+void FlutterWindow::OnDestroy() {
+ if (flutter_controller_) {
+ flutter_controller_ = nullptr;
+ }
+
+ Win32Window::OnDestroy();
+}
+
+LRESULT
+FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept {
+ // Give Flutter, including plugins, an opportunity to handle window messages.
+ if (flutter_controller_) {
+ std::optional<LRESULT> result =
+ flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
+ lparam);
+ if (result) {
+ return *result;
+ }
+ }
+
+ switch (message) {
+ case WM_FONTCHANGE:
+ flutter_controller_->engine()->ReloadSystemFonts();
+ break;
+ }
+
+ return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
+}
diff --git a/pkgs/jni/example/windows/runner/flutter_window.h b/pkgs/jni/example/windows/runner/flutter_window.h
new file mode 100644
index 0000000..6da0652
--- /dev/null
+++ b/pkgs/jni/example/windows/runner/flutter_window.h
@@ -0,0 +1,33 @@
+#ifndef RUNNER_FLUTTER_WINDOW_H_
+#define RUNNER_FLUTTER_WINDOW_H_
+
+#include <flutter/dart_project.h>
+#include <flutter/flutter_view_controller.h>
+
+#include <memory>
+
+#include "win32_window.h"
+
+// A window that does nothing but host a Flutter view.
+class FlutterWindow : public Win32Window {
+ public:
+ // Creates a new FlutterWindow hosting a Flutter view running |project|.
+ explicit FlutterWindow(const flutter::DartProject& project);
+ virtual ~FlutterWindow();
+
+ protected:
+ // Win32Window:
+ bool OnCreate() override;
+ void OnDestroy() override;
+ LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
+ LPARAM const lparam) noexcept override;
+
+ private:
+ // The project to run.
+ flutter::DartProject project_;
+
+ // The Flutter instance hosted by this window.
+ std::unique_ptr<flutter::FlutterViewController> flutter_controller_;
+};
+
+#endif // RUNNER_FLUTTER_WINDOW_H_
diff --git a/pkgs/jni/example/windows/runner/main.cpp b/pkgs/jni/example/windows/runner/main.cpp
new file mode 100644
index 0000000..fa17f9e
--- /dev/null
+++ b/pkgs/jni/example/windows/runner/main.cpp
@@ -0,0 +1,43 @@
+#include <flutter/dart_project.h>
+#include <flutter/flutter_view_controller.h>
+#include <windows.h>
+
+#include "flutter_window.h"
+#include "utils.h"
+
+int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
+ _In_ wchar_t *command_line, _In_ int show_command) {
+ // Attach to console when present (e.g., 'flutter run') or create a
+ // new console when running with a debugger.
+ if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
+ CreateAndAttachConsole();
+ }
+
+ // Initialize COM, so that it is available for use in the library and/or
+ // plugins.
+ ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
+
+ flutter::DartProject project(L"data");
+
+ std::vector<std::string> command_line_arguments =
+ GetCommandLineArguments();
+
+ project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
+
+ FlutterWindow window(project);
+ Win32Window::Point origin(10, 10);
+ Win32Window::Size size(1280, 720);
+ if (!window.CreateAndShow(L"jni_example", origin, size)) {
+ return EXIT_FAILURE;
+ }
+ window.SetQuitOnClose(true);
+
+ ::MSG msg;
+ while (::GetMessage(&msg, nullptr, 0, 0)) {
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ }
+
+ ::CoUninitialize();
+ return EXIT_SUCCESS;
+}
diff --git a/pkgs/jni/example/windows/runner/resource.h b/pkgs/jni/example/windows/runner/resource.h
new file mode 100644
index 0000000..66a65d1
--- /dev/null
+++ b/pkgs/jni/example/windows/runner/resource.h
@@ -0,0 +1,16 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Runner.rc
+//
+#define IDI_APP_ICON 101
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/pkgs/jni/example/windows/runner/resources/app_icon.ico b/pkgs/jni/example/windows/runner/resources/app_icon.ico
new file mode 100644
index 0000000..c04e20c
--- /dev/null
+++ b/pkgs/jni/example/windows/runner/resources/app_icon.ico
Binary files differ
diff --git a/pkgs/jni/example/windows/runner/runner.exe.manifest b/pkgs/jni/example/windows/runner/runner.exe.manifest
new file mode 100644
index 0000000..c977c4a
--- /dev/null
+++ b/pkgs/jni/example/windows/runner/runner.exe.manifest
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <application xmlns="urn:schemas-microsoft-com:asm.v3">
+ <windowsSettings>
+ <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
+ </windowsSettings>
+ </application>
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <!-- Windows 10 -->
+ <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+ <!-- Windows 8.1 -->
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+ <!-- Windows 8 -->
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+ <!-- Windows 7 -->
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+ </application>
+ </compatibility>
+</assembly>
diff --git a/pkgs/jni/example/windows/runner/utils.cpp b/pkgs/jni/example/windows/runner/utils.cpp
new file mode 100644
index 0000000..f5bf9fa
--- /dev/null
+++ b/pkgs/jni/example/windows/runner/utils.cpp
@@ -0,0 +1,64 @@
+#include "utils.h"
+
+#include <flutter_windows.h>
+#include <io.h>
+#include <stdio.h>
+#include <windows.h>
+
+#include <iostream>
+
+void CreateAndAttachConsole() {
+ if (::AllocConsole()) {
+ FILE *unused;
+ if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
+ _dup2(_fileno(stdout), 1);
+ }
+ if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
+ _dup2(_fileno(stdout), 2);
+ }
+ std::ios::sync_with_stdio();
+ FlutterDesktopResyncOutputStreams();
+ }
+}
+
+std::vector<std::string> GetCommandLineArguments() {
+ // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
+ int argc;
+ wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
+ if (argv == nullptr) {
+ return std::vector<std::string>();
+ }
+
+ std::vector<std::string> command_line_arguments;
+
+ // Skip the first argument as it's the binary name.
+ for (int i = 1; i < argc; i++) {
+ command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
+ }
+
+ ::LocalFree(argv);
+
+ return command_line_arguments;
+}
+
+std::string Utf8FromUtf16(const wchar_t* utf16_string) {
+ if (utf16_string == nullptr) {
+ return std::string();
+ }
+ int target_length = ::WideCharToMultiByte(
+ CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
+ -1, nullptr, 0, nullptr, nullptr);
+ std::string utf8_string;
+ if (target_length == 0 || target_length > utf8_string.max_size()) {
+ return utf8_string;
+ }
+ utf8_string.resize(target_length);
+ int converted_length = ::WideCharToMultiByte(
+ CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
+ -1, utf8_string.data(),
+ target_length, nullptr, nullptr);
+ if (converted_length == 0) {
+ return std::string();
+ }
+ return utf8_string;
+}
diff --git a/pkgs/jni/example/windows/runner/utils.h b/pkgs/jni/example/windows/runner/utils.h
new file mode 100644
index 0000000..3879d54
--- /dev/null
+++ b/pkgs/jni/example/windows/runner/utils.h
@@ -0,0 +1,19 @@
+#ifndef RUNNER_UTILS_H_
+#define RUNNER_UTILS_H_
+
+#include <string>
+#include <vector>
+
+// Creates a console for the process, and redirects stdout and stderr to
+// it for both the runner and the Flutter library.
+void CreateAndAttachConsole();
+
+// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
+// encoded in UTF-8. Returns an empty std::string on failure.
+std::string Utf8FromUtf16(const wchar_t* utf16_string);
+
+// Gets the command line arguments passed in as a std::vector<std::string>,
+// encoded in UTF-8. Returns an empty std::vector<std::string> on failure.
+std::vector<std::string> GetCommandLineArguments();
+
+#endif // RUNNER_UTILS_H_
diff --git a/pkgs/jni/example/windows/runner/win32_window.cpp b/pkgs/jni/example/windows/runner/win32_window.cpp
new file mode 100644
index 0000000..c10f08d
--- /dev/null
+++ b/pkgs/jni/example/windows/runner/win32_window.cpp
@@ -0,0 +1,245 @@
+#include "win32_window.h"
+
+#include <flutter_windows.h>
+
+#include "resource.h"
+
+namespace {
+
+constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
+
+// The number of Win32Window objects that currently exist.
+static int g_active_window_count = 0;
+
+using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd);
+
+// Scale helper to convert logical scaler values to physical using passed in
+// scale factor
+int Scale(int source, double scale_factor) {
+ return static_cast<int>(source * scale_factor);
+}
+
+// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
+// This API is only needed for PerMonitor V1 awareness mode.
+void EnableFullDpiSupportIfAvailable(HWND hwnd) {
+ HMODULE user32_module = LoadLibraryA("User32.dll");
+ if (!user32_module) {
+ return;
+ }
+ auto enable_non_client_dpi_scaling =
+ reinterpret_cast<EnableNonClientDpiScaling*>(
+ GetProcAddress(user32_module, "EnableNonClientDpiScaling"));
+ if (enable_non_client_dpi_scaling != nullptr) {
+ enable_non_client_dpi_scaling(hwnd);
+ FreeLibrary(user32_module);
+ }
+}
+
+} // namespace
+
+// Manages the Win32Window's window class registration.
+class WindowClassRegistrar {
+ public:
+ ~WindowClassRegistrar() = default;
+
+ // Returns the singleton registar instance.
+ static WindowClassRegistrar* GetInstance() {
+ if (!instance_) {
+ instance_ = new WindowClassRegistrar();
+ }
+ return instance_;
+ }
+
+ // Returns the name of the window class, registering the class if it hasn't
+ // previously been registered.
+ const wchar_t* GetWindowClass();
+
+ // Unregisters the window class. Should only be called if there are no
+ // instances of the window.
+ void UnregisterWindowClass();
+
+ private:
+ WindowClassRegistrar() = default;
+
+ static WindowClassRegistrar* instance_;
+
+ bool class_registered_ = false;
+};
+
+WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr;
+
+const wchar_t* WindowClassRegistrar::GetWindowClass() {
+ if (!class_registered_) {
+ WNDCLASS window_class{};
+ window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
+ window_class.lpszClassName = kWindowClassName;
+ window_class.style = CS_HREDRAW | CS_VREDRAW;
+ window_class.cbClsExtra = 0;
+ window_class.cbWndExtra = 0;
+ window_class.hInstance = GetModuleHandle(nullptr);
+ window_class.hIcon =
+ LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
+ window_class.hbrBackground = 0;
+ window_class.lpszMenuName = nullptr;
+ window_class.lpfnWndProc = Win32Window::WndProc;
+ RegisterClass(&window_class);
+ class_registered_ = true;
+ }
+ return kWindowClassName;
+}
+
+void WindowClassRegistrar::UnregisterWindowClass() {
+ UnregisterClass(kWindowClassName, nullptr);
+ class_registered_ = false;
+}
+
+Win32Window::Win32Window() {
+ ++g_active_window_count;
+}
+
+Win32Window::~Win32Window() {
+ --g_active_window_count;
+ Destroy();
+}
+
+bool Win32Window::CreateAndShow(const std::wstring& title,
+ const Point& origin,
+ const Size& size) {
+ Destroy();
+
+ const wchar_t* window_class =
+ WindowClassRegistrar::GetInstance()->GetWindowClass();
+
+ const POINT target_point = {static_cast<LONG>(origin.x),
+ static_cast<LONG>(origin.y)};
+ HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST);
+ UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);
+ double scale_factor = dpi / 96.0;
+
+ HWND window = CreateWindow(
+ window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+ Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
+ Scale(size.width, scale_factor), Scale(size.height, scale_factor),
+ nullptr, nullptr, GetModuleHandle(nullptr), this);
+
+ if (!window) {
+ return false;
+ }
+
+ return OnCreate();
+}
+
+// static
+LRESULT CALLBACK Win32Window::WndProc(HWND const window,
+ UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept {
+ if (message == WM_NCCREATE) {
+ auto window_struct = reinterpret_cast<CREATESTRUCT*>(lparam);
+ SetWindowLongPtr(window, GWLP_USERDATA,
+ reinterpret_cast<LONG_PTR>(window_struct->lpCreateParams));
+
+ auto that = static_cast<Win32Window*>(window_struct->lpCreateParams);
+ EnableFullDpiSupportIfAvailable(window);
+ that->window_handle_ = window;
+ } else if (Win32Window* that = GetThisFromHandle(window)) {
+ return that->MessageHandler(window, message, wparam, lparam);
+ }
+
+ return DefWindowProc(window, message, wparam, lparam);
+}
+
+LRESULT
+Win32Window::MessageHandler(HWND hwnd,
+ UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept {
+ switch (message) {
+ case WM_DESTROY:
+ window_handle_ = nullptr;
+ Destroy();
+ if (quit_on_close_) {
+ PostQuitMessage(0);
+ }
+ return 0;
+
+ case WM_DPICHANGED: {
+ auto newRectSize = reinterpret_cast<RECT*>(lparam);
+ LONG newWidth = newRectSize->right - newRectSize->left;
+ LONG newHeight = newRectSize->bottom - newRectSize->top;
+
+ SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,
+ newHeight, SWP_NOZORDER | SWP_NOACTIVATE);
+
+ return 0;
+ }
+ case WM_SIZE: {
+ RECT rect = GetClientArea();
+ if (child_content_ != nullptr) {
+ // Size and position the child window.
+ MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
+ rect.bottom - rect.top, TRUE);
+ }
+ return 0;
+ }
+
+ case WM_ACTIVATE:
+ if (child_content_ != nullptr) {
+ SetFocus(child_content_);
+ }
+ return 0;
+ }
+
+ return DefWindowProc(window_handle_, message, wparam, lparam);
+}
+
+void Win32Window::Destroy() {
+ OnDestroy();
+
+ if (window_handle_) {
+ DestroyWindow(window_handle_);
+ window_handle_ = nullptr;
+ }
+ if (g_active_window_count == 0) {
+ WindowClassRegistrar::GetInstance()->UnregisterWindowClass();
+ }
+}
+
+Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
+ return reinterpret_cast<Win32Window*>(
+ GetWindowLongPtr(window, GWLP_USERDATA));
+}
+
+void Win32Window::SetChildContent(HWND content) {
+ child_content_ = content;
+ SetParent(content, window_handle_);
+ RECT frame = GetClientArea();
+
+ MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
+ frame.bottom - frame.top, true);
+
+ SetFocus(child_content_);
+}
+
+RECT Win32Window::GetClientArea() {
+ RECT frame;
+ GetClientRect(window_handle_, &frame);
+ return frame;
+}
+
+HWND Win32Window::GetHandle() {
+ return window_handle_;
+}
+
+void Win32Window::SetQuitOnClose(bool quit_on_close) {
+ quit_on_close_ = quit_on_close;
+}
+
+bool Win32Window::OnCreate() {
+ // No-op; provided for subclasses.
+ return true;
+}
+
+void Win32Window::OnDestroy() {
+ // No-op; provided for subclasses.
+}
diff --git a/pkgs/jni/example/windows/runner/win32_window.h b/pkgs/jni/example/windows/runner/win32_window.h
new file mode 100644
index 0000000..17ba431
--- /dev/null
+++ b/pkgs/jni/example/windows/runner/win32_window.h
@@ -0,0 +1,98 @@
+#ifndef RUNNER_WIN32_WINDOW_H_
+#define RUNNER_WIN32_WINDOW_H_
+
+#include <windows.h>
+
+#include <functional>
+#include <memory>
+#include <string>
+
+// A class abstraction for a high DPI-aware Win32 Window. Intended to be
+// inherited from by classes that wish to specialize with custom
+// rendering and input handling
+class Win32Window {
+ public:
+ struct Point {
+ unsigned int x;
+ unsigned int y;
+ Point(unsigned int x, unsigned int y) : x(x), y(y) {}
+ };
+
+ struct Size {
+ unsigned int width;
+ unsigned int height;
+ Size(unsigned int width, unsigned int height)
+ : width(width), height(height) {}
+ };
+
+ Win32Window();
+ virtual ~Win32Window();
+
+ // Creates and shows a win32 window with |title| and position and size using
+ // |origin| and |size|. New windows are created on the default monitor. Window
+ // sizes are specified to the OS in physical pixels, hence to ensure a
+ // consistent size to will treat the width height passed in to this function
+ // as logical pixels and scale to appropriate for the default monitor. Returns
+ // true if the window was created successfully.
+ bool CreateAndShow(const std::wstring& title,
+ const Point& origin,
+ const Size& size);
+
+ // Release OS resources associated with window.
+ void Destroy();
+
+ // Inserts |content| into the window tree.
+ void SetChildContent(HWND content);
+
+ // Returns the backing Window handle to enable clients to set icon and other
+ // window properties. Returns nullptr if the window has been destroyed.
+ HWND GetHandle();
+
+ // If true, closing this window will quit the application.
+ void SetQuitOnClose(bool quit_on_close);
+
+ // Return a RECT representing the bounds of the current client area.
+ RECT GetClientArea();
+
+ protected:
+ // Processes and route salient window messages for mouse handling,
+ // size change and DPI. Delegates handling of these to member overloads that
+ // inheriting classes can handle.
+ virtual LRESULT MessageHandler(HWND window,
+ UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept;
+
+ // Called when CreateAndShow is called, allowing subclass window-related
+ // setup. Subclasses should return false if setup fails.
+ virtual bool OnCreate();
+
+ // Called when Destroy is called.
+ virtual void OnDestroy();
+
+ private:
+ friend class WindowClassRegistrar;
+
+ // OS callback called by message pump. Handles the WM_NCCREATE message which
+ // is passed when the non-client area is being created and enables automatic
+ // non-client DPI scaling so that the non-client area automatically
+ // responsponds to changes in DPI. All other messages are handled by
+ // MessageHandler.
+ static LRESULT CALLBACK WndProc(HWND const window,
+ UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept;
+
+ // Retrieves a class instance pointer for |window|
+ static Win32Window* GetThisFromHandle(HWND const window) noexcept;
+
+ bool quit_on_close_ = false;
+
+ // window handle for top level window.
+ HWND window_handle_ = nullptr;
+
+ // window handle for hosted content.
+ HWND child_content_ = nullptr;
+};
+
+#endif // RUNNER_WIN32_WINDOW_H_
diff --git a/pkgs/jni/ffigen.yaml b/pkgs/jni/ffigen.yaml
new file mode 100644
index 0000000..782668e
--- /dev/null
+++ b/pkgs/jni/ffigen.yaml
@@ -0,0 +1,157 @@
+# Run with `dart run ffigen --config ffigen.yaml`.
+name: JniBindings
+description: |
+ Bindings for libdartjni.so which is part of jni plugin.
+
+ It also transitively includes type definitions such as JNIEnv from third_party/jni.h;
+
+ However, functions prefixed JNI_ are not usable because they are in a different shared library.
+
+ Regenerate bindings with `flutter pub run ffigen.dart --config ffigen.yaml`.
+output: 'lib/src/third_party/jni_bindings_generated.dart'
+headers:
+ entry-points:
+ - 'src/dartjni.h' # Exports majority of JNI functions
+ - 'src/third_party/global_jni_env.h' # Exports GlobalJniEnv type
+ - 'src/jni_constants.h'
+ include-directives:
+ - 'src/dartjni.h'
+ - 'src/third_party/global_jni_env.h'
+ - 'third_party/jni.h' # jni.h from Android NDK
+ - 'src/jni_constants.h'
+compiler-opts:
+ - '-Ithird_party/'
+enums:
+ rename:
+ 'JniType': 'JniCallType'
+ 'jobjectRefType': 'JObjectRefType'
+functions:
+ exclude:
+ # Exclude init functions supposed to be defined in loaded DLL, not JNI
+ - 'JNI_.*'
+ - 'GetJniContextPtr'
+ - 'setJniGetters'
+ - 'jni_log'
+ # Inline functions
+ # keep-sorted start
+ - 'acquire_lock'
+ - 'attach_thread'
+ - 'check_exception'
+ - 'destroy_cond'
+ - 'destroy_lock'
+ - 'init_cond'
+ - 'init_lock'
+ - 'load_class'
+ - 'load_class_global_ref'
+ - 'load_class_local_ref'
+ - 'load_class_platform'
+ - 'load_env'
+ - 'load_field'
+ - 'load_method'
+ - 'load_static_field'
+ - 'load_static_method'
+ - 'release_lock'
+ - 'signal_cond'
+ - 'thread_id'
+ - 'to_global_ref'
+ - 'to_global_ref_result'
+ - 'wait_for'
+ # keep-sorted end
+structs:
+ exclude:
+ - 'JniContext'
+ - 'JniLocks'
+ - 'JNIEnv'
+ - '_JNIEnv'
+ - 'JNIInvokeInterface'
+ - '__va_list_tag'
+ - 'CallbackResult'
+ rename:
+ ## opaque struct definitions, base types of jfieldID and jmethodID
+ '_jfieldID': 'jfieldID_'
+ '_jmethodID':
+ 'jmethodID_'
+ #'JNI(.*)': 'Jni$1'
+unions:
+ rename:
+ 'jvalue': 'JValue'
+globals:
+ exclude:
+ - 'jni'
+ - 'jniEnv'
+ - 'context_getter'
+ - 'env_getter'
+typedefs:
+ exclude:
+ - 'va_list'
+ - '__builtin_va_list'
+ rename:
+ 'JNI(.*)': 'Jni$1'
+ # Primitives
+ 'jbyte': 'JByteMarker'
+ 'jboolean': 'JBooleanMarker'
+ 'jchar': 'JCharMarker'
+ 'jshort': 'JShortMarker'
+ 'jint': 'JIntMarker'
+ 'jlong': 'JLongMarker'
+ 'jfloat': 'JFloatMarker'
+ 'jdouble': 'JDoubleMarker'
+ 'jsize': 'JSizeMarker'
+
+ 'jclass': 'JClassPtr'
+ 'jobject': 'JObjectPtr'
+ 'jmethodID': 'JMethodIDPtr'
+ 'jfieldID': 'JFieldIDPtr'
+ 'jthrowable': 'JThrowablePtr'
+ 'jstring': 'JStringPtr'
+ 'jarray': 'JArrayPtr'
+ 'jobjectArray': 'JObjectArrayPtr'
+ 'jbooleanArray': 'JBooleanArrayPtr'
+ 'jbyteArray': 'JByteArrayPtr'
+ 'jcharArray': 'JCharArrayPtr'
+ 'jshortArray': 'JShortArrayPtr'
+ 'jintArray': 'JIntArrayPtr'
+ 'jlongArray': 'JLongArrayPtr'
+ 'jfloatArray': 'JFloatArrayPtr'
+ 'jdoubleArray': 'JDoubleArrayPtr'
+ 'jweak': 'JWeakPtr'
+ 'jvalue': 'JValue'
+preamble: |
+ // Autogenerated file. Do not edit.
+ // Generated from an annotated version of jni.h provided in Android NDK.
+ // (NDK Version 23.1.7779620)
+ // The license for original file is provided below:
+
+ /*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ /*
+ * JNI specification, as defined by Sun:
+ * http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html
+ *
+ * Everything here is expected to be VM-neutral.
+ */
+
+ // ignore_for_file: always_specify_types
+ // ignore_for_file: camel_case_types
+ // ignore_for_file: non_constant_identifier_names
+ // ignore_for_file: constant_identifier_names
+ // ignore_for_file: unused_field
+ // ignore_for_file: unused_element
+ // coverage:ignore-file
+comments:
+ style: any
+ length: full
diff --git a/pkgs/jni/ffigen_exts.yaml b/pkgs/jni/ffigen_exts.yaml
new file mode 100644
index 0000000..d292ad6
--- /dev/null
+++ b/pkgs/jni/ffigen_exts.yaml
@@ -0,0 +1,16 @@
+# Run with `dart run ffigen --config ffigen.yaml`.
+name: JniExtensions
+description: |
+ This config is for use by the script that generates extension methods in C.
+ This config only scans jni.h and does not do renaming etc..
+output: 'unused.dart'
+headers:
+ entry-points:
+ - 'third_party/jni.h' # Exports majority of JNI functions
+ #- 'src/third_party/global_jni_env.h' # Exports GlobalJniEnv type
+ include-directives:
+ #- 'src/dartjni.h'
+ #- 'src/third_party/global_jni_env.h'
+ - 'third_party/jni.h' # jni.h from Android NDK
+compiler-opts:
+ - '-Ithird_party/'
diff --git a/pkgs/jni/java/.gitignore b/pkgs/jni/java/.gitignore
new file mode 100644
index 0000000..9f97022
--- /dev/null
+++ b/pkgs/jni/java/.gitignore
@@ -0,0 +1 @@
+target/
\ No newline at end of file
diff --git a/pkgs/jni/java/README.md b/pkgs/jni/java/README.md
new file mode 100644
index 0000000..18a6cd3
--- /dev/null
+++ b/pkgs/jni/java/README.md
@@ -0,0 +1,4 @@
+# Jni Java
+
+This is a standalone java support which includes `PortContinuation` to support
+converting from Kotlin's `suspend fun` to Dart's `async` functions.
diff --git a/pkgs/jni/java/pom.xml b/pkgs/jni/java/pom.xml
new file mode 100644
index 0000000..2bd6f88
--- /dev/null
+++ b/pkgs/jni/java/pom.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.example</groupId>
+ <artifactId>java</artifactId>
+ <version>1.0-SNAPSHOT</version>
+
+ <properties>
+ <maven.compiler.source>11</maven.compiler.source>
+ <maven.compiler.target>11</maven.compiler.target>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <build>
+ <finalName>jni</finalName>
+ <directory>${target}</directory>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-stdlib</artifactId>
+ <version>1.6.20</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlinx</groupId>
+ <artifactId>kotlinx-coroutines-core</artifactId>
+ <version>1.6.4</version>
+ <type>pom</type>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/pkgs/jni/java/src/main/java/com/github/dart_lang/jni/PortCleaner.java b/pkgs/jni/java/src/main/java/com/github/dart_lang/jni/PortCleaner.java
new file mode 100644
index 0000000..161ef5e
--- /dev/null
+++ b/pkgs/jni/java/src/main/java/com/github/dart_lang/jni/PortCleaner.java
@@ -0,0 +1,88 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jni;
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+
+/// A registry of Java objects with associated Dart resources that cleans up the
+/// resources after they get unreachable and collected by the garbage collector.
+///
+/// A simple alternative to [java.lang.ref.Cleaner] which is only available in
+/// Android API level 33+.
+class PortCleaner {
+ static {
+ System.loadLibrary("dartjni");
+ }
+
+ private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
+ private final PortPhantom list = new PortPhantom();
+
+ private class PortPhantom extends PhantomReference<Object> {
+ final long port;
+
+ /// Form a linked list.
+ PortPhantom prev = this, next = this;
+
+ PortPhantom(Object referent, long port) {
+ super(referent, queue);
+ this.port = port;
+ insert();
+ }
+
+ /// Only used for the head of the list.
+ PortPhantom() {
+ super(null, null);
+ this.port = 0;
+ }
+
+ void insert() {
+ synchronized (list) {
+ prev = list;
+ next = list.next;
+ next.prev = this;
+ list.next = this;
+ }
+ }
+
+ private void remove() {
+ synchronized (list) {
+ next.prev = prev;
+ prev.next = next;
+ prev = this;
+ next = this;
+ }
+ }
+ }
+
+ PortCleaner() {
+ // Only a single PortCleaner and therefore thread will be created.
+ Thread thread =
+ new Thread(
+ () -> {
+ while (true) {
+ try {
+ PortPhantom portPhantom = (PortPhantom) queue.remove();
+ portPhantom.remove();
+ if (portPhantom.port != 0) {
+ clean(portPhantom.port);
+ }
+ } catch (Throwable e) {
+ // Ignore.
+ }
+ }
+ },
+ "PortCleaner");
+ thread.setDaemon(true);
+ thread.start();
+ }
+
+ /// Registers [obj] to be cleaned up later by sending a signal through [port].
+ void register(Object obj, long port) {
+ new PortPhantom(obj, port);
+ }
+
+ private static native void clean(long port);
+}
diff --git a/pkgs/jni/java/src/main/java/com/github/dart_lang/jni/PortContinuation.java b/pkgs/jni/java/src/main/java/com/github/dart_lang/jni/PortContinuation.java
new file mode 100644
index 0000000..2900ab1
--- /dev/null
+++ b/pkgs/jni/java/src/main/java/com/github/dart_lang/jni/PortContinuation.java
@@ -0,0 +1,38 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jni;
+
+import kotlin.coroutines.Continuation;
+import kotlin.coroutines.CoroutineContext;
+import kotlinx.coroutines.Dispatchers;
+
+/// An implementation of kotlin.coroutines.Continuation which sends the address
+/// of the object to Dart through a native port.
+///
+/// This allows converting Kotlin coroutines to Dart async methods.
+/// The implementation of native void _resumeWith is located in `dartjni.c`.
+public class PortContinuation<T> implements Continuation<T> {
+ static {
+ System.loadLibrary("dartjni");
+ }
+
+ private final long port;
+
+ public PortContinuation(long port) {
+ this.port = port;
+ }
+
+ @Override
+ public CoroutineContext getContext() {
+ return (CoroutineContext) Dispatchers.getIO();
+ }
+
+ @Override
+ public void resumeWith(Object o) {
+ _resumeWith(port, o);
+ }
+
+ private native void _resumeWith(long port, Object result);
+}
diff --git a/pkgs/jni/java/src/main/java/com/github/dart_lang/jni/PortProxy.java b/pkgs/jni/java/src/main/java/com/github/dart_lang/jni/PortProxy.java
new file mode 100644
index 0000000..3caf02a
--- /dev/null
+++ b/pkgs/jni/java/src/main/java/com/github/dart_lang/jni/PortProxy.java
@@ -0,0 +1,104 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jni;
+
+import java.lang.reflect.*;
+
+public class PortProxy implements InvocationHandler {
+ static {
+ System.loadLibrary("dartjni");
+ }
+
+ private static final PortCleaner cleaner = new PortCleaner();
+ private final long port;
+ private final long isolateId;
+ private final long functionPtr;
+
+ private PortProxy(long port, long isolateId, long functionPtr) {
+ this.port = port;
+ this.isolateId = isolateId;
+ this.functionPtr = functionPtr;
+ }
+
+ private static String getDescriptor(Method method) {
+ StringBuilder descriptor = new StringBuilder();
+ descriptor.append(method.getName()).append('(');
+ Class<?>[] parameterTypes = method.getParameterTypes();
+ for (Class<?> paramType : parameterTypes) {
+ appendType(descriptor, paramType);
+ }
+ descriptor.append(')');
+ appendType(descriptor, method.getReturnType());
+ return descriptor.toString();
+ }
+
+ private static void appendType(StringBuilder descriptor, Class<?> type) {
+ if (type == void.class) {
+ descriptor.append('V');
+ } else if (type == boolean.class) {
+ descriptor.append('Z');
+ } else if (type == byte.class) {
+ descriptor.append('B');
+ } else if (type == char.class) {
+ descriptor.append('C');
+ } else if (type == short.class) {
+ descriptor.append('S');
+ } else if (type == int.class) {
+ descriptor.append('I');
+ } else if (type == long.class) {
+ descriptor.append('J');
+ } else if (type == float.class) {
+ descriptor.append('F');
+ } else if (type == double.class) {
+ descriptor.append('D');
+ } else if (type.isArray()) {
+ descriptor.append('[');
+ appendType(descriptor, type.getComponentType());
+ } else {
+ descriptor.append('L').append(type.getName().replace('.', '/')).append(';');
+ }
+ }
+
+ public static Object newInstance(String binaryName, long port, long isolateId, long functionPtr)
+ throws ClassNotFoundException {
+ Class<?> clazz = Class.forName(binaryName);
+ Object obj =
+ Proxy.newProxyInstance(
+ clazz.getClassLoader(),
+ new Class[] {clazz},
+ new PortProxy(port, isolateId, functionPtr));
+ cleaner.register(obj, port);
+ return obj;
+ }
+
+ private static final class DartException extends Exception {
+ private DartException(String message) {
+ super(message);
+ }
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws DartException {
+ Object[] result = _invoke(port, isolateId, functionPtr, proxy, getDescriptor(method), args);
+ _cleanUp((Long) result[0]);
+ if (result[1] instanceof DartException) {
+ throw (DartException) result[1];
+ }
+ return result[1];
+ }
+
+ /// Returns an array with two objects:
+ /// [0]: The address of the result pointer used for the clean-up.
+ /// [1]: The result of the invocation.
+ private static native Object[] _invoke(
+ long port,
+ long isolateId,
+ long functionPtr,
+ Object proxy,
+ String methodDescriptor,
+ Object[] args);
+
+ private static native void _cleanUp(long resultPtr);
+}
diff --git a/pkgs/jni/lib/internal_helpers_for_jnigen.dart b/pkgs/jni/lib/internal_helpers_for_jnigen.dart
new file mode 100644
index 0000000..257b0c2
--- /dev/null
+++ b/pkgs/jni/lib/internal_helpers_for_jnigen.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This library exports the methods meant for use by generated code only, and
+/// not to be used directly.
+library internal_helpers_for_jnigen;
+
+export 'src/accessors.dart';
+export 'src/jni.dart' show ProtectedJniExtensions;
+export 'src/jreference.dart';
+export 'src/method_invocation.dart';
diff --git a/pkgs/jni/lib/jni.dart b/pkgs/jni/lib/jni.dart
new file mode 100644
index 0000000..5f0f34c
--- /dev/null
+++ b/pkgs/jni/lib/jni.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Package jni provides dart bindings for the Java Native Interface (JNI) on
+/// Android and desktop platforms.
+///
+/// It's intended as a supplement to the jnigen tool, a Java wrapper generator
+/// using JNI. The goal of this package is to provide sufficiently complete
+/// and ergonomic access to underlying JNI APIs.
+///
+/// Therefore, some understanding of JNI is required to use this module.
+///
+/// ## Java VM
+/// On Android, the existing JVM is used, a new JVM needs to be spawned on
+/// flutter desktop & standalone targets.
+///
+/// ```dart
+/// if (!Platform.isAndroid) {
+/// // Spin up a JVM instance with custom classpath etc..
+/// Jni.spawn(/* options */);
+/// }
+/// ```
+///
+/// ## Dart standalone support
+/// On dart standalone target, we unfortunately have no mechanism to bundle
+/// the wrapper libraries with the executable. Thus it needs to be explicitly
+/// placed in a accessible directory and provided as an argument to Jni.spawn.
+///
+/// This module depends on a shared library written in C. Therefore on dart
+/// standalone:
+///
+/// * Run `dart run jni:setup` to build the shared library. This command builds
+/// all dependency libraries with native code (package:jni and jnigen-generated)
+/// libraries if any.
+///
+/// The default output directory is build/jni_libs, which can be changed
+/// using `-B` switch.
+///
+/// * Provide the location of library to `Jni.spawn` call.
+///
+/// ## JNIEnv
+/// `GlobalJniEnv` type provides a thin wrapper over `JNIEnv*` which can be used
+/// from across threads, and always returns JNI global references. This is
+/// needed because Dart doesn't make guarantees about even the straight-line
+/// code being scheduled on the same thread.
+///
+/// ## Debugging
+/// Debugging JNI errors hard in general.
+///
+/// * On desktop platforms you can use JniEnv.ExceptionDescribe to print any
+/// pending exception to stdout.
+/// * On Android, things are slightly easier since CheckJNI is usually enabled
+/// in debug builds. If you are not getting clear stack traces on JNI errors,
+/// check the Android NDK page on how to enable CheckJNI using ADB.
+/// * As a rule of thumb, when there's a NoClassDefFound / NoMethodFound error,
+/// first check your class and method signatures for typos. Another common
+/// reason for NoClassDefFound error is missing classes in classpath.
+
+/// This library provides classes and functions for JNI interop from Dart.
+library jni;
+
+export 'src/errors.dart';
+export 'src/jni.dart' hide ProtectedJniExtensions;
+export 'src/jvalues.dart' hide JValueArgs, toJValues;
+export 'src/types.dart';
+export 'src/jarray.dart';
+export 'src/jobject.dart';
+export 'src/jreference.dart' show JReferenceUseExtension;
+
+export 'src/lang/lang.dart';
+export 'src/nio/nio.dart';
+export 'src/util/util.dart';
+
+export 'src/third_party/generated_bindings.dart'
+ hide JniBindings, JniEnv, JniEnv1, JniExceptionDetails;
+
+export 'package:ffi/ffi.dart' show using, Arena;
+export 'dart:ffi' show nullptr;
diff --git a/pkgs/jni/lib/jni_symbols.yaml b/pkgs/jni/lib/jni_symbols.yaml
new file mode 100644
index 0000000..ac4a74c
--- /dev/null
+++ b/pkgs/jni/lib/jni_symbols.yaml
@@ -0,0 +1,85 @@
+version: 1.0.0
+files:
+ 'jni.dart':
+ 'java.lang.Object':
+ name: JObject
+ type_class: JObjectType
+ super_count: 0
+ 'java.lang.String':
+ name: JString
+ type_class: JStringType
+ super_count: 1
+ 'java.lang.Number':
+ name: JNumber
+ type_class: JNumberType
+ super_count: 1
+ 'java.lang.Byte':
+ name: JByte
+ type_class: JByteType
+ super_count: 2
+ 'java.lang.Short':
+ name: JShort
+ type_class: JShortType
+ super_count: 2
+ 'java.lang.Integer':
+ name: JInteger
+ type_class: JIntegerType
+ super_count: 2
+ 'java.lang.Long':
+ name: JLong
+ type_class: JLongType
+ super_count: 2
+ 'java.lang.Float':
+ name: JFloat
+ type_class: JFloatType
+ super_count: 2
+ 'java.lang.Double':
+ name: JDouble
+ type_class: JDoubleType
+ super_count: 2
+ 'java.lang.Boolean':
+ name: JBoolean
+ type_class: JBooleanType
+ super_count: 1
+ 'java.lang.Character':
+ name: JCharacter
+ type_class: JCharacterType
+ super_count: 1
+ 'java.util.Set':
+ name: JSet
+ type_class: JSetType
+ super_count: 1
+ type_params:
+ E:
+ 'java.lang.Object': DECLARED
+ 'java.util.List':
+ name: JList
+ type_class: JListType
+ super_count: 1
+ type_params:
+ E:
+ 'java.lang.Object': DECLARED
+ 'java.util.Iterator':
+ name: JIterator
+ type_class: JIteratorType
+ super_count: 1
+ type_params:
+ E:
+ 'java.lang.Object': DECLARED
+ 'java.util.Map':
+ name: JMap
+ type_class: JMapType
+ super_count: 1
+ type_params:
+ K:
+ 'java.lang.Object': DECLARED
+ V:
+ 'java.lang.Object': DECLARED
+ 'java.nio.Buffer':
+ name: JBuffer
+ type_class: JBufferType
+ super_count: 1
+ 'java.nio.ByteBuffer':
+ name: JByteBuffer
+ type_class: JByteBufferType
+ super_count: 2
diff --git a/pkgs/jni/lib/src/accessors.dart b/pkgs/jni/lib/src/accessors.dart
new file mode 100644
index 0000000..e505b94
--- /dev/null
+++ b/pkgs/jni/lib/src/accessors.dart
@@ -0,0 +1,162 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart' show using;
+
+import 'package:jni/src/jvalues.dart';
+
+import 'errors.dart';
+import 'third_party/generated_bindings.dart';
+import 'jni.dart';
+
+void _check(JThrowablePtr exception) {
+ if (exception != nullptr) {
+ Jni.accessors.throwException(exception);
+ }
+}
+
+extension JniResultMethods on JniResult {
+ void check() => _check(exception);
+
+ int get byte {
+ check();
+ return value.b;
+ }
+
+ int get short {
+ check();
+ return value.s;
+ }
+
+ int get char {
+ check();
+ return value.c;
+ }
+
+ int get integer {
+ check();
+ return value.i;
+ }
+
+ int get long {
+ check();
+ return value.j;
+ }
+
+ double get float {
+ check();
+ return value.f;
+ }
+
+ double get doubleFloat {
+ check();
+ return value.d;
+ }
+
+ JObjectPtr get object {
+ check();
+ return value.l;
+ }
+
+ bool get boolean {
+ check();
+ return value.z != 0;
+ }
+}
+
+extension JniIdLookupResultMethods on JniPointerResult {
+ JMethodIDPtr get methodID {
+ _check(exception);
+ return value.cast<jmethodID_>();
+ }
+
+ JFieldIDPtr get fieldID {
+ _check(exception);
+ return value.cast<jfieldID_>();
+ }
+
+ Pointer<Void> get checkedRef {
+ _check(exception);
+ return value;
+ }
+
+ Pointer<T> getPointer<T extends NativeType>() {
+ return value.cast<T>();
+ }
+}
+
+extension JniClassLookupResultMethods on JniClassLookupResult {
+ JClassPtr get checkedClassRef {
+ _check(exception);
+ return value;
+ }
+}
+
+extension JThrowableCheckMethod on JThrowablePtr {
+ void check() {
+ _check(this);
+ }
+}
+
+extension JniAccessorWrappers on JniAccessors {
+ /// Rethrows Java exception in Dart as [JniException].
+ ///
+ /// The original exception object is deleted by this method. The message
+ /// and Java stack trace are included in the exception.
+ void throwException(JThrowablePtr exception) {
+ final details = getExceptionDetails(exception);
+ final env = Jni.env;
+ final message = env.toDartString(details.message);
+ final stacktrace = env.toDartString(details.stacktrace);
+ env.DeleteGlobalRef(exception);
+ env.DeleteGlobalRef(details.message);
+ env.DeleteGlobalRef(details.stacktrace);
+ throw JniException(message, stacktrace);
+ }
+
+ // TODO(PR): How to name these methods? These only wrap toNativeChars()
+ // so that generated bindings are less verbose.
+ JClassPtr getClassOf(String internalName) =>
+ using((arena) => getClass(internalName.toNativeChars(arena)))
+ .checkedClassRef;
+
+ JMethodIDPtr getMethodIDOf(JClassPtr cls, String name, String signature) =>
+ using((arena) => getMethodID(
+ cls, name.toNativeChars(arena), signature.toNativeChars(arena)))
+ .methodID;
+
+ JMethodIDPtr getStaticMethodIDOf(
+ JClassPtr cls, String name, String signature) =>
+ using((arena) => getStaticMethodID(
+ cls, name.toNativeChars(arena), signature.toNativeChars(arena)))
+ .methodID;
+
+ JFieldIDPtr getFieldIDOf(JClassPtr cls, String name, String signature) =>
+ using((arena) => getFieldID(
+ cls, name.toNativeChars(arena), signature.toNativeChars(arena)))
+ .fieldID;
+
+ JFieldIDPtr getStaticFieldIDOf(
+ JClassPtr cls, String name, String signature) =>
+ using((arena) => getStaticFieldID(
+ cls, name.toNativeChars(arena), signature.toNativeChars(arena)))
+ .fieldID;
+
+ JniResult newObjectWithArgs(
+ JClassPtr cls, JMethodIDPtr ctor, List<dynamic> args) =>
+ using((arena) {
+ return newObject(cls, ctor, toJValues(args, allocator: arena));
+ });
+
+ JniResult callMethodWithArgs(
+ JObjectPtr obj, JMethodIDPtr id, int callType, List<dynamic> args) =>
+ using((arena) =>
+ callMethod(obj, id, callType, toJValues(args, allocator: arena)));
+
+ JniResult callStaticMethodWithArgs(
+ JClassPtr cls, JMethodIDPtr id, int callType, List<dynamic> args) =>
+ using((arena) => callStaticMethod(
+ cls, id, callType, toJValues(args, allocator: arena)));
+}
diff --git a/pkgs/jni/lib/src/build_util/build_util.dart b/pkgs/jni/lib/src/build_util/build_util.dart
new file mode 100644
index 0000000..8d267df
--- /dev/null
+++ b/pkgs/jni/lib/src/build_util/build_util.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Any shared build logic should be here. This way it can be reused across bin/,
+// tool/ and test/.
+
+import 'dart:io';
+
+const ansiRed = '\x1b[31m';
+const ansiDefault = '\x1b[39;49m';
+
+/// Returns true if [artifact] does not exist, or any file in [sourceDir] is
+/// newer than [artifact].
+bool needsBuild(File artifact, Directory sourceDir) {
+ if (!artifact.existsSync()) return true;
+ final fileLastModified = artifact.lastModifiedSync();
+ for (final entry in sourceDir.listSync(recursive: true)) {
+ if (entry.statSync().modified.isAfter(fileLastModified)) {
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/pkgs/jni/lib/src/errors.dart b/pkgs/jni/lib/src/errors.dart
new file mode 100644
index 0000000..848d93e
--- /dev/null
+++ b/pkgs/jni/lib/src/errors.dart
@@ -0,0 +1,144 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:jni/src/third_party/generated_bindings.dart';
+
+// TODO(#393): Add the fact that [JException] is now a [JObject] to the
+// CHANGELOG.
+
+final class UseAfterReleaseError extends Error {
+ @override
+ String toString() {
+ return 'Use after release error';
+ }
+}
+
+// TODO(#393): Use NullPointerError once it's available.
+final class JNullError extends Error {
+ @override
+ String toString() => 'The reference was null';
+}
+
+final class DoubleReleaseError extends Error {
+ @override
+ String toString() {
+ return 'Double release error';
+ }
+}
+
+/// Represents JNI errors that might be returned by methods like
+/// `JNI_CreateJavaVM`.
+sealed class JniError extends Error {
+ static const _errors = {
+ JniErrorCode.JNI_ERR: JniGenericError.new,
+ JniErrorCode.JNI_EDETACHED: JniThreadDetachedError.new,
+ JniErrorCode.JNI_EVERSION: JniVersionError.new,
+ JniErrorCode.JNI_ENOMEM: JniOutOfMemoryError.new,
+ JniErrorCode.JNI_EEXIST: JniVmExistsError.new,
+ JniErrorCode.JNI_EINVAL: JniArgumentError.new,
+ };
+
+ final String message;
+
+ JniError(this.message);
+
+ factory JniError.of(int status) {
+ if (!_errors.containsKey(status)) {
+ status = JniErrorCode.JNI_ERR;
+ }
+ return _errors[status]!();
+ }
+
+ @override
+ String toString() {
+ return 'JniError: $message';
+ }
+}
+
+final class JniGenericError extends JniError {
+ JniGenericError() : super('Generic JNI error');
+}
+
+final class JniThreadDetachedError extends JniError {
+ JniThreadDetachedError() : super('Thread detached from VM');
+}
+
+final class JniVersionError extends JniError {
+ JniVersionError() : super('JNI version error');
+}
+
+final class JniOutOfMemoryError extends JniError {
+ JniOutOfMemoryError() : super('Out of memory');
+}
+
+final class JniVmExistsError extends JniError {
+ JniVmExistsError() : super('VM Already created');
+}
+
+final class JniArgumentError extends JniError {
+ JniArgumentError() : super('Invalid arguments');
+}
+
+final class NoJvmInstanceError extends Error {
+ @override
+ String toString() => 'No JNI instance is available';
+}
+
+// TODO(#395): Remove this when calltypes are removed.
+extension on int {
+ static const _names = {
+ JniCallType.booleanType: 'bool',
+ JniCallType.byteType: 'byte',
+ JniCallType.shortType: 'short',
+ JniCallType.charType: 'char',
+ JniCallType.intType: 'int',
+ JniCallType.longType: 'long',
+ JniCallType.floatType: 'float',
+ JniCallType.doubleType: 'double',
+ JniCallType.objectType: 'object',
+ JniCallType.voidType: 'void',
+ };
+ String str() => _names[this]!;
+}
+
+// TODO(#395): Remove this when `JniCallType`s are removed.
+final class InvalidCallTypeError extends Error {
+ final int type;
+ final Set<int> allowed;
+
+ InvalidCallTypeError(this.type, this.allowed);
+
+ @override
+ String toString() => 'Invalid type for call ${type.str()}. '
+ 'Allowed types are ${allowed.map((t) => t.str()).toSet()}';
+}
+
+// TODO(#393): Remove this class in favor of `JThrowable`.
+class JniException implements Exception {
+ /// Error message from Java exception.
+ final String message;
+
+ /// Stack trace from Java.
+ final String stackTrace;
+
+ JniException(this.message, this.stackTrace);
+
+ @override
+ String toString() => 'Exception in Java code called through JNI: '
+ '$message\n\n$stackTrace\n';
+}
+
+final class HelperNotFoundError extends Error {
+ final String path;
+
+ HelperNotFoundError(this.path);
+
+ @override
+ String toString() => '''
+Lookup for helper library $path failed.
+Please ensure that `dartjni` shared library is built.
+Provided jni:setup script can be used to build the shared library.
+If the library is already built, ensure that the JVM libraries can be
+loaded from Dart.''';
+}
diff --git a/pkgs/jni/lib/src/jarray.dart b/pkgs/jni/lib/src/jarray.dart
new file mode 100644
index 0000000..2364312
--- /dev/null
+++ b/pkgs/jni/lib/src/jarray.dart
@@ -0,0 +1,369 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// ignore_for_file: unnecessary_cast, overridden_fields
+
+import 'dart:ffi';
+
+import 'package:collection/collection.dart';
+import 'package:ffi/ffi.dart';
+import 'package:jni/src/accessors.dart';
+import 'package:jni/src/third_party/generated_bindings.dart';
+
+import 'jni.dart';
+import 'jobject.dart';
+import 'types.dart';
+
+final class JArrayType<T> extends JObjType<JArray<T>> {
+ final JType<T> elementType;
+
+ const JArrayType(this.elementType);
+
+ @override
+ String get signature => '[${elementType.signature}';
+
+ @override
+ JArray<T> fromRef(Pointer<Void> ref) => JArray.fromRef(elementType, ref);
+
+ @override
+ JObjType get superType => const JObjectType();
+
+ @override
+ final int superCount = 1;
+
+ @override
+ int get hashCode => Object.hash(JArrayType, elementType);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == (JArrayType<T>) &&
+ other is JArrayType<T> &&
+ elementType == other.elementType;
+ }
+}
+
+class JArray<E> extends JObject {
+ final JType<E> elementType;
+
+ @override
+ late final JArrayType<E> $type = type(elementType) as JArrayType<E>;
+
+ /// The type which includes information such as the signature of this class.
+ static JObjType<JArray<T>> type<T>(JType<T> innerType) =>
+ JArrayType(innerType);
+
+ /// Construct a new [JArray] with [reference] as its underlying reference.
+ JArray.fromRef(this.elementType, JArrayPtr reference)
+ : super.fromRef(reference);
+
+ /// Creates a [JArray] of the given length from the given [type].
+ ///
+ /// The [length] must be a non-negative integer.
+ factory JArray(JType<E> type, int length) {
+ const primitiveCallTypes = {
+ 'B': JniCallType.byteType,
+ 'Z': JniCallType.booleanType,
+ 'C': JniCallType.charType,
+ 'S': JniCallType.shortType,
+ 'I': JniCallType.intType,
+ 'J': JniCallType.longType,
+ 'F': JniCallType.floatType,
+ 'D': JniCallType.doubleType,
+ };
+ if (!primitiveCallTypes.containsKey(type.signature) && type is JObjType) {
+ final clazz = (type as JObjType).getClass();
+ final array = JArray<E>.fromRef(
+ type,
+ Jni.accessors.newObjectArray(length, clazz.reference, nullptr).object,
+ );
+ clazz.release();
+ return array;
+ }
+ return JArray.fromRef(
+ type,
+ Jni.accessors
+ .newPrimitiveArray(length, primitiveCallTypes[type.signature]!)
+ .object,
+ );
+ }
+
+ /// Creates a [JArray] of the given length with [fill] at each position.
+ ///
+ /// The [length] must be a non-negative integer.
+ static JArray<E> filled<E extends JObject>(int length, E fill) {
+ RangeError.checkNotNegative(length);
+ final clazz = fill.$type.getClass();
+ final array = JArray<E>.fromRef(
+ fill.$type as JObjType<E>,
+ Jni.accessors
+ .newObjectArray(length, clazz.reference, fill.reference)
+ .object,
+ );
+ clazz.release();
+ return array;
+ }
+
+ int? _length;
+
+ JniResult elementAt(int index, int type) {
+ RangeError.checkValidIndex(index, this);
+ return Jni.accessors.getArrayElement(reference, index, type);
+ }
+
+ /// The number of elements in this array.
+ int get length {
+ return _length ??= Jni.env.GetArrayLength(reference);
+ }
+}
+
+extension NativeArray<E extends JPrimitive> on JArray<E> {
+ void _allocate<T extends NativeType>(
+ int size,
+ void Function(Pointer<T> ptr) use,
+ ) {
+ using((arena) {
+ final ptr = arena.allocate<T>(size);
+ use(ptr);
+ }, malloc);
+ }
+}
+
+extension BoolArray on JArray<jboolean> {
+ bool operator [](int index) {
+ return elementAt(index, JniCallType.booleanType).boolean;
+ }
+
+ void operator []=(int index, bool value) {
+ RangeError.checkValidIndex(index, this);
+ _allocate<JBooleanMarker>(sizeOf<JBooleanMarker>(), (ptr) {
+ ptr.value = value ? 1 : 0;
+ Jni.env.SetBooleanArrayRegion(reference, index, 1, ptr);
+ });
+ }
+
+ void setRange(int start, int end, Iterable<bool> iterable,
+ [int skipCount = 0]) {
+ RangeError.checkValidRange(start, end, length);
+ final size = end - start;
+ final it = iterable.skip(skipCount).take(size);
+ _allocate<JBooleanMarker>(sizeOf<JBooleanMarker>() * size, (ptr) {
+ it.forEachIndexed((index, element) {
+ ptr[index] = element ? 1 : 0;
+ });
+ Jni.env.SetBooleanArrayRegion(reference, start, size, ptr);
+ });
+ }
+}
+
+extension ByteArray on JArray<jbyte> {
+ int operator [](int index) {
+ return elementAt(index, JniCallType.byteType).byte;
+ }
+
+ void operator []=(int index, int value) {
+ RangeError.checkValidIndex(index, this);
+ _allocate<JByteMarker>(sizeOf<JByteMarker>(), (ptr) {
+ ptr.value = value;
+ Jni.env.SetByteArrayRegion(reference, index, 1, ptr);
+ });
+ }
+
+ void setRange(int start, int end, Iterable<int> iterable,
+ [int skipCount = 0]) {
+ RangeError.checkValidRange(start, end, length);
+ final size = end - start;
+ final it = iterable.skip(skipCount).take(size);
+ _allocate<JByteMarker>(sizeOf<JByteMarker>() * size, (ptr) {
+ it.forEachIndexed((index, element) {
+ ptr[index] = element;
+ });
+ Jni.env.SetByteArrayRegion(reference, start, size, ptr);
+ });
+ }
+}
+
+extension CharArray on JArray<jchar> {
+ String operator [](int index) {
+ return String.fromCharCode(
+ elementAt(index, JniCallType.charType).char,
+ );
+ }
+
+ void operator []=(int index, String value) {
+ RangeError.checkValidIndex(index, this);
+ _allocate<JCharMarker>(sizeOf<JCharMarker>(), (ptr) {
+ ptr.value = value.codeUnits.first;
+ Jni.env.SetCharArrayRegion(reference, index, 1, ptr);
+ });
+ }
+
+ void setRange(int start, int end, Iterable<String> iterable,
+ [int skipCount = 0]) {
+ RangeError.checkValidRange(start, end, length);
+ final size = end - start;
+ final it = iterable.skip(skipCount).take(size);
+ _allocate<JCharMarker>(sizeOf<JCharMarker>() * size, (ptr) {
+ it.forEachIndexed((index, element) {
+ ptr[index] = element.codeUnits.first;
+ });
+ Jni.env.SetCharArrayRegion(reference, start, size, ptr);
+ });
+ }
+}
+
+extension ShortArray on JArray<jshort> {
+ int operator [](int index) {
+ return elementAt(index, JniCallType.shortType).short;
+ }
+
+ void operator []=(int index, int value) {
+ RangeError.checkValidIndex(index, this);
+ _allocate<JShortMarker>(sizeOf<JShortMarker>(), (ptr) {
+ ptr.value = value;
+ Jni.env.SetShortArrayRegion(reference, index, 1, ptr);
+ });
+ }
+
+ void setRange(int start, int end, Iterable<int> iterable,
+ [int skipCount = 0]) {
+ RangeError.checkValidRange(start, end, length);
+ final size = end - start;
+ final it = iterable.skip(skipCount).take(size);
+ _allocate<JShortMarker>(sizeOf<JShortMarker>() * size, (ptr) {
+ it.forEachIndexed((index, element) {
+ ptr[index] = element;
+ });
+ Jni.env.SetShortArrayRegion(reference, start, size, ptr);
+ });
+ }
+}
+
+extension IntArray on JArray<jint> {
+ int operator [](int index) {
+ return elementAt(index, JniCallType.intType).integer;
+ }
+
+ void operator []=(int index, int value) {
+ RangeError.checkValidIndex(index, this);
+ _allocate<JIntMarker>(sizeOf<JIntMarker>(), (ptr) {
+ ptr.value = value;
+ Jni.env.SetIntArrayRegion(reference, index, 1, ptr);
+ });
+ }
+
+ void setRange(int start, int end, Iterable<int> iterable,
+ [int skipCount = 0]) {
+ RangeError.checkValidRange(start, end, length);
+ final size = end - start;
+ final it = iterable.skip(skipCount).take(size);
+ _allocate<JIntMarker>(sizeOf<JIntMarker>() * size, (ptr) {
+ it.forEachIndexed((index, element) {
+ ptr[index] = element;
+ });
+ Jni.env.SetIntArrayRegion(reference, start, size, ptr);
+ });
+ }
+}
+
+extension LongArray on JArray<jlong> {
+ int operator [](int index) {
+ return elementAt(index, JniCallType.longType).long;
+ }
+
+ void operator []=(int index, int value) {
+ RangeError.checkValidIndex(index, this);
+ _allocate<JLongMarker>(sizeOf<JLongMarker>(), (ptr) {
+ ptr.value = value;
+ Jni.env.SetLongArrayRegion(reference, index, 1, ptr);
+ });
+ }
+
+ void setRange(int start, int end, Iterable<int> iterable,
+ [int skipCount = 0]) {
+ RangeError.checkValidRange(start, end, length);
+ final size = end - start;
+ final it = iterable.skip(skipCount).take(size);
+ _allocate<JLongMarker>(sizeOf<JLongMarker>() * size, (ptr) {
+ it.forEachIndexed((index, element) {
+ ptr[index] = element;
+ });
+ Jni.env.SetLongArrayRegion(reference, start, size, ptr);
+ });
+ }
+}
+
+extension FloatArray on JArray<jfloat> {
+ double operator [](int index) {
+ return elementAt(index, JniCallType.floatType).float;
+ }
+
+ void operator []=(int index, double value) {
+ RangeError.checkValidIndex(index, this);
+ _allocate<JFloatMarker>(sizeOf<JFloatMarker>(), (ptr) {
+ ptr.value = value;
+ Jni.env.SetFloatArrayRegion(reference, index, 1, ptr);
+ });
+ }
+
+ void setRange(int start, int end, Iterable<double> iterable,
+ [int skipCount = 0]) {
+ RangeError.checkValidRange(start, end, length);
+ final size = end - start;
+ final it = iterable.skip(skipCount).take(size);
+ _allocate<JFloatMarker>(sizeOf<JFloatMarker>() * size, (ptr) {
+ it.forEachIndexed((index, element) {
+ ptr[index] = element;
+ });
+ Jni.env.SetFloatArrayRegion(reference, start, size, ptr);
+ });
+ }
+}
+
+extension DoubleArray on JArray<jdouble> {
+ double operator [](int index) {
+ return elementAt(index, JniCallType.doubleType).doubleFloat;
+ }
+
+ void operator []=(int index, double value) {
+ RangeError.checkValidIndex(index, this);
+ _allocate<JDoubleMarker>(sizeOf<JDoubleMarker>(), (ptr) {
+ ptr.value = value;
+ Jni.env.SetDoubleArrayRegion(reference, index, 1, ptr);
+ });
+ }
+
+ void setRange(int start, int end, Iterable<double> iterable,
+ [int skipCount = 0]) {
+ RangeError.checkValidRange(start, end, length);
+ final size = end - start;
+ final it = iterable.skip(skipCount).take(size);
+ _allocate<JDoubleMarker>(sizeOf<JDoubleMarker>() * size, (ptr) {
+ it.forEachIndexed((index, element) {
+ ptr[index] = element;
+ });
+ Jni.env.SetDoubleArrayRegion(reference, start, size, ptr);
+ });
+ }
+}
+
+extension ObjectArray<T extends JObject> on JArray<T> {
+ T operator [](int index) {
+ return (elementType as JObjType<T>)
+ .fromRef(elementAt(index, JniCallType.objectType).object);
+ }
+
+ void operator []=(int index, T value) {
+ RangeError.checkValidIndex(index, this);
+ Jni.env.SetObjectArrayElement(reference, index, value.reference);
+ }
+
+ void setRange(int start, int end, Iterable<T> iterable, [int skipCount = 0]) {
+ RangeError.checkValidRange(start, end, length);
+ final size = end - start;
+ final it = iterable.skip(skipCount).take(size);
+ it.forEachIndexed((index, element) {
+ this[index] = element;
+ });
+ }
+}
diff --git a/pkgs/jni/lib/src/jfinal_string.dart b/pkgs/jni/lib/src/jfinal_string.dart
new file mode 100644
index 0000000..ce32799
--- /dev/null
+++ b/pkgs/jni/lib/src/jfinal_string.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+
+import 'jreference.dart';
+import 'lang/jstring.dart';
+import 'third_party/generated_bindings.dart';
+
+/// Used for `static final` Java strings, where the constant string is
+/// available.
+///
+/// If only its value is used using [toDartString], the [reference] is never
+/// populated, saving a method call.
+class JFinalString extends JString with JLazyReference {
+ @override
+ final JObjectPtr Function() lazyReference;
+
+ final String string;
+
+ JFinalString(this.lazyReference, this.string) : super.fromRef(nullptr);
+
+ @override
+ String toDartString({bool releaseOriginal = false}) {
+ if (releaseOriginal) {
+ release();
+ }
+ return string;
+ }
+}
diff --git a/pkgs/jni/lib/src/jni.dart b/pkgs/jni/lib/src/jni.dart
new file mode 100644
index 0000000..4993aee
--- /dev/null
+++ b/pkgs/jni/lib/src/jni.dart
@@ -0,0 +1,383 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+import 'dart:io';
+import 'dart:isolate';
+
+import 'package:ffi/ffi.dart';
+import 'package:path/path.dart';
+
+import 'errors.dart';
+import 'jobject.dart';
+import 'third_party/generated_bindings.dart';
+import 'jvalues.dart';
+import 'accessors.dart';
+
+String _getLibraryFileName(String base) {
+ if (Platform.isLinux || Platform.isAndroid) {
+ return "lib$base.so";
+ } else if (Platform.isWindows) {
+ return "$base.dll";
+ } else if (Platform.isMacOS) {
+ return "lib$base.dylib";
+ } else {
+ throw UnsupportedError("cannot derive library name: unsupported platform");
+ }
+}
+
+/// Load Dart-JNI Helper library.
+///
+/// If path is provided, it's used to load the library.
+/// Else just the platform-specific filename is passed to DynamicLibrary.open
+DynamicLibrary _loadDartJniLibrary({String? dir, String baseName = "dartjni"}) {
+ final fileName = _getLibraryFileName(baseName);
+ final libPath = (dir != null) ? join(dir, fileName) : fileName;
+ try {
+ final dylib = DynamicLibrary.open(libPath);
+ return dylib;
+ } on Error {
+ throw HelperNotFoundError(libPath);
+ }
+}
+
+/// Utilities to spawn and manage JNI.
+abstract final class Jni {
+ static final DynamicLibrary _dylib = _loadDartJniLibrary(dir: _dylibDir);
+ static final JniBindings _bindings = JniBindings(_dylib);
+ static final _getJniEnvFn = _dylib.lookup<Void>('GetJniEnv');
+ static final _getJniContextFn = _dylib.lookup<Void>('GetJniContextPtr');
+
+ /// Store dylibDir if any was used.
+ static String? _dylibDir;
+
+ /// Sets the directory where dynamic libraries are looked for.
+ /// On dart standalone, call this in new isolate before doing
+ /// any JNI operation.
+ ///
+ /// (The reason is that dylibs need to be loaded in every isolate.
+ /// On flutter it's done by library. On dart standalone we don't
+ /// know the library path.)
+ static void setDylibDir({required String dylibDir}) {
+ _dylibDir = dylibDir;
+ }
+
+ /// Initializes DartApiDL used for Continuations and interface implementation.
+ static void initDLApi() {
+ assert(NativeApi.majorVersion == 2);
+ assert(NativeApi.minorVersion >= 3);
+ final result = _bindings.InitDartApiDL(NativeApi.initializeApiDLData);
+ assert(result == 0);
+ }
+
+ /// Spawn an instance of JVM using JNI. This method should be called at the
+ /// beginning of the program with appropriate options, before other isolates
+ /// are spawned.
+ ///
+ /// [dylibDir] is path of the directory where the wrapper library is found.
+ /// This parameter needs to be passed manually on __Dart standalone target__,
+ /// since we have no reliable way to bundle it with the package.
+ ///
+ /// [jvmOptions], [ignoreUnrecognized], & [jniVersion] are passed to the JVM.
+ /// Strings in [classPath], if any, are used to construct an additional
+ /// JVM option of the form "-Djava.class.path={paths}".
+ static void spawn({
+ String? dylibDir,
+ List<String> jvmOptions = const [],
+ List<String> classPath = const [],
+ bool ignoreUnrecognized = false,
+ int jniVersion = JniVersions.JNI_VERSION_1_6,
+ }) {
+ final status = spawnIfNotExists(
+ dylibDir: dylibDir,
+ jvmOptions: jvmOptions,
+ classPath: classPath,
+ ignoreUnrecognized: ignoreUnrecognized,
+ jniVersion: jniVersion,
+ );
+ if (status == false) {
+ throw JniVmExistsError();
+ }
+ }
+
+ /// Same as [spawn] but if a JVM exists, returns silently instead of
+ /// throwing [JvmExistsError].
+ ///
+ /// If the options are different than that of existing VM, the existing VM's
+ /// options will remain in effect.
+ static bool spawnIfNotExists({
+ String? dylibDir,
+ List<String> jvmOptions = const [],
+ List<String> classPath = const [],
+ bool ignoreUnrecognized = false,
+ int jniVersion = JniVersions.JNI_VERSION_1_6,
+ }) =>
+ using((arena) {
+ _dylibDir = dylibDir;
+ final jvmArgs = _createVMArgs(
+ options: jvmOptions,
+ classPath: classPath,
+ version: jniVersion,
+ dylibPath: dylibDir,
+ ignoreUnrecognized: ignoreUnrecognized,
+ allocator: arena,
+ );
+ final status = _bindings.SpawnJvm(jvmArgs);
+ if (status == JniErrorCode.JNI_OK) {
+ return true;
+ } else if (status == DART_JNI_SINGLETON_EXISTS) {
+ return false;
+ } else {
+ throw JniError.of(status);
+ }
+ });
+
+ static Pointer<JavaVMInitArgs> _createVMArgs({
+ List<String> options = const [],
+ List<String> classPath = const [],
+ String? dylibPath,
+ bool ignoreUnrecognized = false,
+ int version = JniVersions.JNI_VERSION_1_6,
+ required Allocator allocator,
+ }) {
+ final args = allocator<JavaVMInitArgs>();
+ if (options.isNotEmpty || classPath.isNotEmpty) {
+ final count = options.length +
+ (dylibPath != null ? 1 : 0) +
+ (classPath.isNotEmpty ? 1 : 0);
+ final optsPtr = (count != 0) ? allocator<JavaVMOption>(count) : nullptr;
+ args.ref.options = optsPtr;
+ for (int i = 0; i < options.length; i++) {
+ optsPtr.elementAt(i).ref.optionString =
+ options[i].toNativeChars(allocator);
+ }
+ if (dylibPath != null) {
+ optsPtr
+ .elementAt(count - 1 - (classPath.isNotEmpty ? 1 : 0))
+ .ref
+ .optionString =
+ "-Djava.library.path=$dylibPath".toNativeChars(allocator);
+ }
+ if (classPath.isNotEmpty) {
+ final classPathString = classPath.join(Platform.isWindows ? ';' : ":");
+ optsPtr.elementAt(count - 1).ref.optionString =
+ "-Djava.class.path=$classPathString".toNativeChars(allocator);
+ }
+ args.ref.nOptions = count;
+ }
+ args.ref.ignoreUnrecognized = ignoreUnrecognized ? 1 : 0;
+ args.ref.version = version;
+ return args;
+ }
+
+ /// Returns pointer to current JNI JavaVM instance
+ Pointer<JavaVM> getJavaVM() {
+ return _bindings.GetJavaVM();
+ }
+
+ /// Returns the instance of [GlobalJniEnvStruct], which is an abstraction over
+ /// JNIEnv without the same-thread restriction.
+ static Pointer<GlobalJniEnvStruct> _fetchGlobalEnv() {
+ final env = _bindings.GetGlobalEnv();
+ if (env == nullptr) {
+ throw NoJvmInstanceError();
+ }
+ return env;
+ }
+
+ /// Points to a process-wide shared instance of [GlobalJniEnv].
+ ///
+ /// It provides an indirection over [JniEnv] so that it can be used from
+ /// any thread, and always returns global object references.
+ static final env = GlobalJniEnv(_fetchGlobalEnv());
+
+ static final accessors = JniAccessors(_bindings.GetAccessors());
+
+ /// Returns current application context on Android.
+ static JObjectPtr getCachedApplicationContext() {
+ return _bindings.GetApplicationContext();
+ }
+
+ /// Returns current activity
+ static JObjectPtr getCurrentActivity() => _bindings.GetCurrentActivity();
+
+ /// Get the initial classLoader of the application.
+ ///
+ /// This is especially useful on Android, where
+ /// JNI threads cannot access application classes using
+ /// the usual `JniEnv.FindClass` method.
+ static JObjectPtr getApplicationClassLoader() => _bindings.GetClassLoader();
+
+ /// Returns class reference found through system-specific mechanism
+ static JClassPtr findClass(String qualifiedName) => using((arena) {
+ final cls = accessors.getClass(qualifiedName.toNativeChars(arena));
+ return cls.checkedClassRef;
+ });
+
+ /// Returns class for [qualifiedName] found by platform-specific mechanism,
+ /// wrapped in a [JClass].
+ static JClass findJClass(String qualifiedName) =>
+ JClass.fromRef(findClass(qualifiedName));
+
+ /// Constructs an instance of class with given arguments.
+ ///
+ /// Use it when one instance is needed, but the constructor or class aren't
+ /// required themselves.
+ static JObject newInstance(
+ String qualifiedName, String ctorSignature, List<dynamic> args) {
+ final cls = findJClass(qualifiedName);
+ final ctor = cls.getCtorID(ctorSignature);
+ final obj = cls.newInstance(ctor, args);
+ cls.release();
+ return obj;
+ }
+
+ /// Converts passed arguments to JValue array.
+ ///
+ /// long, bool, double and JObject types are converted out of the box.
+ /// Wrap values in types such as [JValueInt] to convert to other primitive
+ /// types such as `int`, `short` and `char`.
+ static Pointer<JValue> jvalues(List<dynamic> args,
+ {Allocator allocator = calloc}) {
+ return toJValues(args, allocator: allocator);
+ }
+
+ /// Returns the value of static field identified by [fieldName] & [signature].
+ ///
+ /// See [JObject.getField] for more explanations about [callType] and [T].
+ static T retrieveStaticField<T>(
+ String className, String fieldName, String signature,
+ [int? callType]) {
+ final cls = findJClass(className);
+ final result = cls.getStaticFieldByName<T>(fieldName, signature, callType);
+ cls.release();
+ return result;
+ }
+
+ /// Calls static method identified by [methodName] and [signature]
+ /// on [className] with [args] as and [callType].
+ ///
+ /// For more explanation on [args] and [callType], see [JObject.getField]
+ /// and [JObject.callMethod] respectively.
+ static T invokeStaticMethod<T>(
+ String className, String methodName, String signature, List<dynamic> args,
+ [int? callType]) {
+ final cls = findJClass(className);
+ final result =
+ cls.callStaticMethodByName<T>(methodName, signature, args, callType);
+ cls.release();
+ return result;
+ }
+}
+
+typedef _SetJniGettersNativeType = Void Function(Pointer<Void>, Pointer<Void>);
+typedef _SetJniGettersDartType = void Function(Pointer<Void>, Pointer<Void>);
+
+/// Extensions for use by `jnigen` generated code.
+extension ProtectedJniExtensions on Jni {
+ static Pointer<T> Function<T extends NativeType>(String) initGeneratedLibrary(
+ String name) {
+ var path = _getLibraryFileName(name);
+ if (Jni._dylibDir != null) {
+ path = join(Jni._dylibDir!, path);
+ }
+ final dl = DynamicLibrary.open(path);
+ final setJniGetters =
+ dl.lookupFunction<_SetJniGettersNativeType, _SetJniGettersDartType>(
+ 'setJniGetters');
+ setJniGetters(Jni._getJniContextFn, Jni._getJniEnvFn);
+ final lookup = dl.lookup;
+ return lookup;
+ }
+
+ /// Returns a new DartException.
+ static JObjectPtr newDartException(String message) {
+ return Jni._bindings
+ .DartException__ctor(Jni.env.toJStringPtr(message))
+ .object;
+ }
+
+ /// Returns a new PortContinuation.
+ static JObjectPtr newPortContinuation(ReceivePort port) {
+ return Jni._bindings
+ .PortContinuation__ctor(port.sendPort.nativePort)
+ .object;
+ }
+
+ /// Returns a new PortProxy for a class with the given [binaryName].
+ static JObjectPtr newPortProxy(
+ String binaryName,
+ ReceivePort port,
+ Pointer<
+ NativeFunction<
+ Pointer<Void> Function(Uint64, Pointer<Void>, Pointer<Void>)>>
+ functionPtr) {
+ return Jni._bindings
+ .PortProxy__newInstance(
+ Jni.env.toJStringPtr(binaryName),
+ port.sendPort.nativePort,
+ functionPtr.address,
+ )
+ .object;
+ }
+
+ /// Returns the result of a callback..
+ static void returnResult(
+ Pointer<CallbackResult> result, JObjectPtr object) async {
+ Jni._bindings.resultFor(result, object);
+ }
+}
+
+extension AdditionalEnvMethods on GlobalJniEnv {
+ /// Convenience method for converting a [JStringPtr] to dart string.
+ /// if [releaseOriginal] is specified, jstring passed will be deleted using
+ /// DeleteGlobalRef.
+ String toDartString(JStringPtr jstringPtr, {bool releaseOriginal = false}) {
+ if (jstringPtr == nullptr) {
+ throw JNullError();
+ }
+ final chars = GetStringChars(jstringPtr, nullptr);
+ if (chars == nullptr) {
+ throw ArgumentError('Not a valid jstring pointer.');
+ }
+ final length = GetStringLength(jstringPtr);
+ final result = chars.cast<Utf16>().toDartString(length: length);
+ ReleaseStringChars(jstringPtr, chars);
+ if (releaseOriginal) {
+ DeleteGlobalRef(jstringPtr);
+ }
+ return result;
+ }
+
+ /// Returns a new [JStringPtr] from contents of [s].
+ JStringPtr toJStringPtr(String s) => using((arena) {
+ final utf = s.toNativeUtf16(allocator: arena).cast<Uint16>();
+ final result = NewString(utf, s.length);
+ if (utf == nullptr) {
+ throw 'Fatal: cannot convert string to Java string: $s';
+ }
+ return result;
+ });
+
+ /// Deletes all references in [refs].
+ void deleteAllRefs(List<JObjectPtr> refs) {
+ for (final ref in refs) {
+ DeleteGlobalRef(ref);
+ }
+ }
+}
+
+extension StringMethodsForJni on String {
+ /// Returns a Utf-8 encoded Pointer<Char> with contents same as this string.
+ Pointer<Char> toNativeChars([Allocator allocator = malloc]) {
+ return toNativeUtf8(allocator: allocator).cast<Char>();
+ }
+}
+
+extension CharPtrMethodsForJni on Pointer<Char> {
+ /// Same as calling `cast<Utf8>` followed by `toDartString`.
+ String toDartString({int? length}) {
+ return cast<Utf8>().toDartString(length: length);
+ }
+}
diff --git a/pkgs/jni/lib/src/jobject.dart b/pkgs/jni/lib/src/jobject.dart
new file mode 100644
index 0000000..15c6972
--- /dev/null
+++ b/pkgs/jni/lib/src/jobject.dart
@@ -0,0 +1,431 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+
+import 'package:ffi/ffi.dart';
+import 'package:jni/src/accessors.dart';
+
+import 'errors.dart';
+import 'jni.dart';
+import 'jreference.dart';
+import 'lang/jstring.dart';
+import 'jvalues.dart';
+import 'third_party/generated_bindings.dart';
+import 'types.dart';
+
+// This typedef is needed because void is a keyword and cannot be used in
+// type switch like a regular type.
+typedef _VoidType = void;
+
+final class JObjectType extends JObjType<JObject> {
+ const JObjectType();
+
+ @override
+ String get signature => "Ljava/lang/Object;";
+
+ @override
+ JObject fromRef(Pointer<Void> ref) => JObject.fromRef(ref);
+
+ @override
+ JObjType get superType => const JObjectType();
+
+ // TODO(#70): Once interface implementation lands, other than [superType],
+ // we should have a list of implemented interfaces.
+
+ @override
+ final int superCount = 0;
+
+ @override
+ int get hashCode => (JObjectType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == JObjectType && other is JObjectType;
+ }
+}
+
+Pointer<T> _getID<T extends NativeType>(
+ JniPointerResult Function(
+ Pointer<Void> ptr, Pointer<Char> name, Pointer<Char> sig)
+ f,
+ Pointer<Void> ptr,
+ String name,
+ String sig,
+) {
+ final result = using(
+ (arena) => f(ptr, name.toNativeChars(arena), sig.toNativeChars(arena)));
+ if (result.exception != nullptr) {
+ Jni.accessors.throwException(result.exception);
+ }
+ return result.value.cast<T>();
+}
+
+int _getCallType(int? callType, int defaultType, Set<int> allowed) {
+ if (callType == null) return defaultType;
+ if (allowed.contains(callType)) return callType;
+ throw InvalidCallTypeError(callType, allowed);
+}
+
+T _callOrGet<T>(int? callType, JniResult Function(int) function) {
+ final int finalCallType;
+ late T result;
+ switch (T) {
+ case bool:
+ finalCallType = _getCallType(
+ callType, JniCallType.booleanType, {JniCallType.booleanType});
+ result = function(finalCallType).boolean as T;
+ break;
+ case int:
+ finalCallType = _getCallType(callType, JniCallType.longType, {
+ JniCallType.byteType,
+ JniCallType.charType,
+ JniCallType.shortType,
+ JniCallType.intType,
+ JniCallType.longType,
+ });
+ final jniResult = function(finalCallType);
+ switch (finalCallType) {
+ case JniCallType.byteType:
+ result = jniResult.byte as T;
+ break;
+ case JniCallType.shortType:
+ result = jniResult.short as T;
+ break;
+ case JniCallType.charType:
+ result = jniResult.char as T;
+ break;
+ case JniCallType.intType:
+ result = jniResult.integer as T;
+ break;
+ case JniCallType.longType:
+ result = jniResult.long as T;
+ break;
+ }
+ break;
+ case double:
+ finalCallType = _getCallType(callType, JniCallType.doubleType,
+ {JniCallType.floatType, JniCallType.doubleType});
+ final jniResult = function(finalCallType);
+ switch (finalCallType) {
+ case JniCallType.floatType:
+ result = jniResult.float as T;
+ break;
+ case JniCallType.doubleType:
+ result = jniResult.doubleFloat as T;
+ break;
+ }
+ break;
+ case String:
+ case JObject:
+ case JString:
+ finalCallType = _getCallType(
+ callType, JniCallType.objectType, {JniCallType.objectType});
+ final ref = function(finalCallType).object;
+ final ctor = T == String
+ ? (ref) => Jni.env.toDartString(ref, releaseOriginal: true)
+ : (T == JObject ? JObject.fromRef : JString.fromRef);
+ result = ctor(ref) as T;
+ break;
+ case const (Pointer<Void>): // JObjectPtr
+ finalCallType = _getCallType(
+ callType, JniCallType.objectType, {JniCallType.objectType});
+ result = function(finalCallType).object as T;
+ break;
+ case _VoidType:
+ finalCallType =
+ _getCallType(callType, JniCallType.voidType, {JniCallType.voidType});
+ function(finalCallType).check();
+ result = null as T;
+ break;
+ case dynamic:
+ throw UnsupportedError("Return type not specified for JNI call");
+ default:
+ throw UnsupportedError('Unknown type $T');
+ }
+ return result;
+}
+
+T _callMethod<T>(int? callType, List<dynamic> args,
+ JniResult Function(int, Pointer<JValue>) f) =>
+ using((arena) {
+ final jArgs = JValueArgs(args, arena);
+ return _callOrGet<T>(callType, (ct) => f(ct, jArgs.values));
+ });
+
+T _getField<T>(int? callType, JniResult Function(int) f) {
+ final result = _callOrGet<T>(callType, f);
+ return result;
+}
+
+/// A high-level wrapper for JNI global object reference.
+///
+/// This is the base class for classes generated by `jnigen`.
+class JObject extends JReference {
+ late final JObjType<JObject> $type = type;
+
+ /// The type which includes information such as the signature of this class.
+ static const JObjType<JObject> type = JObjectType();
+
+ /// Construct a new [JObject] with [reference] as its underlying reference.
+ JObject.fromRef(JObjectPtr reference) : super.fromRef(reference);
+
+ JClass? _jClass;
+
+ JClass get _class {
+ return _jClass ??= getClass();
+ }
+
+ @override
+ void release() {
+ _jClass?.release();
+ super.release();
+ }
+
+ /// Returns [JClass] corresponding to concrete class of this object.
+ ///
+ /// This may be a subclass of compile-time class.
+ JClass getClass() {
+ final classRef = Jni.env.GetObjectClass(reference);
+ if (classRef == nullptr) {
+ Jni.accessors.throwException(Jni.env.ExceptionOccurred());
+ }
+ return JClass.fromRef(classRef);
+ }
+
+ /// Get [JFieldIDPtr] of instance field identified by [fieldName] & [signature].
+ JFieldIDPtr getFieldID(String fieldName, String signature) {
+ return _getID(
+ Jni.accessors.getFieldID, _class.reference, fieldName, signature);
+ }
+
+ /// Get [JFieldIDPtr] of static field identified by [fieldName] & [signature].
+ JFieldIDPtr getStaticFieldID(String fieldName, String signature) {
+ return _getID<jfieldID_>(
+ Jni.accessors.getStaticFieldID, _class.reference, fieldName, signature);
+ }
+
+ /// Get [JMethodIDPtr] of instance method [methodName] with [signature].
+ JMethodIDPtr getMethodID(String methodName, String signature) {
+ return _getID<jmethodID_>(
+ Jni.accessors.getMethodID, _class.reference, methodName, signature);
+ }
+
+ /// Get [JMethodIDPtr] of static method [methodName] with [signature].
+ JMethodIDPtr getStaticMethodID(String methodName, String signature) {
+ return _getID<jmethodID_>(Jni.accessors.getStaticMethodID, _class.reference,
+ methodName, signature);
+ }
+
+ /// Retrieve the value of the field using [fieldID].
+ ///
+ /// [callType] determines the return type of the underlying JNI call made.
+ /// If the Java field is of `long` type, this must be [JniCallType.longType] and
+ /// so on. Default is chosen based on return type [T], which maps int -> int,
+ /// double -> double, void -> void, and JObject types to `Object`.
+ ///
+ /// If [T] is String or [JObject], required conversions are performed and
+ /// final value is returned.
+ T getField<T>(JFieldIDPtr fieldID, [int? callType]) {
+ if (callType == JniCallType.voidType) {
+ throw ArgumentError("void is not a valid field type.");
+ }
+ return _getField<T>(
+ callType, (ct) => Jni.accessors.getField(reference, fieldID, ct));
+ }
+
+ /// Get value of the field identified by [name] and [signature].
+ ///
+ /// See [getField] for an explanation about [callType] parameter.
+ T getFieldByName<T>(String name, String signature, [int? callType]) {
+ final id = getFieldID(name, signature);
+ return getField<T>(id, callType);
+ }
+
+ /// Get value of the static field using [fieldID].
+ ///
+ /// See [getField] for an explanation about [callType] parameter.
+ T getStaticField<T>(JFieldIDPtr fieldID, [int? callType]) {
+ if (callType == JniCallType.voidType) {
+ throw ArgumentError("void is not a valid field type.");
+ }
+ return _getField<T>(callType,
+ (ct) => Jni.accessors.getStaticField(_class.reference, fieldID, ct));
+ }
+
+ /// Get value of the static field identified by [name] and [signature].
+ ///
+ /// See [getField] for an explanation about [callType] parameter.
+ T getStaticFieldByName<T>(String name, String signature, [int? callType]) {
+ final id = getStaticFieldID(name, signature);
+ return getStaticField<T>(id, callType);
+ }
+
+ /// Call the method using [methodID],
+ ///
+ /// [args] can consist of primitive types, JNI primitive wrappers such as
+ /// [JValueLong], strings, and subclasses of [JObject].
+ ///
+ /// See [getField] for an explanation about [callType] and return type [T].
+ T callMethod<T>(JMethodIDPtr methodID, List<dynamic> args, [int? callType]) {
+ return _callMethod<T>(callType, args,
+ (ct, jvs) => Jni.accessors.callMethod(reference, methodID, ct, jvs));
+ }
+
+ /// Call instance method identified by [name] and [signature].
+ ///
+ /// This implementation looks up the method and calls it using [callMethod].
+ T callMethodByName<T>(String name, String signature, List<dynamic> args,
+ [int? callType]) {
+ final id = getMethodID(name, signature);
+ return callMethod<T>(id, args, callType);
+ }
+
+ /// Call static method using [methodID]. See [callMethod] and [getField] for
+ /// more details about [args] and [callType].
+ T callStaticMethod<T>(JMethodIDPtr methodID, List<dynamic> args,
+ [int? callType]) {
+ return _callMethod<T>(
+ callType,
+ args,
+ (ct, jvs) =>
+ Jni.accessors.callStaticMethod(reference, methodID, ct, jvs));
+ }
+
+ /// Call static method identified by [name] and [signature].
+ ///
+ /// This implementation looks up the method and calls [callStaticMethod].
+ T callStaticMethodByName<T>(String name, String signature, List<dynamic> args,
+ [int? callType]) {
+ final id = getStaticMethodID(name, signature);
+ return callStaticMethod<T>(id, args, callType);
+ }
+
+ /// Casts this object to another [type].
+ ///
+ /// If [releaseOriginal] is `true`, the casted object will be released.
+ T castTo<T extends JObject>(
+ JObjType<T> type, {
+ bool releaseOriginal = false,
+ }) {
+ if (releaseOriginal) {
+ _jClass?.release();
+ final ret = type.fromRef(reference);
+ setAsReleased();
+ return ret;
+ }
+ final newRef = Jni.env.NewGlobalRef(reference);
+ return type.fromRef(newRef);
+ }
+
+ static final _objectClass = Jni.findJClass('java/lang/Object');
+
+ static final _hashCodeId =
+ Jni.accessors.getMethodIDOf(_objectClass.reference, r"hashCode", r"()I");
+ @override
+ int get hashCode => Jni.accessors.callMethodWithArgs(
+ reference, _hashCodeId, JniCallType.intType, []).integer;
+
+ static final _equalsId = Jni.accessors.getMethodIDOf(
+ _objectClass.reference, r"equals", r"(Ljava/lang/Object;)Z");
+ @override
+ bool operator ==(Object other) {
+ if (other is! JObject) {
+ return false;
+ }
+ return Jni.accessors.callMethodWithArgs(reference, _equalsId,
+ JniCallType.booleanType, [other.reference]).boolean;
+ }
+
+ static final _toStringId = Jni.accessors.getMethodIDOf(
+ _objectClass.reference, r"toString", r"()Ljava/lang/String;");
+ @override
+ String toString() {
+ return JString.fromRef(Jni.accessors.callMethodWithArgs(
+ reference, _toStringId, JniCallType.objectType, []).object)
+ .toDartString(releaseOriginal: true);
+ }
+}
+
+/// A high level wrapper over a JNI class reference.
+class JClass extends JReference {
+ /// Construct a new [JClass] with [reference] as its underlying reference.
+ JClass.fromRef(JObjectPtr reference) : super.fromRef(reference);
+
+ /// Get [JFieldIDPtr] of static field [fieldName] with [signature].
+ JFieldIDPtr getStaticFieldID(String fieldName, String signature) {
+ return _getID<jfieldID_>(
+ Jni.accessors.getStaticFieldID, reference, fieldName, signature);
+ }
+
+ /// Get [JMethodIDPtr] of static method [methodName] with [signature].
+ JMethodIDPtr getStaticMethodID(String methodName, String signature) {
+ return _getID<jmethodID_>(
+ Jni.accessors.getStaticMethodID, reference, methodName, signature);
+ }
+
+ /// Get [JFieldIDPtr] of field [fieldName] with [signature].
+ JFieldIDPtr getFieldID(String fieldName, String signature) {
+ return _getID<jfieldID_>(
+ Jni.accessors.getFieldID, reference, fieldName, signature);
+ }
+
+ /// Get [JMethodIDPtr] of method [methodName] with [signature].
+ JMethodIDPtr getMethodID(String methodName, String signature) {
+ return _getID<jmethodID_>(
+ Jni.accessors.getMethodID, reference, methodName, signature);
+ }
+
+ /// Get [JMethodIDPtr] of constructor with [signature].
+ JMethodIDPtr getCtorID(String signature) => getMethodID("<init>", signature);
+
+ /// Get the value of static field using [fieldID].
+ ///
+ /// See [JObject.getField] for more explanation about [callType].
+ T getStaticField<T>(JFieldIDPtr fieldID, [int? callType]) {
+ if (callType == JniCallType.voidType) {
+ throw ArgumentError("void is not a valid field type.");
+ }
+ return _getField<T>(
+ callType, (ct) => Jni.accessors.getStaticField(reference, fieldID, ct));
+ }
+
+ /// Get the value of static field identified by [name] and [signature].
+ ///
+ /// This implementation looks up the field ID and calls [getStaticField].
+ T getStaticFieldByName<T>(String name, String signature, [int? callType]) {
+ final id = getStaticFieldID(name, signature);
+ return getStaticField<T>(id, callType);
+ }
+
+ /// Call the static method using [methodID].
+ ///
+ /// See [JObject.callMethod] and [JObject.getField] for more explanation
+ /// about [args] and [callType].
+ T callStaticMethod<T>(JMethodIDPtr methodID, List<dynamic> args,
+ [int? callType]) {
+ return _callMethod<T>(
+ callType,
+ args,
+ (ct, jvs) =>
+ Jni.accessors.callStaticMethod(reference, methodID, ct, jvs));
+ }
+
+ /// Call the static method identified by [name] and [signature].
+ ///
+ /// This implementation looks up the method ID and calls [callStaticMethod].
+ T callStaticMethodByName<T>(String name, String signature, List<dynamic> args,
+ [int? callType]) {
+ final id = getStaticMethodID(name, signature);
+ return callStaticMethod<T>(id, args, callType);
+ }
+
+ /// Create a new instance of this class with [ctor] and [args].
+ JObject newInstance(JMethodIDPtr ctor, List<dynamic> args) => using((arena) {
+ final jArgs = JValueArgs(args, arena);
+ final res =
+ Jni.accessors.newObject(reference, ctor, jArgs.values).object;
+ return JObject.fromRef(res);
+ });
+}
diff --git a/pkgs/jni/lib/src/jprimitives.dart b/pkgs/jni/lib/src/jprimitives.dart
new file mode 100644
index 0000000..04448da
--- /dev/null
+++ b/pkgs/jni/lib/src/jprimitives.dart
@@ -0,0 +1,99 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// The types here are mapped to primitive types in Java, so they're all in
+// lowercase.
+// ignore_for_file: camel_case_types
+
+part of 'types.dart';
+
+abstract final class JPrimitive {}
+
+abstract final class jbyte extends JPrimitive {
+ static const type = jbyteType();
+}
+
+final class jbyteType extends JType<jbyte> {
+ const jbyteType();
+
+ @override
+ final signature = 'B';
+}
+
+abstract final class jboolean extends JPrimitive {
+ static const type = jbooleanType();
+}
+
+final class jbooleanType extends JType<jboolean> {
+ const jbooleanType();
+
+ @override
+ final signature = 'Z';
+}
+
+abstract final class jchar extends JPrimitive {
+ static const type = jcharType();
+}
+
+final class jcharType extends JType<jchar> {
+ const jcharType();
+
+ @override
+ final signature = 'C';
+}
+
+abstract final class jshort extends JPrimitive {
+ static const type = jshortType();
+}
+
+final class jshortType extends JType<jshort> {
+ const jshortType();
+
+ @override
+ final signature = 'S';
+}
+
+abstract final class jint extends JPrimitive {
+ static const type = jintType();
+}
+
+final class jintType extends JType<jint> {
+ const jintType();
+
+ @override
+ final signature = 'I';
+}
+
+abstract final class jlong extends JPrimitive {
+ static const type = jlongType();
+}
+
+final class jlongType extends JType<jlong> {
+ const jlongType();
+
+ @override
+ final signature = 'J';
+}
+
+abstract final class jfloat extends JPrimitive {
+ static const type = jfloatType();
+}
+
+final class jfloatType extends JType<jfloat> {
+ const jfloatType();
+
+ @override
+ final signature = 'F';
+}
+
+abstract final class jdouble extends JPrimitive {
+ static const type = jdoubleType();
+}
+
+final class jdoubleType extends JType<jdouble> {
+ const jdoubleType();
+
+ @override
+ final signature = 'D';
+}
diff --git a/pkgs/jni/lib/src/jreference.dart b/pkgs/jni/lib/src/jreference.dart
new file mode 100644
index 0000000..093e297
--- /dev/null
+++ b/pkgs/jni/lib/src/jreference.dart
@@ -0,0 +1,136 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+
+import 'package:ffi/ffi.dart';
+import 'package:jni/src/third_party/generated_bindings.dart';
+
+import 'errors.dart';
+import 'jni.dart';
+
+extension ProtectedJReference on JReference {
+ void setAsReleased() {
+ if (_released) {
+ throw DoubleReleaseError();
+ }
+ _released = true;
+ JReference._finalizer.detach(this);
+ }
+
+ void ensureNotNull() {
+ if (isNull) {
+ throw JNullError();
+ }
+ }
+
+ /// Similar to [reference].
+ ///
+ /// Detaches the finalizer so the underlying pointer will not be deleted.
+ JObjectPtr toPointer() {
+ final ref = reference;
+ setAsReleased();
+ return ref;
+ }
+}
+
+/// A managed JNI global reference.
+///
+/// Uses a [NativeFinalizer] to delete the JNI global reference when finalized.
+abstract class JReference implements Finalizable {
+ static final _finalizer =
+ NativeFinalizer(Jni.env.ptr.ref.DeleteGlobalRef.cast());
+
+ JReference.fromRef(this._reference) {
+ if (_reference != nullptr) {
+ _finalizer.attach(this, _reference, detach: this);
+ }
+ }
+
+ bool _released = false;
+
+ /// Whether the underlying JNI reference is `null` or not.
+ bool get isNull => reference == nullptr;
+
+ /// Whether the underlying JNI reference is deleted or not.
+ bool get isReleased => _released;
+
+ /// Deletes the underlying JNI reference and marks this as released.
+ ///
+ /// Throws [DoubleReleaseError] if this is already released.
+ ///
+ /// Further uses of this object will throw [UseAfterReleaseError].
+ void release() {
+ setAsReleased();
+ Jni.env.DeleteGlobalRef(_reference);
+ }
+
+ /// The underlying JNI global object reference.
+ ///
+ /// Throws [UseAfterReleaseError] if the object is previously released.
+ ///
+ /// Be careful when storing this in a variable since it might have gotten
+ /// released upon use.
+ JObjectPtr get reference {
+ if (_released) throw UseAfterReleaseError();
+ return _reference;
+ }
+
+ final JObjectPtr _reference;
+
+ /// Registers this object to be released at the end of [arena]'s lifetime.
+ void releasedBy(Arena arena) => arena.onReleaseAll(release);
+}
+
+/// Creates a "lazy" [JReference].
+///
+/// The first use of [reference] will call [lazyReference].
+///
+/// This is useful when the Java object is not necessarily used directly, and
+/// there are alternative ways to get a Dart representation of the Object.
+///
+/// Object mixed in with this must call their super.[fromRef] constructor
+/// with [nullptr].
+///
+/// Also see [JFinalString].
+mixin JLazyReference on JReference {
+ JObjectPtr? _lazyReference;
+
+ JObjectPtr Function() get lazyReference;
+
+ @override
+ JObjectPtr get reference {
+ if (_lazyReference == null) {
+ _lazyReference = lazyReference();
+ JReference._finalizer.attach(this, _lazyReference!, detach: this);
+ return _lazyReference!;
+ }
+ if (_released) {
+ throw UseAfterReleaseError();
+ }
+ return _lazyReference!;
+ }
+
+ @override
+ void release() {
+ setAsReleased();
+ if (_lazyReference == null) {
+ return;
+ }
+ Jni.env.DeleteGlobalRef(_lazyReference!);
+ }
+}
+
+extension JReferenceUseExtension<T extends JReference> on T {
+ /// Applies [callback] on [this] object and then delete the underlying JNI
+ /// reference, returning the result of [callback].
+ R use<R>(R Function(T) callback) {
+ try {
+ final result = callback(this);
+ return result;
+ } finally {
+ release();
+ }
+ }
+}
diff --git a/pkgs/jni/lib/src/jvalues.dart b/pkgs/jni/lib/src/jvalues.dart
new file mode 100644
index 0000000..dc17736
--- /dev/null
+++ b/pkgs/jni/lib/src/jvalues.dart
@@ -0,0 +1,144 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+import 'package:ffi/ffi.dart';
+
+import 'jobject.dart';
+import 'third_party/generated_bindings.dart';
+import 'jni.dart';
+
+void _fillJValue(Pointer<JValue> pos, dynamic arg) {
+ if (arg is JObject) {
+ pos.ref.l = arg.reference;
+ return;
+ }
+
+ switch (arg.runtimeType) {
+ case int:
+ pos.ref.j = arg;
+ break;
+ case bool:
+ pos.ref.z = arg ? 1 : 0;
+ break;
+ case const (Pointer<Void>):
+ case const (Pointer<Never>): // for nullptr
+ pos.ref.l = arg;
+ break;
+ case double:
+ pos.ref.d = arg;
+ break;
+ case JValueFloat:
+ pos.ref.f = (arg as JValueFloat).value;
+ break;
+ case JValueInt:
+ pos.ref.i = (arg as JValueInt).value;
+ break;
+ case JValueShort:
+ pos.ref.s = (arg as JValueShort).value;
+ break;
+ case JValueChar:
+ pos.ref.c = (arg as JValueChar).value;
+ break;
+ case JValueByte:
+ pos.ref.b = (arg as JValueByte).value;
+ break;
+ default:
+ throw UnsupportedError("cannot convert ${arg.runtimeType} to jvalue");
+ }
+}
+
+/// Converts passed arguments to JValue array
+/// for use in methods that take arguments.
+///
+/// int, bool, double and JObject types are converted out of the box.
+/// wrap values in types such as [JValueLong]
+/// to convert to other primitive types instead.
+Pointer<JValue> toJValues(List<dynamic> args, {Allocator allocator = calloc}) {
+ final result = allocator<JValue>(args.length);
+ for (int i = 0; i < args.length; i++) {
+ final arg = args[i];
+ final pos = result.elementAt(i);
+ _fillJValue(pos, arg);
+ }
+ return result;
+}
+
+/// Use this class as wrapper to convert an integer
+/// to Java `int` in jvalues method.
+final class JValueInt {
+ int value;
+ JValueInt(this.value);
+}
+
+/// Use this class as wrapper to convert an integer
+/// to Java `short` in jvalues method.
+final class JValueShort {
+ int value;
+ JValueShort(this.value);
+}
+
+/// Use this class as wrapper to convert an integer
+/// to Java `byte` in jvalues method.
+final class JValueByte {
+ int value;
+ JValueByte(this.value);
+}
+
+/// Use this class as wrapper to convert an double
+/// to Java `float` in jvalues method.
+final class JValueFloat {
+ double value;
+ JValueFloat(this.value);
+}
+
+/// Use this class as wrapper to convert an integer
+/// to Java `char` in jvalues method.
+final class JValueChar {
+ int value;
+ JValueChar(this.value);
+ JValueChar.fromString(String s) : value = 0 {
+ if (s.length != 1) {
+ throw "Expected string of length 1";
+ }
+ value = s.codeUnitAt(0).toInt();
+ }
+}
+
+/// class used to convert dart types passed to convenience methods
+/// into their corresponding Java values.
+///
+/// Similar to Jni.jvalues, but instead of a pointer, an instance
+/// with a dispose method is returned.
+/// This allows us to take dart strings.
+///
+/// Returned value is allocated using provided allocator.
+/// But default allocator may be used for string conversions.
+final class JValueArgs {
+ late Pointer<JValue> values;
+ final List<JObjectPtr> createdRefs = [];
+
+ JValueArgs(List<dynamic> args, Arena arena) {
+ values = arena<JValue>(args.length);
+ for (int i = 0; i < args.length; i++) {
+ final arg = args[i];
+ final ptr = values.elementAt(i);
+ if (arg is String) {
+ final jstr = Jni.env.toJStringPtr(arg);
+ ptr.ref.l = jstr;
+ createdRefs.add(jstr);
+ } else {
+ _fillJValue(ptr, arg);
+ }
+ arena.onReleaseAll(_dispose);
+ }
+ }
+
+ /// Deletes temporary references such as [JStringPtr]s.
+ void _dispose() {
+ for (var ref in createdRefs) {
+ Jni.env.DeleteGlobalRef(ref);
+ }
+ }
+}
diff --git a/pkgs/jni/lib/src/lang/jboolean.dart b/pkgs/jni/lib/src/lang/jboolean.dart
new file mode 100644
index 0000000..9ea92b4
--- /dev/null
+++ b/pkgs/jni/lib/src/lang/jboolean.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../accessors.dart';
+import '../jobject.dart';
+import '../jreference.dart';
+import '../jni.dart';
+import '../third_party/generated_bindings.dart';
+import '../types.dart';
+
+final class JBooleanType extends JObjType<JBoolean> {
+ const JBooleanType();
+
+ @override
+ String get signature => r"Ljava/lang/Boolean;";
+
+ @override
+ JBoolean fromRef(JObjectPtr ref) => JBoolean.fromRef(ref);
+
+ @override
+ JObjType get superType => const JObjectType();
+
+ @override
+ final superCount = 2;
+
+ @override
+ int get hashCode => (JBooleanType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == JBooleanType && other is JBooleanType;
+ }
+}
+
+class JBoolean extends JObject {
+ @override
+ // ignore: overridden_fields
+ late final JObjType<JBoolean> $type = type;
+
+ JBoolean.fromRef(
+ JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = JBooleanType();
+
+ static final _class = Jni.findJClass(r"java/lang/Boolean");
+
+ static final _ctorId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"(Z)V");
+ JBoolean(bool boolean)
+ : super.fromRef(Jni.accessors.newObjectWithArgs(
+ _class.reference, _ctorId, [boolean ? 1 : 0]).object);
+
+ static final _booleanValueId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"booleanValue", r"()Z");
+
+ bool booleanValue({bool releaseOriginal = false}) {
+ ensureNotNull();
+ final ret = Jni.accessors.callMethodWithArgs(
+ reference, _booleanValueId, JniCallType.booleanType, []).boolean;
+ if (releaseOriginal) {
+ release();
+ }
+ return ret;
+ }
+}
diff --git a/pkgs/jni/lib/src/lang/jbyte.dart b/pkgs/jni/lib/src/lang/jbyte.dart
new file mode 100644
index 0000000..6b5aa98
--- /dev/null
+++ b/pkgs/jni/lib/src/lang/jbyte.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../accessors.dart';
+import '../jni.dart';
+import '../jvalues.dart';
+import '../third_party/generated_bindings.dart';
+import '../types.dart';
+import 'jnumber.dart';
+
+final class JByteType extends JObjType<JByte> {
+ const JByteType();
+
+ @override
+ String get signature => r"Ljava/lang/Byte;";
+
+ @override
+ JByte fromRef(JObjectPtr ref) => JByte.fromRef(ref);
+
+ @override
+ JObjType get superType => const JNumberType();
+
+ @override
+ final superCount = 2;
+
+ @override
+ int get hashCode => (JByteType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == JByteType && other is JByteType;
+ }
+}
+
+class JByte extends JNumber {
+ @override
+ // ignore: overridden_fields
+ late final JObjType<JByte> $type = type;
+
+ JByte.fromRef(
+ JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = JByteType();
+
+ static final _class = Jni.findJClass(r"java/lang/Byte");
+
+ static final _ctorId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"(B)V");
+ JByte(int num)
+ : super.fromRef(Jni.accessors.newObjectWithArgs(
+ _class.reference, _ctorId, [JValueByte(num)]).object);
+}
diff --git a/pkgs/jni/lib/src/lang/jcharacter.dart b/pkgs/jni/lib/src/lang/jcharacter.dart
new file mode 100644
index 0000000..b50f67f
--- /dev/null
+++ b/pkgs/jni/lib/src/lang/jcharacter.dart
@@ -0,0 +1,66 @@
+import '../accessors.dart';
+import '../jni.dart';
+import '../jobject.dart';
+import '../jreference.dart';
+import '../jvalues.dart';
+import '../third_party/generated_bindings.dart';
+import '../types.dart';
+
+final class JCharacterType extends JObjType<JCharacter> {
+ const JCharacterType();
+
+ @override
+ String get signature => r"Ljava/lang/Character;";
+
+ @override
+ JCharacter fromRef(JObjectPtr ref) => JCharacter.fromRef(ref);
+
+ @override
+ JObjType get superType => const JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => (JCharacterType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == (JCharacterType) && other is JCharacterType;
+ }
+}
+
+class JCharacter extends JObject {
+ @override
+ // ignore: overridden_fields
+ late final JObjType<JCharacter> $type = type;
+
+ JCharacter.fromRef(
+ JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = JCharacterType();
+
+ static final _class = Jni.findJClass(r"java/lang/Character");
+
+ static final _ctorId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"(C)V");
+
+ JCharacter(int c)
+ : super.fromRef(Jni.accessors.newObjectWithArgs(
+ _class.reference, _ctorId, [JValueChar(c)]).object);
+
+ static final _charValueId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"charValue", r"()C");
+
+ int charValue({bool releaseOriginal = false}) {
+ ensureNotNull();
+ final ret = Jni.accessors.callMethodWithArgs(
+ reference, _charValueId, JniCallType.charType, []).char;
+ if (releaseOriginal) {
+ release();
+ }
+ return ret;
+ }
+}
diff --git a/pkgs/jni/lib/src/lang/jdouble.dart b/pkgs/jni/lib/src/lang/jdouble.dart
new file mode 100644
index 0000000..6db163e
--- /dev/null
+++ b/pkgs/jni/lib/src/lang/jdouble.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../accessors.dart';
+import '../jni.dart';
+import '../third_party/generated_bindings.dart';
+import '../types.dart';
+import 'jnumber.dart';
+
+final class JDoubleType extends JObjType<JDouble> {
+ const JDoubleType();
+
+ @override
+ String get signature => r"Ljava/lang/Double;";
+
+ @override
+ JDouble fromRef(JObjectPtr ref) => JDouble.fromRef(ref);
+
+ @override
+ JObjType get superType => const JNumberType();
+
+ @override
+ final superCount = 2;
+
+ @override
+ int get hashCode => (JDoubleType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == JDoubleType && other is JDoubleType;
+ }
+}
+
+class JDouble extends JNumber {
+ @override
+ // ignore: overridden_fields
+ late final JObjType<JDouble> $type = type;
+
+ JDouble.fromRef(
+ JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = JDoubleType();
+
+ static final _class = Jni.findJClass(r"java/lang/Double");
+
+ static final _ctorId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"(D)V");
+ JDouble(double num)
+ : super.fromRef(Jni.accessors
+ .newObjectWithArgs(_class.reference, _ctorId, [num]).object);
+}
diff --git a/pkgs/jni/lib/src/lang/jfloat.dart b/pkgs/jni/lib/src/lang/jfloat.dart
new file mode 100644
index 0000000..a352659
--- /dev/null
+++ b/pkgs/jni/lib/src/lang/jfloat.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../accessors.dart';
+import '../jni.dart';
+import '../jvalues.dart';
+import '../third_party/generated_bindings.dart';
+import '../types.dart';
+import 'jnumber.dart';
+
+final class JFloatType extends JObjType<JFloat> {
+ const JFloatType();
+
+ @override
+ String get signature => r"Ljava/lang/Float;";
+
+ @override
+ JFloat fromRef(JObjectPtr ref) => JFloat.fromRef(ref);
+
+ @override
+ JObjType get superType => const JNumberType();
+
+ @override
+ final superCount = 2;
+
+ @override
+ int get hashCode => (JFloatType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == JFloatType && other is JFloatType;
+ }
+}
+
+class JFloat extends JNumber {
+ @override
+ // ignore: overridden_fields
+ late final JObjType<JFloat> $type = type;
+
+ JFloat.fromRef(
+ JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = JFloatType();
+
+ static final _class = Jni.findJClass(r"java/lang/Float");
+
+ static final _ctorId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"(F)V");
+
+ JFloat(double num)
+ : super.fromRef(Jni.accessors.newObjectWithArgs(
+ _class.reference, _ctorId, [JValueFloat(num)]).object);
+}
diff --git a/pkgs/jni/lib/src/lang/jinteger.dart b/pkgs/jni/lib/src/lang/jinteger.dart
new file mode 100644
index 0000000..8ece466
--- /dev/null
+++ b/pkgs/jni/lib/src/lang/jinteger.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../accessors.dart';
+import '../jni.dart';
+import '../jvalues.dart';
+import '../third_party/generated_bindings.dart';
+import '../types.dart';
+import 'jnumber.dart';
+
+final class JIntegerType extends JObjType<JInteger> {
+ const JIntegerType();
+
+ @override
+ String get signature => r"Ljava/lang/Integer;";
+
+ @override
+ JInteger fromRef(JObjectPtr ref) => JInteger.fromRef(ref);
+
+ @override
+ JObjType get superType => const JNumberType();
+
+ @override
+ final superCount = 2;
+
+ @override
+ int get hashCode => (JIntegerType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == JIntegerType && other is JIntegerType;
+ }
+}
+
+class JInteger extends JNumber {
+ @override
+ // ignore: overridden_fields
+ late final JObjType<JInteger> $type = type;
+
+ JInteger.fromRef(
+ JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = JIntegerType();
+
+ static final _class = Jni.findJClass(r"java/lang/Integer");
+
+ static final _ctorId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"(I)V");
+
+ JInteger(int num)
+ : super.fromRef(Jni.accessors.newObjectWithArgs(
+ _class.reference, _ctorId, [JValueInt(num)]).object);
+}
diff --git a/pkgs/jni/lib/src/lang/jlong.dart b/pkgs/jni/lib/src/lang/jlong.dart
new file mode 100644
index 0000000..66d054b
--- /dev/null
+++ b/pkgs/jni/lib/src/lang/jlong.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../accessors.dart';
+import '../jni.dart';
+import '../third_party/generated_bindings.dart';
+import '../types.dart';
+import 'jnumber.dart';
+
+final class JLongType extends JObjType<JLong> {
+ const JLongType();
+
+ @override
+ String get signature => r"Ljava/lang/Long;";
+
+ @override
+ JLong fromRef(JObjectPtr ref) => JLong.fromRef(ref);
+
+ @override
+ JObjType get superType => const JNumberType();
+
+ @override
+ final superCount = 2;
+
+ @override
+ int get hashCode => (JLongType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == JLongType && other is JLongType;
+ }
+}
+
+class JLong extends JNumber {
+ @override
+ // ignore: overridden_fields
+ late final JObjType<JLong> $type = type;
+
+ JLong.fromRef(
+ JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = JLongType();
+
+ static final _class = Jni.findJClass(r"java/lang/Long");
+
+ static final _ctorId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"(J)V");
+
+ JLong(int num)
+ : super.fromRef(Jni.accessors
+ .newObjectWithArgs(_class.reference, _ctorId, [num]).object);
+}
diff --git a/pkgs/jni/lib/src/lang/jnumber.dart b/pkgs/jni/lib/src/lang/jnumber.dart
new file mode 100644
index 0000000..45d86dc
--- /dev/null
+++ b/pkgs/jni/lib/src/lang/jnumber.dart
@@ -0,0 +1,158 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../accessors.dart';
+import '../jni.dart';
+import '../jobject.dart';
+import '../jreference.dart';
+import '../third_party/generated_bindings.dart';
+import '../types.dart';
+import 'jboolean.dart';
+import 'jbyte.dart';
+import 'jcharacter.dart';
+import 'jdouble.dart';
+import 'jfloat.dart';
+import 'jinteger.dart';
+import 'jlong.dart';
+import 'jshort.dart';
+
+final class JNumberType extends JObjType<JNumber> {
+ const JNumberType();
+
+ @override
+ String get signature => r"Ljava/lang/Number;";
+
+ @override
+ JNumber fromRef(JObjectPtr ref) => JNumber.fromRef(ref);
+
+ @override
+ JObjType get superType => const JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => (JNumberType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == JNumberType && other is JNumberType;
+ }
+}
+
+class JNumber extends JObject {
+ @override
+ // ignore: overridden_fields
+ late final JObjType<JNumber> $type = type;
+
+ JNumber.fromRef(
+ JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = Jni.findJClass(r"java/lang/Number");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = JNumberType();
+ static final _ctorId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ JNumber()
+ : super.fromRef(Jni.accessors
+ .newObjectWithArgs(_class.reference, _ctorId, []).object);
+
+ static final _intValueId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"intValue", r"()I");
+
+ int intValue({bool releaseOriginal = false}) {
+ ensureNotNull();
+ final ret = Jni.accessors.callMethodWithArgs(
+ reference, _intValueId, JniCallType.intType, []).integer;
+ if (releaseOriginal) {
+ release();
+ }
+ return ret;
+ }
+
+ static final _longValueId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"longValue", r"()J");
+
+ int longValue({bool releaseOriginal = false}) {
+ ensureNotNull();
+ final ret = Jni.accessors.callMethodWithArgs(
+ reference, _longValueId, JniCallType.longType, []).long;
+ if (releaseOriginal) {
+ release();
+ }
+ return ret;
+ }
+
+ static final _floatValueId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"floatValue", r"()F");
+
+ double floatValue({bool releaseOriginal = false}) {
+ ensureNotNull();
+ final ret = Jni.accessors.callMethodWithArgs(
+ reference, _floatValueId, JniCallType.floatType, []).float;
+ if (releaseOriginal) {
+ release();
+ }
+ return ret;
+ }
+
+ static final _doubleValueId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"doubleValue", r"()D");
+
+ double doubleValue({bool releaseOriginal = false}) {
+ ensureNotNull();
+ final ret = Jni.accessors.callMethodWithArgs(
+ reference, _doubleValueId, JniCallType.doubleType, []).doubleFloat;
+ if (releaseOriginal) {
+ release();
+ }
+ return ret;
+ }
+
+ static final _byteValueId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"byteValue", r"()B");
+
+ int byteValue({bool releaseOriginal = false}) {
+ ensureNotNull();
+ final ret = Jni.accessors.callMethodWithArgs(
+ reference, _byteValueId, JniCallType.byteType, []).byte;
+ if (releaseOriginal) {
+ release();
+ }
+ return ret;
+ }
+
+ static final _shortValueId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"shortValue", r"()S");
+
+ int shortValue({bool releaseOriginal = false}) {
+ ensureNotNull();
+ final ret = Jni.accessors.callMethodWithArgs(
+ reference, _shortValueId, JniCallType.shortType, []).short;
+ if (releaseOriginal) {
+ release();
+ }
+ return ret;
+ }
+}
+
+extension IntToJava on int {
+ JByte toJByte() => JByte(this);
+ JShort toJShort() => JShort(this);
+ JInteger toJInteger() => JInteger(this);
+ JLong toJLong() => JLong(this);
+ JCharacter toJCharacter() => JCharacter(this);
+}
+
+extension DoubleToJava on double {
+ JFloat toJFloat() => JFloat(this);
+ JDouble toJDouble() => JDouble(this);
+}
+
+extension BoolToJava on bool {
+ JBoolean toJBoolean() => JBoolean(this);
+}
diff --git a/pkgs/jni/lib/src/lang/jshort.dart b/pkgs/jni/lib/src/lang/jshort.dart
new file mode 100644
index 0000000..39d3c1d
--- /dev/null
+++ b/pkgs/jni/lib/src/lang/jshort.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../accessors.dart';
+import '../jni.dart';
+import '../jvalues.dart';
+import '../third_party/generated_bindings.dart';
+import '../types.dart';
+import 'jnumber.dart';
+
+final class JShortType extends JObjType<JShort> {
+ const JShortType();
+
+ @override
+ String get signature => r"Ljava/lang/Short;";
+
+ @override
+ JShort fromRef(JObjectPtr ref) => JShort.fromRef(ref);
+
+ @override
+ JObjType get superType => const JNumberType();
+
+ @override
+ final superCount = 2;
+
+ @override
+ int get hashCode => (JShortType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == JShortType && other is JShortType;
+ }
+}
+
+class JShort extends JNumber {
+ @override
+ // ignore: overridden_fields
+ late final JObjType<JShort> $type = type;
+
+ JShort.fromRef(
+ JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = JShortType();
+
+ static final _class = Jni.findJClass(r"java/lang/Short");
+
+ static final _ctorId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"(S)V");
+
+ JShort(int num)
+ : super.fromRef(Jni.accessors.newObjectWithArgs(
+ _class.reference, _ctorId, [JValueShort(num)]).object);
+}
diff --git a/pkgs/jni/lib/src/lang/jstring.dart b/pkgs/jni/lib/src/lang/jstring.dart
new file mode 100644
index 0000000..9b8fbbb
--- /dev/null
+++ b/pkgs/jni/lib/src/lang/jstring.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+
+import 'package:jni/src/jreference.dart';
+
+import '../jni.dart';
+import '../jobject.dart';
+import '../third_party/generated_bindings.dart';
+import '../types.dart';
+
+final class JStringType extends JObjType<JString> {
+ const JStringType();
+
+ @override
+ String get signature => "Ljava/lang/String;";
+
+ @override
+ JString fromRef(Pointer<Void> ref) => JString.fromRef(ref);
+
+ @override
+ JObjType get superType => const JObjectType();
+
+ @override
+ final int superCount = 1;
+
+ @override
+ int get hashCode => (JStringType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == JStringType && other is JStringType;
+ }
+}
+
+class JString extends JObject {
+ @override
+ // ignore: overridden_fields
+ late final JObjType<JString> $type = type;
+
+ /// The type which includes information such as the signature of this class.
+ static const JObjType<JString> type = JStringType();
+
+ /// Construct a new [JString] with [reference] as its underlying reference.
+ JString.fromRef(JStringPtr reference) : super.fromRef(reference);
+
+ /// The number of Unicode characters in this Java string.
+ int get length => Jni.env.GetStringLength(reference);
+
+ /// Construct a [JString] from the contents of Dart string [s].
+ JString.fromString(String s) : super.fromRef(Jni.env.toJStringPtr(s));
+
+ /// Returns the contents as a Dart String.
+ ///
+ /// If [releaseOriginal] is true, the underlying reference is deleted
+ /// after conversion and this object will be marked as released.
+ String toDartString({bool releaseOriginal = false}) {
+ ensureNotNull();
+ final result = Jni.env.toDartString(reference);
+ if (releaseOriginal) {
+ release();
+ }
+ return result;
+ }
+}
+
+extension ToJStringMethod on String {
+ /// Returns a [JString] with the contents of this String.
+ JString toJString() {
+ return JString.fromString(this);
+ }
+}
diff --git a/pkgs/jni/lib/src/lang/lang.dart b/pkgs/jni/lib/src/lang/lang.dart
new file mode 100644
index 0000000..786488c
--- /dev/null
+++ b/pkgs/jni/lib/src/lang/lang.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'jboolean.dart';
+export 'jbyte.dart';
+export 'jcharacter.dart';
+export 'jdouble.dart';
+export 'jfloat.dart';
+export 'jinteger.dart';
+export 'jlong.dart';
+export 'jnumber.dart';
+export 'jshort.dart';
+export 'jstring.dart';
diff --git a/pkgs/jni/lib/src/method_invocation.dart b/pkgs/jni/lib/src/method_invocation.dart
new file mode 100644
index 0000000..69cdc4a
--- /dev/null
+++ b/pkgs/jni/lib/src/method_invocation.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+
+import 'third_party/generated_bindings.dart';
+
+import 'lang/jstring.dart';
+import 'jarray.dart';
+import 'jobject.dart';
+
+class $MethodInvocation {
+ final Pointer<CallbackResult> result;
+ final JString methodDescriptor;
+ final JArray<JObject> args;
+
+ $MethodInvocation._(this.result, this.methodDescriptor, this.args);
+
+ factory $MethodInvocation.fromAddresses(
+ int resultAddress,
+ int descriptorAddress,
+ int argsAddress,
+ ) {
+ return $MethodInvocation._(
+ Pointer<CallbackResult>.fromAddress(resultAddress),
+ JString.fromRef(Pointer<Void>.fromAddress(descriptorAddress)),
+ JArray.fromRef(
+ const JObjectType(),
+ Pointer<Void>.fromAddress(argsAddress),
+ ),
+ );
+ }
+
+ factory $MethodInvocation.fromMessage(List<dynamic> message) {
+ return $MethodInvocation.fromAddresses(message[0], message[1], message[2]);
+ }
+}
diff --git a/pkgs/jni/lib/src/nio/jbuffer.dart b/pkgs/jni/lib/src/nio/jbuffer.dart
new file mode 100644
index 0000000..cae6bc9
--- /dev/null
+++ b/pkgs/jni/lib/src/nio/jbuffer.dart
@@ -0,0 +1,255 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../accessors.dart';
+import '../jni.dart';
+import '../jobject.dart';
+import '../jvalues.dart';
+import '../third_party/generated_bindings.dart';
+import '../types.dart';
+
+final class JBufferType extends JObjType<JBuffer> {
+ const JBufferType();
+
+ @override
+ String get signature => r"Ljava/nio/Buffer;";
+
+ @override
+ JBuffer fromRef(JObjectPtr ref) => JBuffer.fromRef(ref);
+
+ @override
+ JObjType get superType => const JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => (JBufferType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == (JBufferType) && other is JBufferType;
+ }
+}
+
+/// A container for data of a specific primitive type.
+///
+/// The bindings for `java.nio.Buffer`.
+///
+/// A buffer is a linear, finite sequence of elements of a specific primitive
+/// type. Aside from its content, the essential properties of a buffer are its
+/// [capacity], [limit], and [position].
+///
+/// There is one subclass of this class for each non-boolean primitive type.
+/// We currently only have the bindings for `java.nio.ByteBuffer` in this
+/// package as [JByteBuffer].
+class JBuffer extends JObject {
+ @override
+ // ignore: overridden_fields
+ late final JObjType<JBuffer> $type = type;
+
+ JBuffer.fromRef(
+ JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = Jni.findJClass(r"java/nio/Buffer");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = JBufferType();
+
+ static final _capacityId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"capacity", r"()I");
+
+ /// The number of elements this buffer contains.
+ ///
+ /// It is never negative and never changes.
+ int get capacity {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _capacityId, JniCallType.intType, []).integer;
+ }
+
+ static final _positionId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"position", r"()I");
+
+ /// The index of the next element to be read or written.
+ ///
+ /// It is never negative and is never greater than its [limit].
+ int get position {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _positionId, JniCallType.intType, []).integer;
+ }
+
+ static final _setPositionId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"position", r"(I)Ljava/nio/Buffer;");
+
+ /// Throws:
+ /// * [IllegalArgumentException] - If the preconditions on [newPosition] do
+ /// not hold.
+ set position(int position) {
+ Jni.env.DeleteGlobalRef(Jni.accessors.callMethodWithArgs(reference,
+ _setPositionId, JniCallType.objectType, [JValueInt(position)]).object);
+ }
+
+ static final _limitId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"limit", r"()I");
+
+ /// The index of the first element that should not be read or written.
+ ///
+ /// It is never negative and is never greater than its [capacity].
+ int get limit {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _limitId, JniCallType.intType, []).integer;
+ }
+
+ static final _setLimitId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"limit", r"(I)Ljava/nio/Buffer;");
+
+ /// Throws:
+ /// * [IllegalArgumentException] - If the preconditions on [newLimit] do not
+ /// hold.
+ set limit(int newLimit) {
+ Jni.env.DeleteGlobalRef(Jni.accessors.callMethodWithArgs(reference,
+ _setLimitId, JniCallType.objectType, [JValueInt(newLimit)]).object);
+ }
+
+ static final _markId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"mark", r"()Ljava/nio/Buffer;");
+
+ /// Sets this buffer's mark at its [position].
+ ///
+ /// Mark is the index to which its [position] will be reset when the [reset]
+ /// method is invoked.
+ void mark() {
+ Jni.env.DeleteGlobalRef(Jni.accessors.callMethodWithArgs(
+ reference, _markId, JniCallType.objectType, []).object);
+ }
+
+ static final _resetId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"reset", r"()Ljava/nio/Buffer;");
+
+ /// Resets this buffer's [position] to the previously-marked position.
+ ///
+ /// Throws:
+ /// * [InvalidMarkException] - If the mark has not been set
+ void reset() {
+ Jni.env.DeleteGlobalRef(Jni.accessors.callMethodWithArgs(
+ reference, _resetId, JniCallType.objectType, []).object);
+ }
+
+ static final _clearId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"clear", r"()Ljava/nio/Buffer;");
+
+ /// Clears this buffer.
+ ///
+ /// The [position] is set to zero, the [limit] is set to
+ /// the [capacity], and the mark is discarded.
+ void clear() {
+ Jni.env.DeleteGlobalRef(Jni.accessors.callMethodWithArgs(
+ reference, _clearId, JniCallType.objectType, []).object);
+ }
+
+ static final _flipId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"flip", r"()Ljava/nio/Buffer;");
+
+ /// Flips this buffer.
+ ///
+ /// The limit is set to the current [position] and then the [position] is set
+ /// to zero. If the mark is defined then it is discarded.
+ void flip() {
+ Jni.env.DeleteGlobalRef(Jni.accessors.callMethodWithArgs(
+ reference, _flipId, JniCallType.objectType, []).object);
+ }
+
+ static final _rewindId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"rewind", r"()Ljava/nio/Buffer;");
+
+ /// Rewinds this buffer.
+ ///
+ /// The [position] is set to zero and the mark is discarded.
+ void rewind() {
+ Jni.env.DeleteGlobalRef(Jni.accessors.callMethodWithArgs(
+ reference, _rewindId, JniCallType.objectType, []).object);
+ }
+
+ static final _remainingId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"remaining", r"()I");
+
+ /// The number of elements between the current [position] and the
+ /// [limit].
+ int get remaining {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _remainingId, JniCallType.intType, []).integer;
+ }
+
+ static final _hasRemainingId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"hasRemaining", r"()Z");
+
+ /// Whether there are any elements between the current [position] and
+ /// the [limit].
+ bool get hasRemaining {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _hasRemainingId, JniCallType.booleanType, []).boolean;
+ }
+
+ static final _isReadOnlyId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"isReadOnly", r"()Z");
+
+ /// Whether or not this buffer is read-only.
+ bool get isReadOnly {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _isReadOnlyId, JniCallType.booleanType, []).boolean;
+ }
+
+ static final _hasArrayId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"hasArray", r"()Z");
+
+ /// Whether or not this buffer is backed by an accessible array.
+ bool get hasArray {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _hasArrayId, JniCallType.booleanType, []).boolean;
+ }
+
+ static final _arrayId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"array", r"()Ljava/lang/Object;");
+
+ /// The array that backs this buffer.
+ ///
+ /// Concrete subclasses like [JByteBuffer] provide more strongly-typed return
+ /// values for this method.
+ ///
+ /// Throws:
+ /// * [ReadOnlyBufferException] - If this buffer is backed by an array but is
+ /// read-only
+ /// * [UnsupportedOperationException] - If this buffer is not backed by an
+ /// accessible array
+ JObject get array {
+ return const JObjectType().fromRef(Jni.accessors.callMethodWithArgs(
+ reference, _arrayId, JniCallType.objectType, []).object);
+ }
+
+ static final _arrayOffsetId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"arrayOffset", r"()I");
+
+ /// The offset within this buffer's backing array of the first element
+ /// of the buffer.
+ ///
+ /// Throws:
+ /// * [ReadOnlyBufferException] - If this buffer is backed by an array but is
+ /// read-only
+ /// * [UnsupportedOperationException] - If this buffer is not backed by an
+ /// accessible array
+ int get arrayOffset {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _arrayOffsetId, JniCallType.intType, []).integer;
+ }
+
+ static final _isDirectId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"isDirect", r"()Z");
+
+ /// Whether or not this buffer is direct.
+ bool get isDirect {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _isDirectId, JniCallType.booleanType, []).boolean;
+ }
+}
diff --git a/pkgs/jni/lib/src/nio/jbyte_buffer.dart b/pkgs/jni/lib/src/nio/jbyte_buffer.dart
new file mode 100644
index 0000000..d5f5488
--- /dev/null
+++ b/pkgs/jni/lib/src/nio/jbyte_buffer.dart
@@ -0,0 +1,315 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+import 'dart:typed_data';
+
+import '../accessors.dart';
+import '../jarray.dart';
+import '../jni.dart';
+import '../jreference.dart';
+import '../jvalues.dart';
+import '../third_party/generated_bindings.dart';
+import '../types.dart';
+import 'jbuffer.dart';
+
+final class JByteBufferType extends JObjType<JByteBuffer> {
+ const JByteBufferType();
+
+ @override
+ String get signature => r"Ljava/nio/ByteBuffer;";
+
+ @override
+ JByteBuffer fromRef(JObjectPtr ref) => JByteBuffer.fromRef(ref);
+
+ @override
+ JObjType get superType => const JBufferType();
+
+ @override
+ final superCount = 2;
+
+ @override
+ int get hashCode => (JByteBufferType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == (JByteBufferType) && other is JByteBufferType;
+ }
+}
+
+/// A byte [JBuffer].
+///
+/// The bindings for `java.nio.ByteBuffer`.
+///
+/// This enables fast memory copying between Java and Dart when directly
+/// allocated (See [JByteBuffer.allocateDirect]).
+///
+/// To create a [JByteBuffer] from the content of a [Uint8List],
+/// use [JByteBuffer.fromList]. This uses direct allocation to enable fast
+/// copying.
+///
+/// [asUint8List] provides a direct access to the underlying [Uint8List] that
+/// this buffer uses. This means any changes to it will change the content of
+/// the buffer and vice versa. This can be used to access to [Uint8List] methods
+/// such as [Uint8List.setRange].
+///
+/// Example:
+/// ```dart
+/// final directBuffer = JByteBuffer.allocateDirect(3);
+/// directBuffer.asUint8List().setAll(0, [1, 2, 3]);
+/// // The buffer is now 1, 2, 3.
+/// ```
+///
+/// Both the original buffer and the [Uint8List] keep the underlying Java buffer
+/// alive. Once all the instances of the original buffer and the lists produced
+/// from [asUint8List] are inaccessible both in Java and Dart, Java will
+/// correctly garbage collects the buffer and frees its underlying memory.
+///
+/// Example:
+/// ```dart
+/// final directBuffer = JByteBuffer.allocateDirect(3);
+/// final data = directBuffer.asUint8List();
+/// directBuffer.release(); // Releasing the original buffer.
+/// data.setAll(0, [1, 2, 3]); // Works! [data] is still accessible.
+/// ```
+///
+/// The original buffer can be [release]d when calling [asUint8List]
+/// by setting the `releaseOriginal` parameter to `true`.
+///
+/// Example:
+/// ```dart
+/// final directBuffer = JByteBuffer.allocateDirect(3);
+/// // [releaseOriginal] is `false` by default.
+/// final data1 = directBuffer.asUint8List();
+/// directBuffer.nextByte = 42; // No problem!
+/// print(data1[0]); // prints 42!
+/// final data2 = directBuffer.asUint8List(releaseOriginal: true);
+/// // directBuffer.nextByte = 42; // throws [UseAfterReleaseException]!
+/// ```
+class JByteBuffer extends JBuffer {
+ @override
+ // ignore: overridden_fields
+ late final JObjType<JByteBuffer> $type = type;
+
+ JByteBuffer.fromRef(
+ JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = Jni.findJClass(r"java/nio/ByteBuffer");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = JByteBufferType();
+
+ static final _allocateDirectId = Jni.accessors.getStaticMethodIDOf(
+ _class.reference, r"allocateDirect", r"(I)Ljava/nio/ByteBuffer;");
+
+ /// Allocates a new direct byte buffer.
+ ///
+ /// Throws:
+ /// * [IllegalArgumentException] - If the capacity is a negative integer
+ factory JByteBuffer.allocateDirect(int capacity) {
+ return JByteBuffer.fromRef(
+ Jni.accessors.callStaticMethodWithArgs(
+ _class.reference,
+ _allocateDirectId,
+ JniCallType.objectType,
+ [JValueInt(capacity)]).object,
+ );
+ }
+
+ static final _allocateId = Jni.accessors.getStaticMethodIDOf(
+ _class.reference, r"allocate", r"(I)Ljava/nio/ByteBuffer;");
+
+ /// Allocates a new byte buffer.
+ ///
+ /// Throws:
+ /// * [IllegalArgumentException] - If the capacity is a negative integer
+ factory JByteBuffer.allocate(int capacity) {
+ return const JByteBufferType().fromRef(Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _allocateId,
+ JniCallType.objectType, [JValueInt(capacity)]).object);
+ }
+
+ static final _wrapWholeId = Jni.accessors.getStaticMethodIDOf(
+ _class.reference, r"wrap", r"([B)Ljava/nio/ByteBuffer;");
+ static final _wrapId = Jni.accessors.getStaticMethodIDOf(
+ _class.reference, r"wrap", r"([BII)Ljava/nio/ByteBuffer;");
+
+ /// Wraps a byte array into a buffer.
+ ///
+ /// The new buffer will be backed by the given byte array; that is,
+ /// modifications to the buffer will cause the array to be modified
+ /// and vice versa.
+ static JByteBuffer wrap(
+ JArray<jbyte> array, [
+ int? offset,
+ int? length,
+ ]) {
+ if (offset == null && length == null) {
+ return const JByteBufferType().fromRef(
+ Jni.accessors.callStaticMethodWithArgs(
+ _class.reference,
+ _wrapWholeId,
+ JniCallType.objectType,
+ [array.reference],
+ ).object,
+ );
+ }
+ offset ??= 0;
+ length ??= array.length - offset;
+ return const JByteBufferType().fromRef(
+ Jni.accessors.callStaticMethodWithArgs(
+ _class.reference,
+ _wrapId,
+ JniCallType.objectType,
+ [array.reference, JValueInt(offset), JValueInt(length)],
+ ).object,
+ );
+ }
+
+ /// Creates a [JByteBuffer] from the content of [list].
+ ///
+ /// The [JByteBuffer] will be allocated using [JByteBuffer.allocateDirect].
+ factory JByteBuffer.fromList(Uint8List list) {
+ final buffer = JByteBuffer.allocateDirect(list.length);
+ buffer._asUint8ListUnsafe().setAll(0, list);
+ return buffer;
+ }
+
+ static final _sliceId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"slice", r"()Ljava/nio/ByteBuffer;");
+
+ /// Creates a new byte buffer whose content is a shared subsequence of this
+ /// buffer's content.
+ JByteBuffer slice() {
+ return const JByteBufferType().fromRef(Jni.accessors.callMethodWithArgs(
+ reference, _sliceId, JniCallType.objectType, []).object);
+ }
+
+ static final _duplicateId = Jni.accessors.getMethodIDOf(
+ _class.reference, r"duplicate", r"()Ljava/nio/ByteBuffer;");
+
+ /// Creates a new byte buffer that shares this buffer's content.
+ JByteBuffer duplicate() {
+ return const JByteBufferType().fromRef(Jni.accessors.callMethodWithArgs(
+ reference, _duplicateId, JniCallType.objectType, []).object);
+ }
+
+ static final _asReadOnlyBufferId = Jni.accessors.getMethodIDOf(
+ _class.reference, r"asReadOnlyBuffer", r"()Ljava/nio/ByteBuffer;");
+
+ /// Creates a new, read-only byte buffer that shares this buffer's content.
+ JByteBuffer asReadOnlyBuffer() {
+ return const JByteBufferType().fromRef(Jni.accessors.callMethodWithArgs(
+ reference, _asReadOnlyBufferId, JniCallType.objectType, []).object);
+ }
+
+ static final _getId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"get", r"()B");
+
+ /// Reads the byte at this buffer's current [position], and then increments the
+ /// [position].
+ ///
+ /// Throws:
+ /// * [BufferOverflowException] - If the buffer's current [position] is not
+ /// smaller than its [limit]
+ int get nextByte {
+ return Jni.accessors
+ .callMethodWithArgs(reference, _getId, JniCallType.byteType, []).byte;
+ }
+
+ static final _putId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"put", r"(B)Ljava/nio/ByteBuffer;");
+
+ /// Writes the given byte into this buffer at the current [position], and then
+ /// increments the [position].
+ ///
+ /// Throws:
+ /// * [BufferOverflowException] - If this buffer's current [position] is not
+ /// smaller than its [limit]
+ /// * [ReadOnlyBufferException] - If this buffer is read-only
+ set nextByte(int b) {
+ Jni.env.DeleteGlobalRef(Jni.accessors.callMethodWithArgs(
+ reference, _putId, JniCallType.objectType, [JValueByte(b)]).object);
+ }
+
+ static final _arrayId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"array", r"()[B");
+
+ @override
+ JArray<jbyte> get array {
+ return const JArrayType(jbyteType()).fromRef(Jni.accessors
+ .callMethodWithArgs(
+ reference, _arrayId, JniCallType.objectType, []).object);
+ }
+
+ void _ensureIsDirect() {
+ if (!isDirect) {
+ throw StateError(
+ 'The buffer must be created with `JByteBuffer.allocateDirect`.',
+ );
+ }
+ }
+
+ Pointer<Void> _directBufferAddress() {
+ final address = Jni.env.GetDirectBufferAddress(reference);
+ if (address == nullptr) {
+ throw StateError(
+ 'The memory region is undefined or '
+ 'direct buffer access is not supported by this JVM.',
+ );
+ }
+ return address;
+ }
+
+ int _directBufferCapacity() {
+ final capacity = Jni.env.GetDirectBufferCapacity(reference);
+ if (capacity == -1) {
+ throw StateError(
+ 'The object is an unaligned view buffer and the processor '
+ 'architecture does not support unaligned access.',
+ );
+ }
+ return capacity;
+ }
+
+ Uint8List _asUint8ListUnsafe() {
+ _ensureIsDirect();
+ final address = _directBufferAddress();
+ final capacity = _directBufferCapacity();
+ return address.cast<Uint8>().asTypedList(capacity);
+ }
+
+ /// Returns this byte buffer as a [Uint8List].
+ ///
+ /// If [releaseOriginal] is `true`, this byte buffer will be released.
+ ///
+ /// Throws [StateError] if the buffer is not direct
+ /// (see [JByteBuffer.allocateDirect]) or the JVM does not support the direct
+ /// buffer operations or the object is an unaligned view buffer and
+ /// the processor does not support unaligned access.
+ Uint8List asUint8List({bool releaseOriginal = false}) {
+ _ensureIsDirect();
+ final address = _directBufferAddress();
+ final capacity = _directBufferCapacity();
+ final token = releaseOriginal ? reference : Jni.env.NewGlobalRef(reference);
+ if (releaseOriginal) {
+ setAsReleased();
+ }
+ return address.cast<Uint8>().asTypedList(
+ capacity,
+ token: token,
+ finalizer: Jni.env.ptr.ref.DeleteGlobalRef.cast(),
+ );
+ }
+}
+
+extension Uint8ListToJava on Uint8List {
+ /// Creates a [JByteBuffer] from the content of this list.
+ ///
+ /// The [JByteBuffer] will be allocated using [JByteBuffer.allocateDirect].
+ JByteBuffer toJByteBuffer() {
+ return JByteBuffer.fromList(this);
+ }
+}
diff --git a/pkgs/jni/lib/src/nio/nio.dart b/pkgs/jni/lib/src/nio/nio.dart
new file mode 100644
index 0000000..3092870
--- /dev/null
+++ b/pkgs/jni/lib/src/nio/nio.dart
@@ -0,0 +1,6 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'jbuffer.dart';
+export 'jbyte_buffer.dart';
diff --git a/pkgs/jni/lib/src/third_party/generated_bindings.dart b/pkgs/jni/lib/src/third_party/generated_bindings.dart
new file mode 100644
index 0000000..6047975
--- /dev/null
+++ b/pkgs/jni/lib/src/third_party/generated_bindings.dart
@@ -0,0 +1,2 @@
+export 'jni_bindings_generated.dart';
+export 'global_env_extensions.dart';
diff --git a/pkgs/jni/lib/src/third_party/global_env_extensions.dart b/pkgs/jni/lib/src/third_party/global_env_extensions.dart
new file mode 100644
index 0000000..2fe4001
--- /dev/null
+++ b/pkgs/jni/lib/src/third_party/global_env_extensions.dart
@@ -0,0 +1,1514 @@
+// Auto generated file. Do not edit.
+
+// This is generated from JNI header in Android NDK. License for the same is
+// provided below.
+
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * JNI specification, as defined by Sun:
+ * http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html
+ *
+ * Everything here is expected to be VM-neutral.
+ */
+
+// ignore_for_file: non_constant_identifier_names
+// coverage:ignore-file
+
+import "dart:ffi" as ffi;
+
+import "jni_bindings_generated.dart";
+
+import "../accessors.dart";
+
+/// Wraps over Pointer<GlobalJniEnvStruct> and exposes function pointer fields
+/// as methods.
+class GlobalJniEnv {
+ final ffi.Pointer<GlobalJniEnvStruct> ptr;
+ GlobalJniEnv(this.ptr);
+ late final _GetVersion =
+ ptr.ref.GetVersion.asFunction<JniResult Function()>();
+
+ int GetVersion() => _GetVersion().integer;
+
+ late final _DefineClass = ptr.ref.DefineClass.asFunction<
+ JniClassLookupResult Function(ffi.Pointer<ffi.Char> name,
+ JObjectPtr loader, ffi.Pointer<JByteMarker> buf, int bufLen)>();
+
+ JClassPtr DefineClass(ffi.Pointer<ffi.Char> name, JObjectPtr loader,
+ ffi.Pointer<JByteMarker> buf, int bufLen) =>
+ _DefineClass(name, loader, buf, bufLen).value;
+
+ late final _FindClass = ptr.ref.FindClass
+ .asFunction<JniClassLookupResult Function(ffi.Pointer<ffi.Char> name)>();
+
+ JClassPtr FindClass(ffi.Pointer<ffi.Char> name) => _FindClass(name).value;
+
+ late final _FromReflectedMethod = ptr.ref.FromReflectedMethod
+ .asFunction<JniPointerResult Function(JObjectPtr method)>();
+
+ JMethodIDPtr FromReflectedMethod(JObjectPtr method) =>
+ _FromReflectedMethod(method).methodID;
+
+ late final _FromReflectedField = ptr.ref.FromReflectedField
+ .asFunction<JniPointerResult Function(JObjectPtr field)>();
+
+ JFieldIDPtr FromReflectedField(JObjectPtr field) =>
+ _FromReflectedField(field).fieldID;
+
+ late final _ToReflectedMethod = ptr.ref.ToReflectedMethod.asFunction<
+ JniResult Function(JClassPtr cls, JMethodIDPtr methodId, int isStatic)>();
+
+ JObjectPtr ToReflectedMethod(
+ JClassPtr cls, JMethodIDPtr methodId, int isStatic) =>
+ _ToReflectedMethod(cls, methodId, isStatic).object;
+
+ late final _GetSuperclass = ptr.ref.GetSuperclass
+ .asFunction<JniClassLookupResult Function(JClassPtr clazz)>();
+
+ JClassPtr GetSuperclass(JClassPtr clazz) => _GetSuperclass(clazz).value;
+
+ late final _IsAssignableFrom = ptr.ref.IsAssignableFrom
+ .asFunction<JniResult Function(JClassPtr clazz1, JClassPtr clazz2)>();
+
+ bool IsAssignableFrom(JClassPtr clazz1, JClassPtr clazz2) =>
+ _IsAssignableFrom(clazz1, clazz2).boolean;
+
+ late final _ToReflectedField = ptr.ref.ToReflectedField.asFunction<
+ JniResult Function(JClassPtr cls, JFieldIDPtr fieldID, int isStatic)>();
+
+ JObjectPtr ToReflectedField(
+ JClassPtr cls, JFieldIDPtr fieldID, int isStatic) =>
+ _ToReflectedField(cls, fieldID, isStatic).object;
+
+ late final _Throw =
+ ptr.ref.Throw.asFunction<JniResult Function(JThrowablePtr obj)>();
+
+ int Throw(JThrowablePtr obj) => _Throw(obj).integer;
+
+ late final _ThrowNew = ptr.ref.ThrowNew.asFunction<
+ JniResult Function(JClassPtr clazz, ffi.Pointer<ffi.Char> message)>();
+
+ int ThrowNew(JClassPtr clazz, ffi.Pointer<ffi.Char> message) =>
+ _ThrowNew(clazz, message).integer;
+
+ late final _ExceptionOccurred =
+ ptr.ref.ExceptionOccurred.asFunction<JniResult Function()>();
+
+ JThrowablePtr ExceptionOccurred() => _ExceptionOccurred().object;
+
+ late final _ExceptionDescribe =
+ ptr.ref.ExceptionDescribe.asFunction<JThrowablePtr Function()>();
+
+ void ExceptionDescribe() => _ExceptionDescribe().check();
+
+ late final _ExceptionClear =
+ ptr.ref.ExceptionClear.asFunction<JThrowablePtr Function()>();
+
+ void ExceptionClear() => _ExceptionClear().check();
+
+ late final _FatalError = ptr.ref.FatalError
+ .asFunction<JThrowablePtr Function(ffi.Pointer<ffi.Char> msg)>();
+
+ void FatalError(ffi.Pointer<ffi.Char> msg) => _FatalError(msg).check();
+
+ late final _PushLocalFrame =
+ ptr.ref.PushLocalFrame.asFunction<JniResult Function(int capacity)>();
+
+ int PushLocalFrame(int capacity) => _PushLocalFrame(capacity).integer;
+
+ late final _PopLocalFrame =
+ ptr.ref.PopLocalFrame.asFunction<JniResult Function(JObjectPtr result)>();
+
+ JObjectPtr PopLocalFrame(JObjectPtr result) => _PopLocalFrame(result).object;
+
+ late final _NewGlobalRef =
+ ptr.ref.NewGlobalRef.asFunction<JniResult Function(JObjectPtr obj)>();
+
+ JObjectPtr NewGlobalRef(JObjectPtr obj) => _NewGlobalRef(obj).object;
+
+ late final _DeleteGlobalRef = ptr.ref.DeleteGlobalRef
+ .asFunction<JThrowablePtr Function(JObjectPtr globalRef)>();
+
+ void DeleteGlobalRef(JObjectPtr globalRef) =>
+ _DeleteGlobalRef(globalRef).check();
+
+ late final _DeleteLocalRef = ptr.ref.DeleteLocalRef
+ .asFunction<JThrowablePtr Function(JObjectPtr localRef)>();
+
+ void DeleteLocalRef(JObjectPtr localRef) => _DeleteLocalRef(localRef).check();
+
+ late final _IsSameObject = ptr.ref.IsSameObject
+ .asFunction<JniResult Function(JObjectPtr ref1, JObjectPtr ref2)>();
+
+ bool IsSameObject(JObjectPtr ref1, JObjectPtr ref2) =>
+ _IsSameObject(ref1, ref2).boolean;
+
+ late final _NewLocalRef =
+ ptr.ref.NewLocalRef.asFunction<JniResult Function(JObjectPtr obj)>();
+
+ JObjectPtr NewLocalRef(JObjectPtr obj) => _NewLocalRef(obj).object;
+
+ late final _EnsureLocalCapacity = ptr.ref.EnsureLocalCapacity
+ .asFunction<JniResult Function(int capacity)>();
+
+ int EnsureLocalCapacity(int capacity) =>
+ _EnsureLocalCapacity(capacity).integer;
+
+ late final _AllocObject =
+ ptr.ref.AllocObject.asFunction<JniResult Function(JClassPtr clazz)>();
+
+ JObjectPtr AllocObject(JClassPtr clazz) => _AllocObject(clazz).object;
+
+ late final _NewObject = ptr.ref.NewObject
+ .asFunction<JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ JObjectPtr NewObject(JClassPtr clazz, JMethodIDPtr methodID) =>
+ _NewObject(clazz, methodID).object;
+
+ late final _NewObjectA = ptr.ref.NewObjectA.asFunction<
+ JniResult Function(
+ JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ JObjectPtr NewObjectA(
+ JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _NewObjectA(clazz, methodID, args).object;
+
+ late final _GetObjectClass = ptr.ref.GetObjectClass
+ .asFunction<JniClassLookupResult Function(JObjectPtr obj)>();
+
+ JClassPtr GetObjectClass(JObjectPtr obj) => _GetObjectClass(obj).value;
+
+ late final _IsInstanceOf = ptr.ref.IsInstanceOf
+ .asFunction<JniResult Function(JObjectPtr obj, JClassPtr clazz)>();
+
+ bool IsInstanceOf(JObjectPtr obj, JClassPtr clazz) =>
+ _IsInstanceOf(obj, clazz).boolean;
+
+ late final _GetMethodID = ptr.ref.GetMethodID.asFunction<
+ JniPointerResult Function(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+ ffi.Pointer<ffi.Char> sig)>();
+
+ JMethodIDPtr GetMethodID(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+ ffi.Pointer<ffi.Char> sig) =>
+ _GetMethodID(clazz, name, sig).methodID;
+
+ late final _CallObjectMethod = ptr.ref.CallObjectMethod
+ .asFunction<JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>();
+
+ JObjectPtr CallObjectMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+ _CallObjectMethod(obj, methodID).object;
+
+ late final _CallObjectMethodA = ptr.ref.CallObjectMethodA.asFunction<
+ JniResult Function(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ JObjectPtr CallObjectMethodA(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallObjectMethodA(obj, methodID, args).object;
+
+ late final _CallBooleanMethod = ptr.ref.CallBooleanMethod
+ .asFunction<JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>();
+
+ bool CallBooleanMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+ _CallBooleanMethod(obj, methodID).boolean;
+
+ late final _CallBooleanMethodA = ptr.ref.CallBooleanMethodA.asFunction<
+ JniResult Function(
+ JObjectPtr obj, JMethodIDPtr methodId, ffi.Pointer<JValue> args)>();
+
+ bool CallBooleanMethodA(
+ JObjectPtr obj, JMethodIDPtr methodId, ffi.Pointer<JValue> args) =>
+ _CallBooleanMethodA(obj, methodId, args).boolean;
+
+ late final _CallByteMethod = ptr.ref.CallByteMethod
+ .asFunction<JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>();
+
+ int CallByteMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+ _CallByteMethod(obj, methodID).byte;
+
+ late final _CallByteMethodA = ptr.ref.CallByteMethodA.asFunction<
+ JniResult Function(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ int CallByteMethodA(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallByteMethodA(obj, methodID, args).byte;
+
+ late final _CallCharMethod = ptr.ref.CallCharMethod
+ .asFunction<JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>();
+
+ int CallCharMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+ _CallCharMethod(obj, methodID).char;
+
+ late final _CallCharMethodA = ptr.ref.CallCharMethodA.asFunction<
+ JniResult Function(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ int CallCharMethodA(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallCharMethodA(obj, methodID, args).char;
+
+ late final _CallShortMethod = ptr.ref.CallShortMethod
+ .asFunction<JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>();
+
+ int CallShortMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+ _CallShortMethod(obj, methodID).short;
+
+ late final _CallShortMethodA = ptr.ref.CallShortMethodA.asFunction<
+ JniResult Function(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ int CallShortMethodA(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallShortMethodA(obj, methodID, args).short;
+
+ late final _CallIntMethod = ptr.ref.CallIntMethod
+ .asFunction<JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>();
+
+ int CallIntMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+ _CallIntMethod(obj, methodID).integer;
+
+ late final _CallIntMethodA = ptr.ref.CallIntMethodA.asFunction<
+ JniResult Function(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ int CallIntMethodA(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallIntMethodA(obj, methodID, args).integer;
+
+ late final _CallLongMethod = ptr.ref.CallLongMethod
+ .asFunction<JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>();
+
+ int CallLongMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+ _CallLongMethod(obj, methodID).long;
+
+ late final _CallLongMethodA = ptr.ref.CallLongMethodA.asFunction<
+ JniResult Function(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ int CallLongMethodA(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallLongMethodA(obj, methodID, args).long;
+
+ late final _CallFloatMethod = ptr.ref.CallFloatMethod
+ .asFunction<JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>();
+
+ double CallFloatMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+ _CallFloatMethod(obj, methodID).float;
+
+ late final _CallFloatMethodA = ptr.ref.CallFloatMethodA.asFunction<
+ JniResult Function(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ double CallFloatMethodA(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallFloatMethodA(obj, methodID, args).float;
+
+ late final _CallDoubleMethod = ptr.ref.CallDoubleMethod
+ .asFunction<JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>();
+
+ double CallDoubleMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+ _CallDoubleMethod(obj, methodID).doubleFloat;
+
+ late final _CallDoubleMethodA = ptr.ref.CallDoubleMethodA.asFunction<
+ JniResult Function(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ double CallDoubleMethodA(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallDoubleMethodA(obj, methodID, args).doubleFloat;
+
+ late final _CallVoidMethod = ptr.ref.CallVoidMethod.asFunction<
+ JThrowablePtr Function(JObjectPtr obj, JMethodIDPtr methodID)>();
+
+ void CallVoidMethod(JObjectPtr obj, JMethodIDPtr methodID) =>
+ _CallVoidMethod(obj, methodID).check();
+
+ late final _CallVoidMethodA = ptr.ref.CallVoidMethodA.asFunction<
+ JThrowablePtr Function(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ void CallVoidMethodA(
+ JObjectPtr obj, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallVoidMethodA(obj, methodID, args).check();
+
+ late final _CallNonvirtualObjectMethod = ptr.ref.CallNonvirtualObjectMethod
+ .asFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ JObjectPtr CallNonvirtualObjectMethod(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallNonvirtualObjectMethod(obj, clazz, methodID).object;
+
+ late final _CallNonvirtualObjectMethodA = ptr.ref.CallNonvirtualObjectMethodA
+ .asFunction<
+ JniResult Function(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ JObjectPtr CallNonvirtualObjectMethodA(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallNonvirtualObjectMethodA(obj, clazz, methodID, args).object;
+
+ late final _CallNonvirtualBooleanMethod = ptr.ref.CallNonvirtualBooleanMethod
+ .asFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ bool CallNonvirtualBooleanMethod(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallNonvirtualBooleanMethod(obj, clazz, methodID).boolean;
+
+ late final _CallNonvirtualBooleanMethodA =
+ ptr.ref.CallNonvirtualBooleanMethodA.asFunction<
+ JniResult Function(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ bool CallNonvirtualBooleanMethodA(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallNonvirtualBooleanMethodA(obj, clazz, methodID, args).boolean;
+
+ late final _CallNonvirtualByteMethod = ptr.ref.CallNonvirtualByteMethod
+ .asFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ int CallNonvirtualByteMethod(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallNonvirtualByteMethod(obj, clazz, methodID).byte;
+
+ late final _CallNonvirtualByteMethodA = ptr.ref.CallNonvirtualByteMethodA
+ .asFunction<
+ JniResult Function(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ int CallNonvirtualByteMethodA(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallNonvirtualByteMethodA(obj, clazz, methodID, args).byte;
+
+ late final _CallNonvirtualCharMethod = ptr.ref.CallNonvirtualCharMethod
+ .asFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ int CallNonvirtualCharMethod(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallNonvirtualCharMethod(obj, clazz, methodID).char;
+
+ late final _CallNonvirtualCharMethodA = ptr.ref.CallNonvirtualCharMethodA
+ .asFunction<
+ JniResult Function(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ int CallNonvirtualCharMethodA(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallNonvirtualCharMethodA(obj, clazz, methodID, args).char;
+
+ late final _CallNonvirtualShortMethod = ptr.ref.CallNonvirtualShortMethod
+ .asFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ int CallNonvirtualShortMethod(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallNonvirtualShortMethod(obj, clazz, methodID).short;
+
+ late final _CallNonvirtualShortMethodA = ptr.ref.CallNonvirtualShortMethodA
+ .asFunction<
+ JniResult Function(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ int CallNonvirtualShortMethodA(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallNonvirtualShortMethodA(obj, clazz, methodID, args).short;
+
+ late final _CallNonvirtualIntMethod = ptr.ref.CallNonvirtualIntMethod
+ .asFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ int CallNonvirtualIntMethod(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallNonvirtualIntMethod(obj, clazz, methodID).integer;
+
+ late final _CallNonvirtualIntMethodA = ptr.ref.CallNonvirtualIntMethodA
+ .asFunction<
+ JniResult Function(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ int CallNonvirtualIntMethodA(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallNonvirtualIntMethodA(obj, clazz, methodID, args).integer;
+
+ late final _CallNonvirtualLongMethod = ptr.ref.CallNonvirtualLongMethod
+ .asFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ int CallNonvirtualLongMethod(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallNonvirtualLongMethod(obj, clazz, methodID).long;
+
+ late final _CallNonvirtualLongMethodA = ptr.ref.CallNonvirtualLongMethodA
+ .asFunction<
+ JniResult Function(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ int CallNonvirtualLongMethodA(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallNonvirtualLongMethodA(obj, clazz, methodID, args).long;
+
+ late final _CallNonvirtualFloatMethod = ptr.ref.CallNonvirtualFloatMethod
+ .asFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ double CallNonvirtualFloatMethod(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallNonvirtualFloatMethod(obj, clazz, methodID).float;
+
+ late final _CallNonvirtualFloatMethodA = ptr.ref.CallNonvirtualFloatMethodA
+ .asFunction<
+ JniResult Function(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ double CallNonvirtualFloatMethodA(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallNonvirtualFloatMethodA(obj, clazz, methodID, args).float;
+
+ late final _CallNonvirtualDoubleMethod = ptr.ref.CallNonvirtualDoubleMethod
+ .asFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ double CallNonvirtualDoubleMethod(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallNonvirtualDoubleMethod(obj, clazz, methodID).doubleFloat;
+
+ late final _CallNonvirtualDoubleMethodA = ptr.ref.CallNonvirtualDoubleMethodA
+ .asFunction<
+ JniResult Function(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ double CallNonvirtualDoubleMethodA(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallNonvirtualDoubleMethodA(obj, clazz, methodID, args).doubleFloat;
+
+ late final _CallNonvirtualVoidMethod = ptr.ref.CallNonvirtualVoidMethod
+ .asFunction<
+ JThrowablePtr Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ void CallNonvirtualVoidMethod(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallNonvirtualVoidMethod(obj, clazz, methodID).check();
+
+ late final _CallNonvirtualVoidMethodA = ptr.ref.CallNonvirtualVoidMethodA
+ .asFunction<
+ JThrowablePtr Function(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ void CallNonvirtualVoidMethodA(JObjectPtr obj, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallNonvirtualVoidMethodA(obj, clazz, methodID, args).check();
+
+ late final _GetFieldID = ptr.ref.GetFieldID.asFunction<
+ JniPointerResult Function(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+ ffi.Pointer<ffi.Char> sig)>();
+
+ JFieldIDPtr GetFieldID(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+ ffi.Pointer<ffi.Char> sig) =>
+ _GetFieldID(clazz, name, sig).fieldID;
+
+ late final _GetObjectField = ptr.ref.GetObjectField
+ .asFunction<JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>();
+
+ JObjectPtr GetObjectField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+ _GetObjectField(obj, fieldID).object;
+
+ late final _GetBooleanField = ptr.ref.GetBooleanField
+ .asFunction<JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>();
+
+ bool GetBooleanField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+ _GetBooleanField(obj, fieldID).boolean;
+
+ late final _GetByteField = ptr.ref.GetByteField
+ .asFunction<JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>();
+
+ int GetByteField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+ _GetByteField(obj, fieldID).byte;
+
+ late final _GetCharField = ptr.ref.GetCharField
+ .asFunction<JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>();
+
+ int GetCharField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+ _GetCharField(obj, fieldID).char;
+
+ late final _GetShortField = ptr.ref.GetShortField
+ .asFunction<JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>();
+
+ int GetShortField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+ _GetShortField(obj, fieldID).short;
+
+ late final _GetIntField = ptr.ref.GetIntField
+ .asFunction<JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>();
+
+ int GetIntField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+ _GetIntField(obj, fieldID).integer;
+
+ late final _GetLongField = ptr.ref.GetLongField
+ .asFunction<JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>();
+
+ int GetLongField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+ _GetLongField(obj, fieldID).long;
+
+ late final _GetFloatField = ptr.ref.GetFloatField
+ .asFunction<JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>();
+
+ double GetFloatField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+ _GetFloatField(obj, fieldID).float;
+
+ late final _GetDoubleField = ptr.ref.GetDoubleField
+ .asFunction<JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>();
+
+ double GetDoubleField(JObjectPtr obj, JFieldIDPtr fieldID) =>
+ _GetDoubleField(obj, fieldID).doubleFloat;
+
+ late final _SetObjectField = ptr.ref.SetObjectField.asFunction<
+ JThrowablePtr Function(
+ JObjectPtr obj, JFieldIDPtr fieldID, JObjectPtr val)>();
+
+ void SetObjectField(JObjectPtr obj, JFieldIDPtr fieldID, JObjectPtr val) =>
+ _SetObjectField(obj, fieldID, val).check();
+
+ late final _SetBooleanField = ptr.ref.SetBooleanField.asFunction<
+ JThrowablePtr Function(JObjectPtr obj, JFieldIDPtr fieldID, int val)>();
+
+ void SetBooleanField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+ _SetBooleanField(obj, fieldID, val).check();
+
+ late final _SetByteField = ptr.ref.SetByteField.asFunction<
+ JThrowablePtr Function(JObjectPtr obj, JFieldIDPtr fieldID, int val)>();
+
+ void SetByteField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+ _SetByteField(obj, fieldID, val).check();
+
+ late final _SetCharField = ptr.ref.SetCharField.asFunction<
+ JThrowablePtr Function(JObjectPtr obj, JFieldIDPtr fieldID, int val)>();
+
+ void SetCharField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+ _SetCharField(obj, fieldID, val).check();
+
+ late final _SetShortField = ptr.ref.SetShortField.asFunction<
+ JThrowablePtr Function(JObjectPtr obj, JFieldIDPtr fieldID, int val)>();
+
+ void SetShortField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+ _SetShortField(obj, fieldID, val).check();
+
+ late final _SetIntField = ptr.ref.SetIntField.asFunction<
+ JThrowablePtr Function(JObjectPtr obj, JFieldIDPtr fieldID, int val)>();
+
+ void SetIntField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+ _SetIntField(obj, fieldID, val).check();
+
+ late final _SetLongField = ptr.ref.SetLongField.asFunction<
+ JThrowablePtr Function(JObjectPtr obj, JFieldIDPtr fieldID, int val)>();
+
+ void SetLongField(JObjectPtr obj, JFieldIDPtr fieldID, int val) =>
+ _SetLongField(obj, fieldID, val).check();
+
+ late final _SetFloatField = ptr.ref.SetFloatField.asFunction<
+ JThrowablePtr Function(
+ JObjectPtr obj, JFieldIDPtr fieldID, double val)>();
+
+ void SetFloatField(JObjectPtr obj, JFieldIDPtr fieldID, double val) =>
+ _SetFloatField(obj, fieldID, val).check();
+
+ late final _SetDoubleField = ptr.ref.SetDoubleField.asFunction<
+ JThrowablePtr Function(
+ JObjectPtr obj, JFieldIDPtr fieldID, double val)>();
+
+ void SetDoubleField(JObjectPtr obj, JFieldIDPtr fieldID, double val) =>
+ _SetDoubleField(obj, fieldID, val).check();
+
+ late final _GetStaticMethodID = ptr.ref.GetStaticMethodID.asFunction<
+ JniPointerResult Function(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+ ffi.Pointer<ffi.Char> sig)>();
+
+ JMethodIDPtr GetStaticMethodID(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+ ffi.Pointer<ffi.Char> sig) =>
+ _GetStaticMethodID(clazz, name, sig).methodID;
+
+ late final _CallStaticObjectMethod = ptr.ref.CallStaticObjectMethod
+ .asFunction<JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ JObjectPtr CallStaticObjectMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallStaticObjectMethod(clazz, methodID).object;
+
+ late final _CallStaticObjectMethodA = ptr.ref.CallStaticObjectMethodA
+ .asFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>();
+
+ JObjectPtr CallStaticObjectMethodA(
+ JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallStaticObjectMethodA(clazz, methodID, args).object;
+
+ late final _CallStaticBooleanMethod = ptr.ref.CallStaticBooleanMethod
+ .asFunction<JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ bool CallStaticBooleanMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallStaticBooleanMethod(clazz, methodID).boolean;
+
+ late final _CallStaticBooleanMethodA = ptr.ref.CallStaticBooleanMethodA
+ .asFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>();
+
+ bool CallStaticBooleanMethodA(
+ JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallStaticBooleanMethodA(clazz, methodID, args).boolean;
+
+ late final _CallStaticByteMethod = ptr.ref.CallStaticByteMethod
+ .asFunction<JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ int CallStaticByteMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallStaticByteMethod(clazz, methodID).byte;
+
+ late final _CallStaticByteMethodA = ptr.ref.CallStaticByteMethodA.asFunction<
+ JniResult Function(
+ JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ int CallStaticByteMethodA(
+ JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallStaticByteMethodA(clazz, methodID, args).byte;
+
+ late final _CallStaticCharMethod = ptr.ref.CallStaticCharMethod
+ .asFunction<JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ int CallStaticCharMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallStaticCharMethod(clazz, methodID).char;
+
+ late final _CallStaticCharMethodA = ptr.ref.CallStaticCharMethodA.asFunction<
+ JniResult Function(
+ JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ int CallStaticCharMethodA(
+ JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallStaticCharMethodA(clazz, methodID, args).char;
+
+ late final _CallStaticShortMethod = ptr.ref.CallStaticShortMethod
+ .asFunction<JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ int CallStaticShortMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallStaticShortMethod(clazz, methodID).short;
+
+ late final _CallStaticShortMethodA = ptr.ref.CallStaticShortMethodA
+ .asFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>();
+
+ int CallStaticShortMethodA(
+ JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallStaticShortMethodA(clazz, methodID, args).short;
+
+ late final _CallStaticIntMethod = ptr.ref.CallStaticIntMethod
+ .asFunction<JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ int CallStaticIntMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallStaticIntMethod(clazz, methodID).integer;
+
+ late final _CallStaticIntMethodA = ptr.ref.CallStaticIntMethodA.asFunction<
+ JniResult Function(
+ JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ int CallStaticIntMethodA(
+ JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallStaticIntMethodA(clazz, methodID, args).integer;
+
+ late final _CallStaticLongMethod = ptr.ref.CallStaticLongMethod
+ .asFunction<JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ int CallStaticLongMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallStaticLongMethod(clazz, methodID).long;
+
+ late final _CallStaticLongMethodA = ptr.ref.CallStaticLongMethodA.asFunction<
+ JniResult Function(
+ JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ int CallStaticLongMethodA(
+ JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallStaticLongMethodA(clazz, methodID, args).long;
+
+ late final _CallStaticFloatMethod = ptr.ref.CallStaticFloatMethod
+ .asFunction<JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ double CallStaticFloatMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallStaticFloatMethod(clazz, methodID).float;
+
+ late final _CallStaticFloatMethodA = ptr.ref.CallStaticFloatMethodA
+ .asFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>();
+
+ double CallStaticFloatMethodA(
+ JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallStaticFloatMethodA(clazz, methodID, args).float;
+
+ late final _CallStaticDoubleMethod = ptr.ref.CallStaticDoubleMethod
+ .asFunction<JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ double CallStaticDoubleMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallStaticDoubleMethod(clazz, methodID).doubleFloat;
+
+ late final _CallStaticDoubleMethodA = ptr.ref.CallStaticDoubleMethodA
+ .asFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>();
+
+ double CallStaticDoubleMethodA(
+ JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallStaticDoubleMethodA(clazz, methodID, args).doubleFloat;
+
+ late final _CallStaticVoidMethod = ptr.ref.CallStaticVoidMethod.asFunction<
+ JThrowablePtr Function(JClassPtr clazz, JMethodIDPtr methodID)>();
+
+ void CallStaticVoidMethod(JClassPtr clazz, JMethodIDPtr methodID) =>
+ _CallStaticVoidMethod(clazz, methodID).check();
+
+ late final _CallStaticVoidMethodA = ptr.ref.CallStaticVoidMethodA.asFunction<
+ JThrowablePtr Function(
+ JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args)>();
+
+ void CallStaticVoidMethodA(
+ JClassPtr clazz, JMethodIDPtr methodID, ffi.Pointer<JValue> args) =>
+ _CallStaticVoidMethodA(clazz, methodID, args).check();
+
+ late final _GetStaticFieldID = ptr.ref.GetStaticFieldID.asFunction<
+ JniPointerResult Function(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+ ffi.Pointer<ffi.Char> sig)>();
+
+ JFieldIDPtr GetStaticFieldID(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+ ffi.Pointer<ffi.Char> sig) =>
+ _GetStaticFieldID(clazz, name, sig).fieldID;
+
+ late final _GetStaticObjectField = ptr.ref.GetStaticObjectField
+ .asFunction<JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>();
+
+ JObjectPtr GetStaticObjectField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+ _GetStaticObjectField(clazz, fieldID).object;
+
+ late final _GetStaticBooleanField = ptr.ref.GetStaticBooleanField
+ .asFunction<JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>();
+
+ bool GetStaticBooleanField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+ _GetStaticBooleanField(clazz, fieldID).boolean;
+
+ late final _GetStaticByteField = ptr.ref.GetStaticByteField
+ .asFunction<JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>();
+
+ int GetStaticByteField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+ _GetStaticByteField(clazz, fieldID).byte;
+
+ late final _GetStaticCharField = ptr.ref.GetStaticCharField
+ .asFunction<JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>();
+
+ int GetStaticCharField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+ _GetStaticCharField(clazz, fieldID).char;
+
+ late final _GetStaticShortField = ptr.ref.GetStaticShortField
+ .asFunction<JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>();
+
+ int GetStaticShortField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+ _GetStaticShortField(clazz, fieldID).short;
+
+ late final _GetStaticIntField = ptr.ref.GetStaticIntField
+ .asFunction<JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>();
+
+ int GetStaticIntField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+ _GetStaticIntField(clazz, fieldID).integer;
+
+ late final _GetStaticLongField = ptr.ref.GetStaticLongField
+ .asFunction<JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>();
+
+ int GetStaticLongField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+ _GetStaticLongField(clazz, fieldID).long;
+
+ late final _GetStaticFloatField = ptr.ref.GetStaticFloatField
+ .asFunction<JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>();
+
+ double GetStaticFloatField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+ _GetStaticFloatField(clazz, fieldID).float;
+
+ late final _GetStaticDoubleField = ptr.ref.GetStaticDoubleField
+ .asFunction<JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>();
+
+ double GetStaticDoubleField(JClassPtr clazz, JFieldIDPtr fieldID) =>
+ _GetStaticDoubleField(clazz, fieldID).doubleFloat;
+
+ late final _SetStaticObjectField = ptr.ref.SetStaticObjectField.asFunction<
+ JThrowablePtr Function(
+ JClassPtr clazz, JFieldIDPtr fieldID, JObjectPtr val)>();
+
+ void SetStaticObjectField(
+ JClassPtr clazz, JFieldIDPtr fieldID, JObjectPtr val) =>
+ _SetStaticObjectField(clazz, fieldID, val).check();
+
+ late final _SetStaticBooleanField = ptr.ref.SetStaticBooleanField.asFunction<
+ JThrowablePtr Function(JClassPtr clazz, JFieldIDPtr fieldID, int val)>();
+
+ void SetStaticBooleanField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+ _SetStaticBooleanField(clazz, fieldID, val).check();
+
+ late final _SetStaticByteField = ptr.ref.SetStaticByteField.asFunction<
+ JThrowablePtr Function(JClassPtr clazz, JFieldIDPtr fieldID, int val)>();
+
+ void SetStaticByteField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+ _SetStaticByteField(clazz, fieldID, val).check();
+
+ late final _SetStaticCharField = ptr.ref.SetStaticCharField.asFunction<
+ JThrowablePtr Function(JClassPtr clazz, JFieldIDPtr fieldID, int val)>();
+
+ void SetStaticCharField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+ _SetStaticCharField(clazz, fieldID, val).check();
+
+ late final _SetStaticShortField = ptr.ref.SetStaticShortField.asFunction<
+ JThrowablePtr Function(JClassPtr clazz, JFieldIDPtr fieldID, int val)>();
+
+ void SetStaticShortField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+ _SetStaticShortField(clazz, fieldID, val).check();
+
+ late final _SetStaticIntField = ptr.ref.SetStaticIntField.asFunction<
+ JThrowablePtr Function(JClassPtr clazz, JFieldIDPtr fieldID, int val)>();
+
+ void SetStaticIntField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+ _SetStaticIntField(clazz, fieldID, val).check();
+
+ late final _SetStaticLongField = ptr.ref.SetStaticLongField.asFunction<
+ JThrowablePtr Function(JClassPtr clazz, JFieldIDPtr fieldID, int val)>();
+
+ void SetStaticLongField(JClassPtr clazz, JFieldIDPtr fieldID, int val) =>
+ _SetStaticLongField(clazz, fieldID, val).check();
+
+ late final _SetStaticFloatField = ptr.ref.SetStaticFloatField.asFunction<
+ JThrowablePtr Function(
+ JClassPtr clazz, JFieldIDPtr fieldID, double val)>();
+
+ void SetStaticFloatField(JClassPtr clazz, JFieldIDPtr fieldID, double val) =>
+ _SetStaticFloatField(clazz, fieldID, val).check();
+
+ late final _SetStaticDoubleField = ptr.ref.SetStaticDoubleField.asFunction<
+ JThrowablePtr Function(
+ JClassPtr clazz, JFieldIDPtr fieldID, double val)>();
+
+ void SetStaticDoubleField(JClassPtr clazz, JFieldIDPtr fieldID, double val) =>
+ _SetStaticDoubleField(clazz, fieldID, val).check();
+
+ late final _NewString = ptr.ref.NewString.asFunction<
+ JniResult Function(ffi.Pointer<JCharMarker> unicodeChars, int len)>();
+
+ JStringPtr NewString(ffi.Pointer<JCharMarker> unicodeChars, int len) =>
+ _NewString(unicodeChars, len).object;
+
+ late final _GetStringLength = ptr.ref.GetStringLength
+ .asFunction<JniResult Function(JStringPtr string)>();
+
+ int GetStringLength(JStringPtr string) => _GetStringLength(string).integer;
+
+ late final _GetStringChars = ptr.ref.GetStringChars.asFunction<
+ JniPointerResult Function(
+ JStringPtr string, ffi.Pointer<JBooleanMarker> isCopy)>();
+
+ ffi.Pointer<JCharMarker> GetStringChars(
+ JStringPtr string, ffi.Pointer<JBooleanMarker> isCopy) =>
+ _GetStringChars(string, isCopy).getPointer<JCharMarker>();
+
+ late final _ReleaseStringChars = ptr.ref.ReleaseStringChars.asFunction<
+ JThrowablePtr Function(
+ JStringPtr string, ffi.Pointer<JCharMarker> isCopy)>();
+
+ void ReleaseStringChars(JStringPtr string, ffi.Pointer<JCharMarker> isCopy) =>
+ _ReleaseStringChars(string, isCopy).check();
+
+ late final _NewStringUTF = ptr.ref.NewStringUTF
+ .asFunction<JniResult Function(ffi.Pointer<ffi.Char> bytes)>();
+
+ JStringPtr NewStringUTF(ffi.Pointer<ffi.Char> bytes) =>
+ _NewStringUTF(bytes).object;
+
+ late final _GetStringUTFLength = ptr.ref.GetStringUTFLength
+ .asFunction<JniResult Function(JStringPtr string)>();
+
+ int GetStringUTFLength(JStringPtr string) =>
+ _GetStringUTFLength(string).integer;
+
+ late final _GetStringUTFChars = ptr.ref.GetStringUTFChars.asFunction<
+ JniPointerResult Function(
+ JStringPtr string, ffi.Pointer<JBooleanMarker> isCopy)>();
+
+ ffi.Pointer<ffi.Char> GetStringUTFChars(
+ JStringPtr string, ffi.Pointer<JBooleanMarker> isCopy) =>
+ _GetStringUTFChars(string, isCopy).getPointer<ffi.Char>();
+
+ late final _ReleaseStringUTFChars = ptr.ref.ReleaseStringUTFChars.asFunction<
+ JThrowablePtr Function(JStringPtr string, ffi.Pointer<ffi.Char> utf)>();
+
+ void ReleaseStringUTFChars(JStringPtr string, ffi.Pointer<ffi.Char> utf) =>
+ _ReleaseStringUTFChars(string, utf).check();
+
+ late final _GetArrayLength =
+ ptr.ref.GetArrayLength.asFunction<JniResult Function(JArrayPtr array)>();
+
+ int GetArrayLength(JArrayPtr array) => _GetArrayLength(array).integer;
+
+ late final _NewObjectArray = ptr.ref.NewObjectArray.asFunction<
+ JniResult Function(
+ int length, JClassPtr elementClass, JObjectPtr initialElement)>();
+
+ JObjectArrayPtr NewObjectArray(
+ int length, JClassPtr elementClass, JObjectPtr initialElement) =>
+ _NewObjectArray(length, elementClass, initialElement).object;
+
+ late final _GetObjectArrayElement = ptr.ref.GetObjectArrayElement
+ .asFunction<JniResult Function(JObjectArrayPtr array, int index)>();
+
+ JObjectPtr GetObjectArrayElement(JObjectArrayPtr array, int index) =>
+ _GetObjectArrayElement(array, index).object;
+
+ late final _SetObjectArrayElement = ptr.ref.SetObjectArrayElement.asFunction<
+ JThrowablePtr Function(
+ JObjectArrayPtr array, int index, JObjectPtr val)>();
+
+ void SetObjectArrayElement(
+ JObjectArrayPtr array, int index, JObjectPtr val) =>
+ _SetObjectArrayElement(array, index, val).check();
+
+ late final _NewBooleanArray =
+ ptr.ref.NewBooleanArray.asFunction<JniResult Function(int length)>();
+
+ JBooleanArrayPtr NewBooleanArray(int length) =>
+ _NewBooleanArray(length).object;
+
+ late final _NewByteArray =
+ ptr.ref.NewByteArray.asFunction<JniResult Function(int length)>();
+
+ JByteArrayPtr NewByteArray(int length) => _NewByteArray(length).object;
+
+ late final _NewCharArray =
+ ptr.ref.NewCharArray.asFunction<JniResult Function(int length)>();
+
+ JCharArrayPtr NewCharArray(int length) => _NewCharArray(length).object;
+
+ late final _NewShortArray =
+ ptr.ref.NewShortArray.asFunction<JniResult Function(int length)>();
+
+ JShortArrayPtr NewShortArray(int length) => _NewShortArray(length).object;
+
+ late final _NewIntArray =
+ ptr.ref.NewIntArray.asFunction<JniResult Function(int length)>();
+
+ JIntArrayPtr NewIntArray(int length) => _NewIntArray(length).object;
+
+ late final _NewLongArray =
+ ptr.ref.NewLongArray.asFunction<JniResult Function(int length)>();
+
+ JLongArrayPtr NewLongArray(int length) => _NewLongArray(length).object;
+
+ late final _NewFloatArray =
+ ptr.ref.NewFloatArray.asFunction<JniResult Function(int length)>();
+
+ JFloatArrayPtr NewFloatArray(int length) => _NewFloatArray(length).object;
+
+ late final _NewDoubleArray =
+ ptr.ref.NewDoubleArray.asFunction<JniResult Function(int length)>();
+
+ JDoubleArrayPtr NewDoubleArray(int length) => _NewDoubleArray(length).object;
+
+ late final _GetBooleanArrayElements = ptr.ref.GetBooleanArrayElements
+ .asFunction<
+ JniPointerResult Function(
+ JBooleanArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>();
+
+ ffi.Pointer<JBooleanMarker> GetBooleanArrayElements(
+ JBooleanArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+ _GetBooleanArrayElements(array, isCopy).getPointer<JBooleanMarker>();
+
+ late final _GetByteArrayElements = ptr.ref.GetByteArrayElements.asFunction<
+ JniPointerResult Function(
+ JByteArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>();
+
+ ffi.Pointer<JByteMarker> GetByteArrayElements(
+ JByteArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+ _GetByteArrayElements(array, isCopy).getPointer<JByteMarker>();
+
+ late final _GetCharArrayElements = ptr.ref.GetCharArrayElements.asFunction<
+ JniPointerResult Function(
+ JCharArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>();
+
+ ffi.Pointer<JCharMarker> GetCharArrayElements(
+ JCharArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+ _GetCharArrayElements(array, isCopy).getPointer<JCharMarker>();
+
+ late final _GetShortArrayElements = ptr.ref.GetShortArrayElements.asFunction<
+ JniPointerResult Function(
+ JShortArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>();
+
+ ffi.Pointer<JShortMarker> GetShortArrayElements(
+ JShortArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+ _GetShortArrayElements(array, isCopy).getPointer<JShortMarker>();
+
+ late final _GetIntArrayElements = ptr.ref.GetIntArrayElements.asFunction<
+ JniPointerResult Function(
+ JIntArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>();
+
+ ffi.Pointer<JIntMarker> GetIntArrayElements(
+ JIntArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+ _GetIntArrayElements(array, isCopy).getPointer<JIntMarker>();
+
+ late final _GetLongArrayElements = ptr.ref.GetLongArrayElements.asFunction<
+ JniPointerResult Function(
+ JLongArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>();
+
+ ffi.Pointer<JLongMarker> GetLongArrayElements(
+ JLongArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+ _GetLongArrayElements(array, isCopy).getPointer<JLongMarker>();
+
+ late final _GetFloatArrayElements = ptr.ref.GetFloatArrayElements.asFunction<
+ JniPointerResult Function(
+ JFloatArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>();
+
+ ffi.Pointer<JFloatMarker> GetFloatArrayElements(
+ JFloatArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+ _GetFloatArrayElements(array, isCopy).getPointer<JFloatMarker>();
+
+ late final _GetDoubleArrayElements = ptr.ref.GetDoubleArrayElements
+ .asFunction<
+ JniPointerResult Function(
+ JDoubleArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>();
+
+ ffi.Pointer<JDoubleMarker> GetDoubleArrayElements(
+ JDoubleArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+ _GetDoubleArrayElements(array, isCopy).getPointer<JDoubleMarker>();
+
+ late final _ReleaseBooleanArrayElements = ptr.ref.ReleaseBooleanArrayElements
+ .asFunction<
+ JThrowablePtr Function(JBooleanArrayPtr array,
+ ffi.Pointer<JBooleanMarker> elems, int mode)>();
+
+ void ReleaseBooleanArrayElements(JBooleanArrayPtr array,
+ ffi.Pointer<JBooleanMarker> elems, int mode) =>
+ _ReleaseBooleanArrayElements(array, elems, mode).check();
+
+ late final _ReleaseByteArrayElements = ptr.ref.ReleaseByteArrayElements
+ .asFunction<
+ JThrowablePtr Function(
+ JByteArrayPtr array, ffi.Pointer<JByteMarker> elems, int mode)>();
+
+ void ReleaseByteArrayElements(
+ JByteArrayPtr array, ffi.Pointer<JByteMarker> elems, int mode) =>
+ _ReleaseByteArrayElements(array, elems, mode).check();
+
+ late final _ReleaseCharArrayElements = ptr.ref.ReleaseCharArrayElements
+ .asFunction<
+ JThrowablePtr Function(
+ JCharArrayPtr array, ffi.Pointer<JCharMarker> elems, int mode)>();
+
+ void ReleaseCharArrayElements(
+ JCharArrayPtr array, ffi.Pointer<JCharMarker> elems, int mode) =>
+ _ReleaseCharArrayElements(array, elems, mode).check();
+
+ late final _ReleaseShortArrayElements = ptr.ref.ReleaseShortArrayElements
+ .asFunction<
+ JThrowablePtr Function(JShortArrayPtr array,
+ ffi.Pointer<JShortMarker> elems, int mode)>();
+
+ void ReleaseShortArrayElements(
+ JShortArrayPtr array, ffi.Pointer<JShortMarker> elems, int mode) =>
+ _ReleaseShortArrayElements(array, elems, mode).check();
+
+ late final _ReleaseIntArrayElements = ptr.ref.ReleaseIntArrayElements
+ .asFunction<
+ JThrowablePtr Function(
+ JIntArrayPtr array, ffi.Pointer<JIntMarker> elems, int mode)>();
+
+ void ReleaseIntArrayElements(
+ JIntArrayPtr array, ffi.Pointer<JIntMarker> elems, int mode) =>
+ _ReleaseIntArrayElements(array, elems, mode).check();
+
+ late final _ReleaseLongArrayElements = ptr.ref.ReleaseLongArrayElements
+ .asFunction<
+ JThrowablePtr Function(
+ JLongArrayPtr array, ffi.Pointer<JLongMarker> elems, int mode)>();
+
+ void ReleaseLongArrayElements(
+ JLongArrayPtr array, ffi.Pointer<JLongMarker> elems, int mode) =>
+ _ReleaseLongArrayElements(array, elems, mode).check();
+
+ late final _ReleaseFloatArrayElements = ptr.ref.ReleaseFloatArrayElements
+ .asFunction<
+ JThrowablePtr Function(JFloatArrayPtr array,
+ ffi.Pointer<JFloatMarker> elems, int mode)>();
+
+ void ReleaseFloatArrayElements(
+ JFloatArrayPtr array, ffi.Pointer<JFloatMarker> elems, int mode) =>
+ _ReleaseFloatArrayElements(array, elems, mode).check();
+
+ late final _ReleaseDoubleArrayElements = ptr.ref.ReleaseDoubleArrayElements
+ .asFunction<
+ JThrowablePtr Function(JDoubleArrayPtr array,
+ ffi.Pointer<JDoubleMarker> elems, int mode)>();
+
+ void ReleaseDoubleArrayElements(
+ JDoubleArrayPtr array, ffi.Pointer<JDoubleMarker> elems, int mode) =>
+ _ReleaseDoubleArrayElements(array, elems, mode).check();
+
+ late final _GetBooleanArrayRegion = ptr.ref.GetBooleanArrayRegion.asFunction<
+ JThrowablePtr Function(JBooleanArrayPtr array, int start, int len,
+ ffi.Pointer<JBooleanMarker> buf)>();
+
+ void GetBooleanArrayRegion(JBooleanArrayPtr array, int start, int len,
+ ffi.Pointer<JBooleanMarker> buf) =>
+ _GetBooleanArrayRegion(array, start, len, buf).check();
+
+ late final _GetByteArrayRegion = ptr.ref.GetByteArrayRegion.asFunction<
+ JThrowablePtr Function(JByteArrayPtr array, int start, int len,
+ ffi.Pointer<JByteMarker> buf)>();
+
+ void GetByteArrayRegion(JByteArrayPtr array, int start, int len,
+ ffi.Pointer<JByteMarker> buf) =>
+ _GetByteArrayRegion(array, start, len, buf).check();
+
+ late final _GetCharArrayRegion = ptr.ref.GetCharArrayRegion.asFunction<
+ JThrowablePtr Function(JCharArrayPtr array, int start, int len,
+ ffi.Pointer<JCharMarker> buf)>();
+
+ void GetCharArrayRegion(JCharArrayPtr array, int start, int len,
+ ffi.Pointer<JCharMarker> buf) =>
+ _GetCharArrayRegion(array, start, len, buf).check();
+
+ late final _GetShortArrayRegion = ptr.ref.GetShortArrayRegion.asFunction<
+ JThrowablePtr Function(JShortArrayPtr array, int start, int len,
+ ffi.Pointer<JShortMarker> buf)>();
+
+ void GetShortArrayRegion(JShortArrayPtr array, int start, int len,
+ ffi.Pointer<JShortMarker> buf) =>
+ _GetShortArrayRegion(array, start, len, buf).check();
+
+ late final _GetIntArrayRegion = ptr.ref.GetIntArrayRegion.asFunction<
+ JThrowablePtr Function(JIntArrayPtr array, int start, int len,
+ ffi.Pointer<JIntMarker> buf)>();
+
+ void GetIntArrayRegion(JIntArrayPtr array, int start, int len,
+ ffi.Pointer<JIntMarker> buf) =>
+ _GetIntArrayRegion(array, start, len, buf).check();
+
+ late final _GetLongArrayRegion = ptr.ref.GetLongArrayRegion.asFunction<
+ JThrowablePtr Function(JLongArrayPtr array, int start, int len,
+ ffi.Pointer<JLongMarker> buf)>();
+
+ void GetLongArrayRegion(JLongArrayPtr array, int start, int len,
+ ffi.Pointer<JLongMarker> buf) =>
+ _GetLongArrayRegion(array, start, len, buf).check();
+
+ late final _GetFloatArrayRegion = ptr.ref.GetFloatArrayRegion.asFunction<
+ JThrowablePtr Function(JFloatArrayPtr array, int start, int len,
+ ffi.Pointer<JFloatMarker> buf)>();
+
+ void GetFloatArrayRegion(JFloatArrayPtr array, int start, int len,
+ ffi.Pointer<JFloatMarker> buf) =>
+ _GetFloatArrayRegion(array, start, len, buf).check();
+
+ late final _GetDoubleArrayRegion = ptr.ref.GetDoubleArrayRegion.asFunction<
+ JThrowablePtr Function(JDoubleArrayPtr array, int start, int len,
+ ffi.Pointer<JDoubleMarker> buf)>();
+
+ void GetDoubleArrayRegion(JDoubleArrayPtr array, int start, int len,
+ ffi.Pointer<JDoubleMarker> buf) =>
+ _GetDoubleArrayRegion(array, start, len, buf).check();
+
+ late final _SetBooleanArrayRegion = ptr.ref.SetBooleanArrayRegion.asFunction<
+ JThrowablePtr Function(JBooleanArrayPtr array, int start, int len,
+ ffi.Pointer<JBooleanMarker> buf)>();
+
+ void SetBooleanArrayRegion(JBooleanArrayPtr array, int start, int len,
+ ffi.Pointer<JBooleanMarker> buf) =>
+ _SetBooleanArrayRegion(array, start, len, buf).check();
+
+ late final _SetByteArrayRegion = ptr.ref.SetByteArrayRegion.asFunction<
+ JThrowablePtr Function(JByteArrayPtr array, int start, int len,
+ ffi.Pointer<JByteMarker> buf)>();
+
+ void SetByteArrayRegion(JByteArrayPtr array, int start, int len,
+ ffi.Pointer<JByteMarker> buf) =>
+ _SetByteArrayRegion(array, start, len, buf).check();
+
+ late final _SetCharArrayRegion = ptr.ref.SetCharArrayRegion.asFunction<
+ JThrowablePtr Function(JCharArrayPtr array, int start, int len,
+ ffi.Pointer<JCharMarker> buf)>();
+
+ void SetCharArrayRegion(JCharArrayPtr array, int start, int len,
+ ffi.Pointer<JCharMarker> buf) =>
+ _SetCharArrayRegion(array, start, len, buf).check();
+
+ late final _SetShortArrayRegion = ptr.ref.SetShortArrayRegion.asFunction<
+ JThrowablePtr Function(JShortArrayPtr array, int start, int len,
+ ffi.Pointer<JShortMarker> buf)>();
+
+ void SetShortArrayRegion(JShortArrayPtr array, int start, int len,
+ ffi.Pointer<JShortMarker> buf) =>
+ _SetShortArrayRegion(array, start, len, buf).check();
+
+ late final _SetIntArrayRegion = ptr.ref.SetIntArrayRegion.asFunction<
+ JThrowablePtr Function(JIntArrayPtr array, int start, int len,
+ ffi.Pointer<JIntMarker> buf)>();
+
+ void SetIntArrayRegion(JIntArrayPtr array, int start, int len,
+ ffi.Pointer<JIntMarker> buf) =>
+ _SetIntArrayRegion(array, start, len, buf).check();
+
+ late final _SetLongArrayRegion = ptr.ref.SetLongArrayRegion.asFunction<
+ JThrowablePtr Function(JLongArrayPtr array, int start, int len,
+ ffi.Pointer<JLongMarker> buf)>();
+
+ void SetLongArrayRegion(JLongArrayPtr array, int start, int len,
+ ffi.Pointer<JLongMarker> buf) =>
+ _SetLongArrayRegion(array, start, len, buf).check();
+
+ late final _SetFloatArrayRegion = ptr.ref.SetFloatArrayRegion.asFunction<
+ JThrowablePtr Function(JFloatArrayPtr array, int start, int len,
+ ffi.Pointer<JFloatMarker> buf)>();
+
+ void SetFloatArrayRegion(JFloatArrayPtr array, int start, int len,
+ ffi.Pointer<JFloatMarker> buf) =>
+ _SetFloatArrayRegion(array, start, len, buf).check();
+
+ late final _SetDoubleArrayRegion = ptr.ref.SetDoubleArrayRegion.asFunction<
+ JThrowablePtr Function(JDoubleArrayPtr array, int start, int len,
+ ffi.Pointer<JDoubleMarker> buf)>();
+
+ void SetDoubleArrayRegion(JDoubleArrayPtr array, int start, int len,
+ ffi.Pointer<JDoubleMarker> buf) =>
+ _SetDoubleArrayRegion(array, start, len, buf).check();
+
+ late final _RegisterNatives = ptr.ref.RegisterNatives.asFunction<
+ JniResult Function(JClassPtr clazz, ffi.Pointer<JNINativeMethod> methods,
+ int nMethods)>();
+
+ int RegisterNatives(JClassPtr clazz, ffi.Pointer<JNINativeMethod> methods,
+ int nMethods) =>
+ _RegisterNatives(clazz, methods, nMethods).integer;
+
+ late final _UnregisterNatives = ptr.ref.UnregisterNatives
+ .asFunction<JniResult Function(JClassPtr clazz)>();
+
+ int UnregisterNatives(JClassPtr clazz) => _UnregisterNatives(clazz).integer;
+
+ late final _MonitorEnter =
+ ptr.ref.MonitorEnter.asFunction<JniResult Function(JObjectPtr obj)>();
+
+ int MonitorEnter(JObjectPtr obj) => _MonitorEnter(obj).integer;
+
+ late final _MonitorExit =
+ ptr.ref.MonitorExit.asFunction<JniResult Function(JObjectPtr obj)>();
+
+ int MonitorExit(JObjectPtr obj) => _MonitorExit(obj).integer;
+
+ late final _GetJavaVM = ptr.ref.GetJavaVM
+ .asFunction<JniResult Function(ffi.Pointer<ffi.Pointer<JavaVM1>> vm)>();
+
+ int GetJavaVM(ffi.Pointer<ffi.Pointer<JavaVM1>> vm) => _GetJavaVM(vm).integer;
+
+ late final _GetStringRegion = ptr.ref.GetStringRegion.asFunction<
+ JThrowablePtr Function(
+ JStringPtr str, int start, int len, ffi.Pointer<JCharMarker> buf)>();
+
+ void GetStringRegion(
+ JStringPtr str, int start, int len, ffi.Pointer<JCharMarker> buf) =>
+ _GetStringRegion(str, start, len, buf).check();
+
+ late final _GetStringUTFRegion = ptr.ref.GetStringUTFRegion.asFunction<
+ JThrowablePtr Function(
+ JStringPtr str, int start, int len, ffi.Pointer<ffi.Char> buf)>();
+
+ void GetStringUTFRegion(
+ JStringPtr str, int start, int len, ffi.Pointer<ffi.Char> buf) =>
+ _GetStringUTFRegion(str, start, len, buf).check();
+
+ late final _GetPrimitiveArrayCritical = ptr.ref.GetPrimitiveArrayCritical
+ .asFunction<
+ JniPointerResult Function(
+ JArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>();
+
+ ffi.Pointer<ffi.Void> GetPrimitiveArrayCritical(
+ JArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy) =>
+ _GetPrimitiveArrayCritical(array, isCopy).getPointer<ffi.Void>();
+
+ late final _ReleasePrimitiveArrayCritical =
+ ptr.ref.ReleasePrimitiveArrayCritical.asFunction<
+ JThrowablePtr Function(
+ JArrayPtr array, ffi.Pointer<ffi.Void> carray, int mode)>();
+
+ void ReleasePrimitiveArrayCritical(
+ JArrayPtr array, ffi.Pointer<ffi.Void> carray, int mode) =>
+ _ReleasePrimitiveArrayCritical(array, carray, mode).check();
+
+ late final _GetStringCritical = ptr.ref.GetStringCritical.asFunction<
+ JniPointerResult Function(
+ JStringPtr str, ffi.Pointer<JBooleanMarker> isCopy)>();
+
+ ffi.Pointer<JCharMarker> GetStringCritical(
+ JStringPtr str, ffi.Pointer<JBooleanMarker> isCopy) =>
+ _GetStringCritical(str, isCopy).getPointer<JCharMarker>();
+
+ late final _ReleaseStringCritical = ptr.ref.ReleaseStringCritical.asFunction<
+ JThrowablePtr Function(
+ JStringPtr str, ffi.Pointer<JCharMarker> carray)>();
+
+ void ReleaseStringCritical(JStringPtr str, ffi.Pointer<JCharMarker> carray) =>
+ _ReleaseStringCritical(str, carray).check();
+
+ late final _NewWeakGlobalRef =
+ ptr.ref.NewWeakGlobalRef.asFunction<JniResult Function(JObjectPtr obj)>();
+
+ JWeakPtr NewWeakGlobalRef(JObjectPtr obj) => _NewWeakGlobalRef(obj).object;
+
+ late final _DeleteWeakGlobalRef = ptr.ref.DeleteWeakGlobalRef
+ .asFunction<JThrowablePtr Function(JWeakPtr obj)>();
+
+ void DeleteWeakGlobalRef(JWeakPtr obj) => _DeleteWeakGlobalRef(obj).check();
+
+ late final _ExceptionCheck =
+ ptr.ref.ExceptionCheck.asFunction<JniResult Function()>();
+
+ bool ExceptionCheck() => _ExceptionCheck().boolean;
+
+ late final _NewDirectByteBuffer = ptr.ref.NewDirectByteBuffer.asFunction<
+ JniResult Function(ffi.Pointer<ffi.Void> address, int capacity)>();
+
+ JObjectPtr NewDirectByteBuffer(ffi.Pointer<ffi.Void> address, int capacity) =>
+ _NewDirectByteBuffer(address, capacity).object;
+
+ late final _GetDirectBufferAddress = ptr.ref.GetDirectBufferAddress
+ .asFunction<JniPointerResult Function(JObjectPtr buf)>();
+
+ ffi.Pointer<ffi.Void> GetDirectBufferAddress(JObjectPtr buf) =>
+ _GetDirectBufferAddress(buf).getPointer<ffi.Void>();
+
+ late final _GetDirectBufferCapacity = ptr.ref.GetDirectBufferCapacity
+ .asFunction<JniResult Function(JObjectPtr buf)>();
+
+ int GetDirectBufferCapacity(JObjectPtr buf) =>
+ _GetDirectBufferCapacity(buf).long;
+
+ late final _GetObjectRefType =
+ ptr.ref.GetObjectRefType.asFunction<JniResult Function(JObjectPtr obj)>();
+
+ int GetObjectRefType(JObjectPtr obj) => _GetObjectRefType(obj).integer;
+}
+
+/// Wraps over the function pointers in JniAccessorsStruct and exposes them as methods.
+class JniAccessors {
+ final ffi.Pointer<JniAccessorsStruct> ptr;
+ JniAccessors(this.ptr);
+
+ late final _getClass = ptr.ref.getClass.asFunction<
+ JniClassLookupResult Function(ffi.Pointer<ffi.Char> internalName)>();
+ JniClassLookupResult getClass(ffi.Pointer<ffi.Char> internalName) =>
+ _getClass(internalName);
+
+ late final _getFieldID = ptr.ref.getFieldID.asFunction<
+ JniPointerResult Function(JClassPtr cls, ffi.Pointer<ffi.Char> fieldName,
+ ffi.Pointer<ffi.Char> signature)>();
+ JniPointerResult getFieldID(JClassPtr cls, ffi.Pointer<ffi.Char> fieldName,
+ ffi.Pointer<ffi.Char> signature) =>
+ _getFieldID(cls, fieldName, signature);
+
+ late final _getStaticFieldID = ptr.ref.getStaticFieldID.asFunction<
+ JniPointerResult Function(JClassPtr cls, ffi.Pointer<ffi.Char> fieldName,
+ ffi.Pointer<ffi.Char> signature)>();
+ JniPointerResult getStaticFieldID(JClassPtr cls,
+ ffi.Pointer<ffi.Char> fieldName, ffi.Pointer<ffi.Char> signature) =>
+ _getStaticFieldID(cls, fieldName, signature);
+
+ late final _getMethodID = ptr.ref.getMethodID.asFunction<
+ JniPointerResult Function(JClassPtr cls, ffi.Pointer<ffi.Char> methodName,
+ ffi.Pointer<ffi.Char> signature)>();
+ JniPointerResult getMethodID(JClassPtr cls, ffi.Pointer<ffi.Char> methodName,
+ ffi.Pointer<ffi.Char> signature) =>
+ _getMethodID(cls, methodName, signature);
+
+ late final _getStaticMethodID = ptr.ref.getStaticMethodID.asFunction<
+ JniPointerResult Function(JClassPtr cls, ffi.Pointer<ffi.Char> methodName,
+ ffi.Pointer<ffi.Char> signature)>();
+ JniPointerResult getStaticMethodID(JClassPtr cls,
+ ffi.Pointer<ffi.Char> methodName, ffi.Pointer<ffi.Char> signature) =>
+ _getStaticMethodID(cls, methodName, signature);
+
+ late final _newObject = ptr.ref.newObject.asFunction<
+ JniResult Function(
+ JClassPtr cls, JMethodIDPtr ctor, ffi.Pointer<JValue> args)>();
+ JniResult newObject(
+ JClassPtr cls, JMethodIDPtr ctor, ffi.Pointer<JValue> args) =>
+ _newObject(cls, ctor, args);
+
+ late final _newPrimitiveArray = ptr.ref.newPrimitiveArray
+ .asFunction<JniResult Function(int length, int type)>();
+ JniResult newPrimitiveArray(int length, int type) =>
+ _newPrimitiveArray(length, type);
+
+ late final _newObjectArray = ptr.ref.newObjectArray.asFunction<
+ JniResult Function(
+ int length, JClassPtr elementClass, JObjectPtr initialElement)>();
+ JniResult newObjectArray(
+ int length, JClassPtr elementClass, JObjectPtr initialElement) =>
+ _newObjectArray(length, elementClass, initialElement);
+
+ late final _getArrayElement = ptr.ref.getArrayElement
+ .asFunction<JniResult Function(JArrayPtr array, int index, int type)>();
+ JniResult getArrayElement(JArrayPtr array, int index, int type) =>
+ _getArrayElement(array, index, type);
+
+ late final _callMethod = ptr.ref.callMethod.asFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID, int callType,
+ ffi.Pointer<JValue> args)>();
+ JniResult callMethod(JObjectPtr obj, JMethodIDPtr methodID, int callType,
+ ffi.Pointer<JValue> args) =>
+ _callMethod(obj, methodID, callType, args);
+
+ late final _callStaticMethod = ptr.ref.callStaticMethod.asFunction<
+ JniResult Function(JClassPtr cls, JMethodIDPtr methodID, int callType,
+ ffi.Pointer<JValue> args)>();
+ JniResult callStaticMethod(JClassPtr cls, JMethodIDPtr methodID, int callType,
+ ffi.Pointer<JValue> args) =>
+ _callStaticMethod(cls, methodID, callType, args);
+
+ late final _getField = ptr.ref.getField.asFunction<
+ JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID, int callType)>();
+ JniResult getField(JObjectPtr obj, JFieldIDPtr fieldID, int callType) =>
+ _getField(obj, fieldID, callType);
+
+ late final _getStaticField = ptr.ref.getStaticField.asFunction<
+ JniResult Function(JClassPtr cls, JFieldIDPtr fieldID, int callType)>();
+ JniResult getStaticField(JClassPtr cls, JFieldIDPtr fieldID, int callType) =>
+ _getStaticField(cls, fieldID, callType);
+
+ late final _getExceptionDetails = ptr.ref.getExceptionDetails
+ .asFunction<JniExceptionDetails Function(JThrowablePtr exception)>();
+ JniExceptionDetails getExceptionDetails(JThrowablePtr exception) =>
+ _getExceptionDetails(exception);
+}
diff --git a/pkgs/jni/lib/src/third_party/jni_bindings_generated.dart b/pkgs/jni/lib/src/third_party/jni_bindings_generated.dart
new file mode 100644
index 0000000..892f69e
--- /dev/null
+++ b/pkgs/jni/lib/src/third_party/jni_bindings_generated.dart
@@ -0,0 +1,3332 @@
+// Autogenerated file. Do not edit.
+// Generated from an annotated version of jni.h provided in Android NDK.
+// (NDK Version 23.1.7779620)
+// The license for original file is provided below:
+
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * JNI specification, as defined by Sun:
+ * http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html
+ *
+ * Everything here is expected to be VM-neutral.
+ */
+
+// ignore_for_file: always_specify_types
+// ignore_for_file: camel_case_types
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: unused_field
+// ignore_for_file: unused_element
+// coverage:ignore-file
+
+// AUTO GENERATED FILE, DO NOT EDIT.
+//
+// Generated by `package:ffigen`.
+// ignore_for_file: type=lint
+import 'dart:ffi' as ffi;
+
+/// Bindings for libdartjni.so which is part of jni plugin.
+///
+/// It also transitively includes type definitions such as JNIEnv from third_party/jni.h;
+///
+/// However, functions prefixed JNI_ are not usable because they are in a different shared library.
+///
+/// Regenerate bindings with `flutter pub run ffigen.dart --config ffigen.yaml`.
+///
+class JniBindings {
+ /// Holds the symbol lookup function.
+ final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
+ _lookup;
+
+ /// The symbols are looked up in [dynamicLibrary].
+ JniBindings(ffi.DynamicLibrary dynamicLibrary)
+ : _lookup = dynamicLibrary.lookup;
+
+ /// The symbols are looked up with [lookup].
+ JniBindings.fromLookup(
+ ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
+ lookup)
+ : _lookup = lookup;
+
+ ffi.Pointer<JniAccessorsStruct> GetAccessors() {
+ return _GetAccessors();
+ }
+
+ late final _GetAccessorsPtr =
+ _lookup<ffi.NativeFunction<ffi.Pointer<JniAccessorsStruct> Function()>>(
+ 'GetAccessors');
+ late final _GetAccessors =
+ _GetAccessorsPtr.asFunction<ffi.Pointer<JniAccessorsStruct> Function()>();
+
+ ffi.Pointer<JavaVM> GetJavaVM() {
+ return _GetJavaVM();
+ }
+
+ late final _GetJavaVMPtr =
+ _lookup<ffi.NativeFunction<ffi.Pointer<JavaVM> Function()>>('GetJavaVM');
+ late final _GetJavaVM =
+ _GetJavaVMPtr.asFunction<ffi.Pointer<JavaVM> Function()>();
+
+ ffi.Pointer<JniEnv> GetJniEnv() {
+ return _GetJniEnv();
+ }
+
+ late final _GetJniEnvPtr =
+ _lookup<ffi.NativeFunction<ffi.Pointer<JniEnv> Function()>>('GetJniEnv');
+ late final _GetJniEnv =
+ _GetJniEnvPtr.asFunction<ffi.Pointer<JniEnv> Function()>();
+
+ /// Spawn a JVM with given arguments.
+ ///
+ /// Returns JNI_OK on success, and one of the documented JNI error codes on
+ /// failure. It returns DART_JNI_SINGLETON_EXISTS if an attempt to spawn multiple
+ /// JVMs is made, even if the underlying API potentially supports multiple VMs.
+ int SpawnJvm(
+ ffi.Pointer<JavaVMInitArgs> args,
+ ) {
+ return _SpawnJvm(
+ args,
+ );
+ }
+
+ late final _SpawnJvmPtr = _lookup<
+ ffi.NativeFunction<ffi.Int Function(ffi.Pointer<JavaVMInitArgs>)>>(
+ 'SpawnJvm');
+ late final _SpawnJvm =
+ _SpawnJvmPtr.asFunction<int Function(ffi.Pointer<JavaVMInitArgs>)>();
+
+ /// Load class through platform-specific mechanism.
+ ///
+ /// Currently uses application classloader on android,
+ /// and JNIEnv->FindClass on other platforms.
+ JClassPtr FindClass(
+ ffi.Pointer<ffi.Char> name,
+ ) {
+ return _FindClass(
+ name,
+ );
+ }
+
+ late final _FindClassPtr =
+ _lookup<ffi.NativeFunction<JClassPtr Function(ffi.Pointer<ffi.Char>)>>(
+ 'FindClass');
+ late final _FindClass =
+ _FindClassPtr.asFunction<JClassPtr Function(ffi.Pointer<ffi.Char>)>();
+
+ /// Returns Application classLoader (on Android),
+ /// which can be used to load application and platform classes.
+ ///
+ /// On other platforms, NULL is returned.
+ JObjectPtr GetClassLoader() {
+ return _GetClassLoader();
+ }
+
+ late final _GetClassLoaderPtr =
+ _lookup<ffi.NativeFunction<JObjectPtr Function()>>('GetClassLoader');
+ late final _GetClassLoader =
+ _GetClassLoaderPtr.asFunction<JObjectPtr Function()>();
+
+ /// Returns application context on Android.
+ ///
+ /// On other platforms, NULL is returned.
+ JObjectPtr GetApplicationContext() {
+ return _GetApplicationContext();
+ }
+
+ late final _GetApplicationContextPtr =
+ _lookup<ffi.NativeFunction<JObjectPtr Function()>>(
+ 'GetApplicationContext');
+ late final _GetApplicationContext =
+ _GetApplicationContextPtr.asFunction<JObjectPtr Function()>();
+
+ /// Returns current activity of the app on Android.
+ JObjectPtr GetCurrentActivity() {
+ return _GetCurrentActivity();
+ }
+
+ late final _GetCurrentActivityPtr =
+ _lookup<ffi.NativeFunction<JObjectPtr Function()>>('GetCurrentActivity');
+ late final _GetCurrentActivity =
+ _GetCurrentActivityPtr.asFunction<JObjectPtr Function()>();
+
+ int InitDartApiDL(
+ ffi.Pointer<ffi.Void> data,
+ ) {
+ return _InitDartApiDL(
+ data,
+ );
+ }
+
+ late final _InitDartApiDLPtr =
+ _lookup<ffi.NativeFunction<ffi.IntPtr Function(ffi.Pointer<ffi.Void>)>>(
+ 'InitDartApiDL');
+ late final _InitDartApiDL =
+ _InitDartApiDLPtr.asFunction<int Function(ffi.Pointer<ffi.Void>)>();
+
+ JniResult DartException__ctor(
+ JStringPtr message,
+ ) {
+ return _DartException__ctor(
+ message,
+ );
+ }
+
+ late final _DartException__ctorPtr =
+ _lookup<ffi.NativeFunction<JniResult Function(JStringPtr)>>(
+ 'DartException__ctor');
+ late final _DartException__ctor =
+ _DartException__ctorPtr.asFunction<JniResult Function(JStringPtr)>();
+
+ JniResult PortContinuation__ctor(
+ int j,
+ ) {
+ return _PortContinuation__ctor(
+ j,
+ );
+ }
+
+ late final _PortContinuation__ctorPtr =
+ _lookup<ffi.NativeFunction<JniResult Function(ffi.Int64)>>(
+ 'PortContinuation__ctor');
+ late final _PortContinuation__ctor =
+ _PortContinuation__ctorPtr.asFunction<JniResult Function(int)>();
+
+ JniResult PortProxy__newInstance(
+ JObjectPtr binaryName,
+ int port,
+ int functionPtr,
+ ) {
+ return _PortProxy__newInstance(
+ binaryName,
+ port,
+ functionPtr,
+ );
+ }
+
+ late final _PortProxy__newInstancePtr = _lookup<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, ffi.Int64, ffi.Int64)>>('PortProxy__newInstance');
+ late final _PortProxy__newInstance = _PortProxy__newInstancePtr.asFunction<
+ JniResult Function(JObjectPtr, int, int)>();
+
+ void resultFor(
+ ffi.Pointer<CallbackResult> result,
+ JObjectPtr object,
+ ) {
+ return _resultFor(
+ result,
+ object,
+ );
+ }
+
+ late final _resultForPtr = _lookup<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<CallbackResult>, JObjectPtr)>>('resultFor');
+ late final _resultFor = _resultForPtr
+ .asFunction<void Function(ffi.Pointer<CallbackResult>, JObjectPtr)>();
+
+ ffi.Pointer<GlobalJniEnvStruct> GetGlobalEnv() {
+ return _GetGlobalEnv();
+ }
+
+ late final _GetGlobalEnvPtr =
+ _lookup<ffi.NativeFunction<ffi.Pointer<GlobalJniEnvStruct> Function()>>(
+ 'GetGlobalEnv');
+ late final _GetGlobalEnv =
+ _GetGlobalEnvPtr.asFunction<ffi.Pointer<GlobalJniEnvStruct> Function()>();
+}
+
+/// Types used by JNI API to distinguish between primitive types.
+abstract class JniCallType {
+ static const int booleanType = 0;
+ static const int byteType = 1;
+ static const int shortType = 2;
+ static const int charType = 3;
+ static const int intType = 4;
+ static const int longType = 5;
+ static const int floatType = 6;
+ static const int doubleType = 7;
+ static const int objectType = 8;
+ static const int voidType = 9;
+}
+
+/// Result type for use by JNI.
+///
+/// If [exception] is null, it means the result is valid.
+/// It's assumed that the caller knows the expected type in [result].
+final class JniResult extends ffi.Struct {
+ external JValue value;
+
+ external JThrowablePtr exception;
+}
+
+final class JValue extends ffi.Union {
+ @JBooleanMarker()
+ external int z;
+
+ @JByteMarker()
+ external int b;
+
+ @JCharMarker()
+ external int c;
+
+ @JShortMarker()
+ external int s;
+
+ @JIntMarker()
+ external int i;
+
+ @JLongMarker()
+ external int j;
+
+ @JFloatMarker()
+ external double f;
+
+ @JDoubleMarker()
+ external double d;
+
+ external JObjectPtr l;
+}
+
+/// Primitive types that match up with Java equivalents.
+typedef JBooleanMarker = ffi.Uint8;
+typedef JByteMarker = ffi.Int8;
+typedef JCharMarker = ffi.Uint16;
+typedef JShortMarker = ffi.Int16;
+typedef JIntMarker = ffi.Int32;
+typedef JLongMarker = ffi.Int64;
+typedef JFloatMarker = ffi.Float;
+typedef JDoubleMarker = ffi.Double;
+
+/// Reference types, in C.
+typedef JObjectPtr = ffi.Pointer<ffi.Void>;
+typedef JThrowablePtr = JObjectPtr;
+
+/// Similar to [JniResult] but for class lookups.
+final class JniClassLookupResult extends ffi.Struct {
+ external JClassPtr value;
+
+ external JThrowablePtr exception;
+}
+
+typedef JClassPtr = JObjectPtr;
+
+/// Similar to [JniResult] but for method/field ID lookups.
+final class JniPointerResult extends ffi.Struct {
+ external ffi.Pointer<ffi.Void> value;
+
+ external JThrowablePtr exception;
+}
+
+/// JniExceptionDetails holds 2 jstring objects, one is the result of
+/// calling `toString` on exception object, other is stack trace;
+final class JniExceptionDetails extends ffi.Struct {
+ external JStringPtr message;
+
+ external JStringPtr stacktrace;
+}
+
+typedef JStringPtr = JObjectPtr;
+
+/// This struct contains functions which wrap method call / field access conveniently along with
+/// exception checking.
+///
+/// Flutter embedding checks for pending JNI exceptions before an FFI transition, which requires us
+/// to check for and clear the exception before returning to dart code, which requires these functions
+/// to return result types.
+final class JniAccessorsStruct extends ffi.Struct {
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniClassLookupResult Function(
+ ffi.Pointer<ffi.Char> internalName)>> getClass;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(
+ JClassPtr cls,
+ ffi.Pointer<ffi.Char> fieldName,
+ ffi.Pointer<ffi.Char> signature)>> getFieldID;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(
+ JClassPtr cls,
+ ffi.Pointer<ffi.Char> fieldName,
+ ffi.Pointer<ffi.Char> signature)>> getStaticFieldID;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(
+ JClassPtr cls,
+ ffi.Pointer<ffi.Char> methodName,
+ ffi.Pointer<ffi.Char> signature)>> getMethodID;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(
+ JClassPtr cls,
+ ffi.Pointer<ffi.Char> methodName,
+ ffi.Pointer<ffi.Char> signature)>> getStaticMethodID;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JClassPtr cls, JMethodIDPtr ctor, ffi.Pointer<JValue> args)>>
+ newObject;
+
+ external ffi.Pointer<
+ ffi
+ .NativeFunction<JniResult Function(JSizeMarker length, ffi.Int type)>>
+ newPrimitiveArray;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JSizeMarker length, JClassPtr elementClass,
+ JObjectPtr initialElement)>> newObjectArray;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JArrayPtr array, ffi.Int index, ffi.Int type)>>
+ getArrayElement;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+ ffi.Int callType, ffi.Pointer<JValue> args)>> callMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr cls, JMethodIDPtr methodID,
+ ffi.Int callType, ffi.Pointer<JValue> args)>> callStaticMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj, JFieldIDPtr fieldID, ffi.Int callType)>> getField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JClassPtr cls, JFieldIDPtr fieldID, ffi.Int callType)>>
+ getStaticField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniExceptionDetails Function(JThrowablePtr exception)>>
+ getExceptionDetails;
+}
+
+typedef JMethodIDPtr = ffi.Pointer<jmethodID_>;
+
+final class jmethodID_ extends ffi.Opaque {}
+
+/// "cardinal indices and sizes"
+typedef JSizeMarker = JIntMarker;
+typedef JArrayPtr = JObjectPtr;
+typedef JFieldIDPtr = ffi.Pointer<jfieldID_>;
+
+final class jfieldID_ extends ffi.Opaque {}
+
+typedef JavaVM = ffi.Pointer<JNIInvokeInterface>;
+
+/// JNI invocation interface.
+final class JNIInvokeInterface extends ffi.Struct {
+ external ffi.Pointer<ffi.Void> reserved0;
+
+ external ffi.Pointer<ffi.Void> reserved1;
+
+ external ffi.Pointer<ffi.Void> reserved2;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JIntMarker Function(ffi.Pointer<JavaVM1> vm)>>
+ DestroyJavaVM;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(
+ ffi.Pointer<JavaVM1> vm,
+ ffi.Pointer<ffi.Pointer<JniEnv>> p_env,
+ ffi.Pointer<ffi.Void> thr_args)>> AttachCurrentThread;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JIntMarker Function(ffi.Pointer<JavaVM1> vm)>>
+ DetachCurrentThread;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(
+ ffi.Pointer<JavaVM1> vm,
+ ffi.Pointer<ffi.Pointer<ffi.Void>> p_env,
+ JIntMarker version)>> GetEnv;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(
+ ffi.Pointer<JavaVM1> vm,
+ ffi.Pointer<ffi.Pointer<JniEnv>> p_env,
+ ffi.Pointer<ffi.Void> thr_args)>> AttachCurrentThreadAsDaemon;
+}
+
+typedef JavaVM1 = ffi.Pointer<JNIInvokeInterface>;
+typedef JniEnv = ffi.Pointer<JNINativeInterface>;
+
+/// Table of interface function pointers.
+final class JNINativeInterface extends ffi.Struct {
+ external ffi.Pointer<ffi.Void> reserved0;
+
+ external ffi.Pointer<ffi.Void> reserved1;
+
+ external ffi.Pointer<ffi.Void> reserved2;
+
+ external ffi.Pointer<ffi.Void> reserved3;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<JIntMarker Function(ffi.Pointer<JniEnv1> env)>>
+ GetVersion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JClassPtr Function(
+ ffi.Pointer<JniEnv1> env,
+ ffi.Pointer<ffi.Char> name,
+ JObjectPtr loader,
+ ffi.Pointer<JByteMarker> buf,
+ JSizeMarker bufLen)>> DefineClass;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JClassPtr Function(
+ ffi.Pointer<JniEnv1> env, ffi.Pointer<ffi.Char> name)>> FindClass;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JMethodIDPtr Function(
+ ffi.Pointer<JniEnv1> env, JObjectPtr method)>>
+ FromReflectedMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JFieldIDPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr field)>>
+ FromReflectedField;
+
+ /// spec doesn't show jboolean parameter
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(
+ ffi.Pointer<JniEnv1> env,
+ JClassPtr cls,
+ JMethodIDPtr methodId,
+ JBooleanMarker isStatic)>> ToReflectedMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JClassPtr Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz)>>
+ GetSuperclass;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JBooleanMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz1,
+ JClassPtr clazz2)>> IsAssignableFrom;
+
+ /// spec doesn't show jboolean parameter
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(ffi.Pointer<JniEnv1> env, JClassPtr cls,
+ JFieldIDPtr fieldID, JBooleanMarker isStatic)>> ToReflectedField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(ffi.Pointer<JniEnv1> env, JThrowablePtr obj)>>
+ Throw;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ ffi.Pointer<ffi.Char> message)>> ThrowNew;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<JThrowablePtr Function(ffi.Pointer<JniEnv1> env)>>
+ ExceptionOccurred;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<JniEnv1> env)>>
+ ExceptionDescribe;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<JniEnv1> env)>>
+ ExceptionClear;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env, ffi.Pointer<ffi.Char> msg)>> FatalError;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(
+ ffi.Pointer<JniEnv1> env, JIntMarker capacity)>> PushLocalFrame;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr result)>>
+ PopLocalFrame;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj)>>
+ NewGlobalRef;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env, JObjectPtr globalRef)>> DeleteGlobalRef;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr localRef)>>
+ DeleteLocalRef;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JBooleanMarker Function(
+ ffi.Pointer<JniEnv1> env, JObjectPtr ref1, JObjectPtr ref2)>>
+ IsSameObject;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj)>>
+ NewLocalRef;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(
+ ffi.Pointer<JniEnv1> env, JIntMarker capacity)>>
+ EnsureLocalCapacity;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz)>>
+ AllocObject;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JMethodIDPtr methodID)>> NewObject;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> NewObjectV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args)>> NewObjectA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JClassPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj)>>
+ GetObjectClass;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JBooleanMarker Function(
+ ffi.Pointer<JniEnv1> env, JObjectPtr obj, JClassPtr clazz)>>
+ IsInstanceOf;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JMethodIDPtr Function(
+ ffi.Pointer<JniEnv1> env,
+ JClassPtr clazz,
+ ffi.Pointer<ffi.Char> name,
+ ffi.Pointer<ffi.Char> sig)>> GetMethodID;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JMethodIDPtr methodID)>> CallObjectMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallObjectMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallObjectMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JBooleanMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JMethodIDPtr methodID)>> CallBooleanMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JBooleanMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr,
+ JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallBooleanMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JBooleanMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JMethodIDPtr methodId,
+ ffi.Pointer<JValue> args)>> CallBooleanMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JByteMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JMethodIDPtr methodID)>> CallByteMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JByteMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallByteMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JByteMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallByteMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JCharMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JMethodIDPtr methodID)>> CallCharMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JCharMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallCharMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JCharMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallCharMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JShortMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JMethodIDPtr methodID)>> CallShortMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JShortMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallShortMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JShortMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallShortMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JMethodIDPtr methodID)>> CallIntMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallIntMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JMethodIDPtr methodID, ffi.Pointer<JValue> args)>> CallIntMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JLongMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JMethodIDPtr methodID)>> CallLongMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JLongMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallLongMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JLongMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallLongMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JFloatMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JMethodIDPtr methodID)>> CallFloatMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JFloatMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallFloatMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JFloatMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallFloatMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JDoubleMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JMethodIDPtr methodID)>> CallDoubleMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JDoubleMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallDoubleMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JDoubleMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallDoubleMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JMethodIDPtr methodID)>> CallVoidMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1>, JObjectPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallVoidMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallVoidMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallNonvirtualObjectMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(
+ ffi.Pointer<JniEnv1>,
+ JObjectPtr,
+ JClassPtr,
+ JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallNonvirtualObjectMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualObjectMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JBooleanMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallNonvirtualBooleanMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JBooleanMarker Function(
+ ffi.Pointer<JniEnv1>,
+ JObjectPtr,
+ JClassPtr,
+ JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallNonvirtualBooleanMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JBooleanMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualBooleanMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JByteMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallNonvirtualByteMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JByteMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
+ JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallNonvirtualByteMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JByteMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualByteMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JCharMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallNonvirtualCharMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JCharMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
+ JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallNonvirtualCharMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JCharMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualCharMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JShortMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallNonvirtualShortMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JShortMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
+ JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallNonvirtualShortMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JShortMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualShortMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JClassPtr clazz, JMethodIDPtr methodID)>> CallNonvirtualIntMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
+ JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallNonvirtualIntMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualIntMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JLongMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallNonvirtualLongMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JLongMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
+ JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallNonvirtualLongMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JLongMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualLongMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JFloatMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallNonvirtualFloatMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JFloatMarker Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
+ JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallNonvirtualFloatMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JFloatMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualFloatMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JDoubleMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallNonvirtualDoubleMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JDoubleMarker Function(
+ ffi.Pointer<JniEnv1>,
+ JObjectPtr,
+ JClassPtr,
+ JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallNonvirtualDoubleMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JDoubleMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualDoubleMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallNonvirtualVoidMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1>, JObjectPtr, JClassPtr,
+ JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallNonvirtualVoidMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualVoidMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JFieldIDPtr Function(
+ ffi.Pointer<JniEnv1> env,
+ JClassPtr clazz,
+ ffi.Pointer<ffi.Char> name,
+ ffi.Pointer<ffi.Char> sig)>> GetFieldID;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID)>> GetObjectField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JBooleanMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID)>> GetBooleanField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JByteMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID)>> GetByteField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JCharMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID)>> GetCharField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JShortMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID)>> GetShortField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID)>> GetIntField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JLongMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID)>> GetLongField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JFloatMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID)>> GetFloatField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JDoubleMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID)>> GetDoubleField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID, JObjectPtr val)>> SetObjectField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID, JBooleanMarker val)>> SetBooleanField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID, JByteMarker val)>> SetByteField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID, JCharMarker val)>> SetCharField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID, JShortMarker val)>> SetShortField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID, JIntMarker val)>> SetIntField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID, JLongMarker val)>> SetLongField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID, JFloatMarker val)>> SetFloatField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj,
+ JFieldIDPtr fieldID, JDoubleMarker val)>> SetDoubleField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JMethodIDPtr Function(
+ ffi.Pointer<JniEnv1> env,
+ JClassPtr clazz,
+ ffi.Pointer<ffi.Char> name,
+ ffi.Pointer<ffi.Char> sig)>> GetStaticMethodID;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallStaticObjectMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallStaticObjectMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(
+ ffi.Pointer<JniEnv1> env,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticObjectMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JBooleanMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallStaticBooleanMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JBooleanMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallStaticBooleanMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JBooleanMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticBooleanMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JByteMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallStaticByteMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JByteMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallStaticByteMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JByteMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticByteMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JCharMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallStaticCharMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JCharMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallStaticCharMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JCharMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticCharMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JShortMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallStaticShortMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JShortMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallStaticShortMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JShortMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticShortMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallStaticIntMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallStaticIntMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticIntMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JLongMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallStaticLongMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JLongMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallStaticLongMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JLongMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticLongMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JFloatMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallStaticFloatMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JFloatMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallStaticFloatMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JFloatMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticFloatMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JDoubleMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallStaticDoubleMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JDoubleMarker Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallStaticDoubleMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JDoubleMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticDoubleMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JMethodIDPtr methodID)>> CallStaticVoidMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1>, JClassPtr, JMethodIDPtr,
+ ffi.Pointer<ffi.Void>)>> CallStaticVoidMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticVoidMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JFieldIDPtr Function(
+ ffi.Pointer<JniEnv1> env,
+ JClassPtr clazz,
+ ffi.Pointer<ffi.Char> name,
+ ffi.Pointer<ffi.Char> sig)>> GetStaticFieldID;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID)>> GetStaticObjectField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JBooleanMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID)>> GetStaticBooleanField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JByteMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID)>> GetStaticByteField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JCharMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID)>> GetStaticCharField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JShortMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID)>> GetStaticShortField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID)>> GetStaticIntField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JLongMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID)>> GetStaticLongField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JFloatMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID)>> GetStaticFloatField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JDoubleMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID)>> GetStaticDoubleField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID, JObjectPtr val)>> SetStaticObjectField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID, JBooleanMarker val)>> SetStaticBooleanField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID, JByteMarker val)>> SetStaticByteField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID, JCharMarker val)>> SetStaticCharField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID, JShortMarker val)>> SetStaticShortField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID, JIntMarker val)>> SetStaticIntField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID, JLongMarker val)>> SetStaticLongField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID, JFloatMarker val)>> SetStaticFloatField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz,
+ JFieldIDPtr fieldID, JDoubleMarker val)>> SetStaticDoubleField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JStringPtr Function(
+ ffi.Pointer<JniEnv1> env,
+ ffi.Pointer<JCharMarker> unicodeChars,
+ JSizeMarker len)>> NewString;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JSizeMarker Function(
+ ffi.Pointer<JniEnv1> env, JStringPtr string)>> GetStringLength;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Pointer<JCharMarker> Function(
+ ffi.Pointer<JniEnv1> env,
+ JStringPtr string,
+ ffi.Pointer<JBooleanMarker> isCopy)>> GetStringChars;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JStringPtr string,
+ ffi.Pointer<JCharMarker> isCopy)>> ReleaseStringChars;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JStringPtr Function(
+ ffi.Pointer<JniEnv1> env, ffi.Pointer<ffi.Char> bytes)>>
+ NewStringUTF;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JSizeMarker Function(
+ ffi.Pointer<JniEnv1> env, JStringPtr string)>> GetStringUTFLength;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Pointer<ffi.Char> Function(
+ ffi.Pointer<JniEnv1> env,
+ JStringPtr string,
+ ffi.Pointer<JBooleanMarker> isCopy)>> GetStringUTFChars;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JStringPtr string,
+ ffi.Pointer<ffi.Char> utf)>> ReleaseStringUTFChars;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JSizeMarker Function(ffi.Pointer<JniEnv1> env, JArrayPtr array)>>
+ GetArrayLength;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectArrayPtr Function(
+ ffi.Pointer<JniEnv1> env,
+ JSizeMarker length,
+ JClassPtr elementClass,
+ JObjectPtr initialElement)>> NewObjectArray;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(ffi.Pointer<JniEnv1> env, JObjectArrayPtr array,
+ JSizeMarker index)>> GetObjectArrayElement;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JObjectArrayPtr array,
+ JSizeMarker index, JObjectPtr val)>> SetObjectArrayElement;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JBooleanArrayPtr Function(
+ ffi.Pointer<JniEnv1> env, JSizeMarker length)>> NewBooleanArray;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JByteArrayPtr Function(
+ ffi.Pointer<JniEnv1> env, JSizeMarker length)>> NewByteArray;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JCharArrayPtr Function(
+ ffi.Pointer<JniEnv1> env, JSizeMarker length)>> NewCharArray;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JShortArrayPtr Function(
+ ffi.Pointer<JniEnv1> env, JSizeMarker length)>> NewShortArray;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntArrayPtr Function(
+ ffi.Pointer<JniEnv1> env, JSizeMarker length)>> NewIntArray;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JLongArrayPtr Function(
+ ffi.Pointer<JniEnv1> env, JSizeMarker length)>> NewLongArray;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JFloatArrayPtr Function(
+ ffi.Pointer<JniEnv1> env, JSizeMarker length)>> NewFloatArray;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JDoubleArrayPtr Function(
+ ffi.Pointer<JniEnv1> env, JSizeMarker length)>> NewDoubleArray;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Pointer<JBooleanMarker> Function(
+ ffi.Pointer<JniEnv1> env,
+ JBooleanArrayPtr array,
+ ffi.Pointer<JBooleanMarker> isCopy)>> GetBooleanArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Pointer<JByteMarker> Function(
+ ffi.Pointer<JniEnv1> env,
+ JByteArrayPtr array,
+ ffi.Pointer<JBooleanMarker> isCopy)>> GetByteArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Pointer<JCharMarker> Function(
+ ffi.Pointer<JniEnv1> env,
+ JCharArrayPtr array,
+ ffi.Pointer<JBooleanMarker> isCopy)>> GetCharArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Pointer<JShortMarker> Function(
+ ffi.Pointer<JniEnv1> env,
+ JShortArrayPtr array,
+ ffi.Pointer<JBooleanMarker> isCopy)>> GetShortArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Pointer<JIntMarker> Function(
+ ffi.Pointer<JniEnv1> env,
+ JIntArrayPtr array,
+ ffi.Pointer<JBooleanMarker> isCopy)>> GetIntArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Pointer<JLongMarker> Function(
+ ffi.Pointer<JniEnv1> env,
+ JLongArrayPtr array,
+ ffi.Pointer<JBooleanMarker> isCopy)>> GetLongArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Pointer<JFloatMarker> Function(
+ ffi.Pointer<JniEnv1> env,
+ JFloatArrayPtr array,
+ ffi.Pointer<JBooleanMarker> isCopy)>> GetFloatArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Pointer<JDoubleMarker> Function(
+ ffi.Pointer<JniEnv1> env,
+ JDoubleArrayPtr array,
+ ffi.Pointer<JBooleanMarker> isCopy)>> GetDoubleArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JBooleanArrayPtr array,
+ ffi.Pointer<JBooleanMarker> elems,
+ JIntMarker mode)>> ReleaseBooleanArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JByteArrayPtr array,
+ ffi.Pointer<JByteMarker> elems,
+ JIntMarker mode)>> ReleaseByteArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JCharArrayPtr array,
+ ffi.Pointer<JCharMarker> elems,
+ JIntMarker mode)>> ReleaseCharArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JShortArrayPtr array,
+ ffi.Pointer<JShortMarker> elems,
+ JIntMarker mode)>> ReleaseShortArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JIntArrayPtr array,
+ ffi.Pointer<JIntMarker> elems,
+ JIntMarker mode)>> ReleaseIntArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JLongArrayPtr array,
+ ffi.Pointer<JLongMarker> elems,
+ JIntMarker mode)>> ReleaseLongArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JFloatArrayPtr array,
+ ffi.Pointer<JFloatMarker> elems,
+ JIntMarker mode)>> ReleaseFloatArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JDoubleArrayPtr array,
+ ffi.Pointer<JDoubleMarker> elems,
+ JIntMarker mode)>> ReleaseDoubleArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JBooleanArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JBooleanMarker> buf)>> GetBooleanArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JByteArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JByteMarker> buf)>> GetByteArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JCharArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JCharMarker> buf)>> GetCharArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JShortArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JShortMarker> buf)>> GetShortArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JIntArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JIntMarker> buf)>> GetIntArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JLongArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JLongMarker> buf)>> GetLongArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JFloatArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JFloatMarker> buf)>> GetFloatArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JDoubleArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JDoubleMarker> buf)>> GetDoubleArrayRegion;
+
+ /// spec shows these without const; some jni.h do, some don't
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JBooleanArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JBooleanMarker> buf)>> SetBooleanArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JByteArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JByteMarker> buf)>> SetByteArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JCharArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JCharMarker> buf)>> SetCharArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JShortArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JShortMarker> buf)>> SetShortArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JIntArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JIntMarker> buf)>> SetIntArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JLongArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JLongMarker> buf)>> SetLongArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JFloatArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JFloatMarker> buf)>> SetFloatArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JDoubleArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JDoubleMarker> buf)>> SetDoubleArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(
+ ffi.Pointer<JniEnv1> env,
+ JClassPtr clazz,
+ ffi.Pointer<JNINativeMethod> methods,
+ JIntMarker nMethods)>> RegisterNatives;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(ffi.Pointer<JniEnv1> env, JClassPtr clazz)>>
+ UnregisterNatives;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj)>>
+ MonitorEnter;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj)>>
+ MonitorExit;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JIntMarker Function(ffi.Pointer<JniEnv1> env,
+ ffi.Pointer<ffi.Pointer<JavaVM1>> vm)>> GetJavaVM;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JStringPtr str,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JCharMarker> buf)>> GetStringRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JStringPtr str,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<ffi.Char> buf)>> GetStringUTFRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Pointer<ffi.Void> Function(
+ ffi.Pointer<JniEnv1> env,
+ JArrayPtr array,
+ ffi.Pointer<JBooleanMarker> isCopy)>> GetPrimitiveArrayCritical;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(
+ ffi.Pointer<JniEnv1> env,
+ JArrayPtr array,
+ ffi.Pointer<ffi.Void> carray,
+ JIntMarker mode)>> ReleasePrimitiveArrayCritical;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Pointer<JCharMarker> Function(
+ ffi.Pointer<JniEnv1> env,
+ JStringPtr str,
+ ffi.Pointer<JBooleanMarker> isCopy)>> GetStringCritical;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JStringPtr str,
+ ffi.Pointer<JCharMarker> carray)>> ReleaseStringCritical;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JWeakPtr Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj)>>
+ NewWeakGlobalRef;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Void Function(ffi.Pointer<JniEnv1> env, JWeakPtr obj)>>
+ DeleteWeakGlobalRef;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<JBooleanMarker Function(ffi.Pointer<JniEnv1> env)>>
+ ExceptionCheck;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JObjectPtr Function(
+ ffi.Pointer<JniEnv1> env,
+ ffi.Pointer<ffi.Void> address,
+ JLongMarker capacity)>> NewDirectByteBuffer;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Pointer<ffi.Void> Function(
+ ffi.Pointer<JniEnv1> env, JObjectPtr buf)>>
+ GetDirectBufferAddress;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JLongMarker Function(ffi.Pointer<JniEnv1> env, JObjectPtr buf)>>
+ GetDirectBufferCapacity;
+
+ /// added in JNI 1.6
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ ffi.Int32 Function(ffi.Pointer<JniEnv1> env, JObjectPtr obj)>>
+ GetObjectRefType;
+}
+
+typedef JniEnv1 = ffi.Pointer<JNINativeInterface>;
+typedef JObjectArrayPtr = JArrayPtr;
+typedef JBooleanArrayPtr = JArrayPtr;
+typedef JByteArrayPtr = JArrayPtr;
+typedef JCharArrayPtr = JArrayPtr;
+typedef JShortArrayPtr = JArrayPtr;
+typedef JIntArrayPtr = JArrayPtr;
+typedef JLongArrayPtr = JArrayPtr;
+typedef JFloatArrayPtr = JArrayPtr;
+typedef JDoubleArrayPtr = JArrayPtr;
+
+final class JNINativeMethod extends ffi.Struct {
+ external ffi.Pointer<ffi.Char> name;
+
+ external ffi.Pointer<ffi.Char> signature;
+
+ external ffi.Pointer<ffi.Void> fnPtr;
+}
+
+typedef JWeakPtr = JObjectPtr;
+
+abstract class JObjectRefType {
+ static const int JNIInvalidRefType = 0;
+ static const int JNILocalRefType = 1;
+ static const int JNIGlobalRefType = 2;
+ static const int JNIWeakGlobalRefType = 3;
+}
+
+final class JavaVMInitArgs extends ffi.Struct {
+ /// use JNI_VERSION_1_2 or later
+ @JIntMarker()
+ external int version;
+
+ @JIntMarker()
+ external int nOptions;
+
+ external ffi.Pointer<JavaVMOption> options;
+
+ @JBooleanMarker()
+ external int ignoreUnrecognized;
+}
+
+/// JNI 1.2+ initialization. (As of 1.6, the pre-1.2 structures are no
+/// longer supported.)
+final class JavaVMOption extends ffi.Struct {
+ external ffi.Pointer<ffi.Char> optionString;
+
+ external ffi.Pointer<ffi.Void> extraInfo;
+}
+
+final class CallbackResult extends ffi.Struct {
+ external MutexLock lock;
+
+ external ConditionVariable cond;
+
+ @ffi.Int()
+ external int ready;
+
+ external JObjectPtr object;
+}
+
+typedef MutexLock = pthread_mutex_t;
+typedef pthread_mutex_t = __darwin_pthread_mutex_t;
+typedef __darwin_pthread_mutex_t = _opaque_pthread_mutex_t;
+
+final class _opaque_pthread_mutex_t extends ffi.Struct {
+ @ffi.Long()
+ external int __sig;
+
+ @ffi.Array.multi([56])
+ external ffi.Array<ffi.Char> __opaque;
+}
+
+typedef ConditionVariable = pthread_cond_t;
+typedef pthread_cond_t = __darwin_pthread_cond_t;
+typedef __darwin_pthread_cond_t = _opaque_pthread_cond_t;
+
+final class _opaque_pthread_cond_t extends ffi.Struct {
+ @ffi.Long()
+ external int __sig;
+
+ @ffi.Array.multi([40])
+ external ffi.Array<ffi.Char> __opaque;
+}
+
+final class GlobalJniEnvStruct extends ffi.Struct {
+ external ffi.Pointer<ffi.Void> reserved0;
+
+ external ffi.Pointer<ffi.Void> reserved1;
+
+ external ffi.Pointer<ffi.Void> reserved2;
+
+ external ffi.Pointer<ffi.Void> reserved3;
+
+ external ffi.Pointer<ffi.NativeFunction<JniResult Function()>> GetVersion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniClassLookupResult Function(
+ ffi.Pointer<ffi.Char> name,
+ JObjectPtr loader,
+ ffi.Pointer<JByteMarker> buf,
+ JSizeMarker bufLen)>> DefineClass;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniClassLookupResult Function(ffi.Pointer<ffi.Char> name)>> FindClass;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JniPointerResult Function(JObjectPtr method)>>
+ FromReflectedMethod;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JniPointerResult Function(JObjectPtr field)>>
+ FromReflectedField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr cls, JMethodIDPtr methodId,
+ JBooleanMarker isStatic)>> ToReflectedMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<JniClassLookupResult Function(JClassPtr clazz)>>
+ GetSuperclass;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz1, JClassPtr clazz2)>>
+ IsAssignableFrom;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JClassPtr cls, JFieldIDPtr fieldID, JBooleanMarker isStatic)>>
+ ToReflectedField;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JniResult Function(JThrowablePtr obj)>> Throw;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JClassPtr clazz, ffi.Pointer<ffi.Char> message)>> ThrowNew;
+
+ external ffi.Pointer<ffi.NativeFunction<JniResult Function()>>
+ ExceptionOccurred;
+
+ external ffi.Pointer<ffi.NativeFunction<JThrowablePtr Function()>>
+ ExceptionDescribe;
+
+ external ffi.Pointer<ffi.NativeFunction<JThrowablePtr Function()>>
+ ExceptionClear;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<JThrowablePtr Function(ffi.Pointer<ffi.Char> msg)>>
+ FatalError;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JniResult Function(JIntMarker capacity)>>
+ PushLocalFrame;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JniResult Function(JObjectPtr result)>>
+ PopLocalFrame;
+
+ external ffi.Pointer<ffi.NativeFunction<JniResult Function(JObjectPtr obj)>>
+ NewGlobalRef;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JThrowablePtr Function(JObjectPtr globalRef)>>
+ DeleteGlobalRef;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JThrowablePtr Function(JObjectPtr localRef)>>
+ DeleteLocalRef;
+
+ external ffi.Pointer<
+ ffi
+ .NativeFunction<JniResult Function(JObjectPtr ref1, JObjectPtr ref2)>>
+ IsSameObject;
+
+ external ffi.Pointer<ffi.NativeFunction<JniResult Function(JObjectPtr obj)>>
+ NewLocalRef;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JniResult Function(JIntMarker capacity)>>
+ EnsureLocalCapacity;
+
+ external ffi.Pointer<ffi.NativeFunction<JniResult Function(JClassPtr clazz)>>
+ AllocObject;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
+ NewObject;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>> NewObjectV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> NewObjectA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<JniClassLookupResult Function(JObjectPtr obj)>>
+ GetObjectClass;
+
+ external ffi.Pointer<
+ ffi
+ .NativeFunction<JniResult Function(JObjectPtr obj, JClassPtr clazz)>>
+ IsInstanceOf;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+ ffi.Pointer<ffi.Char> sig)>> GetMethodID;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
+ CallObjectMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallObjectMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallObjectMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
+ CallBooleanMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallBooleanMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodId,
+ ffi.Pointer<JValue> args)>> CallBooleanMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
+ CallByteMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallByteMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallByteMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
+ CallCharMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallCharMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallCharMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
+ CallShortMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallShortMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallShortMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
+ CallIntMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>> CallIntMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallIntMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
+ CallLongMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallLongMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallLongMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
+ CallFloatMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallFloatMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallFloatMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID)>>
+ CallDoubleMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallDoubleMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallDoubleMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(JObjectPtr obj, JMethodIDPtr methodID)>>
+ CallVoidMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JObjectPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallVoidMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(JObjectPtr obj, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallVoidMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallNonvirtualObjectMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallNonvirtualObjectMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualObjectMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallNonvirtualBooleanMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallNonvirtualBooleanMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualBooleanMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallNonvirtualByteMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallNonvirtualByteMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualByteMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallNonvirtualCharMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallNonvirtualCharMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualCharMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallNonvirtualShortMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallNonvirtualShortMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualShortMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallNonvirtualIntMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallNonvirtualIntMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualIntMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallNonvirtualLongMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallNonvirtualLongMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualLongMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallNonvirtualFloatMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallNonvirtualFloatMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualFloatMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallNonvirtualDoubleMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallNonvirtualDoubleMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualDoubleMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JObjectPtr obj, JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallNonvirtualVoidMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JObjectPtr, JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallNonvirtualVoidMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JObjectPtr obj,
+ JClassPtr clazz,
+ JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallNonvirtualVoidMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+ ffi.Pointer<ffi.Char> sig)>> GetFieldID;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>>
+ GetObjectField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>>
+ GetBooleanField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>>
+ GetByteField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>>
+ GetCharField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>>
+ GetShortField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>> GetIntField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>>
+ GetLongField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>>
+ GetFloatField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectPtr obj, JFieldIDPtr fieldID)>>
+ GetDoubleField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JObjectPtr obj, JFieldIDPtr fieldID, JObjectPtr val)>>
+ SetObjectField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JObjectPtr obj, JFieldIDPtr fieldID, JBooleanMarker val)>>
+ SetBooleanField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JObjectPtr obj, JFieldIDPtr fieldID, JByteMarker val)>>
+ SetByteField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JObjectPtr obj, JFieldIDPtr fieldID, JCharMarker val)>>
+ SetCharField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JObjectPtr obj, JFieldIDPtr fieldID, JShortMarker val)>>
+ SetShortField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JObjectPtr obj, JFieldIDPtr fieldID, JIntMarker val)>>
+ SetIntField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JObjectPtr obj, JFieldIDPtr fieldID, JLongMarker val)>>
+ SetLongField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JObjectPtr obj, JFieldIDPtr fieldID, JFloatMarker val)>>
+ SetFloatField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JObjectPtr obj, JFieldIDPtr fieldID, JDoubleMarker val)>>
+ SetDoubleField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+ ffi.Pointer<ffi.Char> sig)>> GetStaticMethodID;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallStaticObjectMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallStaticObjectMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticObjectMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallStaticBooleanMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallStaticBooleanMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticBooleanMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallStaticByteMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallStaticByteMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticByteMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallStaticCharMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallStaticCharMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticCharMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallStaticShortMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallStaticShortMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticShortMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallStaticIntMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallStaticIntMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticIntMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallStaticLongMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallStaticLongMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticLongMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallStaticFloatMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallStaticFloatMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticFloatMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallStaticDoubleMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallStaticDoubleMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticDoubleMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(JClassPtr clazz, JMethodIDPtr methodID)>>
+ CallStaticVoidMethod;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JClassPtr, JMethodIDPtr, ffi.Pointer<ffi.Void>)>>
+ CallStaticVoidMethodV;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(JClassPtr clazz, JMethodIDPtr methodID,
+ ffi.Pointer<JValue> args)>> CallStaticVoidMethodA;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(JClassPtr clazz, ffi.Pointer<ffi.Char> name,
+ ffi.Pointer<ffi.Char> sig)>> GetStaticFieldID;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
+ GetStaticObjectField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
+ GetStaticBooleanField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
+ GetStaticByteField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
+ GetStaticCharField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
+ GetStaticShortField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
+ GetStaticIntField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
+ GetStaticLongField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
+ GetStaticFloatField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JClassPtr clazz, JFieldIDPtr fieldID)>>
+ GetStaticDoubleField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JClassPtr clazz, JFieldIDPtr fieldID, JObjectPtr val)>>
+ SetStaticObjectField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JClassPtr clazz, JFieldIDPtr fieldID, JBooleanMarker val)>>
+ SetStaticBooleanField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JClassPtr clazz, JFieldIDPtr fieldID, JByteMarker val)>>
+ SetStaticByteField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JClassPtr clazz, JFieldIDPtr fieldID, JCharMarker val)>>
+ SetStaticCharField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JClassPtr clazz, JFieldIDPtr fieldID, JShortMarker val)>>
+ SetStaticShortField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JClassPtr clazz, JFieldIDPtr fieldID, JIntMarker val)>>
+ SetStaticIntField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JClassPtr clazz, JFieldIDPtr fieldID, JLongMarker val)>>
+ SetStaticLongField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JClassPtr clazz, JFieldIDPtr fieldID, JFloatMarker val)>>
+ SetStaticFloatField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JClassPtr clazz, JFieldIDPtr fieldID, JDoubleMarker val)>>
+ SetStaticDoubleField;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ ffi.Pointer<JCharMarker> unicodeChars, JSizeMarker len)>>
+ NewString;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JniResult Function(JStringPtr string)>>
+ GetStringLength;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(
+ JStringPtr string, ffi.Pointer<JBooleanMarker> isCopy)>>
+ GetStringChars;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JStringPtr string, ffi.Pointer<JCharMarker> isCopy)>>
+ ReleaseStringChars;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<JniResult Function(ffi.Pointer<ffi.Char> bytes)>>
+ NewStringUTF;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JniResult Function(JStringPtr string)>>
+ GetStringUTFLength;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(
+ JStringPtr string, ffi.Pointer<JBooleanMarker> isCopy)>>
+ GetStringUTFChars;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JStringPtr string, ffi.Pointer<ffi.Char> utf)>>
+ ReleaseStringUTFChars;
+
+ external ffi.Pointer<ffi.NativeFunction<JniResult Function(JArrayPtr array)>>
+ GetArrayLength;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JSizeMarker length, JClassPtr elementClass,
+ JObjectPtr initialElement)>> NewObjectArray;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(JObjectArrayPtr array, JSizeMarker index)>>
+ GetObjectArrayElement;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JObjectArrayPtr array, JSizeMarker index, JObjectPtr val)>>
+ SetObjectArrayElement;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JniResult Function(JSizeMarker length)>>
+ NewBooleanArray;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JniResult Function(JSizeMarker length)>>
+ NewByteArray;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JniResult Function(JSizeMarker length)>>
+ NewCharArray;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JniResult Function(JSizeMarker length)>>
+ NewShortArray;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JniResult Function(JSizeMarker length)>>
+ NewIntArray;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JniResult Function(JSizeMarker length)>>
+ NewLongArray;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JniResult Function(JSizeMarker length)>>
+ NewFloatArray;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JniResult Function(JSizeMarker length)>>
+ NewDoubleArray;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(
+ JBooleanArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
+ GetBooleanArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(
+ JByteArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
+ GetByteArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(
+ JCharArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
+ GetCharArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(
+ JShortArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
+ GetShortArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(
+ JIntArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
+ GetIntArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(
+ JLongArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
+ GetLongArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(
+ JFloatArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
+ GetFloatArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(
+ JDoubleArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
+ GetDoubleArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JBooleanArrayPtr array,
+ ffi.Pointer<JBooleanMarker> elems,
+ JIntMarker mode)>> ReleaseBooleanArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JByteArrayPtr array,
+ ffi.Pointer<JByteMarker> elems,
+ JIntMarker mode)>> ReleaseByteArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JCharArrayPtr array,
+ ffi.Pointer<JCharMarker> elems,
+ JIntMarker mode)>> ReleaseCharArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JShortArrayPtr array,
+ ffi.Pointer<JShortMarker> elems,
+ JIntMarker mode)>> ReleaseShortArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JIntArrayPtr array,
+ ffi.Pointer<JIntMarker> elems,
+ JIntMarker mode)>> ReleaseIntArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JLongArrayPtr array,
+ ffi.Pointer<JLongMarker> elems,
+ JIntMarker mode)>> ReleaseLongArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JFloatArrayPtr array,
+ ffi.Pointer<JFloatMarker> elems,
+ JIntMarker mode)>> ReleaseFloatArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JDoubleArrayPtr array,
+ ffi.Pointer<JDoubleMarker> elems,
+ JIntMarker mode)>> ReleaseDoubleArrayElements;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JBooleanArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JBooleanMarker> buf)>> GetBooleanArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JByteArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JByteMarker> buf)>> GetByteArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JCharArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JCharMarker> buf)>> GetCharArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JShortArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JShortMarker> buf)>> GetShortArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(JIntArrayPtr array, JSizeMarker start,
+ JSizeMarker len, ffi.Pointer<JIntMarker> buf)>> GetIntArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JLongArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JLongMarker> buf)>> GetLongArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JFloatArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JFloatMarker> buf)>> GetFloatArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JDoubleArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JDoubleMarker> buf)>> GetDoubleArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JBooleanArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JBooleanMarker> buf)>> SetBooleanArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JByteArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JByteMarker> buf)>> SetByteArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JCharArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JCharMarker> buf)>> SetCharArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JShortArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JShortMarker> buf)>> SetShortArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(JIntArrayPtr array, JSizeMarker start,
+ JSizeMarker len, ffi.Pointer<JIntMarker> buf)>> SetIntArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JLongArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JLongMarker> buf)>> SetLongArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JFloatArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JFloatMarker> buf)>> SetFloatArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JDoubleArrayPtr array,
+ JSizeMarker start,
+ JSizeMarker len,
+ ffi.Pointer<JDoubleMarker> buf)>> SetDoubleArrayRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ JClassPtr clazz,
+ ffi.Pointer<JNINativeMethod> methods,
+ JIntMarker nMethods)>> RegisterNatives;
+
+ external ffi.Pointer<ffi.NativeFunction<JniResult Function(JClassPtr clazz)>>
+ UnregisterNatives;
+
+ external ffi.Pointer<ffi.NativeFunction<JniResult Function(JObjectPtr obj)>>
+ MonitorEnter;
+
+ external ffi.Pointer<ffi.NativeFunction<JniResult Function(JObjectPtr obj)>>
+ MonitorExit;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(ffi.Pointer<ffi.Pointer<JavaVM>> vm)>> GetJavaVM;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(JStringPtr str, JSizeMarker start,
+ JSizeMarker len, ffi.Pointer<JCharMarker> buf)>> GetStringRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(JStringPtr str, JSizeMarker start,
+ JSizeMarker len, ffi.Pointer<ffi.Char> buf)>> GetStringUTFRegion;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(
+ JArrayPtr array, ffi.Pointer<JBooleanMarker> isCopy)>>
+ GetPrimitiveArrayCritical;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(JArrayPtr array, ffi.Pointer<ffi.Void> carray,
+ JIntMarker mode)>> ReleasePrimitiveArrayCritical;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniPointerResult Function(
+ JStringPtr str, ffi.Pointer<JBooleanMarker> isCopy)>>
+ GetStringCritical;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JThrowablePtr Function(
+ JStringPtr str, ffi.Pointer<JCharMarker> carray)>>
+ ReleaseStringCritical;
+
+ external ffi.Pointer<ffi.NativeFunction<JniResult Function(JObjectPtr obj)>>
+ NewWeakGlobalRef;
+
+ external ffi.Pointer<ffi.NativeFunction<JThrowablePtr Function(JWeakPtr obj)>>
+ DeleteWeakGlobalRef;
+
+ external ffi.Pointer<ffi.NativeFunction<JniResult Function()>> ExceptionCheck;
+
+ external ffi.Pointer<
+ ffi.NativeFunction<
+ JniResult Function(
+ ffi.Pointer<ffi.Void> address, JLongMarker capacity)>>
+ NewDirectByteBuffer;
+
+ external ffi
+ .Pointer<ffi.NativeFunction<JniPointerResult Function(JObjectPtr buf)>>
+ GetDirectBufferAddress;
+
+ external ffi.Pointer<ffi.NativeFunction<JniResult Function(JObjectPtr buf)>>
+ GetDirectBufferCapacity;
+
+ external ffi.Pointer<ffi.NativeFunction<JniResult Function(JObjectPtr obj)>>
+ GetObjectRefType;
+}
+
+/// This file re-exports some JNI constants as enum, because they are not
+/// currently being included when they are in macro form.
+abstract class JniBooleanValues {
+ static const int JNI_FALSE = 0;
+ static const int JNI_TRUE = 1;
+}
+
+abstract class JniVersions {
+ static const int JNI_VERSION_1_1 = 65537;
+ static const int JNI_VERSION_1_2 = 65538;
+ static const int JNI_VERSION_1_4 = 65540;
+ static const int JNI_VERSION_1_6 = 65542;
+}
+
+abstract class JniErrorCode {
+ /// no error
+ static const int JNI_OK = 0;
+
+ /// generic error
+ static const int JNI_ERR = -1;
+
+ /// thread detached from the VM
+ static const int JNI_EDETACHED = -2;
+
+ /// JNI version error
+ static const int JNI_EVERSION = -3;
+
+ /// Out of memory
+ static const int JNI_ENOMEM = -4;
+
+ /// VM already created
+ static const int JNI_EEXIST = -5;
+
+ /// Invalid argument
+ static const int JNI_EINVAL = -6;
+}
+
+abstract class JniBufferWriteBack {
+ /// copy content, do not free buffer
+ static const int JNI_COMMIT = 1;
+
+ /// free buffer w/o copying back
+ static const int JNI_ABORT = 2;
+}
+
+const int DART_JNI_SINGLETON_EXISTS = -99;
diff --git a/pkgs/jni/lib/src/types.dart b/pkgs/jni/lib/src/types.dart
new file mode 100644
index 0000000..d560b2d
--- /dev/null
+++ b/pkgs/jni/lib/src/types.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+
+import 'jni.dart';
+import 'jobject.dart';
+
+part 'jprimitives.dart';
+
+sealed class JType<T> {
+ const JType();
+
+ String get signature;
+}
+
+abstract class JObjType<T extends JObject> extends JType<T> {
+ /// Number of super types. Distance to the root type.
+ int get superCount;
+
+ JObjType get superType;
+
+ const JObjType();
+
+ /// Creates an object from this type using the reference.
+ T fromRef(Pointer<Void> ref);
+
+ JClass getClass() {
+ if (signature.startsWith('L') && signature.endsWith(';')) {
+ return Jni.findJClass(signature.substring(1, signature.length - 1));
+ }
+ return Jni.findJClass(signature);
+ }
+}
+
+/// Lowest common ancestor of two types in the inheritance tree.
+JObjType _lowestCommonAncestor(JObjType a, JObjType b) {
+ while (a.superCount > b.superCount) {
+ a = a.superType;
+ }
+ while (b.superCount > a.superCount) {
+ b = b.superType;
+ }
+ while (a != b) {
+ a = a.superType;
+ b = b.superType;
+ }
+ return a;
+}
+
+JObjType lowestCommonSuperType(List<JObjType> types) {
+ return types.reduce(_lowestCommonAncestor);
+}
diff --git a/pkgs/jni/lib/src/util/jiterator.dart b/pkgs/jni/lib/src/util/jiterator.dart
new file mode 100644
index 0000000..0d0122f
--- /dev/null
+++ b/pkgs/jni/lib/src/util/jiterator.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../accessors.dart';
+import '../jni.dart';
+import '../jobject.dart';
+import '../third_party/generated_bindings.dart';
+import '../types.dart';
+
+final class JIteratorType<$E extends JObject> extends JObjType<JIterator<$E>> {
+ final JObjType<$E> E;
+
+ const JIteratorType(
+ this.E,
+ );
+
+ @override
+ String get signature => r"Ljava/util/Iterator;";
+
+ @override
+ JIterator<$E> fromRef(JObjectPtr ref) => JIterator.fromRef(E, ref);
+
+ @override
+ JObjType get superType => const JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash(JIteratorType, E);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == (JIteratorType<$E>) &&
+ other is JIteratorType<$E> &&
+ E == other.E;
+ }
+}
+
+class JIterator<$E extends JObject> extends JObject implements Iterator<$E> {
+ @override
+ // ignore: overridden_fields
+ late final JObjType $type = type(E);
+
+ final JObjType<$E> E;
+
+ JIterator.fromRef(
+ this.E,
+ JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = Jni.findJClass(r"java/util/Iterator");
+
+ /// The type which includes information such as the signature of this class.
+ static JIteratorType<$E> type<$E extends JObject>(
+ JObjType<$E> E,
+ ) {
+ return JIteratorType(
+ E,
+ );
+ }
+
+ $E? _current;
+
+ @override
+ $E get current => _current as $E;
+
+ static final _hasNextId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"hasNext", r"()Z");
+ bool _hasNext() {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _hasNextId, JniCallType.booleanType, []).boolean;
+ }
+
+ static final _nextId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"next", r"()Ljava/lang/Object;");
+ $E _next() {
+ return E.fromRef(Jni.accessors.callMethodWithArgs(
+ reference, _nextId, JniCallType.objectType, []).object);
+ }
+
+ @override
+ bool moveNext() {
+ if (!_hasNext()) {
+ return false;
+ }
+ _current = _next();
+ return true;
+ }
+}
diff --git a/pkgs/jni/lib/src/util/jlist.dart b/pkgs/jni/lib/src/util/jlist.dart
new file mode 100644
index 0000000..9779032
--- /dev/null
+++ b/pkgs/jni/lib/src/util/jlist.dart
@@ -0,0 +1,279 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+import 'dart:ffi';
+
+import 'package:jni/src/util/jset.dart';
+
+import '../accessors.dart';
+import '../jni.dart';
+import '../jobject.dart';
+import '../jvalues.dart';
+import '../third_party/generated_bindings.dart';
+import '../types.dart';
+import 'jiterator.dart';
+
+final class JListType<$E extends JObject> extends JObjType<JList<$E>> {
+ final JObjType<$E> E;
+
+ const JListType(
+ this.E,
+ );
+
+ @override
+ String get signature => r"Ljava/util/List;";
+
+ @override
+ JList<$E> fromRef(JObjectPtr ref) => JList.fromRef(E, ref);
+
+ @override
+ JObjType get superType => const JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash(JListType, E);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == JListType && other is JListType && E == other.E;
+ }
+}
+
+class JList<$E extends JObject> extends JObject with ListMixin<$E> {
+ @override
+ // ignore: overridden_fields
+ late final JObjType<JList> $type = type(E);
+
+ final JObjType<$E> E;
+
+ JList.fromRef(
+ this.E,
+ JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = Jni.findJClass(r"java/util/List");
+
+ /// The type which includes information such as the signature of this class.
+ static JListType<$E> type<$E extends JObject>(
+ JObjType<$E> E,
+ ) {
+ return JListType(
+ E,
+ );
+ }
+
+ static final _arrayListClassRef = Jni.findJClass(r"java/util/ArrayList");
+ static final _ctorId = Jni.accessors
+ .getMethodIDOf(_arrayListClassRef.reference, r"<init>", r"()V");
+ JList.array(this.E)
+ : super.fromRef(Jni.accessors.newObjectWithArgs(
+ _arrayListClassRef.reference, _ctorId, []).object);
+
+ static final _sizeId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"size", r"()I");
+ @override
+ int get length => Jni.accessors
+ .callMethodWithArgs(reference, _sizeId, JniCallType.intType, []).integer;
+
+ @override
+ set length(int newLength) {
+ RangeError.checkNotNegative(newLength);
+ while (length < newLength) {
+ add(E.fromRef(nullptr));
+ }
+ while (newLength < length) {
+ removeAt(length - 1);
+ }
+ }
+
+ static final _getId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"get", r"(I)Ljava/lang/Object;");
+ @override
+ $E operator [](int index) {
+ RangeError.checkValidIndex(index, this);
+ return E.fromRef(Jni.accessors.callMethodWithArgs(
+ reference, _getId, JniCallType.objectType, [JValueInt(index)]).object);
+ }
+
+ static final _setId = Jni.accessors.getMethodIDOf(
+ _class.reference, r"set", r"(ILjava/lang/Object;)Ljava/lang/Object;");
+ @override
+ void operator []=(int index, $E value) {
+ RangeError.checkValidIndex(index, this);
+ E.fromRef(Jni.accessors.callMethodWithArgs(reference, _setId,
+ JniCallType.objectType, [JValueInt(index), value.reference]).object);
+ }
+
+ static final _addId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"add", r"(Ljava/lang/Object;)Z");
+ @override
+ void add($E element) {
+ Jni.accessors.callMethodWithArgs(reference, _addId, JniCallType.booleanType,
+ [element.reference]).check();
+ }
+
+ static final _collectionClass = Jni.findJClass("java/util/Collection");
+ static final _addAllId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"addAll", r"(Ljava/util/Collection;)Z");
+ @override
+ void addAll(Iterable<$E> iterable) {
+ if (iterable is JObject &&
+ Jni.env.IsInstanceOf(
+ (iterable as JObject).reference, _collectionClass.reference)) {
+ Jni.accessors.callMethodWithArgs(reference, _addAllId,
+ JniCallType.booleanType, [(iterable as JObject).reference]).boolean;
+ return;
+ }
+ return super.addAll(iterable);
+ }
+
+ static final _clearId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"clear", r"()V");
+ @override
+ void clear() {
+ Jni.accessors.callMethodWithArgs(
+ reference, _clearId, JniCallType.voidType, []).check();
+ }
+
+ static final _containsId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"contains", r"(Ljava/lang/Object;)Z");
+ @override
+ bool contains(Object? element) {
+ if (element is! JObject) return false;
+ return Jni.accessors.callMethodWithArgs(reference, _containsId,
+ JniCallType.booleanType, [element.reference]).boolean;
+ }
+
+ static final _getRangeId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"subList", r"(II)Ljava/util/List;");
+ @override
+ JList<$E> getRange(int start, int end) {
+ RangeError.checkValidRange(start, end, this.length);
+ return JListType(E).fromRef(
+ Jni.accessors.callMethodWithArgs(reference, _getRangeId,
+ JniCallType.objectType, [JValueInt(start), JValueInt(end)]).object,
+ );
+ }
+
+ static final _indexOfId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"indexOf", r"(Ljava/lang/Object;)I");
+ @override
+ int indexOf(Object? element, [int start = 0]) {
+ if (element is! JObject) return -1;
+ if (start < 0) start = 0;
+ if (start == 0) {
+ return Jni.accessors.callMethodWithArgs(reference, _indexOfId,
+ JniCallType.intType, [element.reference]).integer;
+ }
+ return Jni.accessors.callMethodWithArgs(
+ getRange(start, length).reference,
+ _indexOfId,
+ JniCallType.intType,
+ [element.reference],
+ ).integer;
+ }
+
+ static final _insertId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"add", r"(ILjava/lang/Object;)V");
+ @override
+ void insert(int index, $E element) {
+ Jni.accessors.callMethodWithArgs(reference, _insertId, JniCallType.voidType,
+ [JValueInt(index), element.reference]).check();
+ }
+
+ static final _insertAllId = Jni.accessors.getMethodIDOf(
+ _class.reference, r"addAll", r"(ILjava/util/Collection;)Z");
+ @override
+ void insertAll(int index, Iterable<$E> iterable) {
+ if (iterable is JObject &&
+ Jni.env.IsInstanceOf(
+ (iterable as JObject).reference, _collectionClass.reference)) {
+ Jni.accessors.callMethodWithArgs(
+ reference,
+ _insertAllId,
+ JniCallType.booleanType,
+ [JValueInt(index), (iterable as JObject).reference],
+ ).boolean;
+ return;
+ }
+ super.insertAll(index, iterable);
+ }
+
+ static final _isEmptyId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"isEmpty", r"()Z");
+ @override
+ bool get isEmpty => Jni.accessors.callMethodWithArgs(
+ reference, _isEmptyId, JniCallType.booleanType, []).boolean;
+
+ @override
+ bool get isNotEmpty => !isEmpty;
+
+ static final _iteratorId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"iterator", r"()Ljava/util/Iterator;");
+ @override
+ JIterator<$E> get iterator =>
+ JIteratorType(E).fromRef(Jni.accessors.callMethodWithArgs(
+ reference, _iteratorId, JniCallType.objectType, []).object);
+
+ static final _lastIndexOfId = Jni.accessors.getMethodIDOf(
+ _class.reference, r"lastIndexOf", r"(Ljava/lang/Object;)I");
+ @override
+ int lastIndexOf(Object? element, [int? start]) {
+ if (element is! JObject) return -1;
+ if (start == null || start >= this.length) start = this.length - 1;
+ if (start == this.length - 1) {
+ return Jni.accessors.callMethodWithArgs(reference, _lastIndexOfId,
+ JniCallType.intType, [element.reference]).integer;
+ }
+ final range = getRange(start, length);
+ final res = Jni.accessors.callMethodWithArgs(
+ range.reference,
+ _lastIndexOfId,
+ JniCallType.intType,
+ [element.reference],
+ ).integer;
+ range.release();
+ return res;
+ }
+
+ static final _removeId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"remove", r"(Ljava/lang/Object;)Z");
+ @override
+ bool remove(Object? element) {
+ if (element is! JObject) return false;
+ return Jni.accessors.callMethodWithArgs(reference, _removeId,
+ JniCallType.booleanType, [element.reference]).boolean;
+ }
+
+ static final _removeAtId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"remove", r"(I)Ljava/lang/Object;");
+ @override
+ $E removeAt(int index) {
+ return E.fromRef(Jni.accessors.callMethodWithArgs(reference, _removeAtId,
+ JniCallType.objectType, [JValueInt(index)]).object);
+ }
+
+ @override
+ void removeRange(int start, int end) {
+ final range = getRange(start, end);
+ range.clear();
+ range.release();
+ }
+
+ @override
+ JSet<$E> toSet() {
+ return toJSet(E);
+ }
+}
+
+extension ToJavaList<E extends JObject> on Iterable<E> {
+ JList<E> toJList(JObjType<E> type) {
+ final list = JList.array(type);
+ list.addAll(this);
+ return list;
+ }
+}
diff --git a/pkgs/jni/lib/src/util/jmap.dart b/pkgs/jni/lib/src/util/jmap.dart
new file mode 100644
index 0000000..73a6d62
--- /dev/null
+++ b/pkgs/jni/lib/src/util/jmap.dart
@@ -0,0 +1,185 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+
+import '../accessors.dart';
+import '../jni.dart';
+import '../jobject.dart';
+import '../third_party/jni_bindings_generated.dart';
+import '../types.dart';
+import 'jset.dart';
+
+final class JMapType<$K extends JObject, $V extends JObject>
+ extends JObjType<JMap<$K, $V>> {
+ final JObjType<$K> K;
+ final JObjType<$V> V;
+
+ const JMapType(
+ this.K,
+ this.V,
+ );
+
+ @override
+ String get signature => r"Ljava/util/Map;";
+
+ @override
+ JMap<$K, $V> fromRef(JObjectPtr ref) => JMap.fromRef(K, V, ref);
+
+ @override
+ JObjType get superType => const JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash(JMapType, K, V);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == (JMapType<$K, $V>) &&
+ other is JMapType<$K, $V> &&
+ K == other.K &&
+ V == other.V;
+ }
+}
+
+class JMap<$K extends JObject, $V extends JObject> extends JObject
+ with MapMixin<$K, $V> {
+ @override
+ // ignore: overridden_fields
+ late final JObjType<JMap> $type = type(K, V);
+
+ final JObjType<$K> K;
+ final JObjType<$V> V;
+
+ JMap.fromRef(
+ this.K,
+ this.V,
+ JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = Jni.findJClass(r"java/util/Map");
+
+ /// The type which includes information such as the signature of this class.
+ static JMapType<$K, $V> type<$K extends JObject, $V extends JObject>(
+ JObjType<$K> K,
+ JObjType<$V> V,
+ ) {
+ return JMapType(
+ K,
+ V,
+ );
+ }
+
+ static final _hashMapClass = Jni.findJClass(r"java/util/HashMap");
+ static final _ctorId =
+ Jni.accessors.getMethodIDOf(_hashMapClass.reference, r"<init>", r"()V");
+ JMap.hash(this.K, this.V)
+ : super.fromRef(Jni.accessors
+ .newObjectWithArgs(_hashMapClass.reference, _ctorId, []).object);
+
+ static final _getId = Jni.accessors.getMethodIDOf(
+ _class.reference, r"get", r"(Ljava/lang/Object;)Ljava/lang/Object;");
+ @override
+ $V? operator [](Object? key) {
+ if (key is! JObject) {
+ return null;
+ }
+ final value = V.fromRef(Jni.accessors.callMethodWithArgs(
+ reference, _getId, JniCallType.objectType, [key.reference]).object);
+ return value.isNull ? null : value;
+ }
+
+ static final _putId = Jni.accessors.getMethodIDOf(_class.reference, r"put",
+ r"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+ @override
+ void operator []=($K key, $V value) {
+ Jni.accessors.callMethodWithArgs(reference, _putId, JniCallType.objectType,
+ [key.reference, value.reference]).object;
+ }
+
+ static final _addAllId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"putAll", r"(Ljava/util/Map;)V");
+ @override
+ void addAll(Map<$K, $V> other) {
+ if (other is JMap<$K, $V>) {
+ Jni.accessors.callMethodWithArgs(reference, _addAllId,
+ JniCallType.voidType, [other.reference]).check();
+ return;
+ }
+ super.addAll(other);
+ }
+
+ static final _clearId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"clear", r"()V");
+ @override
+ void clear() {
+ Jni.accessors.callMethodWithArgs(
+ reference, _clearId, JniCallType.voidType, []).check();
+ }
+
+ static final _containsKeyId = Jni.accessors.getMethodIDOf(
+ _class.reference, r"containsKey", r"(Ljava/lang/Object;)Z");
+ @override
+ bool containsKey(Object? key) {
+ if (key is! JObject) {
+ return false;
+ }
+ return Jni.accessors.callMethodWithArgs(reference, _containsKeyId,
+ JniCallType.booleanType, [key.reference]).boolean;
+ }
+
+ static final _containsValueId = Jni.accessors.getMethodIDOf(
+ _class.reference, r"containsValue", r"(Ljava/lang/Object;)Z");
+ @override
+ bool containsValue(Object? value) {
+ if (value is! JObject) {
+ return false;
+ }
+ return Jni.accessors.callMethodWithArgs(reference, _containsValueId,
+ JniCallType.booleanType, [value.reference]).boolean;
+ }
+
+ static final isEmptyId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"isEmpty", r"()Z");
+ @override
+ bool get isEmpty => Jni.accessors.callMethodWithArgs(
+ reference, isEmptyId, JniCallType.booleanType, []).boolean;
+
+ @override
+ bool get isNotEmpty => !isEmpty;
+
+ static final _keysId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"keySet", r"()Ljava/util/Set;");
+ @override
+ JSet<$K> get keys => JSetType(K).fromRef(Jni.accessors.callMethodWithArgs(
+ reference, _keysId, JniCallType.objectType, []).object);
+
+ static final _sizeId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"size", r"()I");
+ @override
+ int get length => Jni.accessors
+ .callMethodWithArgs(reference, _sizeId, JniCallType.intType, []).integer;
+
+ static final _removeId = Jni.accessors.getMethodIDOf(
+ _class.reference, r"remove", r"(Ljava/lang/Object;)Ljava/lang/Object;");
+ @override
+ $V? remove(Object? key) {
+ if (key is! JObject) {
+ return null;
+ }
+ final value = V.fromRef(Jni.accessors.callMethodWithArgs(
+ reference, _removeId, JniCallType.objectType, [key.reference]).object);
+ return value.isNull ? null : value;
+ }
+}
+
+extension ToJavaMap<K extends JObject, V extends JObject> on Map<K, V> {
+ JMap<K, V> toJMap(JObjType<K> keyType, JObjType<V> valueType) {
+ final map = JMap.hash(keyType, valueType);
+ map.addAll(this);
+ return map;
+ }
+}
diff --git a/pkgs/jni/lib/src/util/jset.dart b/pkgs/jni/lib/src/util/jset.dart
new file mode 100644
index 0000000..df51003
--- /dev/null
+++ b/pkgs/jni/lib/src/util/jset.dart
@@ -0,0 +1,214 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+
+import 'package:jni/src/third_party/generated_bindings.dart';
+
+import '../accessors.dart';
+import '../jni.dart';
+import '../jobject.dart';
+import '../types.dart';
+import 'jiterator.dart';
+
+final class JSetType<$E extends JObject> extends JObjType<JSet<$E>> {
+ final JObjType<$E> E;
+
+ const JSetType(
+ this.E,
+ );
+
+ @override
+ String get signature => r"Ljava/util/Set;";
+
+ @override
+ JSet<$E> fromRef(JObjectPtr ref) => JSet.fromRef(E, ref);
+
+ @override
+ JObjType get superType => const JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash(JSetType, E);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == (JSetType<$E>) &&
+ other is JSetType<$E> &&
+ E == other.E;
+ }
+}
+
+class JSet<$E extends JObject> extends JObject with SetMixin<$E> {
+ @override
+ // ignore: overridden_fields
+ late final JObjType<JSet> $type = type(E);
+
+ final JObjType<$E> E;
+
+ JSet.fromRef(
+ this.E,
+ JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = Jni.findJClass(r"java/util/Set");
+
+ /// The type which includes information such as the signature of this class.
+ static JSetType<$E> type<$E extends JObject>(
+ JObjType<$E> E,
+ ) {
+ return JSetType(
+ E,
+ );
+ }
+
+ static final _hashSetClass = Jni.findJClass(r"java/util/HashSet");
+ static final _ctorId =
+ Jni.accessors.getMethodIDOf(_hashSetClass.reference, r"<init>", r"()V");
+ JSet.hash(this.E)
+ : super.fromRef(Jni.accessors
+ .newObjectWithArgs(_hashSetClass.reference, _ctorId, []).object);
+
+ static final _addId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"add", r"(Ljava/lang/Object;)Z");
+ @override
+ bool add($E value) {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _addId, JniCallType.booleanType, [value.reference]).boolean;
+ }
+
+ static final _addAllId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"addAll", r"(Ljava/util/Collection;)Z");
+ @override
+ void addAll(Iterable<$E> elements) {
+ if (elements is JObject &&
+ Jni.env.IsInstanceOf(
+ (elements as JObject).reference, _collectionClass.reference)) {
+ Jni.accessors.callMethodWithArgs(
+ reference,
+ _addAllId,
+ JniCallType.booleanType,
+ [(elements as JObject).reference],
+ ).boolean;
+ return;
+ }
+ return super.addAll(elements);
+ }
+
+ static final _clearId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"clear", r"()V");
+ @override
+ void clear() {
+ return Jni.accessors.callMethodWithArgs(
+ reference, _clearId, JniCallType.voidType, []).check();
+ }
+
+ static final _containsId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"contains", r"(Ljava/lang/Object;)Z");
+
+ @override
+ bool contains(Object? element) {
+ if (element is! JObject) {
+ return false;
+ }
+ return Jni.accessors.callMethodWithArgs(reference, _containsId,
+ JniCallType.booleanType, [element.reference]).boolean;
+ }
+
+ static final _containsAllId = Jni.accessors.getMethodIDOf(
+ _class.reference, r"containsAll", r"(Ljava/util/Collection;)Z");
+ static final _collectionClass = Jni.findJClass("java/util/Collection");
+ @override
+ bool containsAll(Iterable<Object?> other) {
+ if (other is JObject &&
+ Jni.env.IsInstanceOf(
+ (other as JObject).reference, _collectionClass.reference)) {
+ return Jni.accessors.callMethodWithArgs(reference, _containsAllId,
+ JniCallType.booleanType, [(other as JObject).reference]).boolean;
+ }
+ return super.containsAll(other);
+ }
+
+ static final _isEmptyId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"isEmpty", r"()Z");
+ @override
+ bool get isEmpty => Jni.accessors.callMethodWithArgs(
+ reference, _isEmptyId, JniCallType.booleanType, []).boolean;
+
+ @override
+ bool get isNotEmpty => !isEmpty;
+
+ static final _iteratorId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"iterator", r"()Ljava/util/Iterator;");
+ @override
+ JIterator<$E> get iterator =>
+ JIteratorType(E).fromRef(Jni.accessors.callMethodWithArgs(
+ reference, _iteratorId, JniCallType.objectType, []).object);
+
+ static final _sizeId =
+ Jni.accessors.getMethodIDOf(_class.reference, r"size", r"()I");
+ @override
+ int get length => Jni.accessors
+ .callMethodWithArgs(reference, _sizeId, JniCallType.intType, []).integer;
+
+ static final _removeId = Jni.accessors
+ .getMethodIDOf(_class.reference, r"remove", r"(Ljava/lang/Object;)Z");
+ @override
+ bool remove(Object? value) {
+ if (value is! $E) {
+ return false;
+ }
+ return Jni.accessors.callMethodWithArgs(reference, _removeId,
+ JniCallType.booleanType, [value.reference]).boolean;
+ }
+
+ static final _removeAllId = Jni.accessors.getMethodIDOf(
+ _class.reference, r"removeAll", r"(Ljava/util/Collection;)Z");
+ @override
+ void removeAll(Iterable<Object?> elements) {
+ if (elements is JObject &&
+ Jni.env.IsInstanceOf(
+ (elements as JObject).reference, _collectionClass.reference)) {
+ Jni.accessors.callMethodWithArgs(reference, _removeAllId,
+ JniCallType.booleanType, [(elements as JObject).reference]).boolean;
+ return;
+ }
+ return super.removeAll(elements);
+ }
+
+ static final _retainAllId = Jni.accessors.getMethodIDOf(
+ _class.reference, r"retainAll", r"(Ljava/util/Collection;)Z");
+ @override
+ void retainAll(Iterable<Object?> elements) {
+ if (elements is JObject &&
+ Jni.env.IsInstanceOf(
+ (elements as JObject).reference, _collectionClass.reference)) {
+ Jni.accessors.callMethodWithArgs(reference, _retainAllId,
+ JniCallType.booleanType, [(elements as JObject).reference]).boolean;
+ return;
+ }
+ return super.retainAll(elements);
+ }
+
+ @override
+ $E? lookup(Object? element) {
+ if (contains(element)) return element as $E;
+ return null;
+ }
+
+ @override
+ JSet<$E> toSet() {
+ return toJSet(E);
+ }
+}
+
+extension ToJavaSet<E extends JObject> on Iterable<E> {
+ JSet<E> toJSet(JObjType<E> type) {
+ final set = JSet.hash(type);
+ set.addAll(this);
+ return set;
+ }
+}
diff --git a/pkgs/jni/lib/src/util/util.dart b/pkgs/jni/lib/src/util/util.dart
new file mode 100644
index 0000000..d0a0dc5
--- /dev/null
+++ b/pkgs/jni/lib/src/util/util.dart
@@ -0,0 +1,8 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'jiterator.dart';
+export 'jlist.dart';
+export 'jmap.dart';
+export 'jset.dart';
diff --git a/pkgs/jni/linux/CMakeLists.txt b/pkgs/jni/linux/CMakeLists.txt
new file mode 100644
index 0000000..953cb0f
--- /dev/null
+++ b/pkgs/jni/linux/CMakeLists.txt
@@ -0,0 +1,22 @@
+# 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)
+
+# Project-level configuration.
+set(PROJECT_NAME "jni")
+project(${PROJECT_NAME} LANGUAGES CXX)
+
+# Invoke the build for native code shared with the other target platforms.
+# This can be changed to accomodate different builds.
+add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared")
+
+# 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.
+set(jni_bundled_libraries
+ # Defined in ../src/CMakeLists.txt.
+ # This can be changed to accomodate different builds.
+ $<TARGET_FILE:jni>
+ PARENT_SCOPE
+)
diff --git a/pkgs/jni/macos/Classes/jni.c b/pkgs/jni/macos/Classes/jni.c
new file mode 100644
index 0000000..28e68ae
--- /dev/null
+++ b/pkgs/jni/macos/Classes/jni.c
@@ -0,0 +1,3 @@
+// Relative import to be able to reuse the C sources.
+// See the comment in ../{projectName}}.podspec for more information.
+#include "../../src/jni.c"
diff --git a/pkgs/jni/macos/jni.podspec b/pkgs/jni/macos/jni.podspec
new file mode 100644
index 0000000..582861a
--- /dev/null
+++ b/pkgs/jni/macos/jni.podspec
@@ -0,0 +1,27 @@
+#
+# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
+# Run `pod lib lint jni.podspec` to validate before publishing.
+#
+Pod::Spec.new do |s|
+ s.name = 'jni'
+ s.version = '0.0.1'
+ s.summary = 'A new Flutter FFI plugin project.'
+ s.description = <<-DESC
+A new Flutter FFI plugin project.
+ DESC
+ s.homepage = 'http://example.com'
+ s.license = { :file => '../LICENSE' }
+ s.author = { 'Your Company' => 'email@example.com' }
+
+ # This will ensure the source files in Classes/ are included in the native
+ # builds of apps using this FFI plugin. Podspec does not support relative
+ # paths, so Classes contains a forwarder C file that relatively imports
+ # `../src/*` so that the C sources can be shared among all target platforms.
+ s.source = { :path => '.' }
+ s.source_files = 'Classes/**/*'
+ s.dependency 'FlutterMacOS'
+
+ s.platform = :osx, '10.11'
+ s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
+ s.swift_version = '5.0'
+end
diff --git a/pkgs/jni/pubspec.yaml b/pkgs/jni/pubspec.yaml
new file mode 100644
index 0000000..6efae3d
--- /dev/null
+++ b/pkgs/jni/pubspec.yaml
@@ -0,0 +1,47 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+name: jni
+description: A library to access JNI from Dart and Flutter that acts as a support library for package:jnigen.
+version: 0.8.0-wip
+repository: https://github.com/dart-lang/jnigen/tree/main/jni
+
+topics:
+ - interop
+ - ffi
+ - java
+ - kotlin
+ - jni
+
+environment:
+ sdk: '>=3.1.0 <4.0.0'
+ flutter: '>=2.11.0'
+
+dependencies:
+ collection: ^1.0.0
+ plugin_platform_interface: ^2.0.2
+ ffi: ^2.0.1
+ path: ^1.8.0
+ package_config: ^2.1.0
+ args: ^2.3.1
+
+dev_dependencies:
+ ## Pin ffigen version because we are depending on internal APIs.
+ ffigen: 8.0.2
+ flutter_lints: ^2.0.0
+ test: ^1.21.1
+ logging: ^1.1.1
+
+# The following section is specific to Flutter packages.
+flutter:
+ plugin:
+ platforms:
+ linux:
+ ffiPlugin: true
+ windows:
+ ffiPlugin: true
+ android:
+ ffiPlugin: true
+ package: com.github.dart_lang.jni
+ pluginClass: JniPlugin
diff --git a/pkgs/jni/src/.clang-format b/pkgs/jni/src/.clang-format
new file mode 100644
index 0000000..a256c2f
--- /dev/null
+++ b/pkgs/jni/src/.clang-format
@@ -0,0 +1,15 @@
+# From dart SDK: https://github.com/dart-lang/sdk/blob/main/.clang-format
+
+# Defines the Chromium style for automatic reformatting.
+# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
+BasedOnStyle: Chromium
+
+# clang-format doesn't seem to do a good job of this for longer comments.
+ReflowComments: 'false'
+
+# We have lots of these. Though we need to put them all in curly braces,
+# clang-format can't do that.
+AllowShortIfStatementsOnASingleLine: 'true'
+
+# Put escaped newlines into the rightmost column.
+AlignEscapedNewlinesLeft: false
diff --git a/pkgs/jni/src/.gitignore b/pkgs/jni/src/.gitignore
new file mode 100644
index 0000000..cf9756b
--- /dev/null
+++ b/pkgs/jni/src/.gitignore
@@ -0,0 +1,8 @@
+CMakeFiles/
+Makefile
+cmake_install.cmake
+libdartjni.so
+CMakeCache.txt
+.cache
+compile_commands.json
+!.clang-format
diff --git a/pkgs/jni/src/CMakeLists.txt b/pkgs/jni/src/CMakeLists.txt
new file mode 100644
index 0000000..2cdb3f7
--- /dev/null
+++ b/pkgs/jni/src/CMakeLists.txt
@@ -0,0 +1,35 @@
+# jni_native_build (Build with jni:setup. Do not delete this line.)
+
+# 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)
+
+project(jni_library VERSION 0.0.1 LANGUAGES C)
+
+add_library(jni SHARED
+ "dartjni.c"
+ "third_party/global_jni_env.c"
+ "include/dart_api_dl.c"
+)
+
+set_target_properties(jni PROPERTIES
+ PUBLIC_HEADER dartjni.h
+ OUTPUT_NAME "dartjni"
+)
+
+target_compile_definitions(jni PUBLIC DART_SHARED_LIB)
+
+if(WIN32)
+ set_target_properties(${TARGET_NAME} PROPERTIES
+ LINK_FLAGS "/DELAYLOAD:jvm.dll")
+endif()
+
+if (ANDROID)
+ target_link_libraries(jni log)
+else()
+ find_package(Java REQUIRED)
+ find_package(JNI REQUIRED)
+ include_directories(${JNI_INCLUDE_DIRS})
+ target_link_libraries(jni ${JNI_LIBRARIES})
+endif()
diff --git a/pkgs/jni/src/README.md b/pkgs/jni/src/README.md
new file mode 100644
index 0000000..6516f65
--- /dev/null
+++ b/pkgs/jni/src/README.md
@@ -0,0 +1,5 @@
+Native code for jni library.
+
+## LSP instructions
+
+see https://releases.llvm.org/8.0.0/tools/clang/tools/extra/docs/clangd/Installation.html#project-setup for creating compile_commands.json for use with LSP based editor plugins (in VS Code, VIM etc..).
\ No newline at end of file
diff --git a/pkgs/jni/src/dartjni.c b/pkgs/jni/src/dartjni.c
new file mode 100644
index 0000000..7c5951b
--- /dev/null
+++ b/pkgs/jni/src/dartjni.c
@@ -0,0 +1,749 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include <jni.h>
+#include <stdarg.h>
+#include <stdint.h>
+
+#include "dartjni.h"
+
+#include "include/dart_api_dl.h"
+
+void initAllLocks(JniLocks* locks) {
+ init_lock(&locks->classLoadingLock);
+ init_lock(&locks->fieldLoadingLock);
+ init_lock(&locks->methodLoadingLock);
+}
+
+/// Stores class and method references for obtaining exception details
+typedef struct JniExceptionMethods {
+ jclass objectClass, exceptionClass, printStreamClass;
+ jclass byteArrayOutputStreamClass;
+ jmethodID toStringMethod, printStackTraceMethod;
+ jmethodID byteArrayOutputStreamCtor, printStreamCtor;
+} JniExceptionMethods;
+
+// Context and shared global state. Initialized once or if thread-local, initialized once in a thread.
+JniContext jni_context = {
+ .jvm = NULL,
+ .classLoader = NULL,
+ .loadClassMethod = NULL,
+ .appContext = NULL,
+ .currentActivity = NULL,
+};
+
+JniContext* jni = &jni_context;
+
+thread_local JNIEnv* jniEnv = NULL;
+
+JniExceptionMethods exceptionMethods;
+
+void initExceptionHandling(JniExceptionMethods* methods) {
+ methods->objectClass = FindClass("java/lang/Object");
+ methods->exceptionClass = FindClass("java/lang/Exception");
+ methods->printStreamClass = FindClass("java/io/PrintStream");
+ methods->byteArrayOutputStreamClass =
+ FindClass("java/io/ByteArrayOutputStream");
+ load_method(methods->objectClass, &methods->toStringMethod, "toString",
+ "()Ljava/lang/String;");
+ load_method(methods->exceptionClass, &methods->printStackTraceMethod,
+ "printStackTrace", "(Ljava/io/PrintStream;)V");
+ load_method(methods->byteArrayOutputStreamClass,
+ &methods->byteArrayOutputStreamCtor, "<init>", "()V");
+ load_method(methods->printStreamClass, &methods->printStreamCtor, "<init>",
+ "(Ljava/io/OutputStream;)V");
+}
+
+/// Get JVM associated with current process.
+/// Returns NULL if no JVM is running.
+FFI_PLUGIN_EXPORT
+JavaVM* GetJavaVM() {
+ return jni_context.jvm;
+}
+
+FFI_PLUGIN_EXPORT
+jclass FindClass(const char* name) {
+ jclass cls = NULL;
+ attach_thread();
+ load_class_global_ref(&cls, name);
+ return cls;
+};
+
+// Android specifics
+
+FFI_PLUGIN_EXPORT
+jobject GetClassLoader() {
+ attach_thread();
+ return (*jniEnv)->NewGlobalRef(jniEnv, jni_context.classLoader);
+}
+
+FFI_PLUGIN_EXPORT
+jobject GetApplicationContext() {
+ attach_thread();
+ return (*jniEnv)->NewGlobalRef(jniEnv, jni_context.appContext);
+}
+
+FFI_PLUGIN_EXPORT
+jobject GetCurrentActivity() {
+ attach_thread();
+ return (*jniEnv)->NewGlobalRef(jniEnv, jni_context.currentActivity);
+}
+
+// JNI Initialization
+
+#ifdef __ANDROID__
+JNIEXPORT void JNICALL
+Java_com_github_dart_1lang_jni_JniPlugin_initializeJni(JNIEnv* env,
+ jobject obj,
+ jobject appContext,
+ jobject classLoader) {
+ jniEnv = env;
+ (*env)->GetJavaVM(env, &jni_context.jvm);
+ jni_context.classLoader = (*env)->NewGlobalRef(env, classLoader);
+ jni_context.appContext = (*env)->NewGlobalRef(env, appContext);
+ jclass classLoaderClass = (*env)->GetObjectClass(env, classLoader);
+ jni_context.loadClassMethod =
+ (*env)->GetMethodID(env, classLoaderClass, "loadClass",
+ "(Ljava/lang/String;)Ljava/lang/Class;");
+ initAllLocks(&jni_context.locks);
+ initExceptionHandling(&exceptionMethods);
+}
+
+JNIEXPORT void JNICALL
+Java_com_github_dart_1lang_jni_JniPlugin_setJniActivity(JNIEnv* env,
+ jobject obj,
+ jobject activity,
+ jobject context) {
+ jniEnv = env;
+ if (jni_context.currentActivity != NULL) {
+ (*env)->DeleteGlobalRef(env, jni_context.currentActivity);
+ }
+ jni_context.currentActivity = (*env)->NewGlobalRef(env, activity);
+ if (jni_context.appContext != NULL) {
+ (*env)->DeleteGlobalRef(env, jni_context.appContext);
+ }
+ jni_context.appContext = (*env)->NewGlobalRef(env, context);
+}
+
+// Sometimes you may get linker error trying to link JNI_CreateJavaVM APIs
+// on Android NDK. So IFDEF is required.
+#else
+#ifdef _WIN32
+// Pre-initialization of critical section on windows - this is required because
+// there's no coordination between multiple isolates calling Spawn.
+//
+// Taken from https://stackoverflow.com/a/12858955
+CRITICAL_SECTION spawnLock = {0};
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, // handle to DLL module
+ DWORD fdwReason, // reason for calling function
+ LPVOID lpReserved) { // reserved
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ // Initialize once for each new process.
+ // Return FALSE to fail DLL load.
+ InitializeCriticalSection(&spawnLock);
+ break;
+ case DLL_PROCESS_DETACH:
+ // Perform any necessary cleanup.
+ DeleteCriticalSection(&spawnLock);
+ break;
+ }
+ return TRUE; // Successful DLL_PROCESS_ATTACH.
+}
+#else
+pthread_mutex_t spawnLock = PTHREAD_MUTEX_INITIALIZER;
+#endif
+FFI_PLUGIN_EXPORT
+int SpawnJvm(JavaVMInitArgs* initArgs) {
+ if (jni_context.jvm != NULL) {
+ return DART_JNI_SINGLETON_EXISTS;
+ }
+
+ acquire_lock(&spawnLock);
+ // Init may have happened in the meanwhile.
+ if (jni_context.jvm != NULL) {
+ release_lock(&spawnLock);
+ return DART_JNI_SINGLETON_EXISTS;
+ }
+ JavaVMOption jvmopt[1];
+ char class_path[] = "-Djava.class.path=.";
+ jvmopt[0].optionString = class_path;
+ JavaVMInitArgs vmArgs;
+ if (!initArgs) {
+ vmArgs.version = JNI_VERSION_1_6;
+ vmArgs.nOptions = 1;
+ vmArgs.options = jvmopt;
+ vmArgs.ignoreUnrecognized = JNI_TRUE;
+ initArgs = &vmArgs;
+ }
+ const long flag =
+ JNI_CreateJavaVM(&jni_context.jvm, __ENVP_CAST & jniEnv, initArgs);
+ if (flag != JNI_OK) {
+ return flag;
+ }
+ initAllLocks(&jni_context.locks);
+ initExceptionHandling(&exceptionMethods);
+ release_lock(&spawnLock);
+
+ return JNI_OK;
+}
+#endif
+
+// accessors - a bunch of functions which are directly called by jnigen generated bindings
+// and also package:jni reflective method access.
+
+JniClassLookupResult getClass(char* internalName) {
+ JniClassLookupResult result = {NULL, NULL};
+ result.value = FindClass(internalName);
+ result.exception = check_exception();
+ return result;
+}
+
+typedef void* (*MemberGetter)(JNIEnv* env, jclass clazz, char* name, char* sig);
+
+static inline JniPointerResult _getId(MemberGetter getter,
+ jclass cls,
+ char* name,
+ char* sig) {
+ JniPointerResult result = {NULL, NULL};
+ attach_thread();
+ result.value = getter(jniEnv, cls, name, sig);
+ result.exception = check_exception();
+ return result;
+}
+
+JniPointerResult getMethodID(jclass cls, char* name, char* sig) {
+ return _getId((MemberGetter)(*jniEnv)->GetMethodID, cls, name, sig);
+}
+
+JniPointerResult getStaticMethodID(jclass cls, char* name, char* sig) {
+ return _getId((MemberGetter)(*jniEnv)->GetStaticMethodID, cls, name, sig);
+}
+
+JniPointerResult getFieldID(jclass cls, char* name, char* sig) {
+ return _getId((MemberGetter)(*jniEnv)->GetFieldID, cls, name, sig);
+}
+
+JniPointerResult getStaticFieldID(jclass cls, char* name, char* sig) {
+ return _getId((MemberGetter)(*jniEnv)->GetStaticFieldID, cls, name, sig);
+}
+
+JniResult callMethod(jobject obj,
+ jmethodID fieldID,
+ int callType,
+ jvalue* args) {
+ attach_thread();
+ jvalue result = {.j = 0};
+ switch (callType) {
+ case booleanType:
+ result.z = (*jniEnv)->CallBooleanMethodA(jniEnv, obj, fieldID, args);
+ break;
+ case byteType:
+ result.b = (*jniEnv)->CallByteMethodA(jniEnv, obj, fieldID, args);
+ break;
+ case shortType:
+ result.s = (*jniEnv)->CallShortMethodA(jniEnv, obj, fieldID, args);
+ break;
+ case charType:
+ result.c = (*jniEnv)->CallCharMethodA(jniEnv, obj, fieldID, args);
+ break;
+ case intType:
+ result.i = (*jniEnv)->CallIntMethodA(jniEnv, obj, fieldID, args);
+ break;
+ case longType:
+ result.j = (*jniEnv)->CallLongMethodA(jniEnv, obj, fieldID, args);
+ break;
+ case floatType:
+ result.f = (*jniEnv)->CallFloatMethodA(jniEnv, obj, fieldID, args);
+ break;
+ case doubleType:
+ result.d = (*jniEnv)->CallDoubleMethodA(jniEnv, obj, fieldID, args);
+ break;
+ case objectType:
+ result.l = (*jniEnv)->CallObjectMethodA(jniEnv, obj, fieldID, args);
+ break;
+ case voidType:
+ (*jniEnv)->CallVoidMethodA(jniEnv, obj, fieldID, args);
+ break;
+ }
+ jthrowable exception = check_exception();
+ if (callType == objectType && exception == NULL) {
+ result.l = to_global_ref(result.l);
+ }
+ JniResult jniResult = {.value = result, .exception = exception};
+ return jniResult;
+}
+
+// TODO(#60): Any way to reduce this boilerplate?
+JniResult callStaticMethod(jclass cls,
+ jmethodID methodID,
+ int callType,
+ jvalue* args) {
+ attach_thread();
+ jvalue result = {.j = 0};
+ switch (callType) {
+ case booleanType:
+ result.z =
+ (*jniEnv)->CallStaticBooleanMethodA(jniEnv, cls, methodID, args);
+ break;
+ case byteType:
+ result.b = (*jniEnv)->CallStaticByteMethodA(jniEnv, cls, methodID, args);
+ break;
+ case shortType:
+ result.s = (*jniEnv)->CallStaticShortMethodA(jniEnv, cls, methodID, args);
+ break;
+ case charType:
+ result.c = (*jniEnv)->CallStaticCharMethodA(jniEnv, cls, methodID, args);
+ break;
+ case intType:
+ result.i = (*jniEnv)->CallStaticIntMethodA(jniEnv, cls, methodID, args);
+ break;
+ case longType:
+ result.j = (*jniEnv)->CallStaticLongMethodA(jniEnv, cls, methodID, args);
+ break;
+ case floatType:
+ result.f = (*jniEnv)->CallStaticFloatMethodA(jniEnv, cls, methodID, args);
+ break;
+ case doubleType:
+ result.d =
+ (*jniEnv)->CallStaticDoubleMethodA(jniEnv, cls, methodID, args);
+ break;
+ case objectType:
+ result.l =
+ (*jniEnv)->CallStaticObjectMethodA(jniEnv, cls, methodID, args);
+ break;
+ case voidType:
+ (*jniEnv)->CallStaticVoidMethodA(jniEnv, cls, methodID, args);
+ break;
+ }
+ jthrowable exception = check_exception();
+ if (callType == objectType && exception == NULL) {
+ result.l = to_global_ref(result.l);
+ }
+ JniResult jniResult = {.value = result, .exception = exception};
+ return jniResult;
+}
+
+JniResult getField(jobject obj, jfieldID fieldID, int callType) {
+ attach_thread();
+ jvalue result = {.j = 0};
+ switch (callType) {
+ case booleanType:
+ result.z = (*jniEnv)->GetBooleanField(jniEnv, obj, fieldID);
+ break;
+ case byteType:
+ result.b = (*jniEnv)->GetByteField(jniEnv, obj, fieldID);
+ break;
+ case shortType:
+ result.s = (*jniEnv)->GetShortField(jniEnv, obj, fieldID);
+ break;
+ case charType:
+ result.c = (*jniEnv)->GetCharField(jniEnv, obj, fieldID);
+ break;
+ case intType:
+ result.i = (*jniEnv)->GetIntField(jniEnv, obj, fieldID);
+ break;
+ case longType:
+ result.j = (*jniEnv)->GetLongField(jniEnv, obj, fieldID);
+ break;
+ case floatType:
+ result.f = (*jniEnv)->GetFloatField(jniEnv, obj, fieldID);
+ break;
+ case doubleType:
+ result.d = (*jniEnv)->GetDoubleField(jniEnv, obj, fieldID);
+ break;
+ case objectType:
+ result.l = (*jniEnv)->GetObjectField(jniEnv, obj, fieldID);
+ break;
+ case voidType:
+ // This error should have been handled in Dart.
+ break;
+ }
+ jthrowable exception = check_exception();
+ if (callType == objectType && exception == NULL) {
+ result.l = to_global_ref(result.l);
+ }
+ JniResult jniResult = {.value = result, .exception = exception};
+ return jniResult;
+}
+
+FFI_PLUGIN_EXPORT
+JniResult getStaticField(jclass cls, jfieldID fieldID, int callType) {
+ attach_thread();
+ jvalue result = {.j = 0};
+ switch (callType) {
+ case booleanType:
+ result.z = (*jniEnv)->GetStaticBooleanField(jniEnv, cls, fieldID);
+ break;
+ case byteType:
+ result.b = (*jniEnv)->GetStaticByteField(jniEnv, cls, fieldID);
+ break;
+ case shortType:
+ result.s = (*jniEnv)->GetStaticShortField(jniEnv, cls, fieldID);
+ break;
+ case charType:
+ result.c = (*jniEnv)->GetStaticCharField(jniEnv, cls, fieldID);
+ break;
+ case intType:
+ result.i = (*jniEnv)->GetStaticIntField(jniEnv, cls, fieldID);
+ break;
+ case longType:
+ result.j = (*jniEnv)->GetStaticLongField(jniEnv, cls, fieldID);
+ break;
+ case floatType:
+ result.f = (*jniEnv)->GetStaticFloatField(jniEnv, cls, fieldID);
+ break;
+ case doubleType:
+ result.d = (*jniEnv)->GetStaticDoubleField(jniEnv, cls, fieldID);
+ break;
+ case objectType:
+ result.l = (*jniEnv)->GetStaticObjectField(jniEnv, cls, fieldID);
+ break;
+ case voidType:
+ // This error should have been handled in dart.
+ // is there a way to mark this as unreachable?
+ // or throw exception in Dart using Dart's C API.
+ break;
+ }
+ jthrowable exception = check_exception();
+ if (callType == objectType && exception == NULL) {
+ result.l = to_global_ref(result.l);
+ }
+ JniResult jniResult = {.value = result, .exception = exception};
+ return jniResult;
+}
+
+JniResult newObject(jclass cls, jmethodID ctor, jvalue* args) {
+ attach_thread();
+ jobject result = (*jniEnv)->NewObjectA(jniEnv, cls, ctor, args);
+ return to_global_ref_result(result);
+}
+
+JniResult newPrimitiveArray(jsize length, int type) {
+ attach_thread();
+ jarray array;
+ switch (type) {
+ case booleanType:
+ array = (*jniEnv)->NewBooleanArray(jniEnv, length);
+ break;
+ case byteType:
+ array = (*jniEnv)->NewByteArray(jniEnv, length);
+ break;
+ case shortType:
+ array = (*jniEnv)->NewShortArray(jniEnv, length);
+ break;
+ case charType:
+ array = (*jniEnv)->NewCharArray(jniEnv, length);
+ break;
+ case intType:
+ array = (*jniEnv)->NewIntArray(jniEnv, length);
+ break;
+ case longType:
+ array = (*jniEnv)->NewLongArray(jniEnv, length);
+ break;
+ case floatType:
+ array = (*jniEnv)->NewFloatArray(jniEnv, length);
+ break;
+ case doubleType:
+ array = (*jniEnv)->NewDoubleArray(jniEnv, length);
+ break;
+ case objectType:
+ case voidType:
+ // This error should have been handled in dart.
+ // is there a way to mark this as unreachable?
+ // or throw exception in Dart using Dart's C API.
+ break;
+ }
+ return to_global_ref_result(array);
+}
+
+JniResult newObjectArray(jsize length,
+ jclass elementClass,
+ jobject initialElement) {
+ attach_thread();
+ jarray array =
+ (*jniEnv)->NewObjectArray(jniEnv, length, elementClass, initialElement);
+ return to_global_ref_result(array);
+}
+
+JniResult getArrayElement(jarray array, int index, int type) {
+ JniResult result = {{.l = NULL}, NULL};
+ attach_thread();
+ jvalue value;
+ switch (type) {
+ case booleanType:
+ (*jniEnv)->GetBooleanArrayRegion(jniEnv, array, index, 1, &value.z);
+ break;
+ case byteType:
+ (*jniEnv)->GetByteArrayRegion(jniEnv, array, index, 1, &value.b);
+ break;
+ case shortType:
+ (*jniEnv)->GetShortArrayRegion(jniEnv, array, index, 1, &value.s);
+ break;
+ case charType:
+ (*jniEnv)->GetCharArrayRegion(jniEnv, array, index, 1, &value.c);
+ break;
+ case intType:
+ (*jniEnv)->GetIntArrayRegion(jniEnv, array, index, 1, &value.i);
+ break;
+ case longType:
+ (*jniEnv)->GetLongArrayRegion(jniEnv, array, index, 1, &value.j);
+ break;
+ case floatType:
+ (*jniEnv)->GetFloatArrayRegion(jniEnv, array, index, 1, &value.f);
+ break;
+ case doubleType:
+ (*jniEnv)->GetDoubleArrayRegion(jniEnv, array, index, 1, &value.d);
+ break;
+ case objectType:
+ value.l = (*jniEnv)->GetObjectArrayElement(jniEnv, array, index);
+ case voidType:
+ // This error should have been handled in dart.
+ // is there a way to mark this as unreachable?
+ // or throw exception in Dart using Dart's C API.
+ break;
+ }
+ jthrowable exception = check_exception();
+ if (type == objectType && exception == NULL) {
+ value.l = to_global_ref(value.l);
+ }
+ JniResult jniResult = {.value = value, .exception = exception};
+ return jniResult;
+}
+
+JniExceptionDetails getExceptionDetails(jthrowable exception) {
+ JniExceptionDetails details;
+ details.message = (*jniEnv)->CallObjectMethod(
+ jniEnv, exception, exceptionMethods.toStringMethod);
+ jobject buffer =
+ (*jniEnv)->NewObject(jniEnv, exceptionMethods.byteArrayOutputStreamClass,
+ exceptionMethods.byteArrayOutputStreamCtor);
+ jobject printStream =
+ (*jniEnv)->NewObject(jniEnv, exceptionMethods.printStreamClass,
+ exceptionMethods.printStreamCtor, buffer);
+ (*jniEnv)->CallVoidMethod(
+ jniEnv, exception, exceptionMethods.printStackTraceMethod, printStream);
+ details.stacktrace = (*jniEnv)->CallObjectMethod(
+ jniEnv, buffer, exceptionMethods.toStringMethod);
+ details.message = to_global_ref(details.message);
+ details.stacktrace = to_global_ref(details.stacktrace);
+ return details;
+}
+
+JniAccessorsStruct accessors = {
+ .getClass = getClass,
+ .getFieldID = getFieldID,
+ .getStaticFieldID = getStaticFieldID,
+ .getMethodID = getMethodID,
+ .getStaticMethodID = getStaticMethodID,
+ .newObject = newObject,
+ .newPrimitiveArray = newPrimitiveArray,
+ .newObjectArray = newObjectArray,
+ .getArrayElement = getArrayElement,
+ .callMethod = callMethod,
+ .callStaticMethod = callStaticMethod,
+ .getField = getField,
+ .getStaticField = getStaticField,
+ .getExceptionDetails = getExceptionDetails,
+};
+
+FFI_PLUGIN_EXPORT JniAccessorsStruct* GetAccessors() {
+ return &accessors;
+}
+
+// These will not be required after migrating to Dart-only bindings.
+FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr() {
+ return jni;
+}
+
+FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv() {
+ if (jni_context.jvm == NULL) {
+ return NULL;
+ }
+ attach_thread();
+ return jniEnv;
+}
+
+FFI_PLUGIN_EXPORT intptr_t InitDartApiDL(void* data) {
+ return Dart_InitializeApiDL(data);
+}
+
+// com.github.dart_lang.jni.DartException
+jclass _c_DartException = NULL;
+
+jmethodID _m_DartException__ctor = NULL;
+FFI_PLUGIN_EXPORT JniResult DartException__ctor(jstring message) {
+ attach_thread();
+ load_class_global_ref(&_c_DartException,
+ "com/github/dart_lang/jni/PortProxy$DartException");
+ if (_c_DartException == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_DartException, &_m_DartException__ctor, "<init>",
+ "(Ljava/lang/String;)V");
+ if (_m_DartException__ctor == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_DartException,
+ _m_DartException__ctor, message);
+ jthrowable exception = check_exception();
+ if (exception == NULL) {
+ _result = to_global_ref(_result);
+ }
+ return (JniResult){.value = {.l = _result}, .exception = check_exception()};
+}
+
+JNIEXPORT void JNICALL
+Java_com_github_dart_1lang_jni_PortContinuation__1resumeWith(JNIEnv* env,
+ jclass clazz,
+ jlong port,
+ jobject result) {
+ attach_thread();
+ Dart_CObject c_post;
+ c_post.type = Dart_CObject_kInt64;
+ c_post.value.as_int64 = (jlong)((*env)->NewGlobalRef(env, result));
+ Dart_PostCObject_DL(port, &c_post);
+}
+
+// com.github.dart_lang.jni.PortContinuation
+jclass _c_PortContinuation = NULL;
+
+jmethodID _m_PortContinuation__ctor = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PortContinuation__ctor(int64_t j) {
+ attach_thread();
+ load_class_global_ref(&_c_PortContinuation,
+ "com/github/dart_lang/jni/PortContinuation");
+ if (_c_PortContinuation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PortContinuation, &_m_PortContinuation__ctor, "<init>",
+ "(J)V");
+ if (_m_PortContinuation__ctor == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_PortContinuation,
+ _m_PortContinuation__ctor, j);
+ jthrowable exception = check_exception();
+ if (exception == NULL) {
+ _result = to_global_ref(_result);
+ }
+ return (JniResult){.value = {.l = _result}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jni.PortProxy
+jclass _c_PortProxy = NULL;
+
+jmethodID _m_PortProxy__newInstance = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PortProxy__newInstance(jobject binaryName,
+ int64_t port,
+ int64_t functionPtr) {
+ attach_thread();
+ load_class_global_ref(&_c_PortProxy, "com/github/dart_lang/jni/PortProxy");
+ if (_c_PortProxy == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_PortProxy, &_m_PortProxy__newInstance, "newInstance",
+ "(Ljava/lang/String;JJJ)Ljava/lang/Object;");
+ if (_m_PortProxy__newInstance == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PortProxy, _m_PortProxy__newInstance, binaryName, port,
+ (jlong)Dart_CurrentIsolate_DL(), functionPtr);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+void resultFor(CallbackResult* result, jobject object) {
+ acquire_lock(&result->lock);
+ result->ready = 1;
+ result->object = object;
+ signal_cond(&result->cond);
+ release_lock(&result->lock);
+}
+
+jclass _c_Object = NULL;
+jclass _c_Long = NULL;
+
+jmethodID _m_Long_init = NULL;
+
+JNIEXPORT jobjectArray JNICALL
+Java_com_github_dart_1lang_jni_PortProxy__1invoke(JNIEnv* env,
+ jclass clazz,
+ jlong port,
+ jlong isolateId,
+ jlong functionPtr,
+ jobject proxy,
+ jstring methodDescriptor,
+ jobjectArray args) {
+ CallbackResult* result = (CallbackResult*)malloc(sizeof(CallbackResult));
+ if (isolateId != (jlong)Dart_CurrentIsolate_DL()) {
+ init_lock(&result->lock);
+ init_cond(&result->cond);
+ acquire_lock(&result->lock);
+ result->ready = 0;
+ result->object = NULL;
+
+ Dart_CObject c_result;
+ c_result.type = Dart_CObject_kInt64;
+ c_result.value.as_int64 = (jlong)result;
+
+ Dart_CObject c_method;
+ c_method.type = Dart_CObject_kInt64;
+ c_method.value.as_int64 =
+ (jlong)((*env)->NewGlobalRef(env, methodDescriptor));
+
+ Dart_CObject c_args;
+ c_args.type = Dart_CObject_kInt64;
+ c_args.value.as_int64 = (jlong)((*env)->NewGlobalRef(env, args));
+
+ Dart_CObject* c_post_arr[] = {&c_result, &c_method, &c_args};
+ Dart_CObject c_post;
+ c_post.type = Dart_CObject_kArray;
+ c_post.value.as_array.values = c_post_arr;
+ c_post.value.as_array.length = sizeof(c_post_arr) / sizeof(c_post_arr[0]);
+
+ Dart_PostCObject_DL(port, &c_post);
+
+ while (!result->ready) {
+ wait_for(&result->cond, &result->lock);
+ }
+
+ release_lock(&result->lock);
+ destroy_lock(&result->lock);
+ destroy_cond(&result->cond);
+ } else {
+ result->object = ((jobject(*)(uint64_t, jobject, jobject))functionPtr)(
+ port, (*env)->NewGlobalRef(env, methodDescriptor),
+ (*env)->NewGlobalRef(env, args));
+ }
+ // Returning an array of length 2.
+ // [0]: The result pointer, used for cleaning up the global reference, and
+ // freeing the memory since we passed the ownership to Java.
+ // [1]: The returned object.
+ attach_thread();
+ load_class_global_ref(&_c_Object, "java/lang/Object");
+ load_class_global_ref(&_c_Long, "java/lang/Long");
+ load_method(_c_Long, &_m_Long_init, "<init>", "(J)V");
+ jobject first = (*env)->NewObject(env, _c_Long, _m_Long_init, (jlong)result);
+ jobject second = result->object;
+ jobjectArray arr = (*env)->NewObjectArray(env, 2, _c_Object, NULL);
+ (*env)->SetObjectArrayElement(env, arr, 0, first);
+ (*env)->SetObjectArrayElement(env, arr, 1, second);
+ return arr;
+}
+
+JNIEXPORT void JNICALL
+Java_com_github_dart_1lang_jni_PortProxy__1cleanUp(JNIEnv* env,
+ jclass clazz,
+ jlong resultPtr) {
+ CallbackResult* result = (CallbackResult*)resultPtr;
+ (*env)->DeleteGlobalRef(env, result->object);
+ free(result);
+}
+
+JNIEXPORT void JNICALL
+Java_com_github_dart_1lang_jni_PortCleaner_clean(JNIEnv* env,
+ jclass clazz,
+ jlong port) {
+ Dart_CObject close_signal;
+ close_signal.type = Dart_CObject_kNull;
+ Dart_PostCObject_DL(port, &close_signal);
+}
diff --git a/pkgs/jni/src/dartjni.h b/pkgs/jni/src/dartjni.h
new file mode 100644
index 0000000..8f1dc74
--- /dev/null
+++ b/pkgs/jni/src/dartjni.h
@@ -0,0 +1,424 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#pragma once
+
+// Note: include appropriate system jni.h as found by CMake, not third_party/jni.h.
+#include <jni.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if _WIN32
+#include <windows.h>
+#else
+#include <pthread.h>
+#include <unistd.h>
+#endif
+
+#if _WIN32
+#define FFI_PLUGIN_EXPORT __declspec(dllexport)
+#else
+#define FFI_PLUGIN_EXPORT
+#endif
+
+#if defined _WIN32
+#define thread_local __declspec(thread)
+#else
+#define thread_local __thread
+#endif
+
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
+
+#ifdef __ANDROID__
+#define __ENVP_CAST (JNIEnv**)
+#else
+#define __ENVP_CAST (void**)
+#endif
+
+/// Locking functions for windows and pthread.
+
+#if defined _WIN32
+#include <windows.h>
+
+typedef CRITICAL_SECTION MutexLock;
+typedef CONDITION_VARIABLE ConditionVariable;
+
+static inline void init_lock(MutexLock* lock) {
+ InitializeCriticalSection(lock);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+ EnterCriticalSection(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+ LeaveCriticalSection(lock);
+}
+
+static inline void destroy_lock(MutexLock* lock) {
+ DeleteCriticalSection(lock);
+}
+
+static inline void init_cond(ConditionVariable* cond) {
+ InitializeConditionVariable(cond);
+}
+
+static inline void signal_cond(ConditionVariable* cond) {
+ WakeConditionVariable(cond);
+}
+
+static inline void wait_for(ConditionVariable* cond, MutexLock* lock) {
+ SleepConditionVariableCS(cond, lock, INFINITE);
+}
+
+static inline void destroy_cond(ConditionVariable* cond) {
+ // Not available.
+}
+
+#elif defined __APPLE__ || defined __LINUX__ || defined __ANDROID__ || \
+ defined __GNUC__
+#include <pthread.h>
+
+typedef pthread_mutex_t MutexLock;
+typedef pthread_cond_t ConditionVariable;
+
+static inline void init_lock(MutexLock* lock) {
+ pthread_mutex_init(lock, NULL);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+ pthread_mutex_lock(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+ pthread_mutex_unlock(lock);
+}
+
+static inline void destroy_lock(MutexLock* lock) {
+ pthread_mutex_destroy(lock);
+}
+
+static inline void init_cond(ConditionVariable* cond) {
+ pthread_cond_init(cond, NULL);
+}
+
+static inline void signal_cond(ConditionVariable* cond) {
+ pthread_cond_signal(cond);
+}
+
+static inline void wait_for(ConditionVariable* cond, MutexLock* lock) {
+ pthread_cond_wait(cond, lock);
+}
+
+static inline void destroy_cond(ConditionVariable* cond) {
+ pthread_cond_destroy(cond);
+}
+
+#else
+
+#error "No locking/condition variable support; Possibly unsupported platform"
+
+#endif
+
+typedef struct CallbackResult {
+ MutexLock lock;
+ ConditionVariable cond;
+ int ready;
+ jobject object;
+} CallbackResult;
+
+typedef struct JniLocks {
+ MutexLock classLoadingLock;
+ MutexLock methodLoadingLock;
+ MutexLock fieldLoadingLock;
+} JniLocks;
+
+/// Represents the error when dart-jni layer has already spawned singleton VM.
+#define DART_JNI_SINGLETON_EXISTS (-99);
+
+/// Stores the global state of the JNI.
+typedef struct JniContext {
+ JavaVM* jvm;
+ jobject classLoader;
+ jmethodID loadClassMethod;
+ jobject currentActivity;
+ jobject appContext;
+ JniLocks locks;
+} JniContext;
+
+// jniEnv for this thread, used by inline functions in this header,
+// therefore declared as extern.
+extern thread_local JNIEnv* jniEnv;
+
+extern JniContext* jni;
+
+/// Types used by JNI API to distinguish between primitive types.
+enum JniType {
+ booleanType = 0,
+ byteType = 1,
+ shortType = 2,
+ charType = 3,
+ intType = 4,
+ longType = 5,
+ floatType = 6,
+ doubleType = 7,
+ objectType = 8,
+ voidType = 9,
+};
+
+/// Result type for use by JNI.
+///
+/// If [exception] is null, it means the result is valid.
+/// It's assumed that the caller knows the expected type in [result].
+typedef struct JniResult {
+ jvalue value;
+ jthrowable exception;
+} JniResult;
+
+/// Similar to [JniResult] but for class lookups.
+typedef struct JniClassLookupResult {
+ jclass value;
+ jthrowable exception;
+} JniClassLookupResult;
+
+/// Similar to [JniResult] but for method/field ID lookups.
+typedef struct JniPointerResult {
+ const void* value;
+ jthrowable exception;
+} JniPointerResult;
+
+/// JniExceptionDetails holds 2 jstring objects, one is the result of
+/// calling `toString` on exception object, other is stack trace;
+typedef struct JniExceptionDetails {
+ jstring message;
+ jstring stacktrace;
+} JniExceptionDetails;
+
+/// This struct contains functions which wrap method call / field access conveniently along with
+/// exception checking.
+///
+/// Flutter embedding checks for pending JNI exceptions before an FFI transition, which requires us
+/// to check for and clear the exception before returning to dart code, which requires these functions
+/// to return result types.
+typedef struct JniAccessorsStruct {
+ JniClassLookupResult (*getClass)(char* internalName);
+ JniPointerResult (*getFieldID)(jclass cls, char* fieldName, char* signature);
+ JniPointerResult (*getStaticFieldID)(jclass cls,
+ char* fieldName,
+ char* signature);
+ JniPointerResult (*getMethodID)(jclass cls,
+ char* methodName,
+ char* signature);
+ JniPointerResult (*getStaticMethodID)(jclass cls,
+ char* methodName,
+ char* signature);
+ JniResult (*newObject)(jclass cls, jmethodID ctor, jvalue* args);
+ JniResult (*newPrimitiveArray)(jsize length, int type);
+ JniResult (*newObjectArray)(jsize length,
+ jclass elementClass,
+ jobject initialElement);
+ JniResult (*getArrayElement)(jarray array, int index, int type);
+ JniResult (*callMethod)(jobject obj,
+ jmethodID methodID,
+ int callType,
+ jvalue* args);
+ JniResult (*callStaticMethod)(jclass cls,
+ jmethodID methodID,
+ int callType,
+ jvalue* args);
+ JniResult (*getField)(jobject obj, jfieldID fieldID, int callType);
+ JniResult (*getStaticField)(jclass cls, jfieldID fieldID, int callType);
+ JniExceptionDetails (*getExceptionDetails)(jthrowable exception);
+} JniAccessorsStruct;
+
+FFI_PLUGIN_EXPORT JniAccessorsStruct* GetAccessors();
+
+FFI_PLUGIN_EXPORT JavaVM* GetJavaVM(void);
+
+FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv(void);
+
+/// Spawn a JVM with given arguments.
+///
+/// Returns JNI_OK on success, and one of the documented JNI error codes on
+/// failure. It returns DART_JNI_SINGLETON_EXISTS if an attempt to spawn multiple
+/// JVMs is made, even if the underlying API potentially supports multiple VMs.
+FFI_PLUGIN_EXPORT int SpawnJvm(JavaVMInitArgs* args);
+
+/// Load class through platform-specific mechanism.
+///
+/// Currently uses application classloader on android,
+/// and JNIEnv->FindClass on other platforms.
+FFI_PLUGIN_EXPORT jclass FindClass(const char* name);
+
+/// Returns Application classLoader (on Android),
+/// which can be used to load application and platform classes.
+///
+/// On other platforms, NULL is returned.
+FFI_PLUGIN_EXPORT jobject GetClassLoader(void);
+
+/// Returns application context on Android.
+///
+/// On other platforms, NULL is returned.
+FFI_PLUGIN_EXPORT jobject GetApplicationContext(void);
+
+/// Returns current activity of the app on Android.
+FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
+
+static inline void attach_thread() {
+ if (jniEnv == NULL) {
+ (*jni->jvm)->AttachCurrentThread(jni->jvm, __ENVP_CAST & jniEnv, NULL);
+ }
+}
+
+/// Load class into [cls] using platform specific mechanism
+static inline void load_class_platform(jclass* cls, const char* name) {
+#ifdef __ANDROID__
+ jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
+ *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni->classLoader,
+ jni->loadClassMethod, className);
+ (*jniEnv)->DeleteLocalRef(jniEnv, className);
+#else
+ *cls = (*jniEnv)->FindClass(jniEnv, name);
+#endif
+}
+
+static inline void load_class_local_ref(jclass* cls, const char* name) {
+ if (*cls == NULL) {
+ acquire_lock(&jni->locks.classLoadingLock);
+ if (*cls == NULL) {
+ load_class_platform(cls, name);
+ }
+ release_lock(&jni->locks.classLoadingLock);
+ }
+}
+
+static inline void load_class_global_ref(jclass* cls, const char* name) {
+ if (*cls == NULL) {
+ jclass tmp = NULL;
+ acquire_lock(&jni->locks.classLoadingLock);
+ if (*cls == NULL) {
+ load_class_platform(&tmp, name);
+ if (!(*jniEnv)->ExceptionCheck(jniEnv)) {
+ *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
+ (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
+ }
+ }
+ release_lock(&jni->locks.classLoadingLock);
+ }
+}
+
+static inline void load_method(jclass cls,
+ jmethodID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.methodLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.methodLoadingLock);
+ }
+}
+
+static inline void load_static_method(jclass cls,
+ jmethodID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.methodLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.methodLoadingLock);
+ }
+}
+
+static inline void load_field(jclass cls,
+ jfieldID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.fieldLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.fieldLoadingLock);
+ }
+}
+
+static inline void load_static_field(jclass cls,
+ jfieldID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.fieldLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.fieldLoadingLock);
+ }
+}
+
+static inline jobject to_global_ref(jobject ref) {
+ jobject g = (*jniEnv)->NewGlobalRef(jniEnv, ref);
+ (*jniEnv)->DeleteLocalRef(jniEnv, ref);
+ return g;
+}
+
+// These functions are useful for C+Dart bindings, and not required for pure dart bindings.
+
+FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr();
+
+/// For use by jni_gen's generated code
+/// don't use these.
+
+// these 2 fn ptr vars will be defined by generated code library
+extern JniContext* (*context_getter)(void);
+extern JNIEnv* (*env_getter)(void);
+
+// this function will be exported by generated code library
+// it will set above 2 variables.
+FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext* (*cg)(void),
+ JNIEnv* (*eg)(void));
+
+static inline void load_env() {
+ if (jniEnv == NULL) {
+ jni = context_getter();
+ jniEnv = env_getter();
+ }
+}
+
+static inline jthrowable check_exception() {
+ jthrowable exception = (*jniEnv)->ExceptionOccurred(jniEnv);
+ if (exception != NULL) (*jniEnv)->ExceptionClear(jniEnv);
+ if (exception == NULL) return NULL;
+ return to_global_ref(exception);
+}
+
+static inline JniResult to_global_ref_result(jobject ref) {
+ JniResult result;
+ result.exception = check_exception();
+ if (result.exception == NULL) {
+ result.value.l = to_global_ref(ref);
+ }
+ return result;
+}
+
+FFI_PLUGIN_EXPORT intptr_t InitDartApiDL(void* data);
+
+FFI_PLUGIN_EXPORT
+JniResult DartException__ctor(jstring message);
+
+FFI_PLUGIN_EXPORT
+JniResult PortContinuation__ctor(int64_t j);
+
+FFI_PLUGIN_EXPORT
+JniResult PortProxy__newInstance(jobject binaryName,
+ int64_t port,
+ int64_t functionPtr);
+
+FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
diff --git a/pkgs/jni/src/include/BUILD.gn b/pkgs/jni/src/include/BUILD.gn
new file mode 100644
index 0000000..2b10262
--- /dev/null
+++ b/pkgs/jni/src/include/BUILD.gn
@@ -0,0 +1,23 @@
+# Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+import("../../sdk_args.gni")
+
+# This rule copies header files to include/
+copy("copy_headers") {
+ visibility = [ "../../sdk:copy_headers" ]
+
+ sources = [
+ "dart_api.h",
+ "dart_api_dl.c",
+ "dart_api_dl.h",
+ "dart_native_api.h",
+ "dart_tools_api.h",
+ "dart_version.h",
+ "internal/dart_api_dl_impl.h",
+ ]
+
+ outputs =
+ [ "$root_out_dir/$dart_sdk_output/include/{{source_target_relative}}" ]
+}
diff --git a/pkgs/jni/src/include/analyze_snapshot_api.h b/pkgs/jni/src/include/analyze_snapshot_api.h
new file mode 100644
index 0000000..0e68d5c
--- /dev/null
+++ b/pkgs/jni/src/include/analyze_snapshot_api.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+ * for details. All rights reserved. Use of this source code is governed by a
+ * BSD-style license that can be found in the LICENSE file.
+ */
+
+#ifndef RUNTIME_INCLUDE_ANALYZE_SNAPSHOT_API_H_
+#define RUNTIME_INCLUDE_ANALYZE_SNAPSHOT_API_H_
+
+#include <stdint.h>
+
+namespace dart {
+namespace snapshot_analyzer {
+typedef struct {
+ const uint8_t* vm_snapshot_data;
+ const uint8_t* vm_snapshot_instructions;
+ const uint8_t* vm_isolate_data;
+ const uint8_t* vm_isolate_instructions;
+} Dart_SnapshotAnalyzerInformation;
+
+void Dart_DumpSnapshotInformationAsJson(char** buffer,
+ intptr_t* buffer_length,
+ Dart_SnapshotAnalyzerInformation* info);
+
+void Dart_DumpSnapshotInformationPP(Dart_SnapshotAnalyzerInformation* info);
+
+} // namespace snapshot_analyzer
+} // namespace dart
+
+#endif // RUNTIME_INCLUDE_ANALYZE_SNAPSHOT_API_H_
diff --git a/pkgs/jni/src/include/bin/dart_io_api.h b/pkgs/jni/src/include/bin/dart_io_api.h
new file mode 100644
index 0000000..cc64797
--- /dev/null
+++ b/pkgs/jni/src/include/bin/dart_io_api.h
@@ -0,0 +1,69 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_INCLUDE_BIN_DART_IO_API_H_
+#define RUNTIME_INCLUDE_BIN_DART_IO_API_H_
+
+#include "dart_tools_api.h"
+
+namespace dart {
+namespace bin {
+
+// Bootstraps 'dart:io'.
+void BootstrapDartIo();
+
+// Cleans up 'dart:io'.
+void CleanupDartIo();
+
+// Lets dart:io know where the system temporary directory is located.
+// Currently only wired up on Android.
+void SetSystemTempDirectory(const char* system_temp);
+
+// Tells the system whether to capture Stdout events.
+void SetCaptureStdout(bool value);
+
+// Tells the system whether to capture Stderr events.
+void SetCaptureStderr(bool value);
+
+// Should Stdout events be captured?
+bool ShouldCaptureStdout();
+
+// Should Stderr events be captured?
+bool ShouldCaptureStderr();
+
+// Set the executable name used by Platform.executable.
+void SetExecutableName(const char* executable_name);
+
+// Set the arguments used by Platform.executableArguments.
+void SetExecutableArguments(int script_index, char** argv);
+
+// Set dart:io implementation specific fields of Dart_EmbedderInformation.
+void GetIOEmbedderInformation(Dart_EmbedderInformation* info);
+
+// Appropriate to assign to Dart_InitializeParams.file_open/read/write/close.
+void* OpenFile(const char* name, bool write);
+void ReadFile(uint8_t** data, intptr_t* file_len, void* stream);
+void WriteFile(const void* buffer, intptr_t num_bytes, void* stream);
+void CloseFile(void* stream);
+
+// Generates 'length' random bytes into 'buffer'. Returns true on success
+// and false on failure. This is appropriate to assign to
+// Dart_InitializeParams.entropy_source.
+bool GetEntropy(uint8_t* buffer, intptr_t length);
+
+// Performs a lookup of the I/O Dart_NativeFunction with a specified 'name' and
+// 'argument_count'. Returns NULL if no I/O native function with a matching
+// name and parameter count is found.
+Dart_NativeFunction LookupIONative(Dart_Handle name,
+ int argument_count,
+ bool* auto_setup_scope);
+
+// Returns the symbol for I/O native function 'nf'. Returns NULL if 'nf' is not
+// a valid I/O native function.
+const uint8_t* LookupIONativeSymbol(Dart_NativeFunction nf);
+
+} // namespace bin
+} // namespace dart
+
+#endif // RUNTIME_INCLUDE_BIN_DART_IO_API_H_
diff --git a/pkgs/jni/src/include/dart_api.h b/pkgs/jni/src/include/dart_api.h
new file mode 100644
index 0000000..99dde6f
--- /dev/null
+++ b/pkgs/jni/src/include/dart_api.h
@@ -0,0 +1,4185 @@
+/*
+ * Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+ * for details. All rights reserved. Use of this source code is governed by a
+ * BSD-style license that can be found in the LICENSE file.
+ */
+
+#ifndef RUNTIME_INCLUDE_DART_API_H_
+#define RUNTIME_INCLUDE_DART_API_H_
+
+/** \mainpage Dart Embedding API Reference
+ *
+ * This reference describes the Dart Embedding API, which is used to embed the
+ * Dart Virtual Machine within C/C++ applications.
+ *
+ * This reference is generated from the header include/dart_api.h.
+ */
+
+/* __STDC_FORMAT_MACROS has to be defined before including <inttypes.h> to
+ * enable platform independent printf format specifiers. */
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdbool.h>
+
+#if defined(__Fuchsia__)
+#include <zircon/types.h>
+#endif
+
+#ifdef __cplusplus
+#define DART_EXTERN_C extern "C"
+#else
+#define DART_EXTERN_C extern
+#endif
+
+#if defined(__CYGWIN__)
+#error Tool chain and platform not supported.
+#elif defined(_WIN32)
+#if defined(DART_SHARED_LIB)
+#define DART_EXPORT DART_EXTERN_C __declspec(dllexport)
+#else
+#define DART_EXPORT DART_EXTERN_C
+#endif
+#else
+#if __GNUC__ >= 4
+#if defined(DART_SHARED_LIB)
+#define DART_EXPORT \
+ DART_EXTERN_C __attribute__((visibility("default"))) __attribute((used))
+#else
+#define DART_EXPORT DART_EXTERN_C
+#endif
+#else
+#error Tool chain not supported.
+#endif
+#endif
+
+#if __GNUC__
+#define DART_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#elif _MSC_VER
+#define DART_WARN_UNUSED_RESULT _Check_return_
+#else
+#define DART_WARN_UNUSED_RESULT
+#endif
+
+/*
+ * =======
+ * Handles
+ * =======
+ */
+
+/**
+ * An isolate is the unit of concurrency in Dart. Each isolate has
+ * its own memory and thread of control. No state is shared between
+ * isolates. Instead, isolates communicate by message passing.
+ *
+ * Each thread keeps track of its current isolate, which is the
+ * isolate which is ready to execute on the current thread. The
+ * current isolate may be NULL, in which case no isolate is ready to
+ * execute. Most of the Dart apis require there to be a current
+ * isolate in order to function without error. The current isolate is
+ * set by any call to Dart_CreateIsolateGroup or Dart_EnterIsolate.
+ */
+typedef struct _Dart_Isolate* Dart_Isolate;
+typedef struct _Dart_IsolateGroup* Dart_IsolateGroup;
+
+/**
+ * An object reference managed by the Dart VM garbage collector.
+ *
+ * Because the garbage collector may move objects, it is unsafe to
+ * refer to objects directly. Instead, we refer to objects through
+ * handles, which are known to the garbage collector and updated
+ * automatically when the object is moved. Handles should be passed
+ * by value (except in cases like out-parameters) and should never be
+ * allocated on the heap.
+ *
+ * Most functions in the Dart Embedding API return a handle. When a
+ * function completes normally, this will be a valid handle to an
+ * object in the Dart VM heap. This handle may represent the result of
+ * the operation or it may be a special valid handle used merely to
+ * indicate successful completion. Note that a valid handle may in
+ * some cases refer to the null object.
+ *
+ * --- Error handles ---
+ *
+ * When a function encounters a problem that prevents it from
+ * completing normally, it returns an error handle (See Dart_IsError).
+ * An error handle has an associated error message that gives more
+ * details about the problem (See Dart_GetError).
+ *
+ * There are four kinds of error handles that can be produced,
+ * depending on what goes wrong:
+ *
+ * - Api error handles are produced when an api function is misused.
+ * This happens when a Dart embedding api function is called with
+ * invalid arguments or in an invalid context.
+ *
+ * - Unhandled exception error handles are produced when, during the
+ * execution of Dart code, an exception is thrown but not caught.
+ * Prototypically this would occur during a call to Dart_Invoke, but
+ * it can occur in any function which triggers the execution of Dart
+ * code (for example, Dart_ToString).
+ *
+ * An unhandled exception error provides access to an exception and
+ * stacktrace via the functions Dart_ErrorGetException and
+ * Dart_ErrorGetStackTrace.
+ *
+ * - Compilation error handles are produced when, during the execution
+ * of Dart code, a compile-time error occurs. As above, this can
+ * occur in any function which triggers the execution of Dart code.
+ *
+ * - Fatal error handles are produced when the system wants to shut
+ * down the current isolate.
+ *
+ * --- Propagating errors ---
+ *
+ * When an error handle is returned from the top level invocation of
+ * Dart code in a program, the embedder must handle the error as they
+ * see fit. Often, the embedder will print the error message produced
+ * by Dart_Error and exit the program.
+ *
+ * When an error is returned while in the body of a native function,
+ * it can be propagated up the call stack by calling
+ * Dart_PropagateError, Dart_SetReturnValue, or Dart_ThrowException.
+ * Errors should be propagated unless there is a specific reason not
+ * to. If an error is not propagated then it is ignored. For
+ * example, if an unhandled exception error is ignored, that
+ * effectively "catches" the unhandled exception. Fatal errors must
+ * always be propagated.
+ *
+ * When an error is propagated, any current scopes created by
+ * Dart_EnterScope will be exited.
+ *
+ * Using Dart_SetReturnValue to propagate an exception is somewhat
+ * more convenient than using Dart_PropagateError, and should be
+ * preferred for reasons discussed below.
+ *
+ * Dart_PropagateError and Dart_ThrowException do not return. Instead
+ * they transfer control non-locally using a setjmp-like mechanism.
+ * This can be inconvenient if you have resources that you need to
+ * clean up before propagating the error.
+ *
+ * When relying on Dart_PropagateError, we often return error handles
+ * rather than propagating them from helper functions. Consider the
+ * following contrived example:
+ *
+ * 1 Dart_Handle isLongStringHelper(Dart_Handle arg) {
+ * 2 intptr_t* length = 0;
+ * 3 result = Dart_StringLength(arg, &length);
+ * 4 if (Dart_IsError(result)) {
+ * 5 return result;
+ * 6 }
+ * 7 return Dart_NewBoolean(length > 100);
+ * 8 }
+ * 9
+ * 10 void NativeFunction_isLongString(Dart_NativeArguments args) {
+ * 11 Dart_EnterScope();
+ * 12 AllocateMyResource();
+ * 13 Dart_Handle arg = Dart_GetNativeArgument(args, 0);
+ * 14 Dart_Handle result = isLongStringHelper(arg);
+ * 15 if (Dart_IsError(result)) {
+ * 16 FreeMyResource();
+ * 17 Dart_PropagateError(result);
+ * 18 abort(); // will not reach here
+ * 19 }
+ * 20 Dart_SetReturnValue(result);
+ * 21 FreeMyResource();
+ * 22 Dart_ExitScope();
+ * 23 }
+ *
+ * In this example, we have a native function which calls a helper
+ * function to do its work. On line 5, the helper function could call
+ * Dart_PropagateError, but that would not give the native function a
+ * chance to call FreeMyResource(), causing a leak. Instead, the
+ * helper function returns the error handle to the caller, giving the
+ * caller a chance to clean up before propagating the error handle.
+ *
+ * When an error is propagated by calling Dart_SetReturnValue, the
+ * native function will be allowed to complete normally and then the
+ * exception will be propagated only once the native call
+ * returns. This can be convenient, as it allows the C code to clean
+ * up normally.
+ *
+ * The example can be written more simply using Dart_SetReturnValue to
+ * propagate the error.
+ *
+ * 1 Dart_Handle isLongStringHelper(Dart_Handle arg) {
+ * 2 intptr_t* length = 0;
+ * 3 result = Dart_StringLength(arg, &length);
+ * 4 if (Dart_IsError(result)) {
+ * 5 return result
+ * 6 }
+ * 7 return Dart_NewBoolean(length > 100);
+ * 8 }
+ * 9
+ * 10 void NativeFunction_isLongString(Dart_NativeArguments args) {
+ * 11 Dart_EnterScope();
+ * 12 AllocateMyResource();
+ * 13 Dart_Handle arg = Dart_GetNativeArgument(args, 0);
+ * 14 Dart_SetReturnValue(isLongStringHelper(arg));
+ * 15 FreeMyResource();
+ * 16 Dart_ExitScope();
+ * 17 }
+ *
+ * In this example, the call to Dart_SetReturnValue on line 14 will
+ * either return the normal return value or the error (potentially
+ * generated on line 3). The call to FreeMyResource on line 15 will
+ * execute in either case.
+ *
+ * --- Local and persistent handles ---
+ *
+ * Local handles are allocated within the current scope (see
+ * Dart_EnterScope) and go away when the current scope exits. Unless
+ * otherwise indicated, callers should assume that all functions in
+ * the Dart embedding api return local handles.
+ *
+ * Persistent handles are allocated within the current isolate. They
+ * can be used to store objects across scopes. Persistent handles have
+ * the lifetime of the current isolate unless they are explicitly
+ * deallocated (see Dart_DeletePersistentHandle).
+ * The type Dart_Handle represents a handle (both local and persistent).
+ * The type Dart_PersistentHandle is a Dart_Handle and it is used to
+ * document that a persistent handle is expected as a parameter to a call
+ * or the return value from a call is a persistent handle.
+ *
+ * FinalizableHandles are persistent handles which are auto deleted when
+ * the object is garbage collected. It is never safe to use these handles
+ * unless you know the object is still reachable.
+ *
+ * WeakPersistentHandles are persistent handles which are automatically set
+ * to point Dart_Null when the object is garbage collected. They are not auto
+ * deleted, so it is safe to use them after the object has become unreachable.
+ */
+typedef struct _Dart_Handle* Dart_Handle;
+typedef Dart_Handle Dart_PersistentHandle;
+typedef struct _Dart_WeakPersistentHandle* Dart_WeakPersistentHandle;
+typedef struct _Dart_FinalizableHandle* Dart_FinalizableHandle;
+// These structs are versioned by DART_API_DL_MAJOR_VERSION, bump the
+// version when changing this struct.
+
+typedef void (*Dart_HandleFinalizer)(void* isolate_callback_data, void* peer);
+
+/**
+ * Is this an error handle?
+ *
+ * Requires there to be a current isolate.
+ */
+DART_EXPORT bool Dart_IsError(Dart_Handle handle);
+
+/**
+ * Is this an api error handle?
+ *
+ * Api error handles are produced when an api function is misused.
+ * This happens when a Dart embedding api function is called with
+ * invalid arguments or in an invalid context.
+ *
+ * Requires there to be a current isolate.
+ */
+DART_EXPORT bool Dart_IsApiError(Dart_Handle handle);
+
+/**
+ * Is this an unhandled exception error handle?
+ *
+ * Unhandled exception error handles are produced when, during the
+ * execution of Dart code, an exception is thrown but not caught.
+ * This can occur in any function which triggers the execution of Dart
+ * code.
+ *
+ * See Dart_ErrorGetException and Dart_ErrorGetStackTrace.
+ *
+ * Requires there to be a current isolate.
+ */
+DART_EXPORT bool Dart_IsUnhandledExceptionError(Dart_Handle handle);
+
+/**
+ * Is this a compilation error handle?
+ *
+ * Compilation error handles are produced when, during the execution
+ * of Dart code, a compile-time error occurs. This can occur in any
+ * function which triggers the execution of Dart code.
+ *
+ * Requires there to be a current isolate.
+ */
+DART_EXPORT bool Dart_IsCompilationError(Dart_Handle handle);
+
+/**
+ * Is this a fatal error handle?
+ *
+ * Fatal error handles are produced when the system wants to shut down
+ * the current isolate.
+ *
+ * Requires there to be a current isolate.
+ */
+DART_EXPORT bool Dart_IsFatalError(Dart_Handle handle);
+
+/**
+ * Gets the error message from an error handle.
+ *
+ * Requires there to be a current isolate.
+ *
+ * \return A C string containing an error message if the handle is
+ * error. An empty C string ("") if the handle is valid. This C
+ * String is scope allocated and is only valid until the next call
+ * to Dart_ExitScope.
+*/
+DART_EXPORT const char* Dart_GetError(Dart_Handle handle);
+
+/**
+ * Is this an error handle for an unhandled exception?
+ */
+DART_EXPORT bool Dart_ErrorHasException(Dart_Handle handle);
+
+/**
+ * Gets the exception Object from an unhandled exception error handle.
+ */
+DART_EXPORT Dart_Handle Dart_ErrorGetException(Dart_Handle handle);
+
+/**
+ * Gets the stack trace Object from an unhandled exception error handle.
+ */
+DART_EXPORT Dart_Handle Dart_ErrorGetStackTrace(Dart_Handle handle);
+
+/**
+ * Produces an api error handle with the provided error message.
+ *
+ * Requires there to be a current isolate.
+ *
+ * \param error the error message.
+ */
+DART_EXPORT Dart_Handle Dart_NewApiError(const char* error);
+DART_EXPORT Dart_Handle Dart_NewCompilationError(const char* error);
+
+/**
+ * Produces a new unhandled exception error handle.
+ *
+ * Requires there to be a current isolate.
+ *
+ * \param exception An instance of a Dart object to be thrown or
+ * an ApiError or CompilationError handle.
+ * When an ApiError or CompilationError handle is passed in
+ * a string object of the error message is created and it becomes
+ * the Dart object to be thrown.
+ */
+DART_EXPORT Dart_Handle Dart_NewUnhandledExceptionError(Dart_Handle exception);
+
+/**
+ * Propagates an error.
+ *
+ * If the provided handle is an unhandled exception error, this
+ * function will cause the unhandled exception to be rethrown. This
+ * will proceed in the standard way, walking up Dart frames until an
+ * appropriate 'catch' block is found, executing 'finally' blocks,
+ * etc.
+ *
+ * If the error is not an unhandled exception error, we will unwind
+ * the stack to the next C frame. Intervening Dart frames will be
+ * discarded; specifically, 'finally' blocks will not execute. This
+ * is the standard way that compilation errors (and the like) are
+ * handled by the Dart runtime.
+ *
+ * In either case, when an error is propagated any current scopes
+ * created by Dart_EnterScope will be exited.
+ *
+ * See the additional discussion under "Propagating Errors" at the
+ * beginning of this file.
+ *
+ * \param handle An error handle (See Dart_IsError)
+ *
+ * On success, this function does not return. On failure, the
+ * process is terminated.
+ */
+DART_EXPORT void Dart_PropagateError(Dart_Handle handle);
+
+/**
+ * Converts an object to a string.
+ *
+ * May generate an unhandled exception error.
+ *
+ * \return The converted string if no error occurs during
+ * the conversion. If an error does occur, an error handle is
+ * returned.
+ */
+DART_EXPORT Dart_Handle Dart_ToString(Dart_Handle object);
+
+/**
+ * Checks to see if two handles refer to identically equal objects.
+ *
+ * If both handles refer to instances, this is equivalent to using the top-level
+ * function identical() from dart:core. Otherwise, returns whether the two
+ * argument handles refer to the same object.
+ *
+ * \param obj1 An object to be compared.
+ * \param obj2 An object to be compared.
+ *
+ * \return True if the objects are identically equal. False otherwise.
+ */
+DART_EXPORT bool Dart_IdentityEquals(Dart_Handle obj1, Dart_Handle obj2);
+
+/**
+ * Allocates a handle in the current scope from a persistent handle.
+ */
+DART_EXPORT Dart_Handle Dart_HandleFromPersistent(Dart_PersistentHandle object);
+
+/**
+ * Allocates a handle in the current scope from a weak persistent handle.
+ *
+ * This will be a handle to Dart_Null if the object has been garbage collected.
+ */
+DART_EXPORT Dart_Handle
+Dart_HandleFromWeakPersistent(Dart_WeakPersistentHandle object);
+
+/**
+ * Allocates a persistent handle for an object.
+ *
+ * This handle has the lifetime of the current isolate unless it is
+ * explicitly deallocated by calling Dart_DeletePersistentHandle.
+ *
+ * Requires there to be a current isolate.
+ */
+DART_EXPORT Dart_PersistentHandle Dart_NewPersistentHandle(Dart_Handle object);
+
+/**
+ * Assign value of local handle to a persistent handle.
+ *
+ * Requires there to be a current isolate.
+ *
+ * \param obj1 A persistent handle whose value needs to be set.
+ * \param obj2 An object whose value needs to be set to the persistent handle.
+ */
+DART_EXPORT void Dart_SetPersistentHandle(Dart_PersistentHandle obj1,
+ Dart_Handle obj2);
+
+/**
+ * Deallocates a persistent handle.
+ *
+ * Requires there to be a current isolate group.
+ */
+DART_EXPORT void Dart_DeletePersistentHandle(Dart_PersistentHandle object);
+
+/**
+ * Allocates a weak persistent handle for an object.
+ *
+ * This handle has the lifetime of the current isolate. The handle can also be
+ * explicitly deallocated by calling Dart_DeleteWeakPersistentHandle.
+ *
+ * If the object becomes unreachable the callback is invoked with the peer as
+ * argument. The callback can be executed on any thread, will have a current
+ * isolate group, but will not have a current isolate. The callback can only
+ * call Dart_DeletePersistentHandle or Dart_DeleteWeakPersistentHandle. This
+ * gives the embedder the ability to cleanup data associated with the object.
+ * The handle will point to the Dart_Null object after the finalizer has been
+ * run. It is illegal to call into the VM with any other Dart_* functions from
+ * the callback. If the handle is deleted before the object becomes
+ * unreachable, the callback is never invoked.
+ *
+ * Requires there to be a current isolate.
+ *
+ * \param object An object with identity.
+ * \param peer A pointer to a native object or NULL. This value is
+ * provided to callback when it is invoked.
+ * \param external_allocation_size The number of externally allocated
+ * bytes for peer. Used to inform the garbage collector.
+ * \param callback A function pointer that will be invoked sometime
+ * after the object is garbage collected, unless the handle has been deleted.
+ * A valid callback needs to be specified it cannot be NULL.
+ *
+ * \return The weak persistent handle or NULL. NULL is returned in case of bad
+ * parameters.
+ */
+DART_EXPORT Dart_WeakPersistentHandle
+Dart_NewWeakPersistentHandle(Dart_Handle object,
+ void* peer,
+ intptr_t external_allocation_size,
+ Dart_HandleFinalizer callback);
+
+/**
+ * Deletes the given weak persistent [object] handle.
+ *
+ * Requires there to be a current isolate group.
+ */
+DART_EXPORT void Dart_DeleteWeakPersistentHandle(
+ Dart_WeakPersistentHandle object);
+
+/**
+ * Updates the external memory size for the given weak persistent handle.
+ *
+ * May trigger garbage collection.
+ */
+DART_EXPORT void Dart_UpdateExternalSize(Dart_WeakPersistentHandle object,
+ intptr_t external_allocation_size);
+
+/**
+ * Allocates a finalizable handle for an object.
+ *
+ * This handle has the lifetime of the current isolate group unless the object
+ * pointed to by the handle is garbage collected, in this case the VM
+ * automatically deletes the handle after invoking the callback associated
+ * with the handle. The handle can also be explicitly deallocated by
+ * calling Dart_DeleteFinalizableHandle.
+ *
+ * If the object becomes unreachable the callback is invoked with the
+ * the peer as argument. The callback can be executed on any thread, will have
+ * an isolate group, but will not have a current isolate. The callback can only
+ * call Dart_DeletePersistentHandle or Dart_DeleteWeakPersistentHandle.
+ * This gives the embedder the ability to cleanup data associated with the
+ * object and clear out any cached references to the handle. All references to
+ * this handle after the callback will be invalid. It is illegal to call into
+ * the VM with any other Dart_* functions from the callback. If the handle is
+ * deleted before the object becomes unreachable, the callback is never
+ * invoked.
+ *
+ * Requires there to be a current isolate.
+ *
+ * \param object An object with identity.
+ * \param peer A pointer to a native object or NULL. This value is
+ * provided to callback when it is invoked.
+ * \param external_allocation_size The number of externally allocated
+ * bytes for peer. Used to inform the garbage collector.
+ * \param callback A function pointer that will be invoked sometime
+ * after the object is garbage collected, unless the handle has been deleted.
+ * A valid callback needs to be specified it cannot be NULL.
+ *
+ * \return The finalizable handle or NULL. NULL is returned in case of bad
+ * parameters.
+ */
+DART_EXPORT Dart_FinalizableHandle
+Dart_NewFinalizableHandle(Dart_Handle object,
+ void* peer,
+ intptr_t external_allocation_size,
+ Dart_HandleFinalizer callback);
+
+/**
+ * Deletes the given finalizable [object] handle.
+ *
+ * The caller has to provide the actual Dart object the handle was created from
+ * to prove the object (and therefore the finalizable handle) is still alive.
+ *
+ * Requires there to be a current isolate.
+ */
+DART_EXPORT void Dart_DeleteFinalizableHandle(Dart_FinalizableHandle object,
+ Dart_Handle strong_ref_to_object);
+
+/**
+ * Updates the external memory size for the given finalizable handle.
+ *
+ * The caller has to provide the actual Dart object the handle was created from
+ * to prove the object (and therefore the finalizable handle) is still alive.
+ *
+ * May trigger garbage collection.
+ */
+DART_EXPORT void Dart_UpdateFinalizableExternalSize(
+ Dart_FinalizableHandle object,
+ Dart_Handle strong_ref_to_object,
+ intptr_t external_allocation_size);
+
+/*
+ * ==========================
+ * Initialization and Globals
+ * ==========================
+ */
+
+/**
+ * Gets the version string for the Dart VM.
+ *
+ * The version of the Dart VM can be accessed without initializing the VM.
+ *
+ * \return The version string for the embedded Dart VM.
+ */
+DART_EXPORT const char* Dart_VersionString(void);
+
+/**
+ * Isolate specific flags are set when creating a new isolate using the
+ * Dart_IsolateFlags structure.
+ *
+ * Current version of flags is encoded in a 32-bit integer with 16 bits used
+ * for each part.
+ */
+
+#define DART_FLAGS_CURRENT_VERSION (0x0000000c)
+
+typedef struct {
+ int32_t version;
+ bool enable_asserts;
+ bool use_field_guards;
+ bool use_osr;
+ bool obfuscate;
+ bool load_vmservice_library;
+ bool copy_parent_code;
+ bool null_safety;
+ bool is_system_isolate;
+ bool snapshot_is_dontneed_safe;
+ bool branch_coverage;
+} Dart_IsolateFlags;
+
+/**
+ * Initialize Dart_IsolateFlags with correct version and default values.
+ */
+DART_EXPORT void Dart_IsolateFlagsInitialize(Dart_IsolateFlags* flags);
+
+/**
+ * An isolate creation and initialization callback function.
+ *
+ * This callback, provided by the embedder, is called when the VM
+ * needs to create an isolate. The callback should create an isolate
+ * by calling Dart_CreateIsolateGroup and load any scripts required for
+ * execution.
+ *
+ * This callback may be called on a different thread than the one
+ * running the parent isolate.
+ *
+ * When the function returns NULL, it is the responsibility of this
+ * function to ensure that Dart_ShutdownIsolate has been called if
+ * required (for example, if the isolate was created successfully by
+ * Dart_CreateIsolateGroup() but the root library fails to load
+ * successfully, then the function should call Dart_ShutdownIsolate
+ * before returning).
+ *
+ * When the function returns NULL, the function should set *error to
+ * a malloc-allocated buffer containing a useful error message. The
+ * caller of this function (the VM) will make sure that the buffer is
+ * freed.
+ *
+ * \param script_uri The uri of the main source file or snapshot to load.
+ * Either the URI of the parent isolate set in Dart_CreateIsolateGroup for
+ * Isolate.spawn, or the argument to Isolate.spawnUri canonicalized by the
+ * library tag handler of the parent isolate.
+ * The callback is responsible for loading the program by a call to
+ * Dart_LoadScriptFromKernel.
+ * \param main The name of the main entry point this isolate will
+ * eventually run. This is provided for advisory purposes only to
+ * improve debugging messages. The main function is not invoked by
+ * this function.
+ * \param package_root Ignored.
+ * \param package_config Uri of the package configuration file (either in format
+ * of .packages or .dart_tool/package_config.json) for this isolate
+ * to resolve package imports against. If this parameter is not passed the
+ * package resolution of the parent isolate should be used.
+ * \param flags Default flags for this isolate being spawned. Either inherited
+ * from the spawning isolate or passed as parameters when spawning the
+ * isolate from Dart code.
+ * \param isolate_data The isolate data which was passed to the
+ * parent isolate when it was created by calling Dart_CreateIsolateGroup().
+ * \param error A structure into which the embedder can place a
+ * C string containing an error message in the case of failures.
+ *
+ * \return The embedder returns NULL if the creation and
+ * initialization was not successful and the isolate if successful.
+ */
+typedef Dart_Isolate (*Dart_IsolateGroupCreateCallback)(
+ const char* script_uri,
+ const char* main,
+ const char* package_root,
+ const char* package_config,
+ Dart_IsolateFlags* flags,
+ void* isolate_data,
+ char** error);
+
+/**
+ * An isolate initialization callback function.
+ *
+ * This callback, provided by the embedder, is called when the VM has created an
+ * isolate within an existing isolate group (i.e. from the same source as an
+ * existing isolate).
+ *
+ * The callback should setup native resolvers and might want to set a custom
+ * message handler via [Dart_SetMessageNotifyCallback] and mark the isolate as
+ * runnable.
+ *
+ * This callback may be called on a different thread than the one
+ * running the parent isolate.
+ *
+ * When the function returns `false`, it is the responsibility of this
+ * function to ensure that `Dart_ShutdownIsolate` has been called.
+ *
+ * When the function returns `false`, the function should set *error to
+ * a malloc-allocated buffer containing a useful error message. The
+ * caller of this function (the VM) will make sure that the buffer is
+ * freed.
+ *
+ * \param child_isolate_data The callback data to associate with the new
+ * child isolate.
+ * \param error A structure into which the embedder can place a
+ * C string containing an error message in the case the initialization fails.
+ *
+ * \return The embedder returns true if the initialization was successful and
+ * false otherwise (in which case the VM will terminate the isolate).
+ */
+typedef bool (*Dart_InitializeIsolateCallback)(void** child_isolate_data,
+ char** error);
+
+/**
+ * An isolate shutdown callback function.
+ *
+ * This callback, provided by the embedder, is called before the vm
+ * shuts down an isolate. The isolate being shutdown will be the current
+ * isolate. It is safe to run Dart code.
+ *
+ * This function should be used to dispose of native resources that
+ * are allocated to an isolate in order to avoid leaks.
+ *
+ * \param isolate_group_data The same callback data which was passed to the
+ * isolate group when it was created.
+ * \param isolate_data The same callback data which was passed to the isolate
+ * when it was created.
+ */
+typedef void (*Dart_IsolateShutdownCallback)(void* isolate_group_data,
+ void* isolate_data);
+
+/**
+ * An isolate cleanup callback function.
+ *
+ * This callback, provided by the embedder, is called after the vm
+ * shuts down an isolate. There will be no current isolate and it is *not*
+ * safe to run Dart code.
+ *
+ * This function should be used to dispose of native resources that
+ * are allocated to an isolate in order to avoid leaks.
+ *
+ * \param isolate_group_data The same callback data which was passed to the
+ * isolate group when it was created.
+ * \param isolate_data The same callback data which was passed to the isolate
+ * when it was created.
+ */
+typedef void (*Dart_IsolateCleanupCallback)(void* isolate_group_data,
+ void* isolate_data);
+
+/**
+ * An isolate group cleanup callback function.
+ *
+ * This callback, provided by the embedder, is called after the vm
+ * shuts down an isolate group.
+ *
+ * This function should be used to dispose of native resources that
+ * are allocated to an isolate in order to avoid leaks.
+ *
+ * \param isolate_group_data The same callback data which was passed to the
+ * isolate group when it was created.
+ *
+ */
+typedef void (*Dart_IsolateGroupCleanupCallback)(void* isolate_group_data);
+
+/**
+ * A thread start callback function.
+ * This callback, provided by the embedder, is called after a thread in the
+ * vm thread pool starts.
+ * This function could be used to adjust thread priority or attach native
+ * resources to the thread.
+ */
+typedef void (*Dart_ThreadStartCallback)(void);
+
+/**
+ * A thread death callback function.
+ * This callback, provided by the embedder, is called before a thread in the
+ * vm thread pool exits.
+ * This function could be used to dispose of native resources that
+ * are associated and attached to the thread, in order to avoid leaks.
+ */
+typedef void (*Dart_ThreadExitCallback)(void);
+
+/**
+ * Opens a file for reading or writing.
+ *
+ * Callback provided by the embedder for file operations. If the
+ * embedder does not allow file operations this callback can be
+ * NULL.
+ *
+ * \param name The name of the file to open.
+ * \param write A boolean variable which indicates if the file is to
+ * opened for writing. If there is an existing file it needs to truncated.
+ */
+typedef void* (*Dart_FileOpenCallback)(const char* name, bool write);
+
+/**
+ * Read contents of file.
+ *
+ * Callback provided by the embedder for file operations. If the
+ * embedder does not allow file operations this callback can be
+ * NULL.
+ *
+ * \param data Buffer allocated in the callback into which the contents
+ * of the file are read into. It is the responsibility of the caller to
+ * free this buffer.
+ * \param file_length A variable into which the length of the file is returned.
+ * In the case of an error this value would be -1.
+ * \param stream Handle to the opened file.
+ */
+typedef void (*Dart_FileReadCallback)(uint8_t** data,
+ intptr_t* file_length,
+ void* stream);
+
+/**
+ * Write data into file.
+ *
+ * Callback provided by the embedder for file operations. If the
+ * embedder does not allow file operations this callback can be
+ * NULL.
+ *
+ * \param data Buffer which needs to be written into the file.
+ * \param length Length of the buffer.
+ * \param stream Handle to the opened file.
+ */
+typedef void (*Dart_FileWriteCallback)(const void* data,
+ intptr_t length,
+ void* stream);
+
+/**
+ * Closes the opened file.
+ *
+ * Callback provided by the embedder for file operations. If the
+ * embedder does not allow file operations this callback can be
+ * NULL.
+ *
+ * \param stream Handle to the opened file.
+ */
+typedef void (*Dart_FileCloseCallback)(void* stream);
+
+typedef bool (*Dart_EntropySource)(uint8_t* buffer, intptr_t length);
+
+/**
+ * Callback provided by the embedder that is used by the vmservice isolate
+ * to request the asset archive. The asset archive must be an uncompressed tar
+ * archive that is stored in a Uint8List.
+ *
+ * If the embedder has no vmservice isolate assets, the callback can be NULL.
+ *
+ * \return The embedder must return a handle to a Uint8List containing an
+ * uncompressed tar archive or null.
+ */
+typedef Dart_Handle (*Dart_GetVMServiceAssetsArchive)(void);
+
+/**
+ * The current version of the Dart_InitializeFlags. Should be incremented every
+ * time Dart_InitializeFlags changes in a binary incompatible way.
+ */
+#define DART_INITIALIZE_PARAMS_CURRENT_VERSION (0x00000008)
+
+/** Forward declaration */
+struct Dart_CodeObserver;
+
+/**
+ * Callback provided by the embedder that is used by the VM to notify on code
+ * object creation, *before* it is invoked the first time.
+ * This is useful for embedders wanting to e.g. keep track of PCs beyond
+ * the lifetime of the garbage collected code objects.
+ * Note that an address range may be used by more than one code object over the
+ * lifecycle of a process. Clients of this function should record timestamps for
+ * these compilation events and when collecting PCs to disambiguate reused
+ * address ranges.
+ */
+typedef void (*Dart_OnNewCodeCallback)(struct Dart_CodeObserver* observer,
+ const char* name,
+ uintptr_t base,
+ uintptr_t size);
+
+typedef struct Dart_CodeObserver {
+ void* data;
+
+ Dart_OnNewCodeCallback on_new_code;
+} Dart_CodeObserver;
+
+/**
+ * Optional callback provided by the embedder that is used by the VM to
+ * implement registration of kernel blobs for the subsequent Isolate.spawnUri
+ * If no callback is provided, the registration of kernel blobs will throw
+ * an error.
+ *
+ * \param kernel_buffer A buffer which contains a kernel program. Callback
+ * should copy the contents of `kernel_buffer` as
+ * it may be freed immediately after registration.
+ * \param kernel_buffer_size The size of `kernel_buffer`.
+ *
+ * \return A C string representing URI which can be later used
+ * to spawn a new isolate. This C String should be scope allocated
+ * or owned by the embedder.
+ * Returns NULL if embedder runs out of memory.
+ */
+typedef const char* (*Dart_RegisterKernelBlobCallback)(
+ const uint8_t* kernel_buffer,
+ intptr_t kernel_buffer_size);
+
+/**
+ * Optional callback provided by the embedder that is used by the VM to
+ * unregister kernel blobs.
+ * If no callback is provided, the unregistration of kernel blobs will throw
+ * an error.
+ *
+ * \param kernel_blob_uri URI of the kernel blob to unregister.
+ */
+typedef void (*Dart_UnregisterKernelBlobCallback)(const char* kernel_blob_uri);
+
+/**
+ * Describes how to initialize the VM. Used with Dart_Initialize.
+ */
+typedef struct {
+ /**
+ * Identifies the version of the struct used by the client.
+ * should be initialized to DART_INITIALIZE_PARAMS_CURRENT_VERSION.
+ */
+ int32_t version;
+
+ /**
+ * A buffer containing snapshot data, or NULL if no snapshot is provided.
+ *
+ * If provided, the buffer must remain valid until Dart_Cleanup returns.
+ */
+ const uint8_t* vm_snapshot_data;
+
+ /**
+ * A buffer containing a snapshot of precompiled instructions, or NULL if
+ * no snapshot is provided.
+ *
+ * If provided, the buffer must remain valid until Dart_Cleanup returns.
+ */
+ const uint8_t* vm_snapshot_instructions;
+
+ /**
+ * A function to be called during isolate group creation.
+ * See Dart_IsolateGroupCreateCallback.
+ */
+ Dart_IsolateGroupCreateCallback create_group;
+
+ /**
+ * A function to be called during isolate
+ * initialization inside an existing isolate group.
+ * See Dart_InitializeIsolateCallback.
+ */
+ Dart_InitializeIsolateCallback initialize_isolate;
+
+ /**
+ * A function to be called right before an isolate is shutdown.
+ * See Dart_IsolateShutdownCallback.
+ */
+ Dart_IsolateShutdownCallback shutdown_isolate;
+
+ /**
+ * A function to be called after an isolate was shutdown.
+ * See Dart_IsolateCleanupCallback.
+ */
+ Dart_IsolateCleanupCallback cleanup_isolate;
+
+ /**
+ * A function to be called after an isolate group is
+ * shutdown. See Dart_IsolateGroupCleanupCallback.
+ */
+ Dart_IsolateGroupCleanupCallback cleanup_group;
+
+ Dart_ThreadStartCallback thread_start;
+ Dart_ThreadExitCallback thread_exit;
+ Dart_FileOpenCallback file_open;
+ Dart_FileReadCallback file_read;
+ Dart_FileWriteCallback file_write;
+ Dart_FileCloseCallback file_close;
+ Dart_EntropySource entropy_source;
+
+ /**
+ * A function to be called by the service isolate when it requires the
+ * vmservice assets archive. See Dart_GetVMServiceAssetsArchive.
+ */
+ Dart_GetVMServiceAssetsArchive get_service_assets;
+
+ bool start_kernel_isolate;
+
+ /**
+ * An external code observer callback function. The observer can be invoked
+ * as early as during the Dart_Initialize() call.
+ */
+ Dart_CodeObserver* code_observer;
+
+ /**
+ * Kernel blob registration callback function. See Dart_RegisterKernelBlobCallback.
+ */
+ Dart_RegisterKernelBlobCallback register_kernel_blob;
+
+ /**
+ * Kernel blob unregistration callback function. See Dart_UnregisterKernelBlobCallback.
+ */
+ Dart_UnregisterKernelBlobCallback unregister_kernel_blob;
+
+#if defined(__Fuchsia__)
+ /**
+ * The resource needed to use zx_vmo_replace_as_executable. Can be
+ * ZX_HANDLE_INVALID if the process has ambient-replace-as-executable or if
+ * executable memory is not needed (e.g., this is an AOT runtime).
+ */
+ zx_handle_t vmex_resource;
+#endif
+} Dart_InitializeParams;
+
+/**
+ * Initializes the VM.
+ *
+ * \param params A struct containing initialization information. The version
+ * field of the struct must be DART_INITIALIZE_PARAMS_CURRENT_VERSION.
+ *
+ * \return NULL if initialization is successful. Returns an error message
+ * otherwise. The caller is responsible for freeing the error message.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT char* Dart_Initialize(
+ Dart_InitializeParams* params);
+
+/**
+ * Cleanup state in the VM before process termination.
+ *
+ * \return NULL if cleanup is successful. Returns an error message otherwise.
+ * The caller is responsible for freeing the error message.
+ *
+ * NOTE: This function must not be called on a thread that was created by the VM
+ * itself.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT char* Dart_Cleanup(void);
+
+/**
+ * Sets command line flags. Should be called before Dart_Initialize.
+ *
+ * \param argc The length of the arguments array.
+ * \param argv An array of arguments.
+ *
+ * \return NULL if successful. Returns an error message otherwise.
+ * The caller is responsible for freeing the error message.
+ *
+ * NOTE: This call does not store references to the passed in c-strings.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT char* Dart_SetVMFlags(int argc,
+ const char** argv);
+
+/**
+ * Returns true if the named VM flag is of boolean type, specified, and set to
+ * true.
+ *
+ * \param flag_name The name of the flag without leading punctuation
+ * (example: "enable_asserts").
+ */
+DART_EXPORT bool Dart_IsVMFlagSet(const char* flag_name);
+
+/*
+ * ========
+ * Isolates
+ * ========
+ */
+
+/**
+ * Creates a new isolate. The new isolate becomes the current isolate.
+ *
+ * A snapshot can be used to restore the VM quickly to a saved state
+ * and is useful for fast startup. If snapshot data is provided, the
+ * isolate will be started using that snapshot data. Requires a core snapshot or
+ * an app snapshot created by Dart_CreateSnapshot or
+ * Dart_CreatePrecompiledSnapshot* from a VM with the same version.
+ *
+ * Requires there to be no current isolate.
+ *
+ * \param script_uri The main source file or snapshot this isolate will load.
+ * The VM will provide this URI to the Dart_IsolateGroupCreateCallback when a
+ * child isolate is created by Isolate.spawn. The embedder should use a URI
+ * that allows it to load the same program into such a child isolate.
+ * \param name A short name for the isolate to improve debugging messages.
+ * Typically of the format 'foo.dart:main()'.
+ * \param isolate_snapshot_data Buffer containing the snapshot data of the
+ * isolate or NULL if no snapshot is provided. If provided, the buffer must
+ * remain valid until the isolate shuts down.
+ * \param isolate_snapshot_instructions Buffer containing the snapshot
+ * instructions of the isolate or NULL if no snapshot is provided. If
+ * provided, the buffer must remain valid until the isolate shuts down.
+ * \param flags Pointer to VM specific flags or NULL for default flags.
+ * \param isolate_group_data Embedder group data. This data can be obtained
+ * by calling Dart_IsolateGroupData and will be passed to the
+ * Dart_IsolateShutdownCallback, Dart_IsolateCleanupCallback, and
+ * Dart_IsolateGroupCleanupCallback.
+ * \param isolate_data Embedder data. This data will be passed to
+ * the Dart_IsolateGroupCreateCallback when new isolates are spawned from
+ * this parent isolate.
+ * \param error Returns NULL if creation is successful, an error message
+ * otherwise. The caller is responsible for calling free() on the error
+ * message.
+ *
+ * \return The new isolate on success, or NULL if isolate creation failed.
+ */
+DART_EXPORT Dart_Isolate
+Dart_CreateIsolateGroup(const char* script_uri,
+ const char* name,
+ const uint8_t* isolate_snapshot_data,
+ const uint8_t* isolate_snapshot_instructions,
+ Dart_IsolateFlags* flags,
+ void* isolate_group_data,
+ void* isolate_data,
+ char** error);
+/**
+ * Creates a new isolate inside the isolate group of [group_member].
+ *
+ * Requires there to be no current isolate.
+ *
+ * \param group_member An isolate from the same group into which the newly created
+ * isolate should be born into. Other threads may not have entered / enter this
+ * member isolate.
+ * \param name A short name for the isolate for debugging purposes.
+ * \param shutdown_callback A callback to be called when the isolate is being
+ * shutdown (may be NULL).
+ * \param cleanup_callback A callback to be called when the isolate is being
+ * cleaned up (may be NULL).
+ * \param child_isolate_data The embedder-specific data associated with this isolate.
+ * \param error Set to NULL if creation is successful, set to an error
+ * message otherwise. The caller is responsible for calling free() on the
+ * error message.
+ *
+ * \return The newly created isolate on success, or NULL if isolate creation
+ * failed.
+ *
+ * If successful, the newly created isolate will become the current isolate.
+ */
+DART_EXPORT Dart_Isolate
+Dart_CreateIsolateInGroup(Dart_Isolate group_member,
+ const char* name,
+ Dart_IsolateShutdownCallback shutdown_callback,
+ Dart_IsolateCleanupCallback cleanup_callback,
+ void* child_isolate_data,
+ char** error);
+
+/* TODO(turnidge): Document behavior when there is already a current
+ * isolate. */
+
+/**
+ * Creates a new isolate from a Dart Kernel file. The new isolate
+ * becomes the current isolate.
+ *
+ * Requires there to be no current isolate.
+ *
+ * \param script_uri The main source file or snapshot this isolate will load.
+ * The VM will provide this URI to the Dart_IsolateGroupCreateCallback when a
+ * child isolate is created by Isolate.spawn. The embedder should use a URI that
+ * allows it to load the same program into such a child isolate.
+ * \param name A short name for the isolate to improve debugging messages.
+ * Typically of the format 'foo.dart:main()'.
+ * \param kernel_buffer A buffer which contains a kernel/DIL program. Must
+ * remain valid until isolate shutdown.
+ * \param kernel_buffer_size The size of `kernel_buffer`.
+ * \param flags Pointer to VM specific flags or NULL for default flags.
+ * \param isolate_group_data Embedder group data. This data can be obtained
+ * by calling Dart_IsolateGroupData and will be passed to the
+ * Dart_IsolateShutdownCallback, Dart_IsolateCleanupCallback, and
+ * Dart_IsolateGroupCleanupCallback.
+ * \param isolate_data Embedder data. This data will be passed to
+ * the Dart_IsolateGroupCreateCallback when new isolates are spawned from
+ * this parent isolate.
+ * \param error Returns NULL if creation is successful, an error message
+ * otherwise. The caller is responsible for calling free() on the error
+ * message.
+ *
+ * \return The new isolate on success, or NULL if isolate creation failed.
+ */
+DART_EXPORT Dart_Isolate
+Dart_CreateIsolateGroupFromKernel(const char* script_uri,
+ const char* name,
+ const uint8_t* kernel_buffer,
+ intptr_t kernel_buffer_size,
+ Dart_IsolateFlags* flags,
+ void* isolate_group_data,
+ void* isolate_data,
+ char** error);
+/**
+ * Shuts down the current isolate. After this call, the current isolate is NULL.
+ * Any current scopes created by Dart_EnterScope will be exited. Invokes the
+ * shutdown callback and any callbacks of remaining weak persistent handles.
+ *
+ * Requires there to be a current isolate.
+ */
+DART_EXPORT void Dart_ShutdownIsolate(void);
+/* TODO(turnidge): Document behavior when there is no current isolate. */
+
+/**
+ * Returns the current isolate. Will return NULL if there is no
+ * current isolate.
+ */
+DART_EXPORT Dart_Isolate Dart_CurrentIsolate(void);
+
+/**
+ * Returns the callback data associated with the current isolate. This
+ * data was set when the isolate got created or initialized.
+ */
+DART_EXPORT void* Dart_CurrentIsolateData(void);
+
+/**
+ * Returns the callback data associated with the given isolate. This
+ * data was set when the isolate got created or initialized.
+ */
+DART_EXPORT void* Dart_IsolateData(Dart_Isolate isolate);
+
+/**
+ * Returns the current isolate group. Will return NULL if there is no
+ * current isolate group.
+ */
+DART_EXPORT Dart_IsolateGroup Dart_CurrentIsolateGroup(void);
+
+/**
+ * Returns the callback data associated with the current isolate group. This
+ * data was passed to the isolate group when it was created.
+ */
+DART_EXPORT void* Dart_CurrentIsolateGroupData(void);
+
+/**
+ * Gets an id that uniquely identifies current isolate group.
+ *
+ * It is the responsibility of the caller to free the returned ID.
+ */
+typedef int64_t Dart_IsolateGroupId;
+DART_EXPORT Dart_IsolateGroupId Dart_CurrentIsolateGroupId(void);
+
+/**
+ * Returns the callback data associated with the specified isolate group. This
+ * data was passed to the isolate when it was created.
+ * The embedder is responsible for ensuring the consistency of this data
+ * with respect to the lifecycle of an isolate group.
+ */
+DART_EXPORT void* Dart_IsolateGroupData(Dart_Isolate isolate);
+
+/**
+ * Returns the debugging name for the current isolate.
+ *
+ * This name is unique to each isolate and should only be used to make
+ * debugging messages more comprehensible.
+ */
+DART_EXPORT Dart_Handle Dart_DebugName(void);
+
+/**
+ * Returns the debugging name for the current isolate.
+ *
+ * This name is unique to each isolate and should only be used to make
+ * debugging messages more comprehensible.
+ *
+ * The returned string is scope allocated and is only valid until the next call
+ * to Dart_ExitScope.
+ */
+DART_EXPORT const char* Dart_DebugNameToCString(void);
+
+/**
+ * Returns the ID for an isolate which is used to query the service protocol.
+ *
+ * It is the responsibility of the caller to free the returned ID.
+ */
+DART_EXPORT const char* Dart_IsolateServiceId(Dart_Isolate isolate);
+
+/**
+ * Enters an isolate. After calling this function,
+ * the current isolate will be set to the provided isolate.
+ *
+ * Requires there to be no current isolate. Multiple threads may not be in
+ * the same isolate at once.
+ */
+DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate);
+
+/**
+ * Kills the given isolate.
+ *
+ * This function has the same effect as dart:isolate's
+ * Isolate.kill(priority:immediate).
+ * It can interrupt ordinary Dart code but not native code. If the isolate is
+ * in the middle of a long running native function, the isolate will not be
+ * killed until control returns to Dart.
+ *
+ * Does not require a current isolate. It is safe to kill the current isolate if
+ * there is one.
+ */
+DART_EXPORT void Dart_KillIsolate(Dart_Isolate isolate);
+
+/**
+ * Notifies the VM that the embedder expects to be idle until |deadline|. The VM
+ * may use this time to perform garbage collection or other tasks to avoid
+ * delays during execution of Dart code in the future.
+ *
+ * |deadline| is measured in microseconds against the system's monotonic time.
+ * This clock can be accessed via Dart_TimelineGetMicros().
+ *
+ * Requires there to be a current isolate.
+ */
+DART_EXPORT void Dart_NotifyIdle(int64_t deadline);
+
+typedef void (*Dart_HeapSamplingReportCallback)(void* context,
+ void* data);
+
+typedef void* (*Dart_HeapSamplingCreateCallback)(
+ Dart_Isolate isolate,
+ Dart_IsolateGroup isolate_group,
+ const char* cls_name,
+ intptr_t allocation_size);
+typedef void (*Dart_HeapSamplingDeleteCallback)(void* data);
+
+/**
+ * Starts the heap sampling profiler for each thread in the VM.
+ */
+DART_EXPORT void Dart_EnableHeapSampling(void);
+
+/*
+ * Stops the heap sampling profiler for each thread in the VM.
+ */
+DART_EXPORT void Dart_DisableHeapSampling(void);
+
+/* Registers callbacks are invoked once per sampled allocation upon object
+ * allocation and garbage collection.
+ *
+ * |create_callback| can be used to associate additional data with the sampled
+ * allocation, such as a stack trace. This data pointer will be passed to
+ * |delete_callback| to allow for proper disposal when the object associated
+ * with the allocation sample is collected.
+ *
+ * The provided callbacks must not call into the VM and should do as little
+ * work as possible to avoid performance penalities during object allocation and
+ * garbage collection.
+ *
+ * NOTE: It is a fatal error to set either callback to null once they have been
+ * initialized.
+ */
+DART_EXPORT void Dart_RegisterHeapSamplingCallback(
+ Dart_HeapSamplingCreateCallback create_callback,
+ Dart_HeapSamplingDeleteCallback delete_callback);
+
+/*
+ * Reports the surviving allocation samples for all live isolate groups in the
+ * VM.
+ *
+ * When the callback is invoked:
+ * - |context| will be the context object provided when invoking
+ * |Dart_ReportSurvivingAllocations|. This can be safely set to null if not
+ * required.
+ * - |heap_size| will be equal to the size of the allocated object associated
+ * with the sample.
+ * - |cls_name| will be a C String representing
+ * the class name of the allocated object. This string is valid for the
+ * duration of the call to Dart_ReportSurvivingAllocations and can be
+ * freed by the VM at any point after the method returns.
+ * - |data| will be set to the data associated with the sample by
+ * |Dart_HeapSamplingCreateCallback|.
+ *
+ * If |force_gc| is true, a full GC will be performed before reporting the
+ * allocations.
+ */
+DART_EXPORT void Dart_ReportSurvivingAllocations(
+ Dart_HeapSamplingReportCallback callback,
+ void* context,
+ bool force_gc);
+
+/*
+ * Sets the average heap sampling rate based on a number of |bytes| for each
+ * thread.
+ *
+ * In other words, approximately every |bytes| allocated will create a sample.
+ * Defaults to 512 KiB.
+ */
+DART_EXPORT void Dart_SetHeapSamplingPeriod(intptr_t bytes);
+
+/**
+ * Notifies the VM that the embedder expects the application's working set has
+ * recently shrunk significantly and is not expected to rise in the near future.
+ * The VM may spend O(heap-size) time performing clean up work.
+ *
+ * Requires there to be a current isolate.
+ */
+DART_EXPORT void Dart_NotifyDestroyed(void);
+
+/**
+ * Notifies the VM that the system is running low on memory.
+ *
+ * Does not require a current isolate. Only valid after calling Dart_Initialize.
+ */
+DART_EXPORT void Dart_NotifyLowMemory(void);
+
+typedef enum {
+ /**
+ * Balanced
+ */
+ Dart_PerformanceMode_Default,
+ /**
+ * Optimize for low latency, at the expense of throughput and memory overhead
+ * by performing work in smaller batches (requiring more overhead) or by
+ * delaying work (requiring more memory). An embedder should not remain in
+ * this mode indefinitely.
+ */
+ Dart_PerformanceMode_Latency,
+ /**
+ * Optimize for high throughput, at the expense of latency and memory overhead
+ * by performing work in larger batches with more intervening growth.
+ */
+ Dart_PerformanceMode_Throughput,
+ /**
+ * Optimize for low memory, at the expensive of throughput and latency by more
+ * frequently performing work.
+ */
+ Dart_PerformanceMode_Memory,
+} Dart_PerformanceMode;
+
+/**
+ * Set the desired performance trade-off.
+ *
+ * Requires a current isolate.
+ *
+ * Returns the previous performance mode.
+ */
+DART_EXPORT Dart_PerformanceMode
+Dart_SetPerformanceMode(Dart_PerformanceMode mode);
+
+/**
+ * Starts the CPU sampling profiler.
+ */
+DART_EXPORT void Dart_StartProfiling(void);
+
+/**
+ * Stops the CPU sampling profiler.
+ *
+ * Note that some profile samples might still be taken after this function
+ * returns due to the asynchronous nature of the implementation on some
+ * platforms.
+ */
+DART_EXPORT void Dart_StopProfiling(void);
+
+/**
+ * Notifies the VM that the current thread should not be profiled until a
+ * matching call to Dart_ThreadEnableProfiling is made.
+ *
+ * NOTE: By default, if a thread has entered an isolate it will be profiled.
+ * This function should be used when an embedder knows a thread is about
+ * to make a blocking call and wants to avoid unnecessary interrupts by
+ * the profiler.
+ */
+DART_EXPORT void Dart_ThreadDisableProfiling(void);
+
+/**
+ * Notifies the VM that the current thread should be profiled.
+ *
+ * NOTE: It is only legal to call this function *after* calling
+ * Dart_ThreadDisableProfiling.
+ *
+ * NOTE: By default, if a thread has entered an isolate it will be profiled.
+ */
+DART_EXPORT void Dart_ThreadEnableProfiling(void);
+
+/**
+ * Register symbol information for the Dart VM's profiler and crash dumps.
+ *
+ * This consumes the output of //topaz/runtime/dart/profiler_symbols, which
+ * should be treated as opaque.
+ */
+DART_EXPORT void Dart_AddSymbols(const char* dso_name,
+ void* buffer,
+ intptr_t buffer_size);
+
+/**
+ * Exits an isolate. After this call, Dart_CurrentIsolate will
+ * return NULL.
+ *
+ * Requires there to be a current isolate.
+ */
+DART_EXPORT void Dart_ExitIsolate(void);
+/* TODO(turnidge): We don't want users of the api to be able to exit a
+ * "pure" dart isolate. Implement and document. */
+
+/**
+ * Creates a full snapshot of the current isolate heap.
+ *
+ * A full snapshot is a compact representation of the dart vm isolate heap
+ * and dart isolate heap states. These snapshots are used to initialize
+ * the vm isolate on startup and fast initialization of an isolate.
+ * A Snapshot of the heap is created before any dart code has executed.
+ *
+ * Requires there to be a current isolate. Not available in the precompiled
+ * runtime (check Dart_IsPrecompiledRuntime).
+ *
+ * \param vm_snapshot_data_buffer Returns a pointer to a buffer containing the
+ * vm snapshot. This buffer is scope allocated and is only valid
+ * until the next call to Dart_ExitScope.
+ * \param vm_snapshot_data_size Returns the size of vm_snapshot_data_buffer.
+ * \param isolate_snapshot_data_buffer Returns a pointer to a buffer containing
+ * the isolate snapshot. This buffer is scope allocated and is only valid
+ * until the next call to Dart_ExitScope.
+ * \param isolate_snapshot_data_size Returns the size of
+ * isolate_snapshot_data_buffer.
+ * \param is_core Create a snapshot containing core libraries.
+ * Such snapshot should be agnostic to null safety mode.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_CreateSnapshot(uint8_t** vm_snapshot_data_buffer,
+ intptr_t* vm_snapshot_data_size,
+ uint8_t** isolate_snapshot_data_buffer,
+ intptr_t* isolate_snapshot_data_size,
+ bool is_core);
+
+/**
+ * Returns whether the buffer contains a kernel file.
+ *
+ * \param buffer Pointer to a buffer that might contain a kernel binary.
+ * \param buffer_size Size of the buffer.
+ *
+ * \return Whether the buffer contains a kernel binary (full or partial).
+ */
+DART_EXPORT bool Dart_IsKernel(const uint8_t* buffer, intptr_t buffer_size);
+
+/**
+ * Make isolate runnable.
+ *
+ * When isolates are spawned, this function is used to indicate that
+ * the creation and initialization (including script loading) of the
+ * isolate is complete and the isolate can start.
+ * This function expects there to be no current isolate.
+ *
+ * \param isolate The isolate to be made runnable.
+ *
+ * \return NULL if successful. Returns an error message otherwise. The caller
+ * is responsible for freeing the error message.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT char* Dart_IsolateMakeRunnable(
+ Dart_Isolate isolate);
+
+/*
+ * ==================
+ * Messages and Ports
+ * ==================
+ */
+
+/**
+ * A port is used to send or receive inter-isolate messages
+ */
+typedef int64_t Dart_Port;
+
+/**
+ * ILLEGAL_PORT is a port number guaranteed never to be associated with a valid
+ * port.
+ */
+#define ILLEGAL_PORT ((Dart_Port)0)
+
+/**
+ * A message notification callback.
+ *
+ * This callback allows the embedder to provide a custom wakeup mechanism for
+ * the delivery of inter-isolate messages. This function is called once per
+ * message on an arbitrary thread. It is the responsibility of the embedder to
+ * eventually call Dart_HandleMessage once per callback received with the
+ * destination isolate set as the current isolate to process the message.
+ */
+typedef void (*Dart_MessageNotifyCallback)(Dart_Isolate destination_isolate);
+
+/**
+ * Allows embedders to provide a custom wakeup mechanism for the delivery of
+ * inter-isolate messages. This setting only applies to the current isolate.
+ *
+ * This mechanism is optional: if not provided, the isolate will be scheduled on
+ * a VM-managed thread pool. An embedder should provide this callback if it
+ * wants to run an isolate on a specific thread or to interleave handling of
+ * inter-isolate messages with other event sources.
+ *
+ * Most embedders will only call this function once, before isolate
+ * execution begins. If this function is called after isolate
+ * execution begins, the embedder is responsible for threading issues.
+ */
+DART_EXPORT void Dart_SetMessageNotifyCallback(
+ Dart_MessageNotifyCallback message_notify_callback);
+/* TODO(turnidge): Consider moving this to isolate creation so that it
+ * is impossible to mess up. */
+
+/**
+ * Query the current message notify callback for the isolate.
+ *
+ * \return The current message notify callback for the isolate.
+ */
+DART_EXPORT Dart_MessageNotifyCallback Dart_GetMessageNotifyCallback(void);
+
+/**
+ * The VM's default message handler supports pausing an isolate before it
+ * processes the first message and right after the it processes the isolate's
+ * final message. This can be controlled for all isolates by two VM flags:
+ *
+ * `--pause-isolates-on-start`
+ * `--pause-isolates-on-exit`
+ *
+ * Additionally, Dart_SetShouldPauseOnStart and Dart_SetShouldPauseOnExit can be
+ * used to control this behaviour on a per-isolate basis.
+ *
+ * When an embedder is using a Dart_MessageNotifyCallback the embedder
+ * needs to cooperate with the VM so that the service protocol can report
+ * accurate information about isolates and so that tools such as debuggers
+ * work reliably.
+ *
+ * The following functions can be used to implement pausing on start and exit.
+ */
+
+/**
+ * If the VM flag `--pause-isolates-on-start` was passed this will be true.
+ *
+ * \return A boolean value indicating if pause on start was requested.
+ */
+DART_EXPORT bool Dart_ShouldPauseOnStart(void);
+
+/**
+ * Override the VM flag `--pause-isolates-on-start` for the current isolate.
+ *
+ * \param should_pause Should the isolate be paused on start?
+ *
+ * NOTE: This must be called before Dart_IsolateMakeRunnable.
+ */
+DART_EXPORT void Dart_SetShouldPauseOnStart(bool should_pause);
+
+/**
+ * Is the current isolate paused on start?
+ *
+ * \return A boolean value indicating if the isolate is paused on start.
+ */
+DART_EXPORT bool Dart_IsPausedOnStart(void);
+
+/**
+ * Called when the embedder has paused the current isolate on start and when
+ * the embedder has resumed the isolate.
+ *
+ * \param paused Is the isolate paused on start?
+ */
+DART_EXPORT void Dart_SetPausedOnStart(bool paused);
+
+/**
+ * If the VM flag `--pause-isolates-on-exit` was passed this will be true.
+ *
+ * \return A boolean value indicating if pause on exit was requested.
+ */
+DART_EXPORT bool Dart_ShouldPauseOnExit(void);
+
+/**
+ * Override the VM flag `--pause-isolates-on-exit` for the current isolate.
+ *
+ * \param should_pause Should the isolate be paused on exit?
+ *
+ */
+DART_EXPORT void Dart_SetShouldPauseOnExit(bool should_pause);
+
+/**
+ * Is the current isolate paused on exit?
+ *
+ * \return A boolean value indicating if the isolate is paused on exit.
+ */
+DART_EXPORT bool Dart_IsPausedOnExit(void);
+
+/**
+ * Called when the embedder has paused the current isolate on exit and when
+ * the embedder has resumed the isolate.
+ *
+ * \param paused Is the isolate paused on exit?
+ */
+DART_EXPORT void Dart_SetPausedOnExit(bool paused);
+
+/**
+ * Called when the embedder has caught a top level unhandled exception error
+ * in the current isolate.
+ *
+ * NOTE: It is illegal to call this twice on the same isolate without first
+ * clearing the sticky error to null.
+ *
+ * \param error The unhandled exception error.
+ */
+DART_EXPORT void Dart_SetStickyError(Dart_Handle error);
+
+/**
+ * Does the current isolate have a sticky error?
+ */
+DART_EXPORT bool Dart_HasStickyError(void);
+
+/**
+ * Gets the sticky error for the current isolate.
+ *
+ * \return A handle to the sticky error object or null.
+ */
+DART_EXPORT Dart_Handle Dart_GetStickyError(void);
+
+/**
+ * Handles the next pending message for the current isolate.
+ *
+ * May generate an unhandled exception error.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_HandleMessage(void);
+
+/**
+ * Drains the microtask queue, then blocks the calling thread until the current
+ * isolate receives a message, then handles all messages.
+ *
+ * \param timeout_millis When non-zero, the call returns after the indicated
+ number of milliseconds even if no message was received.
+ * \return A valid handle if no error occurs, otherwise an error handle.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_WaitForEvent(int64_t timeout_millis);
+
+/**
+ * Handles any pending messages for the vm service for the current
+ * isolate.
+ *
+ * This function may be used by an embedder at a breakpoint to avoid
+ * pausing the vm service.
+ *
+ * This function can indirectly cause the message notify callback to
+ * be called.
+ *
+ * \return true if the vm service requests the program resume
+ * execution, false otherwise
+ */
+DART_EXPORT bool Dart_HandleServiceMessages(void);
+
+/**
+ * Does the current isolate have pending service messages?
+ *
+ * \return true if the isolate has pending service messages, false otherwise.
+ */
+DART_EXPORT bool Dart_HasServiceMessages(void);
+
+/**
+ * Processes any incoming messages for the current isolate.
+ *
+ * This function may only be used when the embedder has not provided
+ * an alternate message delivery mechanism with
+ * Dart_SetMessageCallbacks. It is provided for convenience.
+ *
+ * This function waits for incoming messages for the current
+ * isolate. As new messages arrive, they are handled using
+ * Dart_HandleMessage. The routine exits when all ports to the
+ * current isolate are closed.
+ *
+ * \return A valid handle if the run loop exited successfully. If an
+ * exception or other error occurs while processing messages, an
+ * error handle is returned.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_RunLoop(void);
+
+/**
+ * Lets the VM run message processing for the isolate.
+ *
+ * This function expects there to a current isolate and the current isolate
+ * must not have an active api scope. The VM will take care of making the
+ * isolate runnable (if not already), handles its message loop and will take
+ * care of shutting the isolate down once it's done.
+ *
+ * \param errors_are_fatal Whether uncaught errors should be fatal.
+ * \param on_error_port A port to notify on uncaught errors (or ILLEGAL_PORT).
+ * \param on_exit_port A port to notify on exit (or ILLEGAL_PORT).
+ * \param error A non-NULL pointer which will hold an error message if the call
+ * fails. The error has to be free()ed by the caller.
+ *
+ * \return If successful the VM takes ownership of the isolate and takes care
+ * of its message loop. If not successful the caller retains ownership of the
+ * isolate.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT bool Dart_RunLoopAsync(
+ bool errors_are_fatal,
+ Dart_Port on_error_port,
+ Dart_Port on_exit_port,
+ char** error);
+
+/* TODO(turnidge): Should this be removed from the public api? */
+
+/**
+ * Gets the main port id for the current isolate.
+ */
+DART_EXPORT Dart_Port Dart_GetMainPortId(void);
+
+/**
+ * Does the current isolate have live ReceivePorts?
+ *
+ * A ReceivePort is live when it has not been closed.
+ */
+DART_EXPORT bool Dart_HasLivePorts(void);
+
+/**
+ * Posts a message for some isolate. The message is a serialized
+ * object.
+ *
+ * Requires there to be a current isolate.
+ *
+ * For posting messages outside of an isolate see \ref Dart_PostCObject.
+ *
+ * \param port_id The destination port.
+ * \param object An object from the current isolate.
+ *
+ * \return True if the message was posted.
+ */
+DART_EXPORT bool Dart_Post(Dart_Port port_id, Dart_Handle object);
+
+/**
+ * Returns a new SendPort with the provided port id.
+ *
+ * \param port_id The destination port.
+ *
+ * \return A new SendPort if no errors occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewSendPort(Dart_Port port_id);
+
+/**
+ * Gets the SendPort id for the provided SendPort.
+ * \param port A SendPort object whose id is desired.
+ * \param port_id Returns the id of the SendPort.
+ * \return Success if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_SendPortGetId(Dart_Handle port,
+ Dart_Port* port_id);
+
+/*
+ * ======
+ * Scopes
+ * ======
+ */
+
+/**
+ * Enters a new scope.
+ *
+ * All new local handles will be created in this scope. Additionally,
+ * some functions may return "scope allocated" memory which is only
+ * valid within this scope.
+ *
+ * Requires there to be a current isolate.
+ */
+DART_EXPORT void Dart_EnterScope(void);
+
+/**
+ * Exits a scope.
+ *
+ * The previous scope (if any) becomes the current scope.
+ *
+ * Requires there to be a current isolate.
+ */
+DART_EXPORT void Dart_ExitScope(void);
+
+/**
+ * The Dart VM uses "zone allocation" for temporary structures. Zones
+ * support very fast allocation of small chunks of memory. The chunks
+ * cannot be deallocated individually, but instead zones support
+ * deallocating all chunks in one fast operation.
+ *
+ * This function makes it possible for the embedder to allocate
+ * temporary data in the VMs zone allocator.
+ *
+ * Zone allocation is possible:
+ * 1. when inside a scope where local handles can be allocated
+ * 2. when processing a message from a native port in a native port
+ * handler
+ *
+ * All the memory allocated this way will be reclaimed either on the
+ * next call to Dart_ExitScope or when the native port handler exits.
+ *
+ * \param size Size of the memory to allocate.
+ *
+ * \return A pointer to the allocated memory. NULL if allocation
+ * failed. Failure might due to is no current VM zone.
+ */
+DART_EXPORT uint8_t* Dart_ScopeAllocate(intptr_t size);
+
+/*
+ * =======
+ * Objects
+ * =======
+ */
+
+/**
+ * Returns the null object.
+ *
+ * \return A handle to the null object.
+ */
+DART_EXPORT Dart_Handle Dart_Null(void);
+
+/**
+ * Is this object null?
+ */
+DART_EXPORT bool Dart_IsNull(Dart_Handle object);
+
+/**
+ * Returns the empty string object.
+ *
+ * \return A handle to the empty string object.
+ */
+DART_EXPORT Dart_Handle Dart_EmptyString(void);
+
+/**
+ * Returns types that are not classes, and which therefore cannot be looked up
+ * as library members by Dart_GetType.
+ *
+ * \return A handle to the dynamic, void or Never type.
+ */
+DART_EXPORT Dart_Handle Dart_TypeDynamic(void);
+DART_EXPORT Dart_Handle Dart_TypeVoid(void);
+DART_EXPORT Dart_Handle Dart_TypeNever(void);
+
+/**
+ * Checks if the two objects are equal.
+ *
+ * The result of the comparison is returned through the 'equal'
+ * parameter. The return value itself is used to indicate success or
+ * failure, not equality.
+ *
+ * May generate an unhandled exception error.
+ *
+ * \param obj1 An object to be compared.
+ * \param obj2 An object to be compared.
+ * \param equal Returns the result of the equality comparison.
+ *
+ * \return A valid handle if no error occurs during the comparison.
+ */
+DART_EXPORT Dart_Handle Dart_ObjectEquals(Dart_Handle obj1,
+ Dart_Handle obj2,
+ bool* equal);
+
+/**
+ * Is this object an instance of some type?
+ *
+ * The result of the test is returned through the 'instanceof' parameter.
+ * The return value itself is used to indicate success or failure.
+ *
+ * \param object An object.
+ * \param type A type.
+ * \param instanceof Return true if 'object' is an instance of type 'type'.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_ObjectIsType(Dart_Handle object,
+ Dart_Handle type,
+ bool* instanceof);
+
+/**
+ * Query object type.
+ *
+ * \param object Some Object.
+ *
+ * \return true if Object is of the specified type.
+ */
+DART_EXPORT bool Dart_IsInstance(Dart_Handle object);
+DART_EXPORT bool Dart_IsNumber(Dart_Handle object);
+DART_EXPORT bool Dart_IsInteger(Dart_Handle object);
+DART_EXPORT bool Dart_IsDouble(Dart_Handle object);
+DART_EXPORT bool Dart_IsBoolean(Dart_Handle object);
+DART_EXPORT bool Dart_IsString(Dart_Handle object);
+DART_EXPORT bool Dart_IsStringLatin1(Dart_Handle object); /* (ISO-8859-1) */
+DART_EXPORT bool Dart_IsExternalString(Dart_Handle object);
+DART_EXPORT bool Dart_IsList(Dart_Handle object);
+DART_EXPORT bool Dart_IsMap(Dart_Handle object);
+DART_EXPORT bool Dart_IsLibrary(Dart_Handle object);
+DART_EXPORT bool Dart_IsType(Dart_Handle handle);
+DART_EXPORT bool Dart_IsFunction(Dart_Handle handle);
+DART_EXPORT bool Dart_IsVariable(Dart_Handle handle);
+DART_EXPORT bool Dart_IsTypeVariable(Dart_Handle handle);
+DART_EXPORT bool Dart_IsClosure(Dart_Handle object);
+DART_EXPORT bool Dart_IsTypedData(Dart_Handle object);
+DART_EXPORT bool Dart_IsByteBuffer(Dart_Handle object);
+DART_EXPORT bool Dart_IsFuture(Dart_Handle object);
+
+/*
+ * =========
+ * Instances
+ * =========
+ */
+
+/*
+ * For the purposes of the embedding api, not all objects returned are
+ * Dart language objects. Within the api, we use the term 'Instance'
+ * to indicate handles which refer to true Dart language objects.
+ *
+ * TODO(turnidge): Reorganize the "Object" section above, pulling down
+ * any functions that more properly belong here. */
+
+/**
+ * Gets the type of a Dart language object.
+ *
+ * \param instance Some Dart object.
+ *
+ * \return If no error occurs, the type is returned. Otherwise an
+ * error handle is returned.
+ */
+DART_EXPORT Dart_Handle Dart_InstanceGetType(Dart_Handle instance);
+
+/**
+ * Returns the name for the provided class type.
+ *
+ * \return A valid string handle if no error occurs during the
+ * operation.
+ */
+DART_EXPORT Dart_Handle Dart_ClassName(Dart_Handle cls_type);
+
+/**
+ * Returns the name for the provided function or method.
+ *
+ * \return A valid string handle if no error occurs during the
+ * operation.
+ */
+DART_EXPORT Dart_Handle Dart_FunctionName(Dart_Handle function);
+
+/**
+ * Returns a handle to the owner of a function.
+ *
+ * The owner of an instance method or a static method is its defining
+ * class. The owner of a top-level function is its defining
+ * library. The owner of the function of a non-implicit closure is the
+ * function of the method or closure that defines the non-implicit
+ * closure.
+ *
+ * \return A valid handle to the owner of the function, or an error
+ * handle if the argument is not a valid handle to a function.
+ */
+DART_EXPORT Dart_Handle Dart_FunctionOwner(Dart_Handle function);
+
+/**
+ * Determines whether a function handle refers to a static function
+ * of method.
+ *
+ * For the purposes of the embedding API, a top-level function is
+ * implicitly declared static.
+ *
+ * \param function A handle to a function or method declaration.
+ * \param is_static Returns whether the function or method is declared static.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_FunctionIsStatic(Dart_Handle function,
+ bool* is_static);
+
+/**
+ * Is this object a closure resulting from a tear-off (closurized method)?
+ *
+ * Returns true for closures produced when an ordinary method is accessed
+ * through a getter call. Returns false otherwise, in particular for closures
+ * produced from local function declarations.
+ *
+ * \param object Some Object.
+ *
+ * \return true if Object is a tear-off.
+ */
+DART_EXPORT bool Dart_IsTearOff(Dart_Handle object);
+
+/**
+ * Retrieves the function of a closure.
+ *
+ * \return A handle to the function of the closure, or an error handle if the
+ * argument is not a closure.
+ */
+DART_EXPORT Dart_Handle Dart_ClosureFunction(Dart_Handle closure);
+
+/**
+ * Returns a handle to the library which contains class.
+ *
+ * \return A valid handle to the library with owns class, null if the class
+ * has no library or an error handle if the argument is not a valid handle
+ * to a class type.
+ */
+DART_EXPORT Dart_Handle Dart_ClassLibrary(Dart_Handle cls_type);
+
+/*
+ * =============================
+ * Numbers, Integers and Doubles
+ * =============================
+ */
+
+/**
+ * Does this Integer fit into a 64-bit signed integer?
+ *
+ * \param integer An integer.
+ * \param fits Returns true if the integer fits into a 64-bit signed integer.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_IntegerFitsIntoInt64(Dart_Handle integer,
+ bool* fits);
+
+/**
+ * Does this Integer fit into a 64-bit unsigned integer?
+ *
+ * \param integer An integer.
+ * \param fits Returns true if the integer fits into a 64-bit unsigned integer.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_IntegerFitsIntoUint64(Dart_Handle integer,
+ bool* fits);
+
+/**
+ * Returns an Integer with the provided value.
+ *
+ * \param value The value of the integer.
+ *
+ * \return The Integer object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value);
+
+/**
+ * Returns an Integer with the provided value.
+ *
+ * \param value The unsigned value of the integer.
+ *
+ * \return The Integer object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewIntegerFromUint64(uint64_t value);
+
+/**
+ * Returns an Integer with the provided value.
+ *
+ * \param value The value of the integer represented as a C string
+ * containing a hexadecimal number.
+ *
+ * \return The Integer object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewIntegerFromHexCString(const char* value);
+
+/**
+ * Gets the value of an Integer.
+ *
+ * The integer must fit into a 64-bit signed integer, otherwise an error occurs.
+ *
+ * \param integer An Integer.
+ * \param value Returns the value of the Integer.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_IntegerToInt64(Dart_Handle integer,
+ int64_t* value);
+
+/**
+ * Gets the value of an Integer.
+ *
+ * The integer must fit into a 64-bit unsigned integer, otherwise an
+ * error occurs.
+ *
+ * \param integer An Integer.
+ * \param value Returns the value of the Integer.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_IntegerToUint64(Dart_Handle integer,
+ uint64_t* value);
+
+/**
+ * Gets the value of an integer as a hexadecimal C string.
+ *
+ * \param integer An Integer.
+ * \param value Returns the value of the Integer as a hexadecimal C
+ * string. This C string is scope allocated and is only valid until
+ * the next call to Dart_ExitScope.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_IntegerToHexCString(Dart_Handle integer,
+ const char** value);
+
+/**
+ * Returns a Double with the provided value.
+ *
+ * \param value A double.
+ *
+ * \return The Double object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewDouble(double value);
+
+/**
+ * Gets the value of a Double
+ *
+ * \param double_obj A Double
+ * \param value Returns the value of the Double.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_DoubleValue(Dart_Handle double_obj, double* value);
+
+/**
+ * Returns a closure of static function 'function_name' in the class 'class_name'
+ * in the exported namespace of specified 'library'.
+ *
+ * \param library Library object
+ * \param cls_type Type object representing a Class
+ * \param function_name Name of the static function in the class
+ *
+ * \return A valid Dart instance if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_GetStaticMethodClosure(Dart_Handle library,
+ Dart_Handle cls_type,
+ Dart_Handle function_name);
+
+/*
+ * ========
+ * Booleans
+ * ========
+ */
+
+/**
+ * Returns the True object.
+ *
+ * Requires there to be a current isolate.
+ *
+ * \return A handle to the True object.
+ */
+DART_EXPORT Dart_Handle Dart_True(void);
+
+/**
+ * Returns the False object.
+ *
+ * Requires there to be a current isolate.
+ *
+ * \return A handle to the False object.
+ */
+DART_EXPORT Dart_Handle Dart_False(void);
+
+/**
+ * Returns a Boolean with the provided value.
+ *
+ * \param value true or false.
+ *
+ * \return The Boolean object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewBoolean(bool value);
+
+/**
+ * Gets the value of a Boolean
+ *
+ * \param boolean_obj A Boolean
+ * \param value Returns the value of the Boolean.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_BooleanValue(Dart_Handle boolean_obj, bool* value);
+
+/*
+ * =======
+ * Strings
+ * =======
+ */
+
+/**
+ * Gets the length of a String.
+ *
+ * \param str A String.
+ * \param length Returns the length of the String.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_StringLength(Dart_Handle str, intptr_t* length);
+
+/**
+ * Returns a String built from the provided C string
+ * (There is an implicit assumption that the C string passed in contains
+ * UTF-8 encoded characters and '\0' is considered as a termination
+ * character).
+ *
+ * \param str A C String
+ *
+ * \return The String object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char* str);
+/* TODO(turnidge): Document what happens when we run out of memory
+ * during this call. */
+
+/**
+ * Returns a String built from an array of UTF-8 encoded characters.
+ *
+ * \param utf8_array An array of UTF-8 encoded characters.
+ * \param length The length of the codepoints array.
+ *
+ * \return The String object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewStringFromUTF8(const uint8_t* utf8_array,
+ intptr_t length);
+
+/**
+ * Returns a String built from an array of UTF-16 encoded characters.
+ *
+ * \param utf16_array An array of UTF-16 encoded characters.
+ * \param length The length of the codepoints array.
+ *
+ * \return The String object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewStringFromUTF16(const uint16_t* utf16_array,
+ intptr_t length);
+
+/**
+ * Returns a String built from an array of UTF-32 encoded characters.
+ *
+ * \param utf32_array An array of UTF-32 encoded characters.
+ * \param length The length of the codepoints array.
+ *
+ * \return The String object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewStringFromUTF32(const int32_t* utf32_array,
+ intptr_t length);
+
+/**
+ * Returns a String which references an external array of
+ * Latin-1 (ISO-8859-1) encoded characters.
+ *
+ * \param latin1_array Array of Latin-1 encoded characters. This must not move.
+ * \param length The length of the characters array.
+ * \param peer An external pointer to associate with this string.
+ * \param external_allocation_size The number of externally allocated
+ * bytes for peer. Used to inform the garbage collector.
+ * \param callback A callback to be called when this string is finalized.
+ *
+ * \return The String object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle
+Dart_NewExternalLatin1String(const uint8_t* latin1_array,
+ intptr_t length,
+ void* peer,
+ intptr_t external_allocation_size,
+ Dart_HandleFinalizer callback);
+
+/**
+ * Returns a String which references an external array of UTF-16 encoded
+ * characters.
+ *
+ * \param utf16_array An array of UTF-16 encoded characters. This must not move.
+ * \param length The length of the characters array.
+ * \param peer An external pointer to associate with this string.
+ * \param external_allocation_size The number of externally allocated
+ * bytes for peer. Used to inform the garbage collector.
+ * \param callback A callback to be called when this string is finalized.
+ *
+ * \return The String object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle
+Dart_NewExternalUTF16String(const uint16_t* utf16_array,
+ intptr_t length,
+ void* peer,
+ intptr_t external_allocation_size,
+ Dart_HandleFinalizer callback);
+
+/**
+ * Gets the C string representation of a String.
+ * (It is a sequence of UTF-8 encoded values with a '\0' termination.)
+ *
+ * \param str A string.
+ * \param cstr Returns the String represented as a C string.
+ * This C string is scope allocated and is only valid until
+ * the next call to Dart_ExitScope.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle str,
+ const char** cstr);
+
+/**
+ * Gets a UTF-8 encoded representation of a String.
+ *
+ * Any unpaired surrogate code points in the string will be converted as
+ * replacement characters (U+FFFD, 0xEF 0xBF 0xBD in UTF-8). If you need
+ * to preserve unpaired surrogates, use the Dart_StringToUTF16 function.
+ *
+ * \param str A string.
+ * \param utf8_array Returns the String represented as UTF-8 code
+ * units. This UTF-8 array is scope allocated and is only valid
+ * until the next call to Dart_ExitScope.
+ * \param length Used to return the length of the array which was
+ * actually used.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_StringToUTF8(Dart_Handle str,
+ uint8_t** utf8_array,
+ intptr_t* length);
+
+/**
+ * Gets the data corresponding to the string object. This function returns
+ * the data only for Latin-1 (ISO-8859-1) string objects. For all other
+ * string objects it returns an error.
+ *
+ * \param str A string.
+ * \param latin1_array An array allocated by the caller, used to return
+ * the string data.
+ * \param length Used to pass in the length of the provided array.
+ * Used to return the length of the array which was actually used.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_StringToLatin1(Dart_Handle str,
+ uint8_t* latin1_array,
+ intptr_t* length);
+
+/**
+ * Gets the UTF-16 encoded representation of a string.
+ *
+ * \param str A string.
+ * \param utf16_array An array allocated by the caller, used to return
+ * the array of UTF-16 encoded characters.
+ * \param length Used to pass in the length of the provided array.
+ * Used to return the length of the array which was actually used.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_StringToUTF16(Dart_Handle str,
+ uint16_t* utf16_array,
+ intptr_t* length);
+
+/**
+ * Gets the storage size in bytes of a String.
+ *
+ * \param str A String.
+ * \param size Returns the storage size in bytes of the String.
+ * This is the size in bytes needed to store the String.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_StringStorageSize(Dart_Handle str, intptr_t* size);
+
+/**
+ * Retrieves some properties associated with a String.
+ * Properties retrieved are:
+ * - character size of the string (one or two byte)
+ * - length of the string
+ * - peer pointer of string if it is an external string.
+ * \param str A String.
+ * \param char_size Returns the character size of the String.
+ * \param str_len Returns the length of the String.
+ * \param peer Returns the peer pointer associated with the String or 0 if
+ * there is no peer pointer for it.
+ * \return Success if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_StringGetProperties(Dart_Handle str,
+ intptr_t* char_size,
+ intptr_t* str_len,
+ void** peer);
+
+/*
+ * =====
+ * Lists
+ * =====
+ */
+
+/**
+ * Returns a List<dynamic> of the desired length.
+ *
+ * \param length The length of the list.
+ *
+ * \return The List object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewList(intptr_t length);
+
+typedef enum {
+ Dart_CoreType_Dynamic,
+ Dart_CoreType_Int,
+ Dart_CoreType_String,
+} Dart_CoreType_Id;
+
+// TODO(bkonyi): convert this to use nullable types once NNBD is enabled.
+/**
+ * Returns a List of the desired length with the desired legacy element type.
+ *
+ * \param element_type_id The type of elements of the list.
+ * \param length The length of the list.
+ *
+ * \return The List object if no error occurs. Otherwise returns an error
+ * handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewListOf(Dart_CoreType_Id element_type_id,
+ intptr_t length);
+
+/**
+ * Returns a List of the desired length with the desired element type.
+ *
+ * \param element_type Handle to a nullable type object. E.g., from
+ * Dart_GetType or Dart_GetNullableType.
+ *
+ * \param length The length of the list.
+ *
+ * \return The List object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewListOfType(Dart_Handle element_type,
+ intptr_t length);
+
+/**
+ * Returns a List of the desired length with the desired element type, filled
+ * with the provided object.
+ *
+ * \param element_type Handle to a type object. E.g., from Dart_GetType.
+ *
+ * \param fill_object Handle to an object of type 'element_type' that will be
+ * used to populate the list. This parameter can only be Dart_Null() if the
+ * length of the list is 0 or 'element_type' is a nullable type.
+ *
+ * \param length The length of the list.
+ *
+ * \return The List object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewListOfTypeFilled(Dart_Handle element_type,
+ Dart_Handle fill_object,
+ intptr_t length);
+
+/**
+ * Gets the length of a List.
+ *
+ * May generate an unhandled exception error.
+ *
+ * \param list A List.
+ * \param length Returns the length of the List.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_ListLength(Dart_Handle list, intptr_t* length);
+
+/**
+ * Gets the Object at some index of a List.
+ *
+ * If the index is out of bounds, an error occurs.
+ *
+ * May generate an unhandled exception error.
+ *
+ * \param list A List.
+ * \param index A valid index into the List.
+ *
+ * \return The Object in the List at the specified index if no error
+ * occurs. Otherwise returns an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_ListGetAt(Dart_Handle list, intptr_t index);
+
+/**
+* Gets a range of Objects from a List.
+*
+* If any of the requested index values are out of bounds, an error occurs.
+*
+* May generate an unhandled exception error.
+*
+* \param list A List.
+* \param offset The offset of the first item to get.
+* \param length The number of items to get.
+* \param result A pointer to fill with the objects.
+*
+* \return Success if no error occurs during the operation.
+*/
+DART_EXPORT Dart_Handle Dart_ListGetRange(Dart_Handle list,
+ intptr_t offset,
+ intptr_t length,
+ Dart_Handle* result);
+
+/**
+ * Sets the Object at some index of a List.
+ *
+ * If the index is out of bounds, an error occurs.
+ *
+ * May generate an unhandled exception error.
+ *
+ * \param list A List.
+ * \param index A valid index into the List.
+ * \param value The Object to put in the List.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_ListSetAt(Dart_Handle list,
+ intptr_t index,
+ Dart_Handle value);
+
+/**
+ * May generate an unhandled exception error.
+ */
+DART_EXPORT Dart_Handle Dart_ListGetAsBytes(Dart_Handle list,
+ intptr_t offset,
+ uint8_t* native_array,
+ intptr_t length);
+
+/**
+ * May generate an unhandled exception error.
+ */
+DART_EXPORT Dart_Handle Dart_ListSetAsBytes(Dart_Handle list,
+ intptr_t offset,
+ const uint8_t* native_array,
+ intptr_t length);
+
+/*
+ * ====
+ * Maps
+ * ====
+ */
+
+/**
+ * Gets the Object at some key of a Map.
+ *
+ * May generate an unhandled exception error.
+ *
+ * \param map A Map.
+ * \param key An Object.
+ *
+ * \return The value in the map at the specified key, null if the map does not
+ * contain the key, or an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_MapGetAt(Dart_Handle map, Dart_Handle key);
+
+/**
+ * Returns whether the Map contains a given key.
+ *
+ * May generate an unhandled exception error.
+ *
+ * \param map A Map.
+ *
+ * \return A handle on a boolean indicating whether map contains the key.
+ * Otherwise returns an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_MapContainsKey(Dart_Handle map, Dart_Handle key);
+
+/**
+ * Gets the list of keys of a Map.
+ *
+ * May generate an unhandled exception error.
+ *
+ * \param map A Map.
+ *
+ * \return The list of key Objects if no error occurs. Otherwise returns an
+ * error handle.
+ */
+DART_EXPORT Dart_Handle Dart_MapKeys(Dart_Handle map);
+
+/*
+ * ==========
+ * Typed Data
+ * ==========
+ */
+
+typedef enum {
+ Dart_TypedData_kByteData = 0,
+ Dart_TypedData_kInt8,
+ Dart_TypedData_kUint8,
+ Dart_TypedData_kUint8Clamped,
+ Dart_TypedData_kInt16,
+ Dart_TypedData_kUint16,
+ Dart_TypedData_kInt32,
+ Dart_TypedData_kUint32,
+ Dart_TypedData_kInt64,
+ Dart_TypedData_kUint64,
+ Dart_TypedData_kFloat32,
+ Dart_TypedData_kFloat64,
+ Dart_TypedData_kInt32x4,
+ Dart_TypedData_kFloat32x4,
+ Dart_TypedData_kFloat64x2,
+ Dart_TypedData_kInvalid
+} Dart_TypedData_Type;
+
+/**
+ * Return type if this object is a TypedData object.
+ *
+ * \return kInvalid if the object is not a TypedData object or the appropriate
+ * Dart_TypedData_Type.
+ */
+DART_EXPORT Dart_TypedData_Type Dart_GetTypeOfTypedData(Dart_Handle object);
+
+/**
+ * Return type if this object is an external TypedData object.
+ *
+ * \return kInvalid if the object is not an external TypedData object or
+ * the appropriate Dart_TypedData_Type.
+ */
+DART_EXPORT Dart_TypedData_Type
+Dart_GetTypeOfExternalTypedData(Dart_Handle object);
+
+/**
+ * Returns a TypedData object of the desired length and type.
+ *
+ * \param type The type of the TypedData object.
+ * \param length The length of the TypedData object (length in type units).
+ *
+ * \return The TypedData object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewTypedData(Dart_TypedData_Type type,
+ intptr_t length);
+
+/**
+ * Returns a TypedData object which references an external data array.
+ *
+ * \param type The type of the data array.
+ * \param data A data array. This array must not move.
+ * \param length The length of the data array (length in type units).
+ *
+ * \return The TypedData object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewExternalTypedData(Dart_TypedData_Type type,
+ void* data,
+ intptr_t length);
+
+/**
+ * Returns a TypedData object which references an external data array.
+ *
+ * \param type The type of the data array.
+ * \param data A data array. This array must not move.
+ * \param length The length of the data array (length in type units).
+ * \param peer A pointer to a native object or NULL. This value is
+ * provided to callback when it is invoked.
+ * \param external_allocation_size The number of externally allocated
+ * bytes for peer. Used to inform the garbage collector.
+ * \param callback A function pointer that will be invoked sometime
+ * after the object is garbage collected, unless the handle has been deleted.
+ * A valid callback needs to be specified it cannot be NULL.
+ *
+ * \return The TypedData object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle
+Dart_NewExternalTypedDataWithFinalizer(Dart_TypedData_Type type,
+ void* data,
+ intptr_t length,
+ void* peer,
+ intptr_t external_allocation_size,
+ Dart_HandleFinalizer callback);
+DART_EXPORT Dart_Handle Dart_NewUnmodifiableExternalTypedDataWithFinalizer(
+ Dart_TypedData_Type type,
+ const void* data,
+ intptr_t length,
+ void* peer,
+ intptr_t external_allocation_size,
+ Dart_HandleFinalizer callback);
+
+/**
+ * Returns a ByteBuffer object for the typed data.
+ *
+ * \param typed_data The TypedData object.
+ *
+ * \return The ByteBuffer object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewByteBuffer(Dart_Handle typed_data);
+
+/**
+ * Acquires access to the internal data address of a TypedData object.
+ *
+ * \param object The typed data object whose internal data address is to
+ * be accessed.
+ * \param type The type of the object is returned here.
+ * \param data The internal data address is returned here.
+ * \param len Size of the typed array is returned here.
+ *
+ * Notes:
+ * When the internal address of the object is acquired any calls to a
+ * Dart API function that could potentially allocate an object or run
+ * any Dart code will return an error.
+ *
+ * Any Dart API functions for accessing the data should not be called
+ * before the corresponding release. In particular, the object should
+ * not be acquired again before its release. This leads to undefined
+ * behavior.
+ *
+ * \return Success if the internal data address is acquired successfully.
+ * Otherwise, returns an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_TypedDataAcquireData(Dart_Handle object,
+ Dart_TypedData_Type* type,
+ void** data,
+ intptr_t* len);
+
+/**
+ * Releases access to the internal data address that was acquired earlier using
+ * Dart_TypedDataAcquireData.
+ *
+ * \param object The typed data object whose internal data address is to be
+ * released.
+ *
+ * \return Success if the internal data address is released successfully.
+ * Otherwise, returns an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_TypedDataReleaseData(Dart_Handle object);
+
+/**
+ * Returns the TypedData object associated with the ByteBuffer object.
+ *
+ * \param byte_buffer The ByteBuffer object.
+ *
+ * \return The TypedData object if no error occurs. Otherwise returns
+ * an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_GetDataFromByteBuffer(Dart_Handle byte_buffer);
+
+/*
+ * ============================================================
+ * Invoking Constructors, Methods, Closures and Field accessors
+ * ============================================================
+ */
+
+/**
+ * Invokes a constructor, creating a new object.
+ *
+ * This function allows hidden constructors (constructors with leading
+ * underscores) to be called.
+ *
+ * \param type Type of object to be constructed.
+ * \param constructor_name The name of the constructor to invoke. Use
+ * Dart_Null() or Dart_EmptyString() to invoke the unnamed constructor.
+ * This name should not include the name of the class.
+ * \param number_of_arguments Size of the arguments array.
+ * \param arguments An array of arguments to the constructor.
+ *
+ * \return If the constructor is called and completes successfully,
+ * then the new object. If an error occurs during execution, then an
+ * error handle is returned.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_New(Dart_Handle type,
+ Dart_Handle constructor_name,
+ int number_of_arguments,
+ Dart_Handle* arguments);
+
+/**
+ * Allocate a new object without invoking a constructor.
+ *
+ * \param type The type of an object to be allocated.
+ *
+ * \return The new object. If an error occurs during execution, then an
+ * error handle is returned.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_Allocate(Dart_Handle type);
+
+/**
+ * Allocate a new object without invoking a constructor, and sets specified
+ * native fields.
+ *
+ * \param type The type of an object to be allocated.
+ * \param num_native_fields The number of native fields to set.
+ * \param native_fields An array containing the value of native fields.
+ *
+ * \return The new object. If an error occurs during execution, then an
+ * error handle is returned.
+ */
+DART_EXPORT Dart_Handle
+Dart_AllocateWithNativeFields(Dart_Handle type,
+ intptr_t num_native_fields,
+ const intptr_t* native_fields);
+
+/**
+ * Invokes a method or function.
+ *
+ * The 'target' parameter may be an object, type, or library. If
+ * 'target' is an object, then this function will invoke an instance
+ * method. If 'target' is a type, then this function will invoke a
+ * static method. If 'target' is a library, then this function will
+ * invoke a top-level function from that library.
+ * NOTE: This API call cannot be used to invoke methods of a type object.
+ *
+ * This function ignores visibility (leading underscores in names).
+ *
+ * May generate an unhandled exception error.
+ *
+ * \param target An object, type, or library.
+ * \param name The name of the function or method to invoke.
+ * \param number_of_arguments Size of the arguments array.
+ * \param arguments An array of arguments to the function.
+ *
+ * \return If the function or method is called and completes
+ * successfully, then the return value is returned. If an error
+ * occurs during execution, then an error handle is returned.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_Invoke(Dart_Handle target,
+ Dart_Handle name,
+ int number_of_arguments,
+ Dart_Handle* arguments);
+/* TODO(turnidge): Document how to invoke operators. */
+
+/**
+ * Invokes a Closure with the given arguments.
+ *
+ * May generate an unhandled exception error.
+ *
+ * \return If no error occurs during execution, then the result of
+ * invoking the closure is returned. If an error occurs during
+ * execution, then an error handle is returned.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_InvokeClosure(Dart_Handle closure,
+ int number_of_arguments,
+ Dart_Handle* arguments);
+
+/**
+ * Invokes a Generative Constructor on an object that was previously
+ * allocated using Dart_Allocate/Dart_AllocateWithNativeFields.
+ *
+ * The 'object' parameter must be an object.
+ *
+ * This function ignores visibility (leading underscores in names).
+ *
+ * May generate an unhandled exception error.
+ *
+ * \param object An object.
+ * \param name The name of the constructor to invoke.
+ * Use Dart_Null() or Dart_EmptyString() to invoke the unnamed constructor.
+ * \param number_of_arguments Size of the arguments array.
+ * \param arguments An array of arguments to the function.
+ *
+ * \return If the constructor is called and completes
+ * successfully, then the object is returned. If an error
+ * occurs during execution, then an error handle is returned.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_InvokeConstructor(Dart_Handle object,
+ Dart_Handle name,
+ int number_of_arguments,
+ Dart_Handle* arguments);
+
+/**
+ * Gets the value of a field.
+ *
+ * The 'container' parameter may be an object, type, or library. If
+ * 'container' is an object, then this function will access an
+ * instance field. If 'container' is a type, then this function will
+ * access a static field. If 'container' is a library, then this
+ * function will access a top-level variable.
+ * NOTE: This API call cannot be used to access fields of a type object.
+ *
+ * This function ignores field visibility (leading underscores in names).
+ *
+ * May generate an unhandled exception error.
+ *
+ * \param container An object, type, or library.
+ * \param name A field name.
+ *
+ * \return If no error occurs, then the value of the field is
+ * returned. Otherwise an error handle is returned.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_GetField(Dart_Handle container, Dart_Handle name);
+
+/**
+ * Sets the value of a field.
+ *
+ * The 'container' parameter may actually be an object, type, or
+ * library. If 'container' is an object, then this function will
+ * access an instance field. If 'container' is a type, then this
+ * function will access a static field. If 'container' is a library,
+ * then this function will access a top-level variable.
+ * NOTE: This API call cannot be used to access fields of a type object.
+ *
+ * This function ignores field visibility (leading underscores in names).
+ *
+ * May generate an unhandled exception error.
+ *
+ * \param container An object, type, or library.
+ * \param name A field name.
+ * \param value The new field value.
+ *
+ * \return A valid handle if no error occurs.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_SetField(Dart_Handle container, Dart_Handle name, Dart_Handle value);
+
+/*
+ * ==========
+ * Exceptions
+ * ==========
+ */
+
+/*
+ * TODO(turnidge): Remove these functions from the api and replace all
+ * uses with Dart_NewUnhandledExceptionError. */
+
+/**
+ * Throws an exception.
+ *
+ * This function causes a Dart language exception to be thrown. This
+ * will proceed in the standard way, walking up Dart frames until an
+ * appropriate 'catch' block is found, executing 'finally' blocks,
+ * etc.
+ *
+ * If an error handle is passed into this function, the error is
+ * propagated immediately. See Dart_PropagateError for a discussion
+ * of error propagation.
+ *
+ * If successful, this function does not return. Note that this means
+ * that the destructors of any stack-allocated C++ objects will not be
+ * called. If there are no Dart frames on the stack, an error occurs.
+ *
+ * \return An error handle if the exception was not thrown.
+ * Otherwise the function does not return.
+ */
+DART_EXPORT Dart_Handle Dart_ThrowException(Dart_Handle exception);
+
+/**
+ * Rethrows an exception.
+ *
+ * Rethrows an exception, unwinding all dart frames on the stack. If
+ * successful, this function does not return. Note that this means
+ * that the destructors of any stack-allocated C++ objects will not be
+ * called. If there are no Dart frames on the stack, an error occurs.
+ *
+ * \return An error handle if the exception was not thrown.
+ * Otherwise the function does not return.
+ */
+DART_EXPORT Dart_Handle Dart_ReThrowException(Dart_Handle exception,
+ Dart_Handle stacktrace);
+
+/*
+ * ===========================
+ * Native fields and functions
+ * ===========================
+ */
+
+/**
+ * Gets the number of native instance fields in an object.
+ */
+DART_EXPORT Dart_Handle Dart_GetNativeInstanceFieldCount(Dart_Handle obj,
+ int* count);
+
+/**
+ * Gets the value of a native field.
+ *
+ * TODO(turnidge): Document.
+ */
+DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj,
+ int index,
+ intptr_t* value);
+
+/**
+ * Sets the value of a native field.
+ *
+ * TODO(turnidge): Document.
+ */
+DART_EXPORT Dart_Handle Dart_SetNativeInstanceField(Dart_Handle obj,
+ int index,
+ intptr_t value);
+
+/**
+ * The arguments to a native function.
+ *
+ * This object is passed to a native function to represent its
+ * arguments and return value. It allows access to the arguments to a
+ * native function by index. It also allows the return value of a
+ * native function to be set.
+ */
+typedef struct _Dart_NativeArguments* Dart_NativeArguments;
+
+/**
+ * Extracts current isolate group data from the native arguments structure.
+ */
+DART_EXPORT void* Dart_GetNativeIsolateGroupData(Dart_NativeArguments args);
+
+typedef enum {
+ Dart_NativeArgument_kBool = 0,
+ Dart_NativeArgument_kInt32,
+ Dart_NativeArgument_kUint32,
+ Dart_NativeArgument_kInt64,
+ Dart_NativeArgument_kUint64,
+ Dart_NativeArgument_kDouble,
+ Dart_NativeArgument_kString,
+ Dart_NativeArgument_kInstance,
+ Dart_NativeArgument_kNativeFields,
+} Dart_NativeArgument_Type;
+
+typedef struct _Dart_NativeArgument_Descriptor {
+ uint8_t type;
+ uint8_t index;
+} Dart_NativeArgument_Descriptor;
+
+typedef union _Dart_NativeArgument_Value {
+ bool as_bool;
+ int32_t as_int32;
+ uint32_t as_uint32;
+ int64_t as_int64;
+ uint64_t as_uint64;
+ double as_double;
+ struct {
+ Dart_Handle dart_str;
+ void* peer;
+ } as_string;
+ struct {
+ intptr_t num_fields;
+ intptr_t* values;
+ } as_native_fields;
+ Dart_Handle as_instance;
+} Dart_NativeArgument_Value;
+
+enum {
+ kNativeArgNumberPos = 0,
+ kNativeArgNumberSize = 8,
+ kNativeArgTypePos = kNativeArgNumberPos + kNativeArgNumberSize,
+ kNativeArgTypeSize = 8,
+};
+
+#define BITMASK(size) ((1 << size) - 1)
+#define DART_NATIVE_ARG_DESCRIPTOR(type, position) \
+ (((type & BITMASK(kNativeArgTypeSize)) << kNativeArgTypePos) | \
+ (position & BITMASK(kNativeArgNumberSize)))
+
+/**
+ * Gets the native arguments based on the types passed in and populates
+ * the passed arguments buffer with appropriate native values.
+ *
+ * \param args the Native arguments block passed into the native call.
+ * \param num_arguments length of argument descriptor array and argument
+ * values array passed in.
+ * \param arg_descriptors an array that describes the arguments that
+ * need to be retrieved. For each argument to be retrieved the descriptor
+ * contains the argument number (0, 1 etc.) and the argument type
+ * described using Dart_NativeArgument_Type, e.g:
+ * DART_NATIVE_ARG_DESCRIPTOR(Dart_NativeArgument_kBool, 1) indicates
+ * that the first argument is to be retrieved and it should be a boolean.
+ * \param arg_values array into which the native arguments need to be
+ * extracted into, the array is allocated by the caller (it could be
+ * stack allocated to avoid the malloc/free performance overhead).
+ *
+ * \return Success if all the arguments could be extracted correctly,
+ * returns an error handle if there were any errors while extracting the
+ * arguments (mismatched number of arguments, incorrect types, etc.).
+ */
+DART_EXPORT Dart_Handle
+Dart_GetNativeArguments(Dart_NativeArguments args,
+ int num_arguments,
+ const Dart_NativeArgument_Descriptor* arg_descriptors,
+ Dart_NativeArgument_Value* arg_values);
+
+/**
+ * Gets the native argument at some index.
+ */
+DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args,
+ int index);
+/* TODO(turnidge): Specify the behavior of an out-of-bounds access. */
+
+/**
+ * Gets the number of native arguments.
+ */
+DART_EXPORT int Dart_GetNativeArgumentCount(Dart_NativeArguments args);
+
+/**
+ * Gets all the native fields of the native argument at some index.
+ * \param args Native arguments structure.
+ * \param arg_index Index of the desired argument in the structure above.
+ * \param num_fields size of the intptr_t array 'field_values' passed in.
+ * \param field_values intptr_t array in which native field values are returned.
+ * \return Success if the native fields where copied in successfully. Otherwise
+ * returns an error handle. On success the native field values are copied
+ * into the 'field_values' array, if the argument at 'arg_index' is a
+ * null object then 0 is copied as the native field values into the
+ * 'field_values' array.
+ */
+DART_EXPORT Dart_Handle
+Dart_GetNativeFieldsOfArgument(Dart_NativeArguments args,
+ int arg_index,
+ int num_fields,
+ intptr_t* field_values);
+
+/**
+ * Gets the native field of the receiver.
+ */
+DART_EXPORT Dart_Handle Dart_GetNativeReceiver(Dart_NativeArguments args,
+ intptr_t* value);
+
+/**
+ * Gets a string native argument at some index.
+ * \param args Native arguments structure.
+ * \param arg_index Index of the desired argument in the structure above.
+ * \param peer Returns the peer pointer if the string argument has one.
+ * \return Success if the string argument has a peer, if it does not
+ * have a peer then the String object is returned. Otherwise returns
+ * an error handle (argument is not a String object).
+ */
+DART_EXPORT Dart_Handle Dart_GetNativeStringArgument(Dart_NativeArguments args,
+ int arg_index,
+ void** peer);
+
+/**
+ * Gets an integer native argument at some index.
+ * \param args Native arguments structure.
+ * \param index Index of the desired argument in the structure above.
+ * \param value Returns the integer value if the argument is an Integer.
+ * \return Success if no error occurs. Otherwise returns an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_GetNativeIntegerArgument(Dart_NativeArguments args,
+ int index,
+ int64_t* value);
+
+/**
+ * Gets a boolean native argument at some index.
+ * \param args Native arguments structure.
+ * \param index Index of the desired argument in the structure above.
+ * \param value Returns the boolean value if the argument is a Boolean.
+ * \return Success if no error occurs. Otherwise returns an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_GetNativeBooleanArgument(Dart_NativeArguments args,
+ int index,
+ bool* value);
+
+/**
+ * Gets a double native argument at some index.
+ * \param args Native arguments structure.
+ * \param index Index of the desired argument in the structure above.
+ * \param value Returns the double value if the argument is a double.
+ * \return Success if no error occurs. Otherwise returns an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_GetNativeDoubleArgument(Dart_NativeArguments args,
+ int index,
+ double* value);
+
+/**
+ * Sets the return value for a native function.
+ *
+ * If retval is an Error handle, then error will be propagated once
+ * the native functions exits. See Dart_PropagateError for a
+ * discussion of how different types of errors are propagated.
+ */
+DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args,
+ Dart_Handle retval);
+
+DART_EXPORT void Dart_SetWeakHandleReturnValue(Dart_NativeArguments args,
+ Dart_WeakPersistentHandle rval);
+
+DART_EXPORT void Dart_SetBooleanReturnValue(Dart_NativeArguments args,
+ bool retval);
+
+DART_EXPORT void Dart_SetIntegerReturnValue(Dart_NativeArguments args,
+ int64_t retval);
+
+DART_EXPORT void Dart_SetDoubleReturnValue(Dart_NativeArguments args,
+ double retval);
+
+/**
+ * A native function.
+ */
+typedef void (*Dart_NativeFunction)(Dart_NativeArguments arguments);
+
+/**
+ * Native entry resolution callback.
+ *
+ * For libraries and scripts which have native functions, the embedder
+ * can provide a native entry resolver. This callback is used to map a
+ * name/arity to a Dart_NativeFunction. If no function is found, the
+ * callback should return NULL.
+ *
+ * The parameters to the native resolver function are:
+ * \param name a Dart string which is the name of the native function.
+ * \param num_of_arguments is the number of arguments expected by the
+ * native function.
+ * \param auto_setup_scope is a boolean flag that can be set by the resolver
+ * to indicate if this function needs a Dart API scope (see Dart_EnterScope/
+ * Dart_ExitScope) to be setup automatically by the VM before calling into
+ * the native function. By default most native functions would require this
+ * to be true but some light weight native functions which do not call back
+ * into the VM through the Dart API may not require a Dart scope to be
+ * setup automatically.
+ *
+ * \return A valid Dart_NativeFunction which resolves to a native entry point
+ * for the native function.
+ *
+ * See Dart_SetNativeResolver.
+ */
+typedef Dart_NativeFunction (*Dart_NativeEntryResolver)(Dart_Handle name,
+ int num_of_arguments,
+ bool* auto_setup_scope);
+/* TODO(turnidge): Consider renaming to NativeFunctionResolver or
+ * NativeResolver. */
+
+/**
+ * Native entry symbol lookup callback.
+ *
+ * For libraries and scripts which have native functions, the embedder
+ * can provide a callback for mapping a native entry to a symbol. This callback
+ * maps a native function entry PC to the native function name. If no native
+ * entry symbol can be found, the callback should return NULL.
+ *
+ * The parameters to the native reverse resolver function are:
+ * \param nf A Dart_NativeFunction.
+ *
+ * \return A const UTF-8 string containing the symbol name or NULL.
+ *
+ * See Dart_SetNativeResolver.
+ */
+typedef const uint8_t* (*Dart_NativeEntrySymbol)(Dart_NativeFunction nf);
+
+/**
+ * FFI Native C function pointer resolver callback.
+ *
+ * See Dart_SetFfiNativeResolver.
+ */
+typedef void* (*Dart_FfiNativeResolver)(const char* name, uintptr_t args_n);
+
+/*
+ * ===========
+ * Environment
+ * ===========
+ */
+
+/**
+ * An environment lookup callback function.
+ *
+ * \param name The name of the value to lookup in the environment.
+ *
+ * \return A valid handle to a string if the name exists in the
+ * current environment or Dart_Null() if not.
+ */
+typedef Dart_Handle (*Dart_EnvironmentCallback)(Dart_Handle name);
+
+/**
+ * Sets the environment callback for the current isolate. This
+ * callback is used to lookup environment values by name in the
+ * current environment. This enables the embedder to supply values for
+ * the const constructors bool.fromEnvironment, int.fromEnvironment
+ * and String.fromEnvironment.
+ */
+DART_EXPORT Dart_Handle
+Dart_SetEnvironmentCallback(Dart_EnvironmentCallback callback);
+
+/**
+ * Sets the callback used to resolve native functions for a library.
+ *
+ * \param library A library.
+ * \param resolver A native entry resolver.
+ *
+ * \return A valid handle if the native resolver was set successfully.
+ */
+DART_EXPORT Dart_Handle
+Dart_SetNativeResolver(Dart_Handle library,
+ Dart_NativeEntryResolver resolver,
+ Dart_NativeEntrySymbol symbol);
+/* TODO(turnidge): Rename to Dart_LibrarySetNativeResolver? */
+
+/**
+ * Returns the callback used to resolve native functions for a library.
+ *
+ * \param library A library.
+ * \param resolver a pointer to a Dart_NativeEntryResolver
+ *
+ * \return A valid handle if the library was found.
+ */
+DART_EXPORT Dart_Handle
+Dart_GetNativeResolver(Dart_Handle library, Dart_NativeEntryResolver* resolver);
+
+/**
+ * Returns the callback used to resolve native function symbols for a library.
+ *
+ * \param library A library.
+ * \param resolver a pointer to a Dart_NativeEntrySymbol.
+ *
+ * \return A valid handle if the library was found.
+ */
+DART_EXPORT Dart_Handle Dart_GetNativeSymbol(Dart_Handle library,
+ Dart_NativeEntrySymbol* resolver);
+
+/**
+ * Sets the callback used to resolve FFI native functions for a library.
+ * The resolved functions are expected to be a C function pointer of the
+ * correct signature (as specified in the `@FfiNative<NFT>()` function
+ * annotation in Dart code).
+ *
+ * NOTE: This is an experimental feature and might change in the future.
+ *
+ * \param library A library.
+ * \param resolver A native function resolver.
+ *
+ * \return A valid handle if the native resolver was set successfully.
+ */
+DART_EXPORT Dart_Handle
+Dart_SetFfiNativeResolver(Dart_Handle library, Dart_FfiNativeResolver resolver);
+
+/*
+ * =====================
+ * Scripts and Libraries
+ * =====================
+ */
+
+typedef enum {
+ Dart_kCanonicalizeUrl = 0,
+ Dart_kImportTag,
+ Dart_kKernelTag,
+} Dart_LibraryTag;
+
+/**
+ * The library tag handler is a multi-purpose callback provided by the
+ * embedder to the Dart VM. The embedder implements the tag handler to
+ * provide the ability to load Dart scripts and imports.
+ *
+ * -- TAGS --
+ *
+ * Dart_kCanonicalizeUrl
+ *
+ * This tag indicates that the embedder should canonicalize 'url' with
+ * respect to 'library'. For most embedders, the
+ * Dart_DefaultCanonicalizeUrl function is a sufficient implementation
+ * of this tag. The return value should be a string holding the
+ * canonicalized url.
+ *
+ * Dart_kImportTag
+ *
+ * This tag is used to load a library from IsolateMirror.loadUri. The embedder
+ * should call Dart_LoadLibraryFromKernel to provide the library to the VM. The
+ * return value should be an error or library (the result from
+ * Dart_LoadLibraryFromKernel).
+ *
+ * Dart_kKernelTag
+ *
+ * This tag is used to load the intermediate file (kernel) generated by
+ * the Dart front end. This tag is typically used when a 'hot-reload'
+ * of an application is needed and the VM is 'use dart front end' mode.
+ * The dart front end typically compiles all the scripts, imports and part
+ * files into one intermediate file hence we don't use the source/import or
+ * script tags. The return value should be an error or a TypedData containing
+ * the kernel bytes.
+ *
+ */
+typedef Dart_Handle (*Dart_LibraryTagHandler)(
+ Dart_LibraryTag tag,
+ Dart_Handle library_or_package_map_url,
+ Dart_Handle url);
+
+/**
+ * Sets library tag handler for the current isolate. This handler is
+ * used to handle the various tags encountered while loading libraries
+ * or scripts in the isolate.
+ *
+ * \param handler Handler code to be used for handling the various tags
+ * encountered while loading libraries or scripts in the isolate.
+ *
+ * \return If no error occurs, the handler is set for the isolate.
+ * Otherwise an error handle is returned.
+ *
+ * TODO(turnidge): Document.
+ */
+DART_EXPORT Dart_Handle
+Dart_SetLibraryTagHandler(Dart_LibraryTagHandler handler);
+
+/**
+ * Handles deferred loading requests. When this handler is invoked, it should
+ * eventually load the deferred loading unit with the given id and call
+ * Dart_DeferredLoadComplete or Dart_DeferredLoadCompleteError. It is
+ * recommended that the loading occur asynchronously, but it is permitted to
+ * call Dart_DeferredLoadComplete or Dart_DeferredLoadCompleteError before the
+ * handler returns.
+ *
+ * If an error is returned, it will be propagated through
+ * `prefix.loadLibrary()`. This is useful for synchronous
+ * implementations, which must propagate any unwind errors from
+ * Dart_DeferredLoadComplete or Dart_DeferredLoadComplete. Otherwise the handler
+ * should return a non-error such as `Dart_Null()`.
+ */
+typedef Dart_Handle (*Dart_DeferredLoadHandler)(intptr_t loading_unit_id);
+
+/**
+ * Sets the deferred load handler for the current isolate. This handler is
+ * used to handle loading deferred imports in an AppJIT or AppAOT program.
+ */
+DART_EXPORT Dart_Handle
+Dart_SetDeferredLoadHandler(Dart_DeferredLoadHandler handler);
+
+/**
+ * Notifies the VM that a deferred load completed successfully. This function
+ * will eventually cause the corresponding `prefix.loadLibrary()` futures to
+ * complete.
+ *
+ * Requires the current isolate to be the same current isolate during the
+ * invocation of the Dart_DeferredLoadHandler.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_DeferredLoadComplete(intptr_t loading_unit_id,
+ const uint8_t* snapshot_data,
+ const uint8_t* snapshot_instructions);
+
+/**
+ * Notifies the VM that a deferred load failed. This function
+ * will eventually cause the corresponding `prefix.loadLibrary()` futures to
+ * complete with an error.
+ *
+ * If `transient` is true, future invocations of `prefix.loadLibrary()` will
+ * trigger new load requests. If false, futures invocation will complete with
+ * the same error.
+ *
+ * Requires the current isolate to be the same current isolate during the
+ * invocation of the Dart_DeferredLoadHandler.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_DeferredLoadCompleteError(intptr_t loading_unit_id,
+ const char* error_message,
+ bool transient);
+
+/**
+ * Canonicalizes a url with respect to some library.
+ *
+ * The url is resolved with respect to the library's url and some url
+ * normalizations are performed.
+ *
+ * This canonicalization function should be sufficient for most
+ * embedders to implement the Dart_kCanonicalizeUrl tag.
+ *
+ * \param base_url The base url relative to which the url is
+ * being resolved.
+ * \param url The url being resolved and canonicalized. This
+ * parameter is a string handle.
+ *
+ * \return If no error occurs, a String object is returned. Otherwise
+ * an error handle is returned.
+ */
+DART_EXPORT Dart_Handle Dart_DefaultCanonicalizeUrl(Dart_Handle base_url,
+ Dart_Handle url);
+
+/**
+ * Loads the root library for the current isolate.
+ *
+ * Requires there to be no current root library.
+ *
+ * \param kernel_buffer A buffer which contains a kernel binary (see
+ * pkg/kernel/binary.md). Must remain valid until isolate group shutdown.
+ * \param kernel_size Length of the passed in buffer.
+ *
+ * \return A handle to the root library, or an error.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_LoadScriptFromKernel(const uint8_t* kernel_buffer, intptr_t kernel_size);
+
+/**
+ * Gets the library for the root script for the current isolate.
+ *
+ * If the root script has not yet been set for the current isolate,
+ * this function returns Dart_Null(). This function never returns an
+ * error handle.
+ *
+ * \return Returns the root Library for the current isolate or Dart_Null().
+ */
+DART_EXPORT Dart_Handle Dart_RootLibrary(void);
+
+/**
+ * Sets the root library for the current isolate.
+ *
+ * \return Returns an error handle if `library` is not a library handle.
+ */
+DART_EXPORT Dart_Handle Dart_SetRootLibrary(Dart_Handle library);
+
+/**
+ * Lookup or instantiate a legacy type by name and type arguments from a
+ * Library.
+ *
+ * \param library The library containing the class or interface.
+ * \param class_name The class name for the type.
+ * \param number_of_type_arguments Number of type arguments.
+ * For non parametric types the number of type arguments would be 0.
+ * \param type_arguments Pointer to an array of type arguments.
+ * For non parametric types a NULL would be passed in for this argument.
+ *
+ * \return If no error occurs, the type is returned.
+ * Otherwise an error handle is returned.
+ */
+DART_EXPORT Dart_Handle Dart_GetType(Dart_Handle library,
+ Dart_Handle class_name,
+ intptr_t number_of_type_arguments,
+ Dart_Handle* type_arguments);
+
+/**
+ * Lookup or instantiate a nullable type by name and type arguments from
+ * Library.
+ *
+ * \param library The library containing the class or interface.
+ * \param class_name The class name for the type.
+ * \param number_of_type_arguments Number of type arguments.
+ * For non parametric types the number of type arguments would be 0.
+ * \param type_arguments Pointer to an array of type arguments.
+ * For non parametric types a NULL would be passed in for this argument.
+ *
+ * \return If no error occurs, the type is returned.
+ * Otherwise an error handle is returned.
+ */
+DART_EXPORT Dart_Handle Dart_GetNullableType(Dart_Handle library,
+ Dart_Handle class_name,
+ intptr_t number_of_type_arguments,
+ Dart_Handle* type_arguments);
+
+/**
+ * Lookup or instantiate a non-nullable type by name and type arguments from
+ * Library.
+ *
+ * \param library The library containing the class or interface.
+ * \param class_name The class name for the type.
+ * \param number_of_type_arguments Number of type arguments.
+ * For non parametric types the number of type arguments would be 0.
+ * \param type_arguments Pointer to an array of type arguments.
+ * For non parametric types a NULL would be passed in for this argument.
+ *
+ * \return If no error occurs, the type is returned.
+ * Otherwise an error handle is returned.
+ */
+DART_EXPORT Dart_Handle
+Dart_GetNonNullableType(Dart_Handle library,
+ Dart_Handle class_name,
+ intptr_t number_of_type_arguments,
+ Dart_Handle* type_arguments);
+
+/**
+ * Creates a nullable version of the provided type.
+ *
+ * \param type The type to be converted to a nullable type.
+ *
+ * \return If no error occurs, a nullable type is returned.
+ * Otherwise an error handle is returned.
+ */
+DART_EXPORT Dart_Handle Dart_TypeToNullableType(Dart_Handle type);
+
+/**
+ * Creates a non-nullable version of the provided type.
+ *
+ * \param type The type to be converted to a non-nullable type.
+ *
+ * \return If no error occurs, a non-nullable type is returned.
+ * Otherwise an error handle is returned.
+ */
+DART_EXPORT Dart_Handle Dart_TypeToNonNullableType(Dart_Handle type);
+
+/**
+ * A type's nullability.
+ *
+ * \param type A Dart type.
+ * \param result An out parameter containing the result of the check. True if
+ * the type is of the specified nullability, false otherwise.
+ *
+ * \return Returns an error handle if type is not of type Type.
+ */
+DART_EXPORT Dart_Handle Dart_IsNullableType(Dart_Handle type, bool* result);
+DART_EXPORT Dart_Handle Dart_IsNonNullableType(Dart_Handle type, bool* result);
+DART_EXPORT Dart_Handle Dart_IsLegacyType(Dart_Handle type, bool* result);
+
+/**
+ * Lookup a class or interface by name from a Library.
+ *
+ * \param library The library containing the class or interface.
+ * \param class_name The name of the class or interface.
+ *
+ * \return If no error occurs, the class or interface is
+ * returned. Otherwise an error handle is returned.
+ */
+DART_EXPORT Dart_Handle Dart_GetClass(Dart_Handle library,
+ Dart_Handle class_name);
+/* TODO(asiva): The above method needs to be removed once all uses
+ * of it are removed from the embedder code. */
+
+/**
+ * Returns an import path to a Library, such as "file:///test.dart" or
+ * "dart:core".
+ */
+DART_EXPORT Dart_Handle Dart_LibraryUrl(Dart_Handle library);
+
+/**
+ * Returns a URL from which a Library was loaded.
+ */
+DART_EXPORT Dart_Handle Dart_LibraryResolvedUrl(Dart_Handle library);
+
+/**
+ * \return An array of libraries.
+ */
+DART_EXPORT Dart_Handle Dart_GetLoadedLibraries(void);
+
+DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url);
+/* TODO(turnidge): Consider returning Dart_Null() when the library is
+ * not found to distinguish that from a true error case. */
+
+/**
+ * Report an loading error for the library.
+ *
+ * \param library The library that failed to load.
+ * \param error The Dart error instance containing the load error.
+ *
+ * \return If the VM handles the error, the return value is
+ * a null handle. If it doesn't handle the error, the error
+ * object is returned.
+ */
+DART_EXPORT Dart_Handle Dart_LibraryHandleError(Dart_Handle library,
+ Dart_Handle error);
+
+/**
+ * Called by the embedder to load a partial program. Does not set the root
+ * library.
+ *
+ * \param kernel_buffer A buffer which contains a kernel binary (see
+ * pkg/kernel/binary.md). Must remain valid until isolate shutdown.
+ * \param kernel_buffer_size Length of the passed in buffer.
+ *
+ * \return A handle to the main library of the compilation unit, or an error.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_LoadLibraryFromKernel(const uint8_t* kernel_buffer,
+ intptr_t kernel_buffer_size);
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_LoadLibrary(Dart_Handle kernel_buffer);
+
+/**
+ * Indicates that all outstanding load requests have been satisfied.
+ * This finalizes all the new classes loaded and optionally completes
+ * deferred library futures.
+ *
+ * Requires there to be a current isolate.
+ *
+ * \param complete_futures Specify true if all deferred library
+ * futures should be completed, false otherwise.
+ *
+ * \return Success if all classes have been finalized and deferred library
+ * futures are completed. Otherwise, returns an error.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_FinalizeLoading(bool complete_futures);
+
+/*
+ * =====
+ * Peers
+ * =====
+ */
+
+/**
+ * The peer field is a lazily allocated field intended for storage of
+ * an uncommonly used values. Most instances types can have a peer
+ * field allocated. The exceptions are subtypes of Null, num, and
+ * bool.
+ */
+
+/**
+ * Returns the value of peer field of 'object' in 'peer'.
+ *
+ * \param object An object.
+ * \param peer An out parameter that returns the value of the peer
+ * field.
+ *
+ * \return Returns an error if 'object' is a subtype of Null, num, or
+ * bool.
+ */
+DART_EXPORT Dart_Handle Dart_GetPeer(Dart_Handle object, void** peer);
+
+/**
+ * Sets the value of the peer field of 'object' to the value of
+ * 'peer'.
+ *
+ * \param object An object.
+ * \param peer A value to store in the peer field.
+ *
+ * \return Returns an error if 'object' is a subtype of Null, num, or
+ * bool.
+ */
+DART_EXPORT Dart_Handle Dart_SetPeer(Dart_Handle object, void* peer);
+
+/*
+ * ======
+ * Kernel
+ * ======
+ */
+
+/**
+ * Experimental support for Dart to Kernel parser isolate.
+ *
+ * TODO(hausner): Document finalized interface.
+ *
+ */
+
+// TODO(33433): Remove kernel service from the embedding API.
+
+typedef enum {
+ Dart_KernelCompilationStatus_Unknown = -1,
+ Dart_KernelCompilationStatus_Ok = 0,
+ Dart_KernelCompilationStatus_Error = 1,
+ Dart_KernelCompilationStatus_Crash = 2,
+ Dart_KernelCompilationStatus_MsgFailed = 3,
+} Dart_KernelCompilationStatus;
+
+typedef struct {
+ Dart_KernelCompilationStatus status;
+ bool null_safety;
+ char* error;
+ uint8_t* kernel;
+ intptr_t kernel_size;
+} Dart_KernelCompilationResult;
+
+typedef enum {
+ Dart_KernelCompilationVerbosityLevel_Error = 0,
+ Dart_KernelCompilationVerbosityLevel_Warning,
+ Dart_KernelCompilationVerbosityLevel_Info,
+ Dart_KernelCompilationVerbosityLevel_All,
+} Dart_KernelCompilationVerbosityLevel;
+
+DART_EXPORT bool Dart_IsKernelIsolate(Dart_Isolate isolate);
+DART_EXPORT bool Dart_KernelIsolateIsRunning(void);
+DART_EXPORT Dart_Port Dart_KernelPort(void);
+
+/**
+ * Compiles the given `script_uri` to a kernel file.
+ *
+ * \param platform_kernel A buffer containing the kernel of the platform (e.g.
+ * `vm_platform_strong.dill`). The VM does not take ownership of this memory.
+ *
+ * \param platform_kernel_size The length of the platform_kernel buffer.
+ *
+ * \param snapshot_compile Set to `true` when the compilation is for a snapshot.
+ * This is used by the frontend to determine if compilation related information
+ * should be printed to console (e.g., null safety mode).
+ *
+ * \param verbosity Specifies the logging behavior of the kernel compilation
+ * service.
+ *
+ * \return Returns the result of the compilation.
+ *
+ * On a successful compilation the returned [Dart_KernelCompilationResult] has
+ * a status of [Dart_KernelCompilationStatus_Ok] and the `kernel`/`kernel_size`
+ * fields are set. The caller takes ownership of the malloc()ed buffer.
+ *
+ * On a failed compilation the `error` might be set describing the reason for
+ * the failed compilation. The caller takes ownership of the malloc()ed
+ * error.
+ *
+ * Requires there to be a current isolate.
+ */
+DART_EXPORT Dart_KernelCompilationResult
+Dart_CompileToKernel(const char* script_uri,
+ const uint8_t* platform_kernel,
+ const intptr_t platform_kernel_size,
+ bool incremental_compile,
+ bool snapshot_compile,
+ const char* package_config,
+ Dart_KernelCompilationVerbosityLevel verbosity);
+
+typedef struct {
+ const char* uri;
+ const char* source;
+} Dart_SourceFile;
+
+DART_EXPORT Dart_KernelCompilationResult Dart_KernelListDependencies(void);
+
+/**
+ * Sets the kernel buffer which will be used to load Dart SDK sources
+ * dynamically at runtime.
+ *
+ * \param platform_kernel A buffer containing kernel which has sources for the
+ * Dart SDK populated. Note: The VM does not take ownership of this memory.
+ *
+ * \param platform_kernel_size The length of the platform_kernel buffer.
+ */
+DART_EXPORT void Dart_SetDartLibrarySourcesKernel(
+ const uint8_t* platform_kernel,
+ const intptr_t platform_kernel_size);
+
+/**
+ * Detect the null safety opt-in status.
+ *
+ * When running from source, it is based on the opt-in status of `script_uri`.
+ * When running from a kernel buffer, it is based on the mode used when
+ * generating `kernel_buffer`.
+ * When running from an appJIT or AOT snapshot, it is based on the mode used
+ * when generating `snapshot_data`.
+ *
+ * \param script_uri Uri of the script that contains the source code
+ *
+ * \param package_config Uri of the package configuration file (either in format
+ * of .packages or .dart_tool/package_config.json) for the null safety
+ * detection to resolve package imports against. If this parameter is not
+ * passed the package resolution of the parent isolate should be used.
+ *
+ * \param original_working_directory current working directory when the VM
+ * process was launched, this is used to correctly resolve the path specified
+ * for package_config.
+ *
+ * \param snapshot_data Buffer containing the snapshot data of the
+ * isolate or NULL if no snapshot is provided. If provided, the buffers must
+ * remain valid until the isolate shuts down.
+ *
+ * \param snapshot_instructions Buffer containing the snapshot instructions of
+ * the isolate or NULL if no snapshot is provided. If provided, the buffers
+ * must remain valid until the isolate shuts down.
+ *
+ * \param kernel_buffer A buffer which contains a kernel/DIL program. Must
+ * remain valid until isolate shutdown.
+ *
+ * \param kernel_buffer_size The size of `kernel_buffer`.
+ *
+ * \return Returns true if the null safety is opted in by the input being
+ * run `script_uri`, `snapshot_data` or `kernel_buffer`.
+ *
+ */
+DART_EXPORT bool Dart_DetectNullSafety(const char* script_uri,
+ const char* package_config,
+ const char* original_working_directory,
+ const uint8_t* snapshot_data,
+ const uint8_t* snapshot_instructions,
+ const uint8_t* kernel_buffer,
+ intptr_t kernel_buffer_size);
+
+#define DART_KERNEL_ISOLATE_NAME "kernel-service"
+
+/*
+ * =======
+ * Service
+ * =======
+ */
+
+#define DART_VM_SERVICE_ISOLATE_NAME "vm-service"
+
+/**
+ * Returns true if isolate is the service isolate.
+ *
+ * \param isolate An isolate
+ *
+ * \return Returns true if 'isolate' is the service isolate.
+ */
+DART_EXPORT bool Dart_IsServiceIsolate(Dart_Isolate isolate);
+
+/**
+ * Writes the CPU profile to the timeline as a series of 'instant' events.
+ *
+ * Note that this is an expensive operation.
+ *
+ * \param main_port The main port of the Isolate whose profile samples to write.
+ * \param error An optional error, must be free()ed by caller.
+ *
+ * \return Returns true if the profile is successfully written and false
+ * otherwise.
+ */
+DART_EXPORT bool Dart_WriteProfileToTimeline(Dart_Port main_port, char** error);
+
+/*
+ * ==============
+ * Precompilation
+ * ==============
+ */
+
+/**
+ * Compiles all functions reachable from entry points and marks
+ * the isolate to disallow future compilation.
+ *
+ * Entry points should be specified using `@pragma("vm:entry-point")`
+ * annotation.
+ *
+ * \return An error handle if a compilation error or runtime error running const
+ * constructors was encountered.
+ */
+DART_EXPORT Dart_Handle Dart_Precompile(void);
+
+typedef void (*Dart_CreateLoadingUnitCallback)(
+ void* callback_data,
+ intptr_t loading_unit_id,
+ void** write_callback_data,
+ void** write_debug_callback_data);
+typedef void (*Dart_StreamingWriteCallback)(void* callback_data,
+ const uint8_t* buffer,
+ intptr_t size);
+typedef void (*Dart_StreamingCloseCallback)(void* callback_data);
+
+DART_EXPORT Dart_Handle Dart_LoadingUnitLibraryUris(intptr_t loading_unit_id);
+
+// On Darwin systems, 'dlsym' adds an '_' to the beginning of the symbol name.
+// Use the '...CSymbol' definitions for resolving through 'dlsym'. The actual
+// symbol names in the objects are given by the '...AsmSymbol' definitions.
+#if defined(__APPLE__)
+#define kSnapshotBuildIdCSymbol "kDartSnapshotBuildId"
+#define kVmSnapshotDataCSymbol "kDartVmSnapshotData"
+#define kVmSnapshotInstructionsCSymbol "kDartVmSnapshotInstructions"
+#define kVmSnapshotBssCSymbol "kDartVmSnapshotBss"
+#define kIsolateSnapshotDataCSymbol "kDartIsolateSnapshotData"
+#define kIsolateSnapshotInstructionsCSymbol "kDartIsolateSnapshotInstructions"
+#define kIsolateSnapshotBssCSymbol "kDartIsolateSnapshotBss"
+#else
+#define kSnapshotBuildIdCSymbol "_kDartSnapshotBuildId"
+#define kVmSnapshotDataCSymbol "_kDartVmSnapshotData"
+#define kVmSnapshotInstructionsCSymbol "_kDartVmSnapshotInstructions"
+#define kVmSnapshotBssCSymbol "_kDartVmSnapshotBss"
+#define kIsolateSnapshotDataCSymbol "_kDartIsolateSnapshotData"
+#define kIsolateSnapshotInstructionsCSymbol "_kDartIsolateSnapshotInstructions"
+#define kIsolateSnapshotBssCSymbol "_kDartIsolateSnapshotBss"
+#endif
+
+#define kSnapshotBuildIdAsmSymbol "_kDartSnapshotBuildId"
+#define kVmSnapshotDataAsmSymbol "_kDartVmSnapshotData"
+#define kVmSnapshotInstructionsAsmSymbol "_kDartVmSnapshotInstructions"
+#define kVmSnapshotBssAsmSymbol "_kDartVmSnapshotBss"
+#define kIsolateSnapshotDataAsmSymbol "_kDartIsolateSnapshotData"
+#define kIsolateSnapshotInstructionsAsmSymbol \
+ "_kDartIsolateSnapshotInstructions"
+#define kIsolateSnapshotBssAsmSymbol "_kDartIsolateSnapshotBss"
+
+/**
+ * Creates a precompiled snapshot.
+ * - A root library must have been loaded.
+ * - Dart_Precompile must have been called.
+ *
+ * Outputs an assembly file defining the symbols listed in the definitions
+ * above.
+ *
+ * The assembly should be compiled as a static or shared library and linked or
+ * loaded by the embedder. Running this snapshot requires a VM compiled with
+ * DART_PRECOMPILED_SNAPSHOT. The kDartVmSnapshotData and
+ * kDartVmSnapshotInstructions should be passed to Dart_Initialize. The
+ * kDartIsolateSnapshotData and kDartIsolateSnapshotInstructions should be
+ * passed to Dart_CreateIsolateGroup.
+ *
+ * The callback will be invoked one or more times to provide the assembly code.
+ *
+ * If stripped is true, then the assembly code will not include DWARF
+ * debugging sections.
+ *
+ * If debug_callback_data is provided, debug_callback_data will be used with
+ * the callback to provide separate debugging information.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_CreateAppAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback,
+ void* callback_data,
+ bool stripped,
+ void* debug_callback_data);
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_CreateAppAOTSnapshotAsAssemblies(
+ Dart_CreateLoadingUnitCallback next_callback,
+ void* next_callback_data,
+ bool stripped,
+ Dart_StreamingWriteCallback write_callback,
+ Dart_StreamingCloseCallback close_callback);
+
+/**
+ * Creates a precompiled snapshot.
+ * - A root library must have been loaded.
+ * - Dart_Precompile must have been called.
+ *
+ * Outputs an ELF shared library defining the symbols
+ * - _kDartVmSnapshotData
+ * - _kDartVmSnapshotInstructions
+ * - _kDartIsolateSnapshotData
+ * - _kDartIsolateSnapshotInstructions
+ *
+ * The shared library should be dynamically loaded by the embedder.
+ * Running this snapshot requires a VM compiled with DART_PRECOMPILED_SNAPSHOT.
+ * The kDartVmSnapshotData and kDartVmSnapshotInstructions should be passed to
+ * Dart_Initialize. The kDartIsolateSnapshotData and
+ * kDartIsolateSnapshotInstructions should be passed to Dart_CreateIsolate.
+ *
+ * The callback will be invoked one or more times to provide the binary output.
+ *
+ * If stripped is true, then the binary output will not include DWARF
+ * debugging sections.
+ *
+ * If debug_callback_data is provided, debug_callback_data will be used with
+ * the callback to provide separate debugging information.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_CreateAppAOTSnapshotAsElf(Dart_StreamingWriteCallback callback,
+ void* callback_data,
+ bool stripped,
+ void* debug_callback_data);
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_CreateAppAOTSnapshotAsElfs(Dart_CreateLoadingUnitCallback next_callback,
+ void* next_callback_data,
+ bool stripped,
+ Dart_StreamingWriteCallback write_callback,
+ Dart_StreamingCloseCallback close_callback);
+
+/**
+ * Like Dart_CreateAppAOTSnapshotAsAssembly, but only includes
+ * kDartVmSnapshotData and kDartVmSnapshotInstructions. It also does
+ * not strip DWARF information from the generated assembly or allow for
+ * separate debug information.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_CreateVMAOTSnapshotAsAssembly(Dart_StreamingWriteCallback callback,
+ void* callback_data);
+
+/**
+ * Sorts the class-ids in depth first traversal order of the inheritance
+ * tree. This is a costly operation, but it can make method dispatch
+ * more efficient and is done before writing snapshots.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_SortClasses(void);
+
+/**
+ * Creates a snapshot that caches compiled code and type feedback for faster
+ * startup and quicker warmup in a subsequent process.
+ *
+ * Outputs a snapshot in two pieces. The pieces should be passed to
+ * Dart_CreateIsolateGroup in a VM using the same VM snapshot pieces used in the
+ * current VM. The instructions piece must be loaded with read and execute
+ * permissions; the data piece may be loaded as read-only.
+ *
+ * - Requires the VM to have not been started with --precompilation.
+ * - Not supported when targeting IA32.
+ * - The VM writing the snapshot and the VM reading the snapshot must be the
+ * same version, must be built in the same DEBUG/RELEASE/PRODUCT mode, must
+ * be targeting the same architecture, and must both be in checked mode or
+ * both in unchecked mode.
+ *
+ * The buffers are scope allocated and are only valid until the next call to
+ * Dart_ExitScope.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_CreateAppJITSnapshotAsBlobs(uint8_t** isolate_snapshot_data_buffer,
+ intptr_t* isolate_snapshot_data_size,
+ uint8_t** isolate_snapshot_instructions_buffer,
+ intptr_t* isolate_snapshot_instructions_size);
+
+/**
+ * Like Dart_CreateAppJITSnapshotAsBlobs, but also creates a new VM snapshot.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_CreateCoreJITSnapshotAsBlobs(
+ uint8_t** vm_snapshot_data_buffer,
+ intptr_t* vm_snapshot_data_size,
+ uint8_t** vm_snapshot_instructions_buffer,
+ intptr_t* vm_snapshot_instructions_size,
+ uint8_t** isolate_snapshot_data_buffer,
+ intptr_t* isolate_snapshot_data_size,
+ uint8_t** isolate_snapshot_instructions_buffer,
+ intptr_t* isolate_snapshot_instructions_size);
+
+/**
+ * Get obfuscation map for precompiled code.
+ *
+ * Obfuscation map is encoded as a JSON array of pairs (original name,
+ * obfuscated name).
+ *
+ * \return Returns an error handler if the VM was built in a mode that does not
+ * support obfuscation.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_GetObfuscationMap(uint8_t** buffer, intptr_t* buffer_length);
+
+/**
+ * Returns whether the VM only supports running from precompiled snapshots and
+ * not from any other kind of snapshot or from source (that is, the VM was
+ * compiled with DART_PRECOMPILED_RUNTIME).
+ */
+DART_EXPORT bool Dart_IsPrecompiledRuntime(void);
+
+/**
+ * Print a native stack trace. Used for crash handling.
+ *
+ * If context is NULL, prints the current stack trace. Otherwise, context
+ * should be a CONTEXT* (Windows) or ucontext_t* (POSIX) from a signal handler
+ * running on the current thread.
+ */
+DART_EXPORT void Dart_DumpNativeStackTrace(void* context);
+
+/**
+ * Indicate that the process is about to abort, and the Dart VM should not
+ * attempt to cleanup resources.
+ */
+DART_EXPORT void Dart_PrepareToAbort(void);
+
+/**
+ * Callback provided by the embedder that is used by the VM to
+ * produce footnotes appended to DWARF stack traces.
+ *
+ * Whenever VM formats a stack trace as a string it would call this callback
+ * passing raw program counters for each frame in the stack trace.
+ *
+ * Embedder can then return a string which if not-null will be appended to the
+ * formatted stack trace.
+ *
+ * Returned string is expected to be `malloc()` allocated. VM takes ownership
+ * of the returned string and will `free()` it.
+ *
+ * \param addresses raw program counter addresses for each frame
+ * \param count number of elements in the addresses array
+ */
+typedef char* (*Dart_DwarfStackTraceFootnoteCallback)(void* addresses[],
+ intptr_t count);
+
+/**
+ * Configure DWARF stack trace footnote callback.
+ */
+DART_EXPORT void Dart_SetDwarfStackTraceFootnoteCallback(
+ Dart_DwarfStackTraceFootnoteCallback callback);
+
+#endif /* INCLUDE_DART_API_H_ */ /* NOLINT */
diff --git a/pkgs/jni/src/include/dart_api_dl.c b/pkgs/jni/src/include/dart_api_dl.c
new file mode 100644
index 0000000..c4a68f4
--- /dev/null
+++ b/pkgs/jni/src/include/dart_api_dl.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+ * for details. All rights reserved. Use of this source code is governed by a
+ * BSD-style license that can be found in the LICENSE file.
+ */
+
+#include "dart_api_dl.h" /* NOLINT */
+#include "dart_version.h" /* NOLINT */
+#include "internal/dart_api_dl_impl.h" /* NOLINT */
+
+#include <string.h>
+
+#define DART_API_DL_DEFINITIONS(name, R, A) name##_Type name##_DL = NULL;
+
+DART_API_ALL_DL_SYMBOLS(DART_API_DL_DEFINITIONS)
+
+#undef DART_API_DL_DEFINITIONS
+
+typedef void* DartApiEntry_function;
+
+DartApiEntry_function FindFunctionPointer(const DartApiEntry* entries,
+ const char* name) {
+ while (entries->name != NULL) {
+ if (strcmp(entries->name, name) == 0) return entries->function;
+ entries++;
+ }
+ return NULL;
+}
+
+intptr_t Dart_InitializeApiDL(void* data) {
+ DartApi* dart_api_data = (DartApi*)data;
+
+ if (dart_api_data->major != DART_API_DL_MAJOR_VERSION) {
+ // If the DartVM we're running on does not have the same version as this
+ // file was compiled against, refuse to initialize. The symbols are not
+ // compatible.
+ return -1;
+ }
+ // Minor versions are allowed to be different.
+ // If the DartVM has a higher minor version, it will provide more symbols
+ // than we initialize here.
+ // If the DartVM has a lower minor version, it will not provide all symbols.
+ // In that case, we leave the missing symbols un-initialized. Those symbols
+ // should not be used by the Dart and native code. The client is responsible
+ // for checking the minor version number himself based on which symbols it
+ // is using.
+ // (If we would error out on this case, recompiling native code against a
+ // newer SDK would break all uses on older SDKs, which is too strict.)
+
+ const DartApiEntry* dart_api_function_pointers = dart_api_data->functions;
+
+#define DART_API_DL_INIT(name, R, A) \
+ name##_DL = \
+ (name##_Type)(FindFunctionPointer(dart_api_function_pointers, #name));
+ DART_API_ALL_DL_SYMBOLS(DART_API_DL_INIT)
+#undef DART_API_DL_INIT
+
+ return 0;
+}
diff --git a/pkgs/jni/src/include/dart_api_dl.h b/pkgs/jni/src/include/dart_api_dl.h
new file mode 100644
index 0000000..cce3450
--- /dev/null
+++ b/pkgs/jni/src/include/dart_api_dl.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+ * for details. All rights reserved. Use of this source code is governed by a
+ * BSD-style license that can be found in the LICENSE file.
+ */
+
+#ifndef RUNTIME_INCLUDE_DART_API_DL_H_
+#define RUNTIME_INCLUDE_DART_API_DL_H_
+
+#include "dart_api.h" /* NOLINT */
+#include "dart_native_api.h" /* NOLINT */
+
+/** \mainpage Dynamically Linked Dart API
+ *
+ * This exposes a subset of symbols from dart_api.h and dart_native_api.h
+ * available in every Dart embedder through dynamic linking.
+ *
+ * All symbols are postfixed with _DL to indicate that they are dynamically
+ * linked and to prevent conflicts with the original symbol.
+ *
+ * Link `dart_api_dl.c` file into your library and invoke
+ * `Dart_InitializeApiDL` with `NativeApi.initializeApiDLData`.
+ */
+
+DART_EXPORT intptr_t Dart_InitializeApiDL(void* data);
+
+// ============================================================================
+// IMPORTANT! Never update these signatures without properly updating
+// DART_API_DL_MAJOR_VERSION and DART_API_DL_MINOR_VERSION.
+//
+// Verbatim copy of `dart_native_api.h` and `dart_api.h` symbol names and types
+// to trigger compile-time errors if the symbols in those files are updated
+// without updating these.
+//
+// Function return and argument types, and typedefs are carbon copied. Structs
+// are typechecked nominally in C/C++, so they are not copied, instead a
+// comment is added to their definition.
+typedef int64_t Dart_Port_DL;
+
+typedef void (*Dart_NativeMessageHandler_DL)(Dart_Port_DL dest_port_id,
+ Dart_CObject* message);
+
+// dart_native_api.h symbols can be called on any thread.
+#define DART_NATIVE_API_DL_SYMBOLS(F) \
+ /***** dart_native_api.h *****/ \
+ /* Dart_Port */ \
+ F(Dart_PostCObject, bool, (Dart_Port_DL port_id, Dart_CObject * message)) \
+ F(Dart_PostInteger, bool, (Dart_Port_DL port_id, int64_t message)) \
+ F(Dart_NewNativePort, Dart_Port_DL, \
+ (const char* name, Dart_NativeMessageHandler_DL handler, \
+ bool handle_concurrently)) \
+ F(Dart_CloseNativePort, bool, (Dart_Port_DL native_port_id))
+
+// dart_api.h symbols can only be called on Dart threads.
+#define DART_API_DL_SYMBOLS(F) \
+ /***** dart_api.h *****/ \
+ /* Errors */ \
+ F(Dart_IsError, bool, (Dart_Handle handle)) \
+ F(Dart_IsApiError, bool, (Dart_Handle handle)) \
+ F(Dart_IsUnhandledExceptionError, bool, (Dart_Handle handle)) \
+ F(Dart_IsCompilationError, bool, (Dart_Handle handle)) \
+ F(Dart_IsFatalError, bool, (Dart_Handle handle)) \
+ F(Dart_GetError, const char*, (Dart_Handle handle)) \
+ F(Dart_ErrorHasException, bool, (Dart_Handle handle)) \
+ F(Dart_ErrorGetException, Dart_Handle, (Dart_Handle handle)) \
+ F(Dart_ErrorGetStackTrace, Dart_Handle, (Dart_Handle handle)) \
+ F(Dart_NewApiError, Dart_Handle, (const char* error)) \
+ F(Dart_NewCompilationError, Dart_Handle, (const char* error)) \
+ F(Dart_NewUnhandledExceptionError, Dart_Handle, (Dart_Handle exception)) \
+ F(Dart_PropagateError, void, (Dart_Handle handle)) \
+ /* Dart_Handle, Dart_PersistentHandle, Dart_WeakPersistentHandle */ \
+ F(Dart_HandleFromPersistent, Dart_Handle, (Dart_PersistentHandle object)) \
+ F(Dart_HandleFromWeakPersistent, Dart_Handle, \
+ (Dart_WeakPersistentHandle object)) \
+ F(Dart_NewPersistentHandle, Dart_PersistentHandle, (Dart_Handle object)) \
+ F(Dart_SetPersistentHandle, void, \
+ (Dart_PersistentHandle obj1, Dart_Handle obj2)) \
+ F(Dart_DeletePersistentHandle, void, (Dart_PersistentHandle object)) \
+ F(Dart_NewWeakPersistentHandle, Dart_WeakPersistentHandle, \
+ (Dart_Handle object, void* peer, intptr_t external_allocation_size, \
+ Dart_HandleFinalizer callback)) \
+ F(Dart_DeleteWeakPersistentHandle, void, (Dart_WeakPersistentHandle object)) \
+ F(Dart_UpdateExternalSize, void, \
+ (Dart_WeakPersistentHandle object, intptr_t external_allocation_size)) \
+ F(Dart_NewFinalizableHandle, Dart_FinalizableHandle, \
+ (Dart_Handle object, void* peer, intptr_t external_allocation_size, \
+ Dart_HandleFinalizer callback)) \
+ F(Dart_DeleteFinalizableHandle, void, \
+ (Dart_FinalizableHandle object, Dart_Handle strong_ref_to_object)) \
+ F(Dart_UpdateFinalizableExternalSize, void, \
+ (Dart_FinalizableHandle object, Dart_Handle strong_ref_to_object, \
+ intptr_t external_allocation_size)) \
+ /* Isolates */ \
+ F(Dart_CurrentIsolate, Dart_Isolate, (void)) \
+ F(Dart_ExitIsolate, void, (void)) \
+ F(Dart_EnterIsolate, void, (Dart_Isolate)) \
+ /* Dart_Port */ \
+ F(Dart_Post, bool, (Dart_Port_DL port_id, Dart_Handle object)) \
+ F(Dart_NewSendPort, Dart_Handle, (Dart_Port_DL port_id)) \
+ F(Dart_SendPortGetId, Dart_Handle, \
+ (Dart_Handle port, Dart_Port_DL * port_id)) \
+ /* Scopes */ \
+ F(Dart_EnterScope, void, (void)) \
+ F(Dart_ExitScope, void, (void)) \
+ /* Objects */ \
+ F(Dart_IsNull, bool, (Dart_Handle))
+
+#define DART_API_ALL_DL_SYMBOLS(F) \
+ DART_NATIVE_API_DL_SYMBOLS(F) \
+ DART_API_DL_SYMBOLS(F)
+// IMPORTANT! Never update these signatures without properly updating
+// DART_API_DL_MAJOR_VERSION and DART_API_DL_MINOR_VERSION.
+//
+// End of verbatim copy.
+// ============================================================================
+
+// Copy of definition of DART_EXPORT without 'used' attribute.
+//
+// The 'used' attribute cannot be used with DART_API_ALL_DL_SYMBOLS because
+// they are not function declarations, but variable declarations with a
+// function pointer type.
+//
+// The function pointer variables are initialized with the addresses of the
+// functions in the VM. If we were to use function declarations instead, we
+// would need to forward the call to the VM adding indirection.
+#if defined(__CYGWIN__)
+#error Tool chain and platform not supported.
+#elif defined(_WIN32)
+#if defined(DART_SHARED_LIB)
+#define DART_EXPORT_DL DART_EXTERN_C __declspec(dllexport)
+#else
+#define DART_EXPORT_DL DART_EXTERN_C
+#endif
+#else
+#if __GNUC__ >= 4
+#if defined(DART_SHARED_LIB)
+#define DART_EXPORT_DL DART_EXTERN_C __attribute__((visibility("default")))
+#else
+#define DART_EXPORT_DL DART_EXTERN_C
+#endif
+#else
+#error Tool chain not supported.
+#endif
+#endif
+
+#define DART_API_DL_DECLARATIONS(name, R, A) \
+ typedef R(*name##_Type) A; \
+ DART_EXPORT_DL name##_Type name##_DL;
+
+DART_API_ALL_DL_SYMBOLS(DART_API_DL_DECLARATIONS)
+
+#undef DART_API_DL_DECLARATIONS
+
+#undef DART_EXPORT_DL
+
+#endif /* RUNTIME_INCLUDE_DART_API_DL_H_ */ /* NOLINT */
diff --git a/pkgs/jni/src/include/dart_embedder_api.h b/pkgs/jni/src/include/dart_embedder_api.h
new file mode 100644
index 0000000..e565ebf
--- /dev/null
+++ b/pkgs/jni/src/include/dart_embedder_api.h
@@ -0,0 +1,108 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_INCLUDE_DART_EMBEDDER_API_H_
+#define RUNTIME_INCLUDE_DART_EMBEDDER_API_H_
+
+#include "include/dart_api.h"
+#include "include/dart_tools_api.h"
+
+namespace dart {
+namespace embedder {
+
+// Initialize all subsystems of the embedder.
+//
+// Must be called before the `Dart_Initialize()` call to initialize the
+// Dart VM.
+//
+// Returns true on success and false otherwise, in which case error would
+// contain error message.
+DART_WARN_UNUSED_RESULT bool InitOnce(char** error);
+
+// Cleans up all subsystems of the embedder.
+//
+// Must be called after the `Dart_Cleanup()` call to initialize the
+// Dart VM.
+void Cleanup();
+
+// Common arguments that are passed to isolate creation callback and to
+// API methods that create isolates.
+struct IsolateCreationData {
+ // URI for the main script that will be running in the isolate.
+ const char* script_uri;
+
+ // Advisory name of the main method that will be run by isolate.
+ // Only used for error messages.
+ const char* main;
+
+ // Isolate creation flags. Might be absent.
+ Dart_IsolateFlags* flags;
+
+ // Isolate group callback data.
+ void* isolate_group_data;
+
+ // Isolate callback data.
+ void* isolate_data;
+};
+
+// Create and initialize kernel-service isolate. This method should be used
+// when VM invokes isolate creation callback with DART_KERNEL_ISOLATE_NAME as
+// script_uri.
+// The isolate is created from the given snapshot (might be kernel data or
+// app-jit snapshot).
+DART_WARN_UNUSED_RESULT Dart_Isolate
+CreateKernelServiceIsolate(const IsolateCreationData& data,
+ const uint8_t* buffer,
+ intptr_t buffer_size,
+ char** error);
+
+// Service isolate configuration.
+struct VmServiceConfiguration {
+ enum {
+ kBindHttpServerToAFreePort = 0,
+ kDoNotAutoStartHttpServer = -1
+ };
+
+ // Address to which HTTP server will be bound.
+ const char* ip;
+
+ // Default port. See enum above for special values.
+ int port;
+
+ // If non-null, connection information for the VM service will be output to a
+ // file in JSON format at the location specified.
+ const char* write_service_info_filename;
+
+ // TODO(vegorov) document these ones.
+ bool dev_mode;
+ bool deterministic;
+ bool disable_auth_codes;
+};
+
+// Create and initialize vm-service isolate from the given AOT snapshot, which
+// is expected to contain all necessary 'vm-service' libraries.
+// This method should be used when VM invokes isolate creation callback with
+// DART_VM_SERVICE_ISOLATE_NAME as script_uri.
+DART_WARN_UNUSED_RESULT Dart_Isolate
+CreateVmServiceIsolate(const IsolateCreationData& data,
+ const VmServiceConfiguration& config,
+ const uint8_t* isolate_data,
+ const uint8_t* isolate_instr,
+ char** error);
+
+// Create and initialize vm-service isolate from the given kernel binary, which
+// is expected to contain all necessary 'vm-service' libraries.
+// This method should be used when VM invokes isolate creation callback with
+// DART_VM_SERVICE_ISOLATE_NAME as script_uri.
+DART_WARN_UNUSED_RESULT Dart_Isolate
+CreateVmServiceIsolateFromKernel(const IsolateCreationData& data,
+ const VmServiceConfiguration& config,
+ const uint8_t* kernel_buffer,
+ intptr_t kernel_buffer_size,
+ char** error);
+
+} // namespace embedder
+} // namespace dart
+
+#endif // RUNTIME_INCLUDE_DART_EMBEDDER_API_H_
diff --git a/pkgs/jni/src/include/dart_native_api.h b/pkgs/jni/src/include/dart_native_api.h
new file mode 100644
index 0000000..79194e0
--- /dev/null
+++ b/pkgs/jni/src/include/dart_native_api.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+ * for details. All rights reserved. Use of this source code is governed by a
+ * BSD-style license that can be found in the LICENSE file.
+ */
+
+#ifndef RUNTIME_INCLUDE_DART_NATIVE_API_H_
+#define RUNTIME_INCLUDE_DART_NATIVE_API_H_
+
+#include "dart_api.h" /* NOLINT */
+
+/*
+ * ==========================================
+ * Message sending/receiving from native code
+ * ==========================================
+ */
+
+/**
+ * A Dart_CObject is used for representing Dart objects as native C
+ * data outside the Dart heap. These objects are totally detached from
+ * the Dart heap. Only a subset of the Dart objects have a
+ * representation as a Dart_CObject.
+ *
+ * The string encoding in the 'value.as_string' is UTF-8.
+ *
+ * All the different types from dart:typed_data are exposed as type
+ * kTypedData. The specific type from dart:typed_data is in the type
+ * field of the as_typed_data structure. The length in the
+ * as_typed_data structure is always in bytes.
+ *
+ * The data for kTypedData is copied on message send and ownership remains with
+ * the caller. The ownership of data for kExternalTyped is passed to the VM on
+ * message send and returned when the VM invokes the
+ * Dart_HandleFinalizer callback; a non-NULL callback must be provided.
+ *
+ * Note that Dart_CObject_kNativePointer is intended for internal use by
+ * dart:io implementation and has no connection to dart:ffi Pointer class.
+ * It represents a pointer to a native resource of a known type.
+ * The receiving side will only see this pointer as an integer and will not
+ * see the specified finalizer.
+ * The specified finalizer will only be invoked if the message is not delivered.
+ */
+typedef enum {
+ Dart_CObject_kNull = 0,
+ Dart_CObject_kBool,
+ Dart_CObject_kInt32,
+ Dart_CObject_kInt64,
+ Dart_CObject_kDouble,
+ Dart_CObject_kString,
+ Dart_CObject_kArray,
+ Dart_CObject_kTypedData,
+ Dart_CObject_kExternalTypedData,
+ Dart_CObject_kSendPort,
+ Dart_CObject_kCapability,
+ Dart_CObject_kNativePointer,
+ Dart_CObject_kUnsupported,
+ Dart_CObject_kUnmodifiableExternalTypedData,
+ Dart_CObject_kNumberOfTypes
+} Dart_CObject_Type;
+// This enum is versioned by DART_API_DL_MAJOR_VERSION, only add at the end
+// and bump the DART_API_DL_MINOR_VERSION.
+
+typedef struct _Dart_CObject {
+ Dart_CObject_Type type;
+ union {
+ bool as_bool;
+ int32_t as_int32;
+ int64_t as_int64;
+ double as_double;
+ const char* as_string;
+ struct {
+ Dart_Port id;
+ Dart_Port origin_id;
+ } as_send_port;
+ struct {
+ int64_t id;
+ } as_capability;
+ struct {
+ intptr_t length;
+ struct _Dart_CObject** values;
+ } as_array;
+ struct {
+ Dart_TypedData_Type type;
+ intptr_t length; /* in elements, not bytes */
+ const uint8_t* values;
+ } as_typed_data;
+ struct {
+ Dart_TypedData_Type type;
+ intptr_t length; /* in elements, not bytes */
+ uint8_t* data;
+ void* peer;
+ Dart_HandleFinalizer callback;
+ } as_external_typed_data;
+ struct {
+ intptr_t ptr;
+ intptr_t size;
+ Dart_HandleFinalizer callback;
+ } as_native_pointer;
+ } value;
+} Dart_CObject;
+// This struct is versioned by DART_API_DL_MAJOR_VERSION, bump the version when
+// changing this struct.
+
+/**
+ * Posts a message on some port. The message will contain the Dart_CObject
+ * object graph rooted in 'message'.
+ *
+ * While the message is being sent the state of the graph of Dart_CObject
+ * structures rooted in 'message' should not be accessed, as the message
+ * generation will make temporary modifications to the data. When the message
+ * has been sent the graph will be fully restored.
+ *
+ * If true is returned, the message was enqueued, and finalizers for external
+ * typed data will eventually run, even if the receiving isolate shuts down
+ * before processing the message. If false is returned, the message was not
+ * enqueued and ownership of external typed data in the message remains with the
+ * caller.
+ *
+ * This function may be called on any thread when the VM is running (that is,
+ * after Dart_Initialize has returned and before Dart_Cleanup has been called).
+ *
+ * \param port_id The destination port.
+ * \param message The message to send.
+ *
+ * \return True if the message was posted.
+ */
+DART_EXPORT bool Dart_PostCObject(Dart_Port port_id, Dart_CObject* message);
+
+/**
+ * Posts a message on some port. The message will contain the integer 'message'.
+ *
+ * \param port_id The destination port.
+ * \param message The message to send.
+ *
+ * \return True if the message was posted.
+ */
+DART_EXPORT bool Dart_PostInteger(Dart_Port port_id, int64_t message);
+
+/**
+ * A native message handler.
+ *
+ * This handler is associated with a native port by calling
+ * Dart_NewNativePort.
+ *
+ * The message received is decoded into the message structure. The
+ * lifetime of the message data is controlled by the caller. All the
+ * data references from the message are allocated by the caller and
+ * will be reclaimed when returning to it.
+ */
+typedef void (*Dart_NativeMessageHandler)(Dart_Port dest_port_id,
+ Dart_CObject* message);
+
+/**
+ * Creates a new native port. When messages are received on this
+ * native port, then they will be dispatched to the provided native
+ * message handler.
+ *
+ * \param name The name of this port in debugging messages.
+ * \param handler The C handler to run when messages arrive on the port.
+ * \param handle_concurrently Is it okay to process requests on this
+ * native port concurrently?
+ *
+ * \return If successful, returns the port id for the native port. In
+ * case of error, returns ILLEGAL_PORT.
+ */
+DART_EXPORT Dart_Port Dart_NewNativePort(const char* name,
+ Dart_NativeMessageHandler handler,
+ bool handle_concurrently);
+/* TODO(turnidge): Currently handle_concurrently is ignored. */
+
+/**
+ * Closes the native port with the given id.
+ *
+ * The port must have been allocated by a call to Dart_NewNativePort.
+ *
+ * \param native_port_id The id of the native port to close.
+ *
+ * \return Returns true if the port was closed successfully.
+ */
+DART_EXPORT bool Dart_CloseNativePort(Dart_Port native_port_id);
+
+/*
+ * ==================
+ * Verification Tools
+ * ==================
+ */
+
+/**
+ * Forces all loaded classes and functions to be compiled eagerly in
+ * the current isolate..
+ *
+ * TODO(turnidge): Document.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_CompileAll(void);
+
+/**
+ * Finalizes all classes.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_FinalizeAllClasses(void);
+
+/* This function is intentionally undocumented.
+ *
+ * It should not be used outside internal tests.
+ */
+DART_EXPORT void* Dart_ExecuteInternalCommand(const char* command, void* arg);
+
+#endif /* INCLUDE_DART_NATIVE_API_H_ */ /* NOLINT */
diff --git a/pkgs/jni/src/include/dart_tools_api.h b/pkgs/jni/src/include/dart_tools_api.h
new file mode 100644
index 0000000..7b706bc
--- /dev/null
+++ b/pkgs/jni/src/include/dart_tools_api.h
@@ -0,0 +1,658 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_INCLUDE_DART_TOOLS_API_H_
+#define RUNTIME_INCLUDE_DART_TOOLS_API_H_
+
+#include "dart_api.h" /* NOLINT */
+
+/** \mainpage Dart Tools Embedding API Reference
+ *
+ * This reference describes the Dart embedding API for tools. Tools include
+ * a debugger, service protocol, and timeline.
+ *
+ * NOTE: The APIs described in this file are unstable and subject to change.
+ *
+ * This reference is generated from the header include/dart_tools_api.h.
+ */
+
+/*
+ * ========
+ * Debugger
+ * ========
+ */
+
+/**
+ * ILLEGAL_ISOLATE_ID is a number guaranteed never to be associated with a
+ * valid isolate.
+ */
+#define ILLEGAL_ISOLATE_ID ILLEGAL_PORT
+
+/**
+ * ILLEGAL_ISOLATE_GROUP_ID is a number guaranteed never to be associated with a
+ * valid isolate group.
+ */
+#define ILLEGAL_ISOLATE_GROUP_ID 0
+
+/*
+ * =======
+ * Service
+ * =======
+ */
+
+/**
+ * A service request callback function.
+ *
+ * These callbacks, registered by the embedder, are called when the VM receives
+ * a service request it can't handle and the service request command name
+ * matches one of the embedder registered handlers.
+ *
+ * The return value of the callback indicates whether the response
+ * should be used as a regular result or an error result.
+ * Specifically, if the callback returns true, a regular JSON-RPC
+ * response is built in the following way:
+ *
+ * {
+ * "jsonrpc": "2.0",
+ * "result": <json_object>,
+ * "id": <some sequence id>,
+ * }
+ *
+ * If the callback returns false, a JSON-RPC error is built like this:
+ *
+ * {
+ * "jsonrpc": "2.0",
+ * "error": <json_object>,
+ * "id": <some sequence id>,
+ * }
+ *
+ * \param method The rpc method name.
+ * \param param_keys Service requests can have key-value pair parameters. The
+ * keys and values are flattened and stored in arrays.
+ * \param param_values The values associated with the keys.
+ * \param num_params The length of the param_keys and param_values arrays.
+ * \param user_data The user_data pointer registered with this handler.
+ * \param result A C string containing a valid JSON object. The returned
+ * pointer will be freed by the VM by calling free.
+ *
+ * \return True if the result is a regular JSON-RPC response, false if the
+ * result is a JSON-RPC error.
+ */
+typedef bool (*Dart_ServiceRequestCallback)(const char* method,
+ const char** param_keys,
+ const char** param_values,
+ intptr_t num_params,
+ void* user_data,
+ const char** json_object);
+
+/**
+ * Register a Dart_ServiceRequestCallback to be called to handle
+ * requests for the named rpc on a specific isolate. The callback will
+ * be invoked with the current isolate set to the request target.
+ *
+ * \param method The name of the method that this callback is responsible for.
+ * \param callback The callback to invoke.
+ * \param user_data The user data passed to the callback.
+ *
+ * NOTE: If multiple callbacks with the same name are registered, only
+ * the last callback registered will be remembered.
+ */
+DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
+ const char* method,
+ Dart_ServiceRequestCallback callback,
+ void* user_data);
+
+/**
+ * Register a Dart_ServiceRequestCallback to be called to handle
+ * requests for the named rpc. The callback will be invoked without a
+ * current isolate.
+ *
+ * \param method The name of the command that this callback is responsible for.
+ * \param callback The callback to invoke.
+ * \param user_data The user data passed to the callback.
+ *
+ * NOTE: If multiple callbacks with the same name are registered, only
+ * the last callback registered will be remembered.
+ */
+DART_EXPORT void Dart_RegisterRootServiceRequestCallback(
+ const char* method,
+ Dart_ServiceRequestCallback callback,
+ void* user_data);
+
+/**
+ * Embedder information which can be requested by the VM for internal or
+ * reporting purposes.
+ *
+ * The pointers in this structure are not going to be cached or freed by the VM.
+ */
+
+ #define DART_EMBEDDER_INFORMATION_CURRENT_VERSION (0x00000001)
+
+typedef struct {
+ int32_t version;
+ const char* name; // [optional] The name of the embedder
+ int64_t current_rss; // [optional] the current RSS of the embedder
+ int64_t max_rss; // [optional] the maximum RSS of the embedder
+} Dart_EmbedderInformation;
+
+/**
+ * Callback provided by the embedder that is used by the VM to request
+ * information.
+ *
+ * \return Returns a pointer to a Dart_EmbedderInformation structure.
+ * The embedder keeps the ownership of the structure and any field in it.
+ * The embedder must ensure that the structure will remain valid until the
+ * next invocation of the callback.
+ */
+typedef void (*Dart_EmbedderInformationCallback)(
+ Dart_EmbedderInformation* info);
+
+/**
+ * Register a Dart_ServiceRequestCallback to be called to handle
+ * requests for the named rpc. The callback will be invoked without a
+ * current isolate.
+ *
+ * \param method The name of the command that this callback is responsible for.
+ * \param callback The callback to invoke.
+ * \param user_data The user data passed to the callback.
+ *
+ * NOTE: If multiple callbacks are registered, only the last callback registered
+ * will be remembered.
+ */
+DART_EXPORT void Dart_SetEmbedderInformationCallback(
+ Dart_EmbedderInformationCallback callback);
+
+/**
+ * Invoke a vm-service method and wait for its result.
+ *
+ * \param request_json The utf8-encoded json-rpc request.
+ * \param request_json_length The length of the json-rpc request.
+ *
+ * \param response_json The returned utf8-encoded json response, must be
+ * free()ed by caller.
+ * \param response_json_length The length of the returned json response.
+ * \param error An optional error, must be free()ed by caller.
+ *
+ * \return Whether the call was successfully performed.
+ *
+ * NOTE: This method does not need a current isolate and must not have the
+ * vm-isolate being the current isolate. It must be called after
+ * Dart_Initialize() and before Dart_Cleanup().
+ */
+DART_EXPORT bool Dart_InvokeVMServiceMethod(uint8_t* request_json,
+ intptr_t request_json_length,
+ uint8_t** response_json,
+ intptr_t* response_json_length,
+ char** error);
+
+/*
+ * ========
+ * Event Streams
+ * ========
+ */
+
+/**
+ * A callback invoked when the VM service gets a request to listen to
+ * some stream.
+ *
+ * \return Returns true iff the embedder supports the named stream id.
+ */
+typedef bool (*Dart_ServiceStreamListenCallback)(const char* stream_id);
+
+/**
+ * A callback invoked when the VM service gets a request to cancel
+ * some stream.
+ */
+typedef void (*Dart_ServiceStreamCancelCallback)(const char* stream_id);
+
+/**
+ * Adds VM service stream callbacks.
+ *
+ * \param listen_callback A function pointer to a listen callback function.
+ * A listen callback function should not be already set when this function
+ * is called. A NULL value removes the existing listen callback function
+ * if any.
+ *
+ * \param cancel_callback A function pointer to a cancel callback function.
+ * A cancel callback function should not be already set when this function
+ * is called. A NULL value removes the existing cancel callback function
+ * if any.
+ *
+ * \return Success if the callbacks were added. Otherwise, returns an
+ * error handle.
+ */
+DART_EXPORT char* Dart_SetServiceStreamCallbacks(
+ Dart_ServiceStreamListenCallback listen_callback,
+ Dart_ServiceStreamCancelCallback cancel_callback);
+
+/**
+ * Sends a data event to clients of the VM Service.
+ *
+ * A data event is used to pass an array of bytes to subscribed VM
+ * Service clients. For example, in the standalone embedder, this is
+ * function used to provide WriteEvents on the Stdout and Stderr
+ * streams.
+ *
+ * If the embedder passes in a stream id for which no client is
+ * subscribed, then the event is ignored.
+ *
+ * \param stream_id The id of the stream on which to post the event.
+ *
+ * \param event_kind A string identifying what kind of event this is.
+ * For example, 'WriteEvent'.
+ *
+ * \param bytes A pointer to an array of bytes.
+ *
+ * \param bytes_length The length of the byte array.
+ *
+ * \return NULL if the arguments are well formed. Otherwise, returns an
+ * error string. The caller is responsible for freeing the error message.
+ */
+DART_EXPORT char* Dart_ServiceSendDataEvent(const char* stream_id,
+ const char* event_kind,
+ const uint8_t* bytes,
+ intptr_t bytes_length);
+
+/*
+ * ========
+ * Reload support
+ * ========
+ *
+ * These functions are used to implement reloading in the Dart VM.
+ * This is an experimental feature, so embedders should be prepared
+ * for these functions to change.
+ */
+
+/**
+ * A callback which determines whether the file at some url has been
+ * modified since some time. If the file cannot be found, true should
+ * be returned.
+ */
+typedef bool (*Dart_FileModifiedCallback)(const char* url, int64_t since);
+
+DART_EXPORT char* Dart_SetFileModifiedCallback(
+ Dart_FileModifiedCallback file_modified_callback);
+
+/**
+ * Returns true if isolate is currently reloading.
+ */
+DART_EXPORT bool Dart_IsReloading();
+
+/*
+ * ========
+ * Timeline
+ * ========
+ */
+
+/**
+ * Enable tracking of specified timeline category. This is operational
+ * only when systrace timeline functionality is turned on.
+ *
+ * \param categories A comma separated list of categories that need to
+ * be enabled, the categories are
+ * "all" : All categories
+ * "API" - Execution of Dart C API functions
+ * "Compiler" - Execution of Dart JIT compiler
+ * "CompilerVerbose" - More detailed Execution of Dart JIT compiler
+ * "Dart" - Execution of Dart code
+ * "Debugger" - Execution of Dart debugger
+ * "Embedder" - Execution of Dart embedder code
+ * "GC" - Execution of Dart Garbage Collector
+ * "Isolate" - Dart Isolate lifecycle execution
+ * "VM" - Execution in Dart VM runtime code
+ * "" - None
+ *
+ * When "all" is specified all the categories are enabled.
+ * When a comma separated list of categories is specified, the categories
+ * that are specified will be enabled and the rest will be disabled.
+ * When "" is specified all the categories are disabled.
+ * The category names are case sensitive.
+ * eg: Dart_EnableTimelineCategory("all");
+ * Dart_EnableTimelineCategory("GC,API,Isolate");
+ * Dart_EnableTimelineCategory("GC,Debugger,Dart");
+ *
+ * \return True if the categories were successfully enabled, False otherwise.
+ */
+DART_EXPORT bool Dart_SetEnabledTimelineCategory(const char* categories);
+
+/**
+ * Returns a timestamp in microseconds. This timestamp is suitable for
+ * passing into the timeline system, and uses the same monotonic clock
+ * as dart:developer's Timeline.now.
+ *
+ * \return A timestamp that can be passed to the timeline system.
+ */
+DART_EXPORT int64_t Dart_TimelineGetMicros();
+
+/**
+ * Returns a raw timestamp in from the monotonic clock.
+ *
+ * \return A raw timestamp from the monotonic clock.
+ */
+DART_EXPORT int64_t Dart_TimelineGetTicks();
+
+/**
+ * Returns the frequency of the monotonic clock.
+ *
+ * \return The frequency of the monotonic clock.
+ */
+DART_EXPORT int64_t Dart_TimelineGetTicksFrequency();
+
+typedef enum {
+ Dart_Timeline_Event_Begin, // Phase = 'B'.
+ Dart_Timeline_Event_End, // Phase = 'E'.
+ Dart_Timeline_Event_Instant, // Phase = 'i'.
+ Dart_Timeline_Event_Duration, // Phase = 'X'.
+ Dart_Timeline_Event_Async_Begin, // Phase = 'b'.
+ Dart_Timeline_Event_Async_End, // Phase = 'e'.
+ Dart_Timeline_Event_Async_Instant, // Phase = 'n'.
+ Dart_Timeline_Event_Counter, // Phase = 'C'.
+ Dart_Timeline_Event_Flow_Begin, // Phase = 's'.
+ Dart_Timeline_Event_Flow_Step, // Phase = 't'.
+ Dart_Timeline_Event_Flow_End, // Phase = 'f'.
+} Dart_Timeline_Event_Type;
+
+/**
+ * Add a timeline event to the embedder stream.
+ *
+ * DEPRECATED: this function will be removed in Dart SDK v3.2.
+ *
+ * \param label The name of the event. Its lifetime must extend at least until
+ * Dart_Cleanup.
+ * \param timestamp0 The first timestamp of the event.
+ * \param timestamp1_or_id When reporting an event of type
+ * |Dart_Timeline_Event_Duration|, the second (end) timestamp of the event
+ * should be passed through |timestamp1_or_id|. When reporting an event of
+ * type |Dart_Timeline_Event_Async_Begin|, |Dart_Timeline_Event_Async_End|,
+ * or |Dart_Timeline_Event_Async_Instant|, the async ID associated with the
+ * event should be passed through |timestamp1_or_id|. When reporting an
+ * event of type |Dart_Timeline_Event_Flow_Begin|,
+ * |Dart_Timeline_Event_Flow_Step|, or |Dart_Timeline_Event_Flow_End|, the
+ * flow ID associated with the event should be passed through
+ * |timestamp1_or_id|. When reporting an event of type
+ * |Dart_Timeline_Event_Begin| or |Dart_Timeline_Event_End|, the event ID
+ * associated with the event should be passed through |timestamp1_or_id|.
+ * Note that this event ID will only be used by the MacOS recorder. The
+ * argument to |timestamp1_or_id| will not be used when reporting events of
+ * other types.
+ * \param argument_count The number of argument names and values.
+ * \param argument_names An array of names of the arguments. The lifetime of the
+ * names must extend at least until Dart_Cleanup. The array may be reclaimed
+ * when this call returns.
+ * \param argument_values An array of values of the arguments. The values and
+ * the array may be reclaimed when this call returns.
+ */
+DART_EXPORT void Dart_TimelineEvent(const char* label,
+ int64_t timestamp0,
+ int64_t timestamp1_or_id,
+ Dart_Timeline_Event_Type type,
+ intptr_t argument_count,
+ const char** argument_names,
+ const char** argument_values);
+
+/**
+ * Add a timeline event to the embedder stream.
+ *
+ * Note regarding flow events: events must be associated with flow IDs in two
+ * different ways to allow flow events to be serialized correctly in both
+ * Chrome's JSON trace event format and Perfetto's proto trace format. Events
+ * of type |Dart_Timeline_Event_Flow_Begin|, |Dart_Timeline_Event_Flow_Step|,
+ * and |Dart_Timeline_Event_Flow_End| must be reported to support serialization
+ * in Chrome's trace format. The |flow_ids| argument must be supplied when
+ * reporting events of type |Dart_Timeline_Event_Begin|,
+ * |Dart_Timeline_Event_Duration|, |Dart_Timeline_Event_Instant|,
+ * |Dart_Timeline_Event_Async_Begin|, and |Dart_Timeline_Event_Async_Instant| to
+ * support serialization in Perfetto's proto format.
+ *
+ * \param label The name of the event. Its lifetime must extend at least until
+ * Dart_Cleanup.
+ * \param timestamp0 The first timestamp of the event.
+ * \param timestamp1_or_id When reporting an event of type
+ * |Dart_Timeline_Event_Duration|, the second (end) timestamp of the event
+ * should be passed through |timestamp1_or_id|. When reporting an event of
+ * type |Dart_Timeline_Event_Async_Begin|, |Dart_Timeline_Event_Async_End|,
+ * or |Dart_Timeline_Event_Async_Instant|, the async ID associated with the
+ * event should be passed through |timestamp1_or_id|. When reporting an
+ * event of type |Dart_Timeline_Event_Flow_Begin|,
+ * |Dart_Timeline_Event_Flow_Step|, or |Dart_Timeline_Event_Flow_End|, the
+ * flow ID associated with the event should be passed through
+ * |timestamp1_or_id|. When reporting an event of type
+ * |Dart_Timeline_Event_Begin| or |Dart_Timeline_Event_End|, the event ID
+ * associated with the event should be passed through |timestamp1_or_id|.
+ * Note that this event ID will only be used by the MacOS recorder. The
+ * argument to |timestamp1_or_id| will not be used when reporting events of
+ * other types.
+ * \param flow_id_count The number of flow IDs associated with this event.
+ * \param flow_ids An array of flow IDs associated with this event. The array
+ * may be reclaimed when this call returns.
+ * \param argument_count The number of argument names and values.
+ * \param argument_names An array of names of the arguments. The lifetime of the
+ * names must extend at least until Dart_Cleanup. The array may be reclaimed
+ * when this call returns.
+ * \param argument_values An array of values of the arguments. The values and
+ * the array may be reclaimed when this call returns.
+ */
+DART_EXPORT void Dart_RecordTimelineEvent(const char* label,
+ int64_t timestamp0,
+ int64_t timestamp1_or_id,
+ intptr_t flow_id_count,
+ const int64_t* flow_ids,
+ Dart_Timeline_Event_Type type,
+ intptr_t argument_count,
+ const char** argument_names,
+ const char** argument_values);
+
+/**
+ * Associates a name with the current thread. This name will be used to name
+ * threads in the timeline. Can only be called after a call to Dart_Initialize.
+ *
+ * \param name The name of the thread.
+ */
+DART_EXPORT void Dart_SetThreadName(const char* name);
+
+typedef struct {
+ const char* name;
+ const char* value;
+} Dart_TimelineRecorderEvent_Argument;
+
+#define DART_TIMELINE_RECORDER_CURRENT_VERSION (0x00000002)
+
+typedef struct {
+ /* Set to DART_TIMELINE_RECORDER_CURRENT_VERSION */
+ int32_t version;
+
+ /* The event's type / phase. */
+ Dart_Timeline_Event_Type type;
+
+ /* The event's timestamp according to the same clock as
+ * Dart_TimelineGetMicros. For a duration event, this is the beginning time.
+ */
+ int64_t timestamp0;
+
+ /**
+ * For a duration event, this is the end time. For an async event, this is the
+ * async ID. For a flow event, this is the flow ID. For a begin or end event,
+ * this is the event ID (which is only referenced by the MacOS recorder).
+ */
+ int64_t timestamp1_or_id;
+
+ /* The current isolate of the event, as if by Dart_GetMainPortId, or
+ * ILLEGAL_PORT if the event had no current isolate. */
+ Dart_Port isolate;
+
+ /* The current isolate group of the event, as if by
+ * Dart_CurrentIsolateGroupId, or ILLEGAL_PORT if the event had no current
+ * isolate group. */
+ Dart_IsolateGroupId isolate_group;
+
+ /* The callback data associated with the isolate if any. */
+ void* isolate_data;
+
+ /* The callback data associated with the isolate group if any. */
+ void* isolate_group_data;
+
+ /* The name / label of the event. */
+ const char* label;
+
+ /* The stream / category of the event. */
+ const char* stream;
+
+ intptr_t argument_count;
+ Dart_TimelineRecorderEvent_Argument* arguments;
+} Dart_TimelineRecorderEvent;
+
+/**
+ * Callback provided by the embedder to handle the completion of timeline
+ * events.
+ *
+ * \param event A timeline event that has just been completed. The VM keeps
+ * ownership of the event and any field in it (i.e., the embedder should copy
+ * any values it needs after the callback returns).
+ */
+typedef void (*Dart_TimelineRecorderCallback)(
+ Dart_TimelineRecorderEvent* event);
+
+/**
+ * Register a `Dart_TimelineRecorderCallback` to be called as timeline events
+ * are completed.
+ *
+ * The callback will be invoked without a current isolate.
+ *
+ * The callback will be invoked on the thread completing the event. Because
+ * `Dart_TimelineEvent` may be called by any thread, the callback may be called
+ * on any thread.
+ *
+ * The callback may be invoked at any time after `Dart_Initialize` is called and
+ * before `Dart_Cleanup` returns.
+ *
+ * If multiple callbacks are registered, only the last callback registered
+ * will be remembered. Providing a NULL callback will clear the registration
+ * (i.e., a NULL callback produced a no-op instead of a crash).
+ *
+ * Setting a callback is insufficient to receive events through the callback. The
+ * VM flag `timeline_recorder` must also be set to `callback`.
+ */
+DART_EXPORT void Dart_SetTimelineRecorderCallback(
+ Dart_TimelineRecorderCallback callback);
+
+/*
+ * =======
+ * Metrics
+ * =======
+ */
+
+/**
+ * Return metrics gathered for the VM and individual isolates.
+ */
+DART_EXPORT int64_t
+Dart_IsolateGroupHeapOldUsedMetric(Dart_IsolateGroup group); // Byte
+DART_EXPORT int64_t
+Dart_IsolateGroupHeapOldCapacityMetric(Dart_IsolateGroup group); // Byte
+DART_EXPORT int64_t
+Dart_IsolateGroupHeapOldExternalMetric(Dart_IsolateGroup group); // Byte
+DART_EXPORT int64_t
+Dart_IsolateGroupHeapNewUsedMetric(Dart_IsolateGroup group); // Byte
+DART_EXPORT int64_t
+Dart_IsolateGroupHeapNewCapacityMetric(Dart_IsolateGroup group); // Byte
+DART_EXPORT int64_t
+Dart_IsolateGroupHeapNewExternalMetric(Dart_IsolateGroup group); // Byte
+
+/*
+ * ========
+ * UserTags
+ * ========
+ */
+
+/*
+ * Gets the current isolate's currently set UserTag instance.
+ *
+ * \return The currently set UserTag instance.
+ */
+DART_EXPORT Dart_Handle Dart_GetCurrentUserTag();
+
+/*
+ * Gets the current isolate's default UserTag instance.
+ *
+ * \return The default UserTag with label 'Default'
+ */
+DART_EXPORT Dart_Handle Dart_GetDefaultUserTag();
+
+/*
+ * Creates a new UserTag instance.
+ *
+ * \param label The name of the new UserTag.
+ *
+ * \return The newly created UserTag instance or an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_NewUserTag(const char* label);
+
+/*
+ * Updates the current isolate's UserTag to a new value.
+ *
+ * \param user_tag The UserTag to be set as the current UserTag.
+ *
+ * \return The previously set UserTag instance or an error handle.
+ */
+DART_EXPORT Dart_Handle Dart_SetCurrentUserTag(Dart_Handle user_tag);
+
+/*
+ * Returns the label of a given UserTag instance.
+ *
+ * \param user_tag The UserTag from which the label will be retrieved.
+ *
+ * \return The UserTag's label. NULL if the user_tag is invalid. The caller is
+ * responsible for freeing the returned label.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT char* Dart_GetUserTagLabel(
+ Dart_Handle user_tag);
+
+/*
+ * =======
+ * Heap Snapshot
+ * =======
+ */
+
+/**
+ * Callback provided by the caller of `Dart_WriteHeapSnapshot` which is
+ * used to write out chunks of the requested heap snapshot.
+ *
+ * \param context An opaque context which was passed to `Dart_WriteHeapSnapshot`
+ * together with this callback.
+ *
+ * \param buffer Pointer to the buffer containing a chunk of the snapshot.
+ * The callback owns the buffer and needs to `free` it.
+ *
+ * \param size Number of bytes in the `buffer` to be written.
+ *
+ * \param is_last Set to `true` for the last chunk. The callback will not
+ * be invoked again after it was invoked once with `is_last` set to `true`.
+ */
+typedef void (*Dart_HeapSnapshotWriteChunkCallback)(void* context,
+ uint8_t* buffer,
+ intptr_t size,
+ bool is_last);
+
+/**
+ * Generate heap snapshot of the current isolate group and stream it into the
+ * given `callback`. VM would produce snapshot in chunks and send these chunks
+ * one by one back to the embedder by invoking the provided `callback`.
+ *
+ * This API enables embedder to stream snapshot into a file or socket without
+ * allocating a buffer to hold the whole snapshot in memory.
+ *
+ * The isolate group will be paused for the duration of this operation.
+ *
+ * \param write Callback used to write chunks of the heap snapshot.
+ *
+ * \param context Opaque context which would be passed on each invocation of
+ * `write` callback.
+ *
+ * \returns `nullptr` if the operation is successful otherwise error message.
+ * Caller owns error message string and needs to `free` it.
+ */
+DART_EXPORT char* Dart_WriteHeapSnapshot(
+ Dart_HeapSnapshotWriteChunkCallback write,
+ void* context);
+
+#endif // RUNTIME_INCLUDE_DART_TOOLS_API_H_
diff --git a/pkgs/jni/src/include/dart_version.h b/pkgs/jni/src/include/dart_version.h
new file mode 100644
index 0000000..e2d3651
--- /dev/null
+++ b/pkgs/jni/src/include/dart_version.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+ * for details. All rights reserved. Use of this source code is governed by a
+ * BSD-style license that can be found in the LICENSE file.
+ */
+
+#ifndef RUNTIME_INCLUDE_DART_VERSION_H_
+#define RUNTIME_INCLUDE_DART_VERSION_H_
+
+// On breaking changes the major version is increased.
+// On backwards compatible changes the minor version is increased.
+// The versioning covers the symbols exposed in dart_api_dl.h
+#define DART_API_DL_MAJOR_VERSION 2
+#define DART_API_DL_MINOR_VERSION 3
+
+#endif /* RUNTIME_INCLUDE_DART_VERSION_H_ */ /* NOLINT */
diff --git a/pkgs/jni/src/include/internal/dart_api_dl_impl.h b/pkgs/jni/src/include/internal/dart_api_dl_impl.h
new file mode 100644
index 0000000..e4a5689
--- /dev/null
+++ b/pkgs/jni/src/include/internal/dart_api_dl_impl.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+ * for details. All rights reserved. Use of this source code is governed by a
+ * BSD-style license that can be found in the LICENSE file.
+ */
+
+#ifndef RUNTIME_INCLUDE_INTERNAL_DART_API_DL_IMPL_H_
+#define RUNTIME_INCLUDE_INTERNAL_DART_API_DL_IMPL_H_
+
+typedef struct {
+ const char* name;
+ void (*function)(void);
+} DartApiEntry;
+
+typedef struct {
+ const int major;
+ const int minor;
+ const DartApiEntry* const functions;
+} DartApi;
+
+#endif /* RUNTIME_INCLUDE_INTERNAL_DART_API_DL_IMPL_H_ */ /* NOLINT */
diff --git a/pkgs/jni/src/jni_constants.h b/pkgs/jni/src/jni_constants.h
new file mode 100644
index 0000000..8423ca1
--- /dev/null
+++ b/pkgs/jni/src/jni_constants.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This file re-exports some JNI constants as enum, because they are not
+// currently being included when they are in macro form.
+
+enum JniBooleanValues { JNI_FALSE = 0, JNI_TRUE = 1 };
+
+enum JniVersions {
+ JNI_VERSION_1_1 = 0x00010001,
+ JNI_VERSION_1_2 = 0x00010002,
+ JNI_VERSION_1_4 = 0x00010004,
+ JNI_VERSION_1_6 = 0x00010006,
+};
+
+enum JniErrorCode {
+ // Error codes from JNI
+ JNI_OK = 0, /* no error */
+ JNI_ERR = -1, /* generic error */
+ JNI_EDETACHED = -2, /* thread detached from the VM */
+ JNI_EVERSION = -3, /* JNI version error */
+ JNI_ENOMEM = -4, /* Out of memory */
+ JNI_EEXIST = -5, /* VM already created */
+ JNI_EINVAL = -6, /* Invalid argument */
+};
+
+enum JniBufferWriteBack {
+ JNI_COMMIT = 1, /* copy content, do not free buffer */
+ JNI_ABORT = 2, /* free buffer w/o copying back */
+};
diff --git a/pkgs/jni/src/third_party/global_jni_env.c b/pkgs/jni/src/third_party/global_jni_env.c
new file mode 100644
index 0000000..7ddc164
--- /dev/null
+++ b/pkgs/jni/src/third_party/global_jni_env.c
@@ -0,0 +1,2509 @@
+// Auto generated file. Do not edit.
+
+// This is generated from JNI header in Android NDK. License for the same is
+// provided below.
+
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * JNI specification, as defined by Sun:
+ * http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html
+ *
+ * Everything here is expected to be VM-neutral.
+ */
+
+#include "global_jni_env.h"
+
+JniResult globalEnv_GetVersion() {
+ attach_thread();
+ jint _result = (*jniEnv)->GetVersion(jniEnv);
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniClassLookupResult globalEnv_DefineClass(char* name,
+ jobject loader,
+ jbyte* buf,
+ jsize bufLen) {
+ attach_thread();
+ jclass _result = (*jniEnv)->DefineClass(jniEnv, name, loader, buf, bufLen);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniClassLookupResult){.value = NULL, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniClassLookupResult){.value = _result, .exception = NULL};
+}
+
+JniClassLookupResult globalEnv_FindClass(char* name) {
+ attach_thread();
+ jclass _result = (*jniEnv)->FindClass(jniEnv, name);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniClassLookupResult){.value = NULL, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniClassLookupResult){.value = _result, .exception = NULL};
+}
+
+JniPointerResult globalEnv_FromReflectedMethod(jobject method) {
+ attach_thread();
+ jmethodID _result = (*jniEnv)->FromReflectedMethod(jniEnv, method);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+JniPointerResult globalEnv_FromReflectedField(jobject field) {
+ attach_thread();
+ jfieldID _result = (*jniEnv)->FromReflectedField(jniEnv, field);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+JniResult globalEnv_ToReflectedMethod(jclass cls,
+ jmethodID methodId,
+ jboolean isStatic) {
+ attach_thread();
+ jobject _result =
+ (*jniEnv)->ToReflectedMethod(jniEnv, cls, methodId, isStatic);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniClassLookupResult globalEnv_GetSuperclass(jclass clazz) {
+ attach_thread();
+ jclass _result = (*jniEnv)->GetSuperclass(jniEnv, clazz);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniClassLookupResult){.value = NULL, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniClassLookupResult){.value = _result, .exception = NULL};
+}
+
+JniResult globalEnv_IsAssignableFrom(jclass clazz1, jclass clazz2) {
+ attach_thread();
+ jboolean _result = (*jniEnv)->IsAssignableFrom(jniEnv, clazz1, clazz2);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.z = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_ToReflectedField(jclass cls,
+ jfieldID fieldID,
+ jboolean isStatic) {
+ attach_thread();
+ jobject _result = (*jniEnv)->ToReflectedField(jniEnv, cls, fieldID, isStatic);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_Throw(jthrowable obj) {
+ attach_thread();
+ jint _result = (*jniEnv)->Throw(jniEnv, obj);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_ThrowNew(jclass clazz, char* message) {
+ attach_thread();
+ jint _result = (*jniEnv)->ThrowNew(jniEnv, clazz, message);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_ExceptionOccurred() {
+ attach_thread();
+ jthrowable _result = (*jniEnv)->ExceptionOccurred(jniEnv);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+jthrowable globalEnv_ExceptionDescribe() {
+ attach_thread();
+ (*jniEnv)->ExceptionDescribe(jniEnv);
+ return NULL;
+}
+
+jthrowable globalEnv_ExceptionClear() {
+ attach_thread();
+ (*jniEnv)->ExceptionClear(jniEnv);
+ return NULL;
+}
+
+jthrowable globalEnv_FatalError(char* msg) {
+ attach_thread();
+ (*jniEnv)->FatalError(jniEnv, msg);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+JniResult globalEnv_PushLocalFrame(jint capacity) {
+ attach_thread();
+ jint _result = (*jniEnv)->PushLocalFrame(jniEnv, capacity);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_PopLocalFrame(jobject result) {
+ attach_thread();
+ jobject _result = (*jniEnv)->PopLocalFrame(jniEnv, result);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_NewGlobalRef(jobject obj) {
+ attach_thread();
+ jobject _result = (*jniEnv)->NewGlobalRef(jniEnv, obj);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+jthrowable globalEnv_DeleteGlobalRef(jobject globalRef) {
+ attach_thread();
+ (*jniEnv)->DeleteGlobalRef(jniEnv, globalRef);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_DeleteLocalRef(jobject localRef) {
+ attach_thread();
+ (*jniEnv)->DeleteLocalRef(jniEnv, localRef);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+JniResult globalEnv_IsSameObject(jobject ref1, jobject ref2) {
+ attach_thread();
+ jboolean _result = (*jniEnv)->IsSameObject(jniEnv, ref1, ref2);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.z = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_NewLocalRef(jobject obj) {
+ attach_thread();
+ jobject _result = (*jniEnv)->NewLocalRef(jniEnv, obj);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_EnsureLocalCapacity(jint capacity) {
+ attach_thread();
+ jint _result = (*jniEnv)->EnsureLocalCapacity(jniEnv, capacity);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_AllocObject(jclass clazz) {
+ attach_thread();
+ jobject _result = (*jniEnv)->AllocObject(jniEnv, clazz);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_NewObject(jclass clazz, jmethodID methodID) {
+ attach_thread();
+ jobject _result = (*jniEnv)->NewObject(jniEnv, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_NewObjectA(jclass clazz, jmethodID methodID, jvalue* args) {
+ attach_thread();
+ jobject _result = (*jniEnv)->NewObjectA(jniEnv, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniClassLookupResult globalEnv_GetObjectClass(jobject obj) {
+ attach_thread();
+ jclass _result = (*jniEnv)->GetObjectClass(jniEnv, obj);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniClassLookupResult){.value = NULL, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniClassLookupResult){.value = _result, .exception = NULL};
+}
+
+JniResult globalEnv_IsInstanceOf(jobject obj, jclass clazz) {
+ attach_thread();
+ jboolean _result = (*jniEnv)->IsInstanceOf(jniEnv, obj, clazz);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.z = _result}, .exception = NULL};
+}
+
+JniPointerResult globalEnv_GetMethodID(jclass clazz, char* name, char* sig) {
+ attach_thread();
+ jmethodID _result = (*jniEnv)->GetMethodID(jniEnv, clazz, name, sig);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+JniResult globalEnv_CallObjectMethod(jobject obj, jmethodID methodID) {
+ attach_thread();
+ jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, obj, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallObjectMethodA(jobject obj,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jobject _result = (*jniEnv)->CallObjectMethodA(jniEnv, obj, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallBooleanMethod(jobject obj, jmethodID methodID) {
+ attach_thread();
+ jboolean _result = (*jniEnv)->CallBooleanMethod(jniEnv, obj, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.z = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallBooleanMethodA(jobject obj,
+ jmethodID methodId,
+ jvalue* args) {
+ attach_thread();
+ jboolean _result = (*jniEnv)->CallBooleanMethodA(jniEnv, obj, methodId, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.z = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallByteMethod(jobject obj, jmethodID methodID) {
+ attach_thread();
+ jbyte _result = (*jniEnv)->CallByteMethod(jniEnv, obj, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.b = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallByteMethodA(jobject obj,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jbyte _result = (*jniEnv)->CallByteMethodA(jniEnv, obj, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.b = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallCharMethod(jobject obj, jmethodID methodID) {
+ attach_thread();
+ jchar _result = (*jniEnv)->CallCharMethod(jniEnv, obj, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.c = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallCharMethodA(jobject obj,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jchar _result = (*jniEnv)->CallCharMethodA(jniEnv, obj, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.c = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallShortMethod(jobject obj, jmethodID methodID) {
+ attach_thread();
+ jshort _result = (*jniEnv)->CallShortMethod(jniEnv, obj, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.s = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallShortMethodA(jobject obj,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jshort _result = (*jniEnv)->CallShortMethodA(jniEnv, obj, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.s = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallIntMethod(jobject obj, jmethodID methodID) {
+ attach_thread();
+ jint _result = (*jniEnv)->CallIntMethod(jniEnv, obj, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallIntMethodA(jobject obj,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jint _result = (*jniEnv)->CallIntMethodA(jniEnv, obj, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallLongMethod(jobject obj, jmethodID methodID) {
+ attach_thread();
+ jlong _result = (*jniEnv)->CallLongMethod(jniEnv, obj, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.j = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallLongMethodA(jobject obj,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jlong _result = (*jniEnv)->CallLongMethodA(jniEnv, obj, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.j = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallFloatMethod(jobject obj, jmethodID methodID) {
+ attach_thread();
+ jfloat _result = (*jniEnv)->CallFloatMethod(jniEnv, obj, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.f = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallFloatMethodA(jobject obj,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jfloat _result = (*jniEnv)->CallFloatMethodA(jniEnv, obj, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.f = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallDoubleMethod(jobject obj, jmethodID methodID) {
+ attach_thread();
+ jdouble _result = (*jniEnv)->CallDoubleMethod(jniEnv, obj, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.d = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallDoubleMethodA(jobject obj,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jdouble _result = (*jniEnv)->CallDoubleMethodA(jniEnv, obj, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.d = _result}, .exception = NULL};
+}
+
+jthrowable globalEnv_CallVoidMethod(jobject obj, jmethodID methodID) {
+ attach_thread();
+ (*jniEnv)->CallVoidMethod(jniEnv, obj, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_CallVoidMethodA(jobject obj,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ (*jniEnv)->CallVoidMethodA(jniEnv, obj, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+JniResult globalEnv_CallNonvirtualObjectMethod(jobject obj,
+ jclass clazz,
+ jmethodID methodID) {
+ attach_thread();
+ jobject _result =
+ (*jniEnv)->CallNonvirtualObjectMethod(jniEnv, obj, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualObjectMethodA(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jobject _result = (*jniEnv)->CallNonvirtualObjectMethodA(jniEnv, obj, clazz,
+ methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualBooleanMethod(jobject obj,
+ jclass clazz,
+ jmethodID methodID) {
+ attach_thread();
+ jboolean _result =
+ (*jniEnv)->CallNonvirtualBooleanMethod(jniEnv, obj, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.z = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualBooleanMethodA(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jboolean _result = (*jniEnv)->CallNonvirtualBooleanMethodA(jniEnv, obj, clazz,
+ methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.z = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualByteMethod(jobject obj,
+ jclass clazz,
+ jmethodID methodID) {
+ attach_thread();
+ jbyte _result =
+ (*jniEnv)->CallNonvirtualByteMethod(jniEnv, obj, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.b = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualByteMethodA(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jbyte _result =
+ (*jniEnv)->CallNonvirtualByteMethodA(jniEnv, obj, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.b = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualCharMethod(jobject obj,
+ jclass clazz,
+ jmethodID methodID) {
+ attach_thread();
+ jchar _result =
+ (*jniEnv)->CallNonvirtualCharMethod(jniEnv, obj, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.c = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualCharMethodA(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jchar _result =
+ (*jniEnv)->CallNonvirtualCharMethodA(jniEnv, obj, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.c = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualShortMethod(jobject obj,
+ jclass clazz,
+ jmethodID methodID) {
+ attach_thread();
+ jshort _result =
+ (*jniEnv)->CallNonvirtualShortMethod(jniEnv, obj, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.s = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualShortMethodA(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jshort _result =
+ (*jniEnv)->CallNonvirtualShortMethodA(jniEnv, obj, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.s = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualIntMethod(jobject obj,
+ jclass clazz,
+ jmethodID methodID) {
+ attach_thread();
+ jint _result =
+ (*jniEnv)->CallNonvirtualIntMethod(jniEnv, obj, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualIntMethodA(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jint _result =
+ (*jniEnv)->CallNonvirtualIntMethodA(jniEnv, obj, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualLongMethod(jobject obj,
+ jclass clazz,
+ jmethodID methodID) {
+ attach_thread();
+ jlong _result =
+ (*jniEnv)->CallNonvirtualLongMethod(jniEnv, obj, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.j = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualLongMethodA(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jlong _result =
+ (*jniEnv)->CallNonvirtualLongMethodA(jniEnv, obj, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.j = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualFloatMethod(jobject obj,
+ jclass clazz,
+ jmethodID methodID) {
+ attach_thread();
+ jfloat _result =
+ (*jniEnv)->CallNonvirtualFloatMethod(jniEnv, obj, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.f = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualFloatMethodA(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jfloat _result =
+ (*jniEnv)->CallNonvirtualFloatMethodA(jniEnv, obj, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.f = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualDoubleMethod(jobject obj,
+ jclass clazz,
+ jmethodID methodID) {
+ attach_thread();
+ jdouble _result =
+ (*jniEnv)->CallNonvirtualDoubleMethod(jniEnv, obj, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.d = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallNonvirtualDoubleMethodA(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jdouble _result = (*jniEnv)->CallNonvirtualDoubleMethodA(jniEnv, obj, clazz,
+ methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.d = _result}, .exception = NULL};
+}
+
+jthrowable globalEnv_CallNonvirtualVoidMethod(jobject obj,
+ jclass clazz,
+ jmethodID methodID) {
+ attach_thread();
+ (*jniEnv)->CallNonvirtualVoidMethod(jniEnv, obj, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_CallNonvirtualVoidMethodA(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ (*jniEnv)->CallNonvirtualVoidMethodA(jniEnv, obj, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+JniPointerResult globalEnv_GetFieldID(jclass clazz, char* name, char* sig) {
+ attach_thread();
+ jfieldID _result = (*jniEnv)->GetFieldID(jniEnv, clazz, name, sig);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+JniResult globalEnv_GetObjectField(jobject obj, jfieldID fieldID) {
+ attach_thread();
+ jobject _result = (*jniEnv)->GetObjectField(jniEnv, obj, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetBooleanField(jobject obj, jfieldID fieldID) {
+ attach_thread();
+ jboolean _result = (*jniEnv)->GetBooleanField(jniEnv, obj, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.z = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetByteField(jobject obj, jfieldID fieldID) {
+ attach_thread();
+ jbyte _result = (*jniEnv)->GetByteField(jniEnv, obj, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.b = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetCharField(jobject obj, jfieldID fieldID) {
+ attach_thread();
+ jchar _result = (*jniEnv)->GetCharField(jniEnv, obj, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.c = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetShortField(jobject obj, jfieldID fieldID) {
+ attach_thread();
+ jshort _result = (*jniEnv)->GetShortField(jniEnv, obj, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.s = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetIntField(jobject obj, jfieldID fieldID) {
+ attach_thread();
+ jint _result = (*jniEnv)->GetIntField(jniEnv, obj, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetLongField(jobject obj, jfieldID fieldID) {
+ attach_thread();
+ jlong _result = (*jniEnv)->GetLongField(jniEnv, obj, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.j = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetFloatField(jobject obj, jfieldID fieldID) {
+ attach_thread();
+ jfloat _result = (*jniEnv)->GetFloatField(jniEnv, obj, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.f = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetDoubleField(jobject obj, jfieldID fieldID) {
+ attach_thread();
+ jdouble _result = (*jniEnv)->GetDoubleField(jniEnv, obj, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.d = _result}, .exception = NULL};
+}
+
+jthrowable globalEnv_SetObjectField(jobject obj,
+ jfieldID fieldID,
+ jobject val) {
+ attach_thread();
+ (*jniEnv)->SetObjectField(jniEnv, obj, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetBooleanField(jobject obj,
+ jfieldID fieldID,
+ jboolean val) {
+ attach_thread();
+ (*jniEnv)->SetBooleanField(jniEnv, obj, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetByteField(jobject obj, jfieldID fieldID, jbyte val) {
+ attach_thread();
+ (*jniEnv)->SetByteField(jniEnv, obj, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetCharField(jobject obj, jfieldID fieldID, jchar val) {
+ attach_thread();
+ (*jniEnv)->SetCharField(jniEnv, obj, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetShortField(jobject obj, jfieldID fieldID, jshort val) {
+ attach_thread();
+ (*jniEnv)->SetShortField(jniEnv, obj, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetIntField(jobject obj, jfieldID fieldID, jint val) {
+ attach_thread();
+ (*jniEnv)->SetIntField(jniEnv, obj, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetLongField(jobject obj, jfieldID fieldID, jlong val) {
+ attach_thread();
+ (*jniEnv)->SetLongField(jniEnv, obj, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetFloatField(jobject obj, jfieldID fieldID, jfloat val) {
+ attach_thread();
+ (*jniEnv)->SetFloatField(jniEnv, obj, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetDoubleField(jobject obj,
+ jfieldID fieldID,
+ jdouble val) {
+ attach_thread();
+ (*jniEnv)->SetDoubleField(jniEnv, obj, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+JniPointerResult globalEnv_GetStaticMethodID(jclass clazz,
+ char* name,
+ char* sig) {
+ attach_thread();
+ jmethodID _result = (*jniEnv)->GetStaticMethodID(jniEnv, clazz, name, sig);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticObjectMethod(jclass clazz, jmethodID methodID) {
+ attach_thread();
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticObjectMethodA(jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jobject _result =
+ (*jniEnv)->CallStaticObjectMethodA(jniEnv, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticBooleanMethod(jclass clazz, jmethodID methodID) {
+ attach_thread();
+ jboolean _result =
+ (*jniEnv)->CallStaticBooleanMethod(jniEnv, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.z = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticBooleanMethodA(jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jboolean _result =
+ (*jniEnv)->CallStaticBooleanMethodA(jniEnv, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.z = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticByteMethod(jclass clazz, jmethodID methodID) {
+ attach_thread();
+ jbyte _result = (*jniEnv)->CallStaticByteMethod(jniEnv, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.b = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticByteMethodA(jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jbyte _result =
+ (*jniEnv)->CallStaticByteMethodA(jniEnv, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.b = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticCharMethod(jclass clazz, jmethodID methodID) {
+ attach_thread();
+ jchar _result = (*jniEnv)->CallStaticCharMethod(jniEnv, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.c = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticCharMethodA(jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jchar _result =
+ (*jniEnv)->CallStaticCharMethodA(jniEnv, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.c = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticShortMethod(jclass clazz, jmethodID methodID) {
+ attach_thread();
+ jshort _result = (*jniEnv)->CallStaticShortMethod(jniEnv, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.s = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticShortMethodA(jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jshort _result =
+ (*jniEnv)->CallStaticShortMethodA(jniEnv, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.s = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticIntMethod(jclass clazz, jmethodID methodID) {
+ attach_thread();
+ jint _result = (*jniEnv)->CallStaticIntMethod(jniEnv, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticIntMethodA(jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jint _result = (*jniEnv)->CallStaticIntMethodA(jniEnv, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticLongMethod(jclass clazz, jmethodID methodID) {
+ attach_thread();
+ jlong _result = (*jniEnv)->CallStaticLongMethod(jniEnv, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.j = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticLongMethodA(jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jlong _result =
+ (*jniEnv)->CallStaticLongMethodA(jniEnv, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.j = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticFloatMethod(jclass clazz, jmethodID methodID) {
+ attach_thread();
+ jfloat _result = (*jniEnv)->CallStaticFloatMethod(jniEnv, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.f = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticFloatMethodA(jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jfloat _result =
+ (*jniEnv)->CallStaticFloatMethodA(jniEnv, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.f = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticDoubleMethod(jclass clazz, jmethodID methodID) {
+ attach_thread();
+ jdouble _result = (*jniEnv)->CallStaticDoubleMethod(jniEnv, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.d = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_CallStaticDoubleMethodA(jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ jdouble _result =
+ (*jniEnv)->CallStaticDoubleMethodA(jniEnv, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.d = _result}, .exception = NULL};
+}
+
+jthrowable globalEnv_CallStaticVoidMethod(jclass clazz, jmethodID methodID) {
+ attach_thread();
+ (*jniEnv)->CallStaticVoidMethod(jniEnv, clazz, methodID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_CallStaticVoidMethodA(jclass clazz,
+ jmethodID methodID,
+ jvalue* args) {
+ attach_thread();
+ (*jniEnv)->CallStaticVoidMethodA(jniEnv, clazz, methodID, args);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+JniPointerResult globalEnv_GetStaticFieldID(jclass clazz,
+ char* name,
+ char* sig) {
+ attach_thread();
+ jfieldID _result = (*jniEnv)->GetStaticFieldID(jniEnv, clazz, name, sig);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticObjectField(jclass clazz, jfieldID fieldID) {
+ attach_thread();
+ jobject _result = (*jniEnv)->GetStaticObjectField(jniEnv, clazz, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticBooleanField(jclass clazz, jfieldID fieldID) {
+ attach_thread();
+ jboolean _result = (*jniEnv)->GetStaticBooleanField(jniEnv, clazz, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.z = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticByteField(jclass clazz, jfieldID fieldID) {
+ attach_thread();
+ jbyte _result = (*jniEnv)->GetStaticByteField(jniEnv, clazz, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.b = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticCharField(jclass clazz, jfieldID fieldID) {
+ attach_thread();
+ jchar _result = (*jniEnv)->GetStaticCharField(jniEnv, clazz, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.c = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticShortField(jclass clazz, jfieldID fieldID) {
+ attach_thread();
+ jshort _result = (*jniEnv)->GetStaticShortField(jniEnv, clazz, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.s = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticIntField(jclass clazz, jfieldID fieldID) {
+ attach_thread();
+ jint _result = (*jniEnv)->GetStaticIntField(jniEnv, clazz, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticLongField(jclass clazz, jfieldID fieldID) {
+ attach_thread();
+ jlong _result = (*jniEnv)->GetStaticLongField(jniEnv, clazz, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.j = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticFloatField(jclass clazz, jfieldID fieldID) {
+ attach_thread();
+ jfloat _result = (*jniEnv)->GetStaticFloatField(jniEnv, clazz, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.f = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStaticDoubleField(jclass clazz, jfieldID fieldID) {
+ attach_thread();
+ jdouble _result = (*jniEnv)->GetStaticDoubleField(jniEnv, clazz, fieldID);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.d = _result}, .exception = NULL};
+}
+
+jthrowable globalEnv_SetStaticObjectField(jclass clazz,
+ jfieldID fieldID,
+ jobject val) {
+ attach_thread();
+ (*jniEnv)->SetStaticObjectField(jniEnv, clazz, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetStaticBooleanField(jclass clazz,
+ jfieldID fieldID,
+ jboolean val) {
+ attach_thread();
+ (*jniEnv)->SetStaticBooleanField(jniEnv, clazz, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetStaticByteField(jclass clazz,
+ jfieldID fieldID,
+ jbyte val) {
+ attach_thread();
+ (*jniEnv)->SetStaticByteField(jniEnv, clazz, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetStaticCharField(jclass clazz,
+ jfieldID fieldID,
+ jchar val) {
+ attach_thread();
+ (*jniEnv)->SetStaticCharField(jniEnv, clazz, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetStaticShortField(jclass clazz,
+ jfieldID fieldID,
+ jshort val) {
+ attach_thread();
+ (*jniEnv)->SetStaticShortField(jniEnv, clazz, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetStaticIntField(jclass clazz,
+ jfieldID fieldID,
+ jint val) {
+ attach_thread();
+ (*jniEnv)->SetStaticIntField(jniEnv, clazz, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetStaticLongField(jclass clazz,
+ jfieldID fieldID,
+ jlong val) {
+ attach_thread();
+ (*jniEnv)->SetStaticLongField(jniEnv, clazz, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetStaticFloatField(jclass clazz,
+ jfieldID fieldID,
+ jfloat val) {
+ attach_thread();
+ (*jniEnv)->SetStaticFloatField(jniEnv, clazz, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetStaticDoubleField(jclass clazz,
+ jfieldID fieldID,
+ jdouble val) {
+ attach_thread();
+ (*jniEnv)->SetStaticDoubleField(jniEnv, clazz, fieldID, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+JniResult globalEnv_NewString(jchar* unicodeChars, jsize len) {
+ attach_thread();
+ jstring _result = (*jniEnv)->NewString(jniEnv, unicodeChars, len);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStringLength(jstring string) {
+ attach_thread();
+ jsize _result = (*jniEnv)->GetStringLength(jniEnv, string);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniPointerResult globalEnv_GetStringChars(jstring string, jboolean* isCopy) {
+ attach_thread();
+ const jchar* _result = (*jniEnv)->GetStringChars(jniEnv, string, isCopy);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+jthrowable globalEnv_ReleaseStringChars(jstring string, jchar* isCopy) {
+ attach_thread();
+ (*jniEnv)->ReleaseStringChars(jniEnv, string, isCopy);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+JniResult globalEnv_NewStringUTF(char* bytes) {
+ attach_thread();
+ jstring _result = (*jniEnv)->NewStringUTF(jniEnv, bytes);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetStringUTFLength(jstring string) {
+ attach_thread();
+ jsize _result = (*jniEnv)->GetStringUTFLength(jniEnv, string);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniPointerResult globalEnv_GetStringUTFChars(jstring string, jboolean* isCopy) {
+ attach_thread();
+ const char* _result = (*jniEnv)->GetStringUTFChars(jniEnv, string, isCopy);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+jthrowable globalEnv_ReleaseStringUTFChars(jstring string, char* utf) {
+ attach_thread();
+ (*jniEnv)->ReleaseStringUTFChars(jniEnv, string, utf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+JniResult globalEnv_GetArrayLength(jarray array) {
+ attach_thread();
+ jsize _result = (*jniEnv)->GetArrayLength(jniEnv, array);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_NewObjectArray(jsize length,
+ jclass elementClass,
+ jobject initialElement) {
+ attach_thread();
+ jobjectArray _result =
+ (*jniEnv)->NewObjectArray(jniEnv, length, elementClass, initialElement);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetObjectArrayElement(jobjectArray array, jsize index) {
+ attach_thread();
+ jobject _result = (*jniEnv)->GetObjectArrayElement(jniEnv, array, index);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+jthrowable globalEnv_SetObjectArrayElement(jobjectArray array,
+ jsize index,
+ jobject val) {
+ attach_thread();
+ (*jniEnv)->SetObjectArrayElement(jniEnv, array, index, val);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+JniResult globalEnv_NewBooleanArray(jsize length) {
+ attach_thread();
+ jbooleanArray _result = (*jniEnv)->NewBooleanArray(jniEnv, length);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_NewByteArray(jsize length) {
+ attach_thread();
+ jbyteArray _result = (*jniEnv)->NewByteArray(jniEnv, length);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_NewCharArray(jsize length) {
+ attach_thread();
+ jcharArray _result = (*jniEnv)->NewCharArray(jniEnv, length);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_NewShortArray(jsize length) {
+ attach_thread();
+ jshortArray _result = (*jniEnv)->NewShortArray(jniEnv, length);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_NewIntArray(jsize length) {
+ attach_thread();
+ jintArray _result = (*jniEnv)->NewIntArray(jniEnv, length);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_NewLongArray(jsize length) {
+ attach_thread();
+ jlongArray _result = (*jniEnv)->NewLongArray(jniEnv, length);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_NewFloatArray(jsize length) {
+ attach_thread();
+ jfloatArray _result = (*jniEnv)->NewFloatArray(jniEnv, length);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_NewDoubleArray(jsize length) {
+ attach_thread();
+ jdoubleArray _result = (*jniEnv)->NewDoubleArray(jniEnv, length);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniPointerResult globalEnv_GetBooleanArrayElements(jbooleanArray array,
+ jboolean* isCopy) {
+ attach_thread();
+ jboolean* _result = (*jniEnv)->GetBooleanArrayElements(jniEnv, array, isCopy);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+JniPointerResult globalEnv_GetByteArrayElements(jbyteArray array,
+ jboolean* isCopy) {
+ attach_thread();
+ jbyte* _result = (*jniEnv)->GetByteArrayElements(jniEnv, array, isCopy);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+JniPointerResult globalEnv_GetCharArrayElements(jcharArray array,
+ jboolean* isCopy) {
+ attach_thread();
+ jchar* _result = (*jniEnv)->GetCharArrayElements(jniEnv, array, isCopy);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+JniPointerResult globalEnv_GetShortArrayElements(jshortArray array,
+ jboolean* isCopy) {
+ attach_thread();
+ jshort* _result = (*jniEnv)->GetShortArrayElements(jniEnv, array, isCopy);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+JniPointerResult globalEnv_GetIntArrayElements(jintArray array,
+ jboolean* isCopy) {
+ attach_thread();
+ jint* _result = (*jniEnv)->GetIntArrayElements(jniEnv, array, isCopy);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+JniPointerResult globalEnv_GetLongArrayElements(jlongArray array,
+ jboolean* isCopy) {
+ attach_thread();
+ jlong* _result = (*jniEnv)->GetLongArrayElements(jniEnv, array, isCopy);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+JniPointerResult globalEnv_GetFloatArrayElements(jfloatArray array,
+ jboolean* isCopy) {
+ attach_thread();
+ jfloat* _result = (*jniEnv)->GetFloatArrayElements(jniEnv, array, isCopy);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+JniPointerResult globalEnv_GetDoubleArrayElements(jdoubleArray array,
+ jboolean* isCopy) {
+ attach_thread();
+ jdouble* _result = (*jniEnv)->GetDoubleArrayElements(jniEnv, array, isCopy);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+jthrowable globalEnv_ReleaseBooleanArrayElements(jbooleanArray array,
+ jboolean* elems,
+ jint mode) {
+ attach_thread();
+ (*jniEnv)->ReleaseBooleanArrayElements(jniEnv, array, elems, mode);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_ReleaseByteArrayElements(jbyteArray array,
+ jbyte* elems,
+ jint mode) {
+ attach_thread();
+ (*jniEnv)->ReleaseByteArrayElements(jniEnv, array, elems, mode);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_ReleaseCharArrayElements(jcharArray array,
+ jchar* elems,
+ jint mode) {
+ attach_thread();
+ (*jniEnv)->ReleaseCharArrayElements(jniEnv, array, elems, mode);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_ReleaseShortArrayElements(jshortArray array,
+ jshort* elems,
+ jint mode) {
+ attach_thread();
+ (*jniEnv)->ReleaseShortArrayElements(jniEnv, array, elems, mode);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_ReleaseIntArrayElements(jintArray array,
+ jint* elems,
+ jint mode) {
+ attach_thread();
+ (*jniEnv)->ReleaseIntArrayElements(jniEnv, array, elems, mode);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_ReleaseLongArrayElements(jlongArray array,
+ jlong* elems,
+ jint mode) {
+ attach_thread();
+ (*jniEnv)->ReleaseLongArrayElements(jniEnv, array, elems, mode);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_ReleaseFloatArrayElements(jfloatArray array,
+ jfloat* elems,
+ jint mode) {
+ attach_thread();
+ (*jniEnv)->ReleaseFloatArrayElements(jniEnv, array, elems, mode);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_ReleaseDoubleArrayElements(jdoubleArray array,
+ jdouble* elems,
+ jint mode) {
+ attach_thread();
+ (*jniEnv)->ReleaseDoubleArrayElements(jniEnv, array, elems, mode);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_GetBooleanArrayRegion(jbooleanArray array,
+ jsize start,
+ jsize len,
+ jboolean* buf) {
+ attach_thread();
+ (*jniEnv)->GetBooleanArrayRegion(jniEnv, array, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_GetByteArrayRegion(jbyteArray array,
+ jsize start,
+ jsize len,
+ jbyte* buf) {
+ attach_thread();
+ (*jniEnv)->GetByteArrayRegion(jniEnv, array, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_GetCharArrayRegion(jcharArray array,
+ jsize start,
+ jsize len,
+ jchar* buf) {
+ attach_thread();
+ (*jniEnv)->GetCharArrayRegion(jniEnv, array, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_GetShortArrayRegion(jshortArray array,
+ jsize start,
+ jsize len,
+ jshort* buf) {
+ attach_thread();
+ (*jniEnv)->GetShortArrayRegion(jniEnv, array, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_GetIntArrayRegion(jintArray array,
+ jsize start,
+ jsize len,
+ jint* buf) {
+ attach_thread();
+ (*jniEnv)->GetIntArrayRegion(jniEnv, array, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_GetLongArrayRegion(jlongArray array,
+ jsize start,
+ jsize len,
+ jlong* buf) {
+ attach_thread();
+ (*jniEnv)->GetLongArrayRegion(jniEnv, array, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_GetFloatArrayRegion(jfloatArray array,
+ jsize start,
+ jsize len,
+ jfloat* buf) {
+ attach_thread();
+ (*jniEnv)->GetFloatArrayRegion(jniEnv, array, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_GetDoubleArrayRegion(jdoubleArray array,
+ jsize start,
+ jsize len,
+ jdouble* buf) {
+ attach_thread();
+ (*jniEnv)->GetDoubleArrayRegion(jniEnv, array, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetBooleanArrayRegion(jbooleanArray array,
+ jsize start,
+ jsize len,
+ jboolean* buf) {
+ attach_thread();
+ (*jniEnv)->SetBooleanArrayRegion(jniEnv, array, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetByteArrayRegion(jbyteArray array,
+ jsize start,
+ jsize len,
+ jbyte* buf) {
+ attach_thread();
+ (*jniEnv)->SetByteArrayRegion(jniEnv, array, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetCharArrayRegion(jcharArray array,
+ jsize start,
+ jsize len,
+ jchar* buf) {
+ attach_thread();
+ (*jniEnv)->SetCharArrayRegion(jniEnv, array, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetShortArrayRegion(jshortArray array,
+ jsize start,
+ jsize len,
+ jshort* buf) {
+ attach_thread();
+ (*jniEnv)->SetShortArrayRegion(jniEnv, array, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetIntArrayRegion(jintArray array,
+ jsize start,
+ jsize len,
+ jint* buf) {
+ attach_thread();
+ (*jniEnv)->SetIntArrayRegion(jniEnv, array, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetLongArrayRegion(jlongArray array,
+ jsize start,
+ jsize len,
+ jlong* buf) {
+ attach_thread();
+ (*jniEnv)->SetLongArrayRegion(jniEnv, array, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetFloatArrayRegion(jfloatArray array,
+ jsize start,
+ jsize len,
+ jfloat* buf) {
+ attach_thread();
+ (*jniEnv)->SetFloatArrayRegion(jniEnv, array, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_SetDoubleArrayRegion(jdoubleArray array,
+ jsize start,
+ jsize len,
+ jdouble* buf) {
+ attach_thread();
+ (*jniEnv)->SetDoubleArrayRegion(jniEnv, array, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+JniResult globalEnv_RegisterNatives(jclass clazz,
+ JNINativeMethod* methods,
+ jint nMethods) {
+ attach_thread();
+ jint _result = (*jniEnv)->RegisterNatives(jniEnv, clazz, methods, nMethods);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_UnregisterNatives(jclass clazz) {
+ attach_thread();
+ jint _result = (*jniEnv)->UnregisterNatives(jniEnv, clazz);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_MonitorEnter(jobject obj) {
+ attach_thread();
+ jint _result = (*jniEnv)->MonitorEnter(jniEnv, obj);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_MonitorExit(jobject obj) {
+ attach_thread();
+ jint _result = (*jniEnv)->MonitorExit(jniEnv, obj);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetJavaVM(JavaVM** vm) {
+ attach_thread();
+ jint _result = (*jniEnv)->GetJavaVM(jniEnv, vm);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+jthrowable globalEnv_GetStringRegion(jstring str,
+ jsize start,
+ jsize len,
+ jchar* buf) {
+ attach_thread();
+ (*jniEnv)->GetStringRegion(jniEnv, str, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+jthrowable globalEnv_GetStringUTFRegion(jstring str,
+ jsize start,
+ jsize len,
+ char* buf) {
+ attach_thread();
+ (*jniEnv)->GetStringUTFRegion(jniEnv, str, start, len, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+JniPointerResult globalEnv_GetPrimitiveArrayCritical(jarray array,
+ jboolean* isCopy) {
+ attach_thread();
+ void* _result = (*jniEnv)->GetPrimitiveArrayCritical(jniEnv, array, isCopy);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+jthrowable globalEnv_ReleasePrimitiveArrayCritical(jarray array,
+ void* carray,
+ jint mode) {
+ attach_thread();
+ (*jniEnv)->ReleasePrimitiveArrayCritical(jniEnv, array, carray, mode);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+JniPointerResult globalEnv_GetStringCritical(jstring str, jboolean* isCopy) {
+ attach_thread();
+ const jchar* _result = (*jniEnv)->GetStringCritical(jniEnv, str, isCopy);
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+jthrowable globalEnv_ReleaseStringCritical(jstring str, jchar* carray) {
+ attach_thread();
+ (*jniEnv)->ReleaseStringCritical(jniEnv, str, carray);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+JniResult globalEnv_NewWeakGlobalRef(jobject obj) {
+ attach_thread();
+ jweak _result = (*jniEnv)->NewWeakGlobalRef(jniEnv, obj);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+jthrowable globalEnv_DeleteWeakGlobalRef(jweak obj) {
+ attach_thread();
+ (*jniEnv)->DeleteWeakGlobalRef(jniEnv, obj);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return _exception;
+ }
+ return NULL;
+}
+
+JniResult globalEnv_ExceptionCheck() {
+ attach_thread();
+ jboolean _result = (*jniEnv)->ExceptionCheck(jniEnv);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.z = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_NewDirectByteBuffer(void* address, jlong capacity) {
+ attach_thread();
+ jobject _result = (*jniEnv)->NewDirectByteBuffer(jniEnv, address, capacity);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ _result = to_global_ref(_result);
+ return (JniResult){.value = {.l = _result}, .exception = NULL};
+}
+
+JniPointerResult globalEnv_GetDirectBufferAddress(jobject buf) {
+ attach_thread();
+ void* _result = (*jniEnv)->GetDirectBufferAddress(jniEnv, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniPointerResult){.value = NULL, .exception = _exception};
+ }
+ return (JniPointerResult){.value = _result, .exception = NULL};
+}
+
+JniResult globalEnv_GetDirectBufferCapacity(jobject buf) {
+ attach_thread();
+ jlong _result = (*jniEnv)->GetDirectBufferCapacity(jniEnv, buf);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.j = _result}, .exception = NULL};
+}
+
+JniResult globalEnv_GetObjectRefType(jobject obj) {
+ attach_thread();
+ int32_t _result = (*jniEnv)->GetObjectRefType(jniEnv, obj);
+ jthrowable _exception = check_exception();
+ if (_exception != NULL) {
+ return (JniResult){.value = {.j = 0}, .exception = _exception};
+ }
+ return (JniResult){.value = {.i = _result}, .exception = NULL};
+}
+
+GlobalJniEnvStruct globalJniEnv = {
+ .reserved0 = NULL,
+ .reserved1 = NULL,
+ .reserved2 = NULL,
+ .reserved3 = NULL,
+ .GetVersion = globalEnv_GetVersion,
+ .DefineClass = globalEnv_DefineClass,
+ .FindClass = globalEnv_FindClass,
+ .FromReflectedMethod = globalEnv_FromReflectedMethod,
+ .FromReflectedField = globalEnv_FromReflectedField,
+ .ToReflectedMethod = globalEnv_ToReflectedMethod,
+ .GetSuperclass = globalEnv_GetSuperclass,
+ .IsAssignableFrom = globalEnv_IsAssignableFrom,
+ .ToReflectedField = globalEnv_ToReflectedField,
+ .Throw = globalEnv_Throw,
+ .ThrowNew = globalEnv_ThrowNew,
+ .ExceptionOccurred = globalEnv_ExceptionOccurred,
+ .ExceptionDescribe = globalEnv_ExceptionDescribe,
+ .ExceptionClear = globalEnv_ExceptionClear,
+ .FatalError = globalEnv_FatalError,
+ .PushLocalFrame = globalEnv_PushLocalFrame,
+ .PopLocalFrame = globalEnv_PopLocalFrame,
+ .NewGlobalRef = globalEnv_NewGlobalRef,
+ .DeleteGlobalRef = globalEnv_DeleteGlobalRef,
+ .DeleteLocalRef = globalEnv_DeleteLocalRef,
+ .IsSameObject = globalEnv_IsSameObject,
+ .NewLocalRef = globalEnv_NewLocalRef,
+ .EnsureLocalCapacity = globalEnv_EnsureLocalCapacity,
+ .AllocObject = globalEnv_AllocObject,
+ .NewObject = globalEnv_NewObject,
+ .NewObjectV = NULL,
+ .NewObjectA = globalEnv_NewObjectA,
+ .GetObjectClass = globalEnv_GetObjectClass,
+ .IsInstanceOf = globalEnv_IsInstanceOf,
+ .GetMethodID = globalEnv_GetMethodID,
+ .CallObjectMethod = globalEnv_CallObjectMethod,
+ .CallObjectMethodV = NULL,
+ .CallObjectMethodA = globalEnv_CallObjectMethodA,
+ .CallBooleanMethod = globalEnv_CallBooleanMethod,
+ .CallBooleanMethodV = NULL,
+ .CallBooleanMethodA = globalEnv_CallBooleanMethodA,
+ .CallByteMethod = globalEnv_CallByteMethod,
+ .CallByteMethodV = NULL,
+ .CallByteMethodA = globalEnv_CallByteMethodA,
+ .CallCharMethod = globalEnv_CallCharMethod,
+ .CallCharMethodV = NULL,
+ .CallCharMethodA = globalEnv_CallCharMethodA,
+ .CallShortMethod = globalEnv_CallShortMethod,
+ .CallShortMethodV = NULL,
+ .CallShortMethodA = globalEnv_CallShortMethodA,
+ .CallIntMethod = globalEnv_CallIntMethod,
+ .CallIntMethodV = NULL,
+ .CallIntMethodA = globalEnv_CallIntMethodA,
+ .CallLongMethod = globalEnv_CallLongMethod,
+ .CallLongMethodV = NULL,
+ .CallLongMethodA = globalEnv_CallLongMethodA,
+ .CallFloatMethod = globalEnv_CallFloatMethod,
+ .CallFloatMethodV = NULL,
+ .CallFloatMethodA = globalEnv_CallFloatMethodA,
+ .CallDoubleMethod = globalEnv_CallDoubleMethod,
+ .CallDoubleMethodV = NULL,
+ .CallDoubleMethodA = globalEnv_CallDoubleMethodA,
+ .CallVoidMethod = globalEnv_CallVoidMethod,
+ .CallVoidMethodV = NULL,
+ .CallVoidMethodA = globalEnv_CallVoidMethodA,
+ .CallNonvirtualObjectMethod = globalEnv_CallNonvirtualObjectMethod,
+ .CallNonvirtualObjectMethodV = NULL,
+ .CallNonvirtualObjectMethodA = globalEnv_CallNonvirtualObjectMethodA,
+ .CallNonvirtualBooleanMethod = globalEnv_CallNonvirtualBooleanMethod,
+ .CallNonvirtualBooleanMethodV = NULL,
+ .CallNonvirtualBooleanMethodA = globalEnv_CallNonvirtualBooleanMethodA,
+ .CallNonvirtualByteMethod = globalEnv_CallNonvirtualByteMethod,
+ .CallNonvirtualByteMethodV = NULL,
+ .CallNonvirtualByteMethodA = globalEnv_CallNonvirtualByteMethodA,
+ .CallNonvirtualCharMethod = globalEnv_CallNonvirtualCharMethod,
+ .CallNonvirtualCharMethodV = NULL,
+ .CallNonvirtualCharMethodA = globalEnv_CallNonvirtualCharMethodA,
+ .CallNonvirtualShortMethod = globalEnv_CallNonvirtualShortMethod,
+ .CallNonvirtualShortMethodV = NULL,
+ .CallNonvirtualShortMethodA = globalEnv_CallNonvirtualShortMethodA,
+ .CallNonvirtualIntMethod = globalEnv_CallNonvirtualIntMethod,
+ .CallNonvirtualIntMethodV = NULL,
+ .CallNonvirtualIntMethodA = globalEnv_CallNonvirtualIntMethodA,
+ .CallNonvirtualLongMethod = globalEnv_CallNonvirtualLongMethod,
+ .CallNonvirtualLongMethodV = NULL,
+ .CallNonvirtualLongMethodA = globalEnv_CallNonvirtualLongMethodA,
+ .CallNonvirtualFloatMethod = globalEnv_CallNonvirtualFloatMethod,
+ .CallNonvirtualFloatMethodV = NULL,
+ .CallNonvirtualFloatMethodA = globalEnv_CallNonvirtualFloatMethodA,
+ .CallNonvirtualDoubleMethod = globalEnv_CallNonvirtualDoubleMethod,
+ .CallNonvirtualDoubleMethodV = NULL,
+ .CallNonvirtualDoubleMethodA = globalEnv_CallNonvirtualDoubleMethodA,
+ .CallNonvirtualVoidMethod = globalEnv_CallNonvirtualVoidMethod,
+ .CallNonvirtualVoidMethodV = NULL,
+ .CallNonvirtualVoidMethodA = globalEnv_CallNonvirtualVoidMethodA,
+ .GetFieldID = globalEnv_GetFieldID,
+ .GetObjectField = globalEnv_GetObjectField,
+ .GetBooleanField = globalEnv_GetBooleanField,
+ .GetByteField = globalEnv_GetByteField,
+ .GetCharField = globalEnv_GetCharField,
+ .GetShortField = globalEnv_GetShortField,
+ .GetIntField = globalEnv_GetIntField,
+ .GetLongField = globalEnv_GetLongField,
+ .GetFloatField = globalEnv_GetFloatField,
+ .GetDoubleField = globalEnv_GetDoubleField,
+ .SetObjectField = globalEnv_SetObjectField,
+ .SetBooleanField = globalEnv_SetBooleanField,
+ .SetByteField = globalEnv_SetByteField,
+ .SetCharField = globalEnv_SetCharField,
+ .SetShortField = globalEnv_SetShortField,
+ .SetIntField = globalEnv_SetIntField,
+ .SetLongField = globalEnv_SetLongField,
+ .SetFloatField = globalEnv_SetFloatField,
+ .SetDoubleField = globalEnv_SetDoubleField,
+ .GetStaticMethodID = globalEnv_GetStaticMethodID,
+ .CallStaticObjectMethod = globalEnv_CallStaticObjectMethod,
+ .CallStaticObjectMethodV = NULL,
+ .CallStaticObjectMethodA = globalEnv_CallStaticObjectMethodA,
+ .CallStaticBooleanMethod = globalEnv_CallStaticBooleanMethod,
+ .CallStaticBooleanMethodV = NULL,
+ .CallStaticBooleanMethodA = globalEnv_CallStaticBooleanMethodA,
+ .CallStaticByteMethod = globalEnv_CallStaticByteMethod,
+ .CallStaticByteMethodV = NULL,
+ .CallStaticByteMethodA = globalEnv_CallStaticByteMethodA,
+ .CallStaticCharMethod = globalEnv_CallStaticCharMethod,
+ .CallStaticCharMethodV = NULL,
+ .CallStaticCharMethodA = globalEnv_CallStaticCharMethodA,
+ .CallStaticShortMethod = globalEnv_CallStaticShortMethod,
+ .CallStaticShortMethodV = NULL,
+ .CallStaticShortMethodA = globalEnv_CallStaticShortMethodA,
+ .CallStaticIntMethod = globalEnv_CallStaticIntMethod,
+ .CallStaticIntMethodV = NULL,
+ .CallStaticIntMethodA = globalEnv_CallStaticIntMethodA,
+ .CallStaticLongMethod = globalEnv_CallStaticLongMethod,
+ .CallStaticLongMethodV = NULL,
+ .CallStaticLongMethodA = globalEnv_CallStaticLongMethodA,
+ .CallStaticFloatMethod = globalEnv_CallStaticFloatMethod,
+ .CallStaticFloatMethodV = NULL,
+ .CallStaticFloatMethodA = globalEnv_CallStaticFloatMethodA,
+ .CallStaticDoubleMethod = globalEnv_CallStaticDoubleMethod,
+ .CallStaticDoubleMethodV = NULL,
+ .CallStaticDoubleMethodA = globalEnv_CallStaticDoubleMethodA,
+ .CallStaticVoidMethod = globalEnv_CallStaticVoidMethod,
+ .CallStaticVoidMethodV = NULL,
+ .CallStaticVoidMethodA = globalEnv_CallStaticVoidMethodA,
+ .GetStaticFieldID = globalEnv_GetStaticFieldID,
+ .GetStaticObjectField = globalEnv_GetStaticObjectField,
+ .GetStaticBooleanField = globalEnv_GetStaticBooleanField,
+ .GetStaticByteField = globalEnv_GetStaticByteField,
+ .GetStaticCharField = globalEnv_GetStaticCharField,
+ .GetStaticShortField = globalEnv_GetStaticShortField,
+ .GetStaticIntField = globalEnv_GetStaticIntField,
+ .GetStaticLongField = globalEnv_GetStaticLongField,
+ .GetStaticFloatField = globalEnv_GetStaticFloatField,
+ .GetStaticDoubleField = globalEnv_GetStaticDoubleField,
+ .SetStaticObjectField = globalEnv_SetStaticObjectField,
+ .SetStaticBooleanField = globalEnv_SetStaticBooleanField,
+ .SetStaticByteField = globalEnv_SetStaticByteField,
+ .SetStaticCharField = globalEnv_SetStaticCharField,
+ .SetStaticShortField = globalEnv_SetStaticShortField,
+ .SetStaticIntField = globalEnv_SetStaticIntField,
+ .SetStaticLongField = globalEnv_SetStaticLongField,
+ .SetStaticFloatField = globalEnv_SetStaticFloatField,
+ .SetStaticDoubleField = globalEnv_SetStaticDoubleField,
+ .NewString = globalEnv_NewString,
+ .GetStringLength = globalEnv_GetStringLength,
+ .GetStringChars = globalEnv_GetStringChars,
+ .ReleaseStringChars = globalEnv_ReleaseStringChars,
+ .NewStringUTF = globalEnv_NewStringUTF,
+ .GetStringUTFLength = globalEnv_GetStringUTFLength,
+ .GetStringUTFChars = globalEnv_GetStringUTFChars,
+ .ReleaseStringUTFChars = globalEnv_ReleaseStringUTFChars,
+ .GetArrayLength = globalEnv_GetArrayLength,
+ .NewObjectArray = globalEnv_NewObjectArray,
+ .GetObjectArrayElement = globalEnv_GetObjectArrayElement,
+ .SetObjectArrayElement = globalEnv_SetObjectArrayElement,
+ .NewBooleanArray = globalEnv_NewBooleanArray,
+ .NewByteArray = globalEnv_NewByteArray,
+ .NewCharArray = globalEnv_NewCharArray,
+ .NewShortArray = globalEnv_NewShortArray,
+ .NewIntArray = globalEnv_NewIntArray,
+ .NewLongArray = globalEnv_NewLongArray,
+ .NewFloatArray = globalEnv_NewFloatArray,
+ .NewDoubleArray = globalEnv_NewDoubleArray,
+ .GetBooleanArrayElements = globalEnv_GetBooleanArrayElements,
+ .GetByteArrayElements = globalEnv_GetByteArrayElements,
+ .GetCharArrayElements = globalEnv_GetCharArrayElements,
+ .GetShortArrayElements = globalEnv_GetShortArrayElements,
+ .GetIntArrayElements = globalEnv_GetIntArrayElements,
+ .GetLongArrayElements = globalEnv_GetLongArrayElements,
+ .GetFloatArrayElements = globalEnv_GetFloatArrayElements,
+ .GetDoubleArrayElements = globalEnv_GetDoubleArrayElements,
+ .ReleaseBooleanArrayElements = globalEnv_ReleaseBooleanArrayElements,
+ .ReleaseByteArrayElements = globalEnv_ReleaseByteArrayElements,
+ .ReleaseCharArrayElements = globalEnv_ReleaseCharArrayElements,
+ .ReleaseShortArrayElements = globalEnv_ReleaseShortArrayElements,
+ .ReleaseIntArrayElements = globalEnv_ReleaseIntArrayElements,
+ .ReleaseLongArrayElements = globalEnv_ReleaseLongArrayElements,
+ .ReleaseFloatArrayElements = globalEnv_ReleaseFloatArrayElements,
+ .ReleaseDoubleArrayElements = globalEnv_ReleaseDoubleArrayElements,
+ .GetBooleanArrayRegion = globalEnv_GetBooleanArrayRegion,
+ .GetByteArrayRegion = globalEnv_GetByteArrayRegion,
+ .GetCharArrayRegion = globalEnv_GetCharArrayRegion,
+ .GetShortArrayRegion = globalEnv_GetShortArrayRegion,
+ .GetIntArrayRegion = globalEnv_GetIntArrayRegion,
+ .GetLongArrayRegion = globalEnv_GetLongArrayRegion,
+ .GetFloatArrayRegion = globalEnv_GetFloatArrayRegion,
+ .GetDoubleArrayRegion = globalEnv_GetDoubleArrayRegion,
+ .SetBooleanArrayRegion = globalEnv_SetBooleanArrayRegion,
+ .SetByteArrayRegion = globalEnv_SetByteArrayRegion,
+ .SetCharArrayRegion = globalEnv_SetCharArrayRegion,
+ .SetShortArrayRegion = globalEnv_SetShortArrayRegion,
+ .SetIntArrayRegion = globalEnv_SetIntArrayRegion,
+ .SetLongArrayRegion = globalEnv_SetLongArrayRegion,
+ .SetFloatArrayRegion = globalEnv_SetFloatArrayRegion,
+ .SetDoubleArrayRegion = globalEnv_SetDoubleArrayRegion,
+ .RegisterNatives = globalEnv_RegisterNatives,
+ .UnregisterNatives = globalEnv_UnregisterNatives,
+ .MonitorEnter = globalEnv_MonitorEnter,
+ .MonitorExit = globalEnv_MonitorExit,
+ .GetJavaVM = globalEnv_GetJavaVM,
+ .GetStringRegion = globalEnv_GetStringRegion,
+ .GetStringUTFRegion = globalEnv_GetStringUTFRegion,
+ .GetPrimitiveArrayCritical = globalEnv_GetPrimitiveArrayCritical,
+ .ReleasePrimitiveArrayCritical = globalEnv_ReleasePrimitiveArrayCritical,
+ .GetStringCritical = globalEnv_GetStringCritical,
+ .ReleaseStringCritical = globalEnv_ReleaseStringCritical,
+ .NewWeakGlobalRef = globalEnv_NewWeakGlobalRef,
+ .DeleteWeakGlobalRef = globalEnv_DeleteWeakGlobalRef,
+ .ExceptionCheck = globalEnv_ExceptionCheck,
+ .NewDirectByteBuffer = globalEnv_NewDirectByteBuffer,
+ .GetDirectBufferAddress = globalEnv_GetDirectBufferAddress,
+ .GetDirectBufferCapacity = globalEnv_GetDirectBufferCapacity,
+ .GetObjectRefType = globalEnv_GetObjectRefType,
+};
+FFI_PLUGIN_EXPORT
+GlobalJniEnvStruct* GetGlobalEnv() {
+ if (jni->jvm == NULL) {
+ return NULL;
+ }
+ return &globalJniEnv;
+}
diff --git a/pkgs/jni/src/third_party/global_jni_env.h b/pkgs/jni/src/third_party/global_jni_env.h
new file mode 100644
index 0000000..562b1bf
--- /dev/null
+++ b/pkgs/jni/src/third_party/global_jni_env.h
@@ -0,0 +1,434 @@
+// Auto generated file. Do not edit.
+
+// This is generated from JNI header in Android NDK. License for the same is
+// provided below.
+
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * JNI specification, as defined by Sun:
+ * http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html
+ *
+ * Everything here is expected to be VM-neutral.
+ */
+
+#include <stdint.h>
+#include "../dartjni.h"
+
+typedef struct GlobalJniEnvStruct {
+ void* reserved0;
+ void* reserved1;
+ void* reserved2;
+ void* reserved3;
+ JniResult (*GetVersion)();
+ JniClassLookupResult (*DefineClass)(char* name,
+ jobject loader,
+ jbyte* buf,
+ jsize bufLen);
+ JniClassLookupResult (*FindClass)(char* name);
+ JniPointerResult (*FromReflectedMethod)(jobject method);
+ JniPointerResult (*FromReflectedField)(jobject field);
+ JniResult (*ToReflectedMethod)(jclass cls,
+ jmethodID methodId,
+ jboolean isStatic);
+ JniClassLookupResult (*GetSuperclass)(jclass clazz);
+ JniResult (*IsAssignableFrom)(jclass clazz1, jclass clazz2);
+ JniResult (*ToReflectedField)(jclass cls,
+ jfieldID fieldID,
+ jboolean isStatic);
+ JniResult (*Throw)(jthrowable obj);
+ JniResult (*ThrowNew)(jclass clazz, char* message);
+ JniResult (*ExceptionOccurred)();
+ jthrowable (*ExceptionDescribe)();
+ jthrowable (*ExceptionClear)();
+ jthrowable (*FatalError)(char* msg);
+ JniResult (*PushLocalFrame)(jint capacity);
+ JniResult (*PopLocalFrame)(jobject result);
+ JniResult (*NewGlobalRef)(jobject obj);
+ jthrowable (*DeleteGlobalRef)(jobject globalRef);
+ jthrowable (*DeleteLocalRef)(jobject localRef);
+ JniResult (*IsSameObject)(jobject ref1, jobject ref2);
+ JniResult (*NewLocalRef)(jobject obj);
+ JniResult (*EnsureLocalCapacity)(jint capacity);
+ JniResult (*AllocObject)(jclass clazz);
+ JniResult (*NewObject)(jclass clazz, jmethodID methodID);
+ JniResult (*NewObjectV)(jclass, jmethodID, void*);
+ JniResult (*NewObjectA)(jclass clazz, jmethodID methodID, jvalue* args);
+ JniClassLookupResult (*GetObjectClass)(jobject obj);
+ JniResult (*IsInstanceOf)(jobject obj, jclass clazz);
+ JniPointerResult (*GetMethodID)(jclass clazz, char* name, char* sig);
+ JniResult (*CallObjectMethod)(jobject obj, jmethodID methodID);
+ JniResult (*CallObjectMethodV)(jobject, jmethodID, void*);
+ JniResult (*CallObjectMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+ JniResult (*CallBooleanMethod)(jobject obj, jmethodID methodID);
+ JniResult (*CallBooleanMethodV)(jobject, jmethodID, void*);
+ JniResult (*CallBooleanMethodA)(jobject obj,
+ jmethodID methodId,
+ jvalue* args);
+ JniResult (*CallByteMethod)(jobject obj, jmethodID methodID);
+ JniResult (*CallByteMethodV)(jobject, jmethodID, void*);
+ JniResult (*CallByteMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+ JniResult (*CallCharMethod)(jobject obj, jmethodID methodID);
+ JniResult (*CallCharMethodV)(jobject, jmethodID, void*);
+ JniResult (*CallCharMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+ JniResult (*CallShortMethod)(jobject obj, jmethodID methodID);
+ JniResult (*CallShortMethodV)(jobject, jmethodID, void*);
+ JniResult (*CallShortMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+ JniResult (*CallIntMethod)(jobject obj, jmethodID methodID);
+ JniResult (*CallIntMethodV)(jobject, jmethodID, void*);
+ JniResult (*CallIntMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+ JniResult (*CallLongMethod)(jobject obj, jmethodID methodID);
+ JniResult (*CallLongMethodV)(jobject, jmethodID, void*);
+ JniResult (*CallLongMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+ JniResult (*CallFloatMethod)(jobject obj, jmethodID methodID);
+ JniResult (*CallFloatMethodV)(jobject, jmethodID, void*);
+ JniResult (*CallFloatMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+ JniResult (*CallDoubleMethod)(jobject obj, jmethodID methodID);
+ JniResult (*CallDoubleMethodV)(jobject, jmethodID, void*);
+ JniResult (*CallDoubleMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+ jthrowable (*CallVoidMethod)(jobject obj, jmethodID methodID);
+ jthrowable (*CallVoidMethodV)(jobject, jmethodID, void*);
+ jthrowable (*CallVoidMethodA)(jobject obj, jmethodID methodID, jvalue* args);
+ JniResult (*CallNonvirtualObjectMethod)(jobject obj,
+ jclass clazz,
+ jmethodID methodID);
+ JniResult (*CallNonvirtualObjectMethodV)(jobject, jclass, jmethodID, void*);
+ JniResult (*CallNonvirtualObjectMethodA)(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniResult (*CallNonvirtualBooleanMethod)(jobject obj,
+ jclass clazz,
+ jmethodID methodID);
+ JniResult (*CallNonvirtualBooleanMethodV)(jobject, jclass, jmethodID, void*);
+ JniResult (*CallNonvirtualBooleanMethodA)(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniResult (*CallNonvirtualByteMethod)(jobject obj,
+ jclass clazz,
+ jmethodID methodID);
+ JniResult (*CallNonvirtualByteMethodV)(jobject, jclass, jmethodID, void*);
+ JniResult (*CallNonvirtualByteMethodA)(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniResult (*CallNonvirtualCharMethod)(jobject obj,
+ jclass clazz,
+ jmethodID methodID);
+ JniResult (*CallNonvirtualCharMethodV)(jobject, jclass, jmethodID, void*);
+ JniResult (*CallNonvirtualCharMethodA)(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniResult (*CallNonvirtualShortMethod)(jobject obj,
+ jclass clazz,
+ jmethodID methodID);
+ JniResult (*CallNonvirtualShortMethodV)(jobject, jclass, jmethodID, void*);
+ JniResult (*CallNonvirtualShortMethodA)(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniResult (*CallNonvirtualIntMethod)(jobject obj,
+ jclass clazz,
+ jmethodID methodID);
+ JniResult (*CallNonvirtualIntMethodV)(jobject, jclass, jmethodID, void*);
+ JniResult (*CallNonvirtualIntMethodA)(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniResult (*CallNonvirtualLongMethod)(jobject obj,
+ jclass clazz,
+ jmethodID methodID);
+ JniResult (*CallNonvirtualLongMethodV)(jobject, jclass, jmethodID, void*);
+ JniResult (*CallNonvirtualLongMethodA)(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniResult (*CallNonvirtualFloatMethod)(jobject obj,
+ jclass clazz,
+ jmethodID methodID);
+ JniResult (*CallNonvirtualFloatMethodV)(jobject, jclass, jmethodID, void*);
+ JniResult (*CallNonvirtualFloatMethodA)(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniResult (*CallNonvirtualDoubleMethod)(jobject obj,
+ jclass clazz,
+ jmethodID methodID);
+ JniResult (*CallNonvirtualDoubleMethodV)(jobject, jclass, jmethodID, void*);
+ JniResult (*CallNonvirtualDoubleMethodA)(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ jthrowable (*CallNonvirtualVoidMethod)(jobject obj,
+ jclass clazz,
+ jmethodID methodID);
+ jthrowable (*CallNonvirtualVoidMethodV)(jobject, jclass, jmethodID, void*);
+ jthrowable (*CallNonvirtualVoidMethodA)(jobject obj,
+ jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniPointerResult (*GetFieldID)(jclass clazz, char* name, char* sig);
+ JniResult (*GetObjectField)(jobject obj, jfieldID fieldID);
+ JniResult (*GetBooleanField)(jobject obj, jfieldID fieldID);
+ JniResult (*GetByteField)(jobject obj, jfieldID fieldID);
+ JniResult (*GetCharField)(jobject obj, jfieldID fieldID);
+ JniResult (*GetShortField)(jobject obj, jfieldID fieldID);
+ JniResult (*GetIntField)(jobject obj, jfieldID fieldID);
+ JniResult (*GetLongField)(jobject obj, jfieldID fieldID);
+ JniResult (*GetFloatField)(jobject obj, jfieldID fieldID);
+ JniResult (*GetDoubleField)(jobject obj, jfieldID fieldID);
+ jthrowable (*SetObjectField)(jobject obj, jfieldID fieldID, jobject val);
+ jthrowable (*SetBooleanField)(jobject obj, jfieldID fieldID, jboolean val);
+ jthrowable (*SetByteField)(jobject obj, jfieldID fieldID, jbyte val);
+ jthrowable (*SetCharField)(jobject obj, jfieldID fieldID, jchar val);
+ jthrowable (*SetShortField)(jobject obj, jfieldID fieldID, jshort val);
+ jthrowable (*SetIntField)(jobject obj, jfieldID fieldID, jint val);
+ jthrowable (*SetLongField)(jobject obj, jfieldID fieldID, jlong val);
+ jthrowable (*SetFloatField)(jobject obj, jfieldID fieldID, jfloat val);
+ jthrowable (*SetDoubleField)(jobject obj, jfieldID fieldID, jdouble val);
+ JniPointerResult (*GetStaticMethodID)(jclass clazz, char* name, char* sig);
+ JniResult (*CallStaticObjectMethod)(jclass clazz, jmethodID methodID);
+ JniResult (*CallStaticObjectMethodV)(jclass, jmethodID, void*);
+ JniResult (*CallStaticObjectMethodA)(jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniResult (*CallStaticBooleanMethod)(jclass clazz, jmethodID methodID);
+ JniResult (*CallStaticBooleanMethodV)(jclass, jmethodID, void*);
+ JniResult (*CallStaticBooleanMethodA)(jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniResult (*CallStaticByteMethod)(jclass clazz, jmethodID methodID);
+ JniResult (*CallStaticByteMethodV)(jclass, jmethodID, void*);
+ JniResult (*CallStaticByteMethodA)(jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniResult (*CallStaticCharMethod)(jclass clazz, jmethodID methodID);
+ JniResult (*CallStaticCharMethodV)(jclass, jmethodID, void*);
+ JniResult (*CallStaticCharMethodA)(jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniResult (*CallStaticShortMethod)(jclass clazz, jmethodID methodID);
+ JniResult (*CallStaticShortMethodV)(jclass, jmethodID, void*);
+ JniResult (*CallStaticShortMethodA)(jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniResult (*CallStaticIntMethod)(jclass clazz, jmethodID methodID);
+ JniResult (*CallStaticIntMethodV)(jclass, jmethodID, void*);
+ JniResult (*CallStaticIntMethodA)(jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniResult (*CallStaticLongMethod)(jclass clazz, jmethodID methodID);
+ JniResult (*CallStaticLongMethodV)(jclass, jmethodID, void*);
+ JniResult (*CallStaticLongMethodA)(jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniResult (*CallStaticFloatMethod)(jclass clazz, jmethodID methodID);
+ JniResult (*CallStaticFloatMethodV)(jclass, jmethodID, void*);
+ JniResult (*CallStaticFloatMethodA)(jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniResult (*CallStaticDoubleMethod)(jclass clazz, jmethodID methodID);
+ JniResult (*CallStaticDoubleMethodV)(jclass, jmethodID, void*);
+ JniResult (*CallStaticDoubleMethodA)(jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ jthrowable (*CallStaticVoidMethod)(jclass clazz, jmethodID methodID);
+ jthrowable (*CallStaticVoidMethodV)(jclass, jmethodID, void*);
+ jthrowable (*CallStaticVoidMethodA)(jclass clazz,
+ jmethodID methodID,
+ jvalue* args);
+ JniPointerResult (*GetStaticFieldID)(jclass clazz, char* name, char* sig);
+ JniResult (*GetStaticObjectField)(jclass clazz, jfieldID fieldID);
+ JniResult (*GetStaticBooleanField)(jclass clazz, jfieldID fieldID);
+ JniResult (*GetStaticByteField)(jclass clazz, jfieldID fieldID);
+ JniResult (*GetStaticCharField)(jclass clazz, jfieldID fieldID);
+ JniResult (*GetStaticShortField)(jclass clazz, jfieldID fieldID);
+ JniResult (*GetStaticIntField)(jclass clazz, jfieldID fieldID);
+ JniResult (*GetStaticLongField)(jclass clazz, jfieldID fieldID);
+ JniResult (*GetStaticFloatField)(jclass clazz, jfieldID fieldID);
+ JniResult (*GetStaticDoubleField)(jclass clazz, jfieldID fieldID);
+ jthrowable (*SetStaticObjectField)(jclass clazz,
+ jfieldID fieldID,
+ jobject val);
+ jthrowable (*SetStaticBooleanField)(jclass clazz,
+ jfieldID fieldID,
+ jboolean val);
+ jthrowable (*SetStaticByteField)(jclass clazz, jfieldID fieldID, jbyte val);
+ jthrowable (*SetStaticCharField)(jclass clazz, jfieldID fieldID, jchar val);
+ jthrowable (*SetStaticShortField)(jclass clazz, jfieldID fieldID, jshort val);
+ jthrowable (*SetStaticIntField)(jclass clazz, jfieldID fieldID, jint val);
+ jthrowable (*SetStaticLongField)(jclass clazz, jfieldID fieldID, jlong val);
+ jthrowable (*SetStaticFloatField)(jclass clazz, jfieldID fieldID, jfloat val);
+ jthrowable (*SetStaticDoubleField)(jclass clazz,
+ jfieldID fieldID,
+ jdouble val);
+ JniResult (*NewString)(jchar* unicodeChars, jsize len);
+ JniResult (*GetStringLength)(jstring string);
+ JniPointerResult (*GetStringChars)(jstring string, jboolean* isCopy);
+ jthrowable (*ReleaseStringChars)(jstring string, jchar* isCopy);
+ JniResult (*NewStringUTF)(char* bytes);
+ JniResult (*GetStringUTFLength)(jstring string);
+ JniPointerResult (*GetStringUTFChars)(jstring string, jboolean* isCopy);
+ jthrowable (*ReleaseStringUTFChars)(jstring string, char* utf);
+ JniResult (*GetArrayLength)(jarray array);
+ JniResult (*NewObjectArray)(jsize length,
+ jclass elementClass,
+ jobject initialElement);
+ JniResult (*GetObjectArrayElement)(jobjectArray array, jsize index);
+ jthrowable (*SetObjectArrayElement)(jobjectArray array,
+ jsize index,
+ jobject val);
+ JniResult (*NewBooleanArray)(jsize length);
+ JniResult (*NewByteArray)(jsize length);
+ JniResult (*NewCharArray)(jsize length);
+ JniResult (*NewShortArray)(jsize length);
+ JniResult (*NewIntArray)(jsize length);
+ JniResult (*NewLongArray)(jsize length);
+ JniResult (*NewFloatArray)(jsize length);
+ JniResult (*NewDoubleArray)(jsize length);
+ JniPointerResult (*GetBooleanArrayElements)(jbooleanArray array,
+ jboolean* isCopy);
+ JniPointerResult (*GetByteArrayElements)(jbyteArray array, jboolean* isCopy);
+ JniPointerResult (*GetCharArrayElements)(jcharArray array, jboolean* isCopy);
+ JniPointerResult (*GetShortArrayElements)(jshortArray array,
+ jboolean* isCopy);
+ JniPointerResult (*GetIntArrayElements)(jintArray array, jboolean* isCopy);
+ JniPointerResult (*GetLongArrayElements)(jlongArray array, jboolean* isCopy);
+ JniPointerResult (*GetFloatArrayElements)(jfloatArray array,
+ jboolean* isCopy);
+ JniPointerResult (*GetDoubleArrayElements)(jdoubleArray array,
+ jboolean* isCopy);
+ jthrowable (*ReleaseBooleanArrayElements)(jbooleanArray array,
+ jboolean* elems,
+ jint mode);
+ jthrowable (*ReleaseByteArrayElements)(jbyteArray array,
+ jbyte* elems,
+ jint mode);
+ jthrowable (*ReleaseCharArrayElements)(jcharArray array,
+ jchar* elems,
+ jint mode);
+ jthrowable (*ReleaseShortArrayElements)(jshortArray array,
+ jshort* elems,
+ jint mode);
+ jthrowable (*ReleaseIntArrayElements)(jintArray array,
+ jint* elems,
+ jint mode);
+ jthrowable (*ReleaseLongArrayElements)(jlongArray array,
+ jlong* elems,
+ jint mode);
+ jthrowable (*ReleaseFloatArrayElements)(jfloatArray array,
+ jfloat* elems,
+ jint mode);
+ jthrowable (*ReleaseDoubleArrayElements)(jdoubleArray array,
+ jdouble* elems,
+ jint mode);
+ jthrowable (*GetBooleanArrayRegion)(jbooleanArray array,
+ jsize start,
+ jsize len,
+ jboolean* buf);
+ jthrowable (*GetByteArrayRegion)(jbyteArray array,
+ jsize start,
+ jsize len,
+ jbyte* buf);
+ jthrowable (*GetCharArrayRegion)(jcharArray array,
+ jsize start,
+ jsize len,
+ jchar* buf);
+ jthrowable (*GetShortArrayRegion)(jshortArray array,
+ jsize start,
+ jsize len,
+ jshort* buf);
+ jthrowable (*GetIntArrayRegion)(jintArray array,
+ jsize start,
+ jsize len,
+ jint* buf);
+ jthrowable (*GetLongArrayRegion)(jlongArray array,
+ jsize start,
+ jsize len,
+ jlong* buf);
+ jthrowable (*GetFloatArrayRegion)(jfloatArray array,
+ jsize start,
+ jsize len,
+ jfloat* buf);
+ jthrowable (*GetDoubleArrayRegion)(jdoubleArray array,
+ jsize start,
+ jsize len,
+ jdouble* buf);
+ jthrowable (*SetBooleanArrayRegion)(jbooleanArray array,
+ jsize start,
+ jsize len,
+ jboolean* buf);
+ jthrowable (*SetByteArrayRegion)(jbyteArray array,
+ jsize start,
+ jsize len,
+ jbyte* buf);
+ jthrowable (*SetCharArrayRegion)(jcharArray array,
+ jsize start,
+ jsize len,
+ jchar* buf);
+ jthrowable (*SetShortArrayRegion)(jshortArray array,
+ jsize start,
+ jsize len,
+ jshort* buf);
+ jthrowable (*SetIntArrayRegion)(jintArray array,
+ jsize start,
+ jsize len,
+ jint* buf);
+ jthrowable (*SetLongArrayRegion)(jlongArray array,
+ jsize start,
+ jsize len,
+ jlong* buf);
+ jthrowable (*SetFloatArrayRegion)(jfloatArray array,
+ jsize start,
+ jsize len,
+ jfloat* buf);
+ jthrowable (*SetDoubleArrayRegion)(jdoubleArray array,
+ jsize start,
+ jsize len,
+ jdouble* buf);
+ JniResult (*RegisterNatives)(jclass clazz,
+ JNINativeMethod* methods,
+ jint nMethods);
+ JniResult (*UnregisterNatives)(jclass clazz);
+ JniResult (*MonitorEnter)(jobject obj);
+ JniResult (*MonitorExit)(jobject obj);
+ JniResult (*GetJavaVM)(JavaVM** vm);
+ jthrowable (*GetStringRegion)(jstring str,
+ jsize start,
+ jsize len,
+ jchar* buf);
+ jthrowable (*GetStringUTFRegion)(jstring str,
+ jsize start,
+ jsize len,
+ char* buf);
+ JniPointerResult (*GetPrimitiveArrayCritical)(jarray array, jboolean* isCopy);
+ jthrowable (*ReleasePrimitiveArrayCritical)(jarray array,
+ void* carray,
+ jint mode);
+ JniPointerResult (*GetStringCritical)(jstring str, jboolean* isCopy);
+ jthrowable (*ReleaseStringCritical)(jstring str, jchar* carray);
+ JniResult (*NewWeakGlobalRef)(jobject obj);
+ jthrowable (*DeleteWeakGlobalRef)(jweak obj);
+ JniResult (*ExceptionCheck)();
+ JniResult (*NewDirectByteBuffer)(void* address, jlong capacity);
+ JniPointerResult (*GetDirectBufferAddress)(jobject buf);
+ JniResult (*GetDirectBufferCapacity)(jobject buf);
+ JniResult (*GetObjectRefType)(jobject obj);
+} GlobalJniEnvStruct;
+FFI_PLUGIN_EXPORT GlobalJniEnvStruct* GetGlobalEnv();
diff --git a/pkgs/jni/test/boxed_test.dart b/pkgs/jni/test/boxed_test.dart
new file mode 100644
index 0000000..261b1ac
--- /dev/null
+++ b/pkgs/jni/test/boxed_test.dart
@@ -0,0 +1,146 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:jni/jni.dart';
+import 'package:test/test.dart';
+
+import 'test_util/test_util.dart';
+
+void main() {
+ // Don't forget to initialize JNI.
+ if (!Platform.isAndroid) {
+ checkDylibIsUpToDate();
+ Jni.spawnIfNotExists(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+ }
+ run(testRunner: test);
+}
+
+void run({required TestRunnerCallback testRunner}) {
+ testRunner('JByte', () {
+ const val = 1 << 5;
+ using((arena) {
+ expect(JByte(val).byteValue(releaseOriginal: true), val);
+ expect((-val).toJByte().byteValue(releaseOriginal: true), -val);
+ });
+ });
+ testRunner('JCharacter', () {
+ const val = 1 << 5;
+ using((arena) {
+ expect(JCharacter(val).charValue(releaseOriginal: true), val);
+ expect(JCharacter(0).charValue(releaseOriginal: true), 0);
+ });
+ });
+ testRunner('JShort', () {
+ const val = 1 << 10;
+ using((arena) {
+ expect(JShort(val).shortValue(releaseOriginal: true), val);
+ expect((-val).toJShort().shortValue(releaseOriginal: true), -val);
+ });
+ });
+ testRunner('JInteger', () {
+ const val = 1 << 20;
+ using((arena) {
+ expect(JInteger(val).intValue(releaseOriginal: true), val);
+ expect((-val).toJInteger().intValue(releaseOriginal: true), -val);
+ });
+ });
+ testRunner('JLong', () {
+ const val = 1 << 40;
+ using((arena) {
+ expect(JLong(val).longValue(releaseOriginal: true), val);
+ expect((-val).toJLong().longValue(releaseOriginal: true), -val);
+ });
+ });
+ testRunner('JFloat', () {
+ const val = 3.14;
+ const eps = 1e-6;
+ using((arena) {
+ expect(JFloat(val).floatValue(releaseOriginal: true), closeTo(val, eps));
+ expect((-val).toJFloat().floatValue(releaseOriginal: true),
+ closeTo(-val, eps));
+ });
+ });
+ testRunner('JDouble', () {
+ const val = 3.14;
+ const eps = 1e-9;
+ using((arena) {
+ expect(
+ JDouble(val).doubleValue(releaseOriginal: true), closeTo(val, eps));
+ expect((-val).toJDouble().doubleValue(releaseOriginal: true),
+ closeTo(-val, eps));
+ });
+ });
+ testRunner('JBoolean', () {
+ using((arena) {
+ expect(JBoolean(false).booleanValue(releaseOriginal: true), false);
+ expect(JBoolean(true).booleanValue(releaseOriginal: true), true);
+ });
+ });
+ testRunner('JByte.\$type hashCode and ==', () {
+ using((arena) {
+ final a = JByte(1)..releasedBy(arena);
+ final b = JByte(2)..releasedBy(arena);
+ expect(a.$type, b.$type);
+ expect(a.$type.hashCode, b.$type.hashCode);
+ });
+ });
+ testRunner('JCharacter.\$type hashCode and ==', () {
+ using((arena) {
+ final a = JCharacter(1)..releasedBy(arena);
+ final b = JCharacter(2)..releasedBy(arena);
+ expect(a.$type, b.$type);
+ expect(a.$type.hashCode, b.$type.hashCode);
+ });
+ });
+ testRunner('JShort.\$type hashCode and ==', () {
+ using((arena) {
+ final a = JShort(1)..releasedBy(arena);
+ final b = JShort(2)..releasedBy(arena);
+ expect(a.$type, b.$type);
+ expect(a.$type.hashCode, b.$type.hashCode);
+ });
+ });
+ testRunner('JInteger.\$type hashCode and ==', () {
+ using((arena) {
+ final a = JInteger(1)..releasedBy(arena);
+ final b = JInteger(2)..releasedBy(arena);
+ expect(a.$type, b.$type);
+ expect(a.$type.hashCode, b.$type.hashCode);
+ });
+ });
+ testRunner('JLong.\$type hashCode and ==', () {
+ using((arena) {
+ final a = JLong(1)..releasedBy(arena);
+ final b = JLong(2)..releasedBy(arena);
+ expect(a.$type, b.$type);
+ expect(a.$type.hashCode, b.$type.hashCode);
+ });
+ });
+ testRunner('JFloat.\$type hashCode and ==', () {
+ using((arena) {
+ final a = JFloat(1.0)..releasedBy(arena);
+ final b = JFloat(2.0)..releasedBy(arena);
+ expect(a.$type, b.$type);
+ expect(a.$type.hashCode, b.$type.hashCode);
+ });
+ });
+ testRunner('JDouble.\$type hashCode and ==', () {
+ using((arena) {
+ final a = JDouble(1.0)..releasedBy(arena);
+ final b = JDouble(2.0)..releasedBy(arena);
+ expect(a.$type, b.$type);
+ expect(a.$type.hashCode, b.$type.hashCode);
+ });
+ });
+ testRunner('JBoolean.\$type hashCode and ==', () {
+ using((arena) {
+ final a = JBoolean(true)..releasedBy(arena);
+ final b = JBoolean(false)..releasedBy(arena);
+ expect(a.$type, b.$type);
+ expect(a.$type.hashCode, b.$type.hashCode);
+ });
+ });
+}
diff --git a/pkgs/jni/test/exception_test.dart b/pkgs/jni/test/exception_test.dart
new file mode 100644
index 0000000..42d2297
--- /dev/null
+++ b/pkgs/jni/test/exception_test.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:test/test.dart';
+import 'package:jni/jni.dart';
+
+import 'test_util/test_util.dart';
+
+void main() {
+ if (!Platform.isAndroid) {
+ checkDylibIsUpToDate();
+ bool caught = false;
+ try {
+ // If library does not exist, a helpful error should be thrown.
+ // we can't test this directly because `test` schedules functions
+ // asynchronously.
+ Jni.spawn(dylibDir: "wrong_dir");
+ } on HelperNotFoundError catch (_) {
+ // stderr.write("\n$_\n");
+ Jni.spawnIfNotExists(
+ dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+ caught = true;
+ } on JniVmExistsError {
+ stderr.writeln('cannot verify: HelperNotFoundError thrown');
+ }
+ if (!caught) {
+ throw "Expected HelperNotFoundException\n"
+ "Read exception_test.dart for details.";
+ }
+ }
+ run(testRunner: test);
+}
+
+void run({required TestRunnerCallback testRunner}) {
+ testRunner("double free throws exception", () {
+ final r = Jni.newInstance("java/util/Random", "()V", []);
+ r.release();
+ expect(r.release, throwsA(isA<DoubleReleaseError>()));
+ });
+
+ testRunner("Use after free throws exception", () {
+ final r = Jni.newInstance("java/util/Random", "()V", []);
+ r.release();
+ expect(() => r.callMethodByName<int>("nextInt", "(I)I", [JValueInt(256)]),
+ throwsA(isA<UseAfterReleaseError>()));
+ });
+
+ testRunner("void fieldType throws exception", () {
+ final r = Jni.newInstance("java/util/Random", "()V", []);
+ expect(() => r.getField<void>(nullptr, JniCallType.voidType),
+ throwsArgumentError);
+ expect(() => r.getStaticField<void>(nullptr, JniCallType.voidType),
+ throwsArgumentError);
+ });
+
+ testRunner("Wrong callType throws error", () {
+ final r = Jni.newInstance("java/util/Random", "()V", []);
+ expect(
+ () => r.callMethodByName<int>(
+ "nextInt", "(I)I", [JValueInt(256)], JniCallType.doubleType),
+ throwsA(isA<InvalidCallTypeError>()));
+ });
+
+ testRunner("An exception in JNI throws JniException in Dart", () {
+ final r = Jni.newInstance("java/util/Random", "()V", []);
+ expect(() => r.callMethodByName<int>("nextInt", "(I)I", [JValueInt(-1)]),
+ throwsA(isA<JniException>()));
+ });
+}
diff --git a/pkgs/jni/test/global_env_test.dart b/pkgs/jni/test/global_env_test.dart
new file mode 100644
index 0000000..a5588cd
--- /dev/null
+++ b/pkgs/jni/test/global_env_test.dart
@@ -0,0 +1,215 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:ffi/ffi.dart';
+import 'package:jni/jni.dart';
+import 'package:jni/src/jvalues.dart';
+import 'package:test/test.dart';
+
+import 'test_util/test_util.dart';
+
+const maxLongInJava = 9223372036854775807;
+
+void main() {
+ // Running on Android through flutter, this plugin
+ // will bind to Android runtime's JVM.
+ // On other platforms eg Flutter desktop or Dart standalone
+ // You need to manually create a JVM at beginning.
+ //
+ // On flutter desktop, the C wrappers are bundled, and helperPath param
+ // is not required.
+ //
+ // On dart standalone, however, there's no way to bundle the wrappers.
+ // You have to manually pass the path to the `dartjni` dynamic library.
+
+ if (!Platform.isAndroid) {
+ checkDylibIsUpToDate();
+ Jni.spawnIfNotExists(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+ }
+ run(testRunner: test);
+}
+
+// We are factoring these tests into a run method which allows us to run same
+// tests with different environments. Eg: standalone and integration tests.
+void run({required TestRunnerCallback testRunner}) {
+ // Tests in this file demonstrate how to use `GlobalJniEnv`, a thin
+ // abstraction over JNIEnv in JNI C API. This can be used from multiple
+ // threads, and converts all returned object references to global references,
+ // so that you don't need to worry about whether your Dart code will be
+ // scheduled on another thread.
+ //
+ // GlobalJniEnv wraps all methods of JNIEnv (UpperCamelCase, reflecting the
+ // original name of the method) and provides few more extension methods
+ // (lowerCamelCase).
+ //
+ // For examples of a higher level API, see `jni_object_tests.dart`.
+ final env = Jni.env;
+ testRunner('initDLApi', () {
+ Jni.initDLApi();
+ });
+
+ testRunner('get JNI Version', () {
+ expect(Jni.env.GetVersion(), isNot(equals(0)));
+ });
+
+ testRunner(
+ 'Manually lookup & call Integer.toHexString',
+ () => using((arena) {
+ // Method names on JniEnv* from C JNI API are capitalized
+ // like in original, while other extension methods
+ // follow Dart naming conventions.
+ final integerClass =
+ env.FindClass("java/lang/Integer".toNativeChars(arena));
+ // Refer JNI spec on how to construct method signatures
+ // Passing wrong signature leads to a segfault
+ final hexMethod = env.GetStaticMethodID(
+ integerClass,
+ "toHexString".toNativeChars(arena),
+ "(I)Ljava/lang/String;".toNativeChars(arena));
+
+ for (var i in [1, 80, 13, 76, 11344]) {
+ // if your argument is int, bool, or JObject (`Pointer<Void>`)
+ // it can be directly placed in the list. To convert into different primitive
+ // types, use JValue<Type> wrappers.
+ final jres = env.CallStaticObjectMethodA(integerClass, hexMethod,
+ Jni.jvalues([JValueInt(i)], allocator: arena));
+
+ // use asDartString extension method on Pointer<JniEnv>
+ // to convert a String jobject result to string
+ final res = env.toDartString(jres);
+ expect(res, equals(i.toRadixString(16)));
+
+ // Any object or class result from java is a local reference
+ // and needs to be deleted explicitly.
+ // Note that method and field IDs aren't local references.
+ // But they are valid only until a reference to corresponding
+ // java class exists.
+ env.DeleteGlobalRef(jres);
+ }
+ env.DeleteGlobalRef(integerClass);
+ }));
+
+ testRunner("asJString extension method", () {
+ const str = "QWERTY QWERTY";
+ // convenience method that wraps
+ // converting dart string to native string,
+ // instantiating java string, and freeing the native string
+ final jstr = env.toJStringPtr(str);
+ expect(str, equals(env.toDartString(jstr)));
+ env.DeleteGlobalRef(jstr);
+ });
+
+ testRunner(
+ 'GlobalJniEnv should catch exceptions',
+ () => using((arena) {
+ final integerClass =
+ env.FindClass("java/lang/Integer".toNativeChars(arena));
+ final parseIntMethod = env.GetStaticMethodID(
+ integerClass,
+ "parseInt".toNativeChars(arena),
+ "(Ljava/lang/String;)I".toNativeChars(arena));
+ final args = JValueArgs(["hello"], arena);
+ expect(
+ () => env.CallStaticIntMethodA(
+ integerClass, parseIntMethod, args.values),
+ throwsA(isA<JniException>()));
+ }));
+
+ testRunner(
+ "Convert back & forth between Dart & Java strings (UTF-8)",
+ () => using((arena) {
+ const str = "ABCD EFGH";
+ final jstr = env.NewStringUTF(str.toNativeChars(arena));
+ final jchars = env.GetStringUTFChars(jstr, nullptr);
+ final jlen = env.GetStringUTFLength(jstr);
+ final dstr = jchars.toDartString(length: jlen);
+ env.ReleaseStringUTFChars(jstr, jchars);
+ expect(str, equals(dstr));
+ env.DeleteGlobalRef(jstr);
+ }));
+
+ testRunner(
+ "Convert back & forth between Dart & Java strings (UTF-16)",
+ () => using((arena) {
+ const str = "ABCD EFGH";
+ final jstr = env.NewString(str.toNativeUtf16().cast(), str.length);
+ final jchars = env.GetStringChars(jstr, nullptr);
+ final jlen = env.GetStringLength(jstr);
+ final dstr = jchars.cast<Utf16>().toDartString(length: jlen);
+ env.ReleaseStringChars(jstr, jchars);
+ expect(str, equals(dstr));
+ env.DeleteGlobalRef(jstr);
+ }));
+
+ testRunner(
+ "Print something from Java",
+ () => using((arena) {
+ final system =
+ env.FindClass("java/lang/System".toNativeChars(arena));
+ final field = env.GetStaticFieldID(
+ system,
+ "out".toNativeChars(arena),
+ "Ljava/io/PrintStream;".toNativeChars(arena));
+ final out = env.GetStaticObjectField(system, field);
+ final printStream = env.GetObjectClass(out);
+ final println = env.GetMethodID(
+ printStream,
+ "println".toNativeChars(arena),
+ "(Ljava/lang/String;)V".toNativeChars(arena));
+ const str = "\nHello World from JNI!";
+ final jstr = env.toJStringPtr(str);
+ env.CallVoidMethodA(out, println, Jni.jvalues([jstr]));
+ env.deleteAllRefs([system, printStream, jstr]);
+ }));
+ testRunner(
+ 'Env create reference methods should retain their default behavior', () {
+ final systemOut = Jni.retrieveStaticField<JObjectPtr>(
+ "java/lang/System", "out", "Ljava/io/PrintStream;");
+ var refType = env.GetObjectRefType(systemOut);
+ expect(refType, equals(JObjectRefType.JNIGlobalRefType));
+ final localRef = env.NewLocalRef(systemOut);
+ refType = env.GetObjectRefType(localRef);
+ expect(refType, equals(JObjectRefType.JNILocalRefType));
+ final weakRef = env.NewWeakGlobalRef(systemOut);
+ refType = env.GetObjectRefType(weakRef);
+ expect(refType, equals(JObjectRefType.JNIWeakGlobalRefType));
+ final globalRef = env.NewGlobalRef(localRef);
+ refType = env.GetObjectRefType(globalRef);
+ expect(refType, equals(JObjectRefType.JNIGlobalRefType));
+ env.DeleteGlobalRef(globalRef);
+ env.DeleteWeakGlobalRef(weakRef);
+ env.DeleteLocalRef(localRef);
+ env.DeleteGlobalRef(systemOut);
+ });
+ testRunner('long methods return long int without loss of precision', () {
+ using((arena) {
+ final longClass = env.FindClass("java/lang/Long".toNativeChars(arena));
+ final maxField = env.GetStaticFieldID(
+ longClass,
+ 'MAX_VALUE'.toNativeChars(arena),
+ 'J'.toNativeChars(arena),
+ );
+ final maxValue = env.GetStaticLongField(longClass, maxField);
+ expect(maxValue, equals(maxLongInJava));
+ env.DeleteGlobalRef(longClass);
+ });
+ });
+
+ testRunner('class <-> object methods', () {
+ using((arena) {
+ final systemOut = Jni.retrieveStaticField<JObjectPtr>(
+ "java/lang/System", "out", "Ljava/io/PrintStream;");
+ final systemErr = Jni.retrieveStaticField<JObjectPtr>(
+ "java/lang/System", "err", "Ljava/io/PrintStream;");
+ final outClass = env.GetObjectClass(systemOut);
+ expect(env.IsInstanceOf(systemOut, outClass), isTrue);
+ expect(env.IsInstanceOf(systemErr, outClass), isTrue);
+ final errClass = env.GetObjectClass(systemErr);
+ expect(env.IsSameObject(outClass, errClass), isTrue);
+ env.deleteAllRefs([systemOut, systemErr, outClass, errClass]);
+ });
+ });
+}
diff --git a/pkgs/jni/test/jarray_test.dart b/pkgs/jni/test/jarray_test.dart
new file mode 100644
index 0000000..064bc84
--- /dev/null
+++ b/pkgs/jni/test/jarray_test.dart
@@ -0,0 +1,374 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:jni/jni.dart';
+import 'package:test/test.dart';
+
+import 'test_util/test_util.dart';
+
+void main() {
+ // Don't forget to initialize JNI.
+ if (!Platform.isAndroid) {
+ checkDylibIsUpToDate();
+ Jni.spawnIfNotExists(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+ }
+ run(testRunner: test);
+}
+
+void run({required TestRunnerCallback testRunner}) {
+ testRunner("Java boolean array", () {
+ using((arena) {
+ final array = JArray(jboolean.type, 3)..releasedBy(arena);
+ expect(array.length, 3);
+ array[0] = true;
+ array[1] = false;
+ array[2] = false;
+ expect(array[0], true);
+ expect(array[1], false);
+ expect(array[2], false);
+ array.setRange(0, 3, [false, true, true, true], 1);
+ expect(array[0], true);
+ expect(array[1], true);
+ expect(array[2], true);
+ expect(() {
+ final _ = array[-1];
+ }, throwsRangeError);
+ expect(() {
+ array[-1] = false;
+ }, throwsRangeError);
+ expect(() {
+ array[3] = false;
+ }, throwsRangeError);
+ });
+ });
+ testRunner("Java char array", () {
+ using((arena) {
+ final array = JArray(jchar.type, 3)..releasedBy(arena);
+ expect(array.length, 3);
+ array[0] = 'ح';
+ array[1] = '2';
+ array[2] = '3';
+ expect(array[0], 'ح');
+ expect(array[1], '2');
+ expect(array[2], '3');
+ array.setRange(0, 3, ['4', '5', '6', '7'], 1);
+ expect(array[0], '5');
+ expect(array[1], '6');
+ expect(array[2], '7');
+ expect(() {
+ final _ = array[-1];
+ }, throwsRangeError);
+ expect(() {
+ array[-1] = '4';
+ }, throwsRangeError);
+ expect(() {
+ array[3] = '4';
+ }, throwsRangeError);
+ });
+ });
+ testRunner("Java byte array", () {
+ using((arena) {
+ final array = JArray(jbyte.type, 3)..releasedBy(arena);
+ expect(array.length, 3);
+ array[0] = 1;
+ array[1] = 2;
+ array[2] = 3 + 256 * 5; // truncates the input;
+ expect(array[0], 1);
+ expect(array[1], 2);
+ expect(array[2], 3);
+ array.setRange(0, 3, [4, 5, 6, 7], 1);
+ expect(array[0], 5);
+ expect(array[1], 6);
+ expect(array[2], 7);
+ expect(() {
+ final _ = array[-1];
+ }, throwsRangeError);
+ expect(() {
+ array[-1] = 4;
+ }, throwsRangeError);
+ expect(() {
+ array[3] = 4;
+ }, throwsRangeError);
+ });
+ });
+ testRunner("Java short array", () {
+ using((arena) {
+ final array = JArray(jshort.type, 3)..releasedBy(arena);
+ expect(array.length, 3);
+ array[0] = 1;
+ array[1] = 2;
+ array[2] = 3 + 256 * 256 * 5; // truncates the input
+ expect(array[0], 1);
+ expect(array[1], 2);
+ expect(array[2], 3);
+ array.setRange(0, 3, [4, 5, 6, 7], 1);
+ expect(array[0], 5);
+ expect(array[1], 6);
+ expect(array[2], 7);
+ expect(() {
+ final _ = array[-1];
+ }, throwsRangeError);
+ expect(() {
+ array[-1] = 4;
+ }, throwsRangeError);
+ expect(() {
+ array[3] = 4;
+ }, throwsRangeError);
+ });
+ });
+ testRunner("Java int array", () {
+ using((arena) {
+ final array = JArray(jint.type, 3)..releasedBy(arena);
+ expect(array.length, 3);
+ array[0] = 1;
+ array[1] = 2;
+ array[2] = 3 + 256 * 256 * 256 * 256 * 5; // truncates the input
+ expect(array[0], 1);
+ expect(array[1], 2);
+ expect(array[2], 3);
+ array.setRange(0, 3, [4, 5, 6, 7], 1);
+ expect(array[0], 5);
+ expect(array[1], 6);
+ expect(array[2], 7);
+ expect(() {
+ final _ = array[-1];
+ }, throwsRangeError);
+ expect(() {
+ array[-1] = 4;
+ }, throwsRangeError);
+ expect(() {
+ array[3] = 4;
+ }, throwsRangeError);
+ });
+ });
+ testRunner("Java long array", () {
+ using((arena) {
+ final array = JArray(jlong.type, 3)..releasedBy(arena);
+ expect(array.length, 3);
+ array[0] = 1;
+ array[1] = 2;
+ array[2] = 3 + 256 * 256 * 256 * 256 * 5;
+ expect(array[0], 1);
+ expect(array[1], 2);
+ expect(array[2], 3 + 256 * 256 * 256 * 256 * 5);
+ array.setRange(0, 3, [4, 5, 6, 7], 1);
+ expect(array[0], 5);
+ expect(array[1], 6);
+ expect(array[2], 7);
+ expect(() {
+ final _ = array[-1];
+ }, throwsRangeError);
+ expect(() {
+ array[-1] = 4;
+ }, throwsRangeError);
+ expect(() {
+ array[3] = 4;
+ }, throwsRangeError);
+ });
+ });
+ const epsilon = 1e-6;
+ testRunner("Java float array", () {
+ using((arena) {
+ final array = JArray(jfloat.type, 3)..releasedBy(arena);
+ expect(array.length, 3);
+ array[0] = 0.5;
+ array[1] = 2;
+ array[2] = 3;
+ expect(array[0], closeTo(0.5, epsilon));
+ expect(array[1], closeTo(2, epsilon));
+ expect(array[2], closeTo(3, epsilon));
+ array.setRange(0, 3, [4, 5, 6, 7], 1);
+ expect(array[0], closeTo(5, epsilon));
+ expect(array[1], closeTo(6, epsilon));
+ expect(array[2], closeTo(7, epsilon));
+ expect(() {
+ final _ = array[-1];
+ }, throwsRangeError);
+ expect(() {
+ array[-1] = 4;
+ }, throwsRangeError);
+ expect(() {
+ array[3] = 4;
+ }, throwsRangeError);
+ });
+ });
+ testRunner("Java double array", () {
+ using((arena) {
+ final array = JArray(jdouble.type, 3)..releasedBy(arena);
+ expect(array.length, 3);
+ array[0] = 0.5;
+ array[1] = 2;
+ array[2] = 3;
+ expect(array[0], closeTo(0.5, epsilon));
+ expect(array[1], closeTo(2, epsilon));
+ expect(array[2], closeTo(3, epsilon));
+ array.setRange(0, 3, [4, 5, 6, 7], 1);
+ expect(array[0], closeTo(5, epsilon));
+ expect(array[1], closeTo(6, epsilon));
+ expect(array[2], closeTo(7, epsilon));
+ expect(() {
+ final _ = array[-1];
+ }, throwsRangeError);
+ expect(() {
+ array[-1] = 4;
+ }, throwsRangeError);
+ expect(() {
+ array[3] = 4;
+ }, throwsRangeError);
+ });
+ });
+ testRunner("Java string array", () {
+ using((arena) {
+ final array = JArray(JString.type, 3)..releasedBy(arena);
+ expect(array.length, 3);
+ array[0] = "حس".toJString()..releasedBy(arena);
+ array[1] = "\$".toJString()..releasedBy(arena);
+ array[2] = "33".toJString()..releasedBy(arena);
+ expect(array[0].toDartString(releaseOriginal: true), "حس");
+ expect(array[1].toDartString(releaseOriginal: true), "\$");
+ expect(array[2].toDartString(releaseOriginal: true), "33");
+ array.setRange(
+ 0,
+ 3,
+ [
+ "44".toJString()..releasedBy(arena),
+ "55".toJString()..releasedBy(arena),
+ "66".toJString()..releasedBy(arena),
+ "77".toJString()..releasedBy(arena),
+ ],
+ 1,
+ );
+ expect(array[0].toDartString(releaseOriginal: true), "55");
+ expect(array[1].toDartString(releaseOriginal: true), "66");
+ expect(array[2].toDartString(releaseOriginal: true), "77");
+ expect(() {
+ final _ = array[-1];
+ }, throwsRangeError);
+ expect(() {
+ array[-1] = "44".toJString()..releasedBy(arena);
+ }, throwsRangeError);
+ expect(() {
+ array[3] = "44".toJString()..releasedBy(arena);
+ }, throwsRangeError);
+ });
+ });
+ testRunner("Java object array", () {
+ using((arena) {
+ final array = JArray(JObject.type, 3)..releasedBy(arena);
+ expect(array.length, 3);
+ expect(array[0].reference, nullptr);
+ expect(array[1].reference, nullptr);
+ expect(array[2].reference, nullptr);
+ });
+ });
+ testRunner("Java 2d array", () {
+ using((arena) {
+ final array = JArray(jint.type, 3)..releasedBy(arena);
+ array[0] = 1;
+ array[1] = 2;
+ array[2] = 3;
+ final twoDimArray = JArray(JArray.type(jint.type), 3)..releasedBy(arena);
+ expect(twoDimArray.length, 3);
+ twoDimArray[0] = array;
+ twoDimArray[1] = array;
+ twoDimArray[2] = array;
+ for (var i = 0; i < 3; ++i) {
+ expect(twoDimArray[i][0], 1);
+ expect(twoDimArray[i][1], 2);
+ expect(twoDimArray[i][2], 3);
+ }
+ twoDimArray[2][2] = 4;
+ expect(twoDimArray[2][2], 4);
+ });
+ });
+ testRunner("JArray.filled", () {
+ using((arena) {
+ final string = "abc".toJString()..releasedBy(arena);
+ final array = JArray.filled(3, string)..releasedBy(arena);
+ expect(
+ () => JArray.filled(-3, JString.fromRef(nullptr)),
+ throwsA(isA<RangeError>()),
+ );
+ expect(array.length, 3);
+ expect(array[0].toDartString(releaseOriginal: true), "abc");
+ expect(array[1].toDartString(releaseOriginal: true), "abc");
+ expect(array[2].toDartString(releaseOriginal: true), "abc");
+ });
+ });
+ testRunner('JArray of JByte', () {
+ using((arena) {
+ final arr = JArray(JByte.type, 1)..releasedBy(arena);
+ expect((arr[0]..releasedBy(arena)).isNull, true);
+ });
+ });
+ testRunner('JArray of JShort', () {
+ using((arena) {
+ final arr = JArray(JShort.type, 1)..releasedBy(arena);
+ expect((arr[0]..releasedBy(arena)).isNull, true);
+ });
+ });
+ testRunner('JArray of JInteger', () {
+ using((arena) {
+ final arr = JArray(JInteger.type, 1)..releasedBy(arena);
+ expect((arr[0]..releasedBy(arena)).isNull, true);
+ });
+ });
+ testRunner('JArray of JCharacter', () {
+ using((arena) {
+ final arr = JArray(JCharacter.type, 1)..releasedBy(arena);
+ expect((arr[0]..releasedBy(arena)).isNull, true);
+ });
+ });
+ testRunner('JArray of JLong', () {
+ using((arena) {
+ final arr = JArray(JLong.type, 1)..releasedBy(arena);
+ expect((arr[0]..releasedBy(arena)).isNull, true);
+ });
+ });
+ testRunner('JArray of JFloat', () {
+ using((arena) {
+ final arr = JArray(JFloat.type, 1)..releasedBy(arena);
+ expect((arr[0]..releasedBy(arena)).isNull, true);
+ });
+ });
+ testRunner('JArray of JDouble', () {
+ using((arena) {
+ final arr = JArray(JDouble.type, 1)..releasedBy(arena);
+ expect((arr[0]..releasedBy(arena)).isNull, true);
+ });
+ });
+ testRunner('JArray of JBoolean', () {
+ using((arena) {
+ final arr = JArray(JBoolean.type, 1)..releasedBy(arena);
+ expect((arr[0]..releasedBy(arena)).isNull, true);
+ });
+ });
+ testRunner('JArray of JSet', () {
+ using((arena) {
+ final arr = JArray(JSet.type(JString.type), 1)..releasedBy(arena);
+ expect((arr[0]..releasedBy(arena)).isNull, true);
+ });
+ });
+ testRunner('JArray of JList', () {
+ using((arena) {
+ final arr = JArray(JList.type(JString.type), 1)..releasedBy(arena);
+ expect((arr[0]..releasedBy(arena)).isNull, true);
+ });
+ });
+ testRunner('JArray of JMap', () {
+ using((arena) {
+ final arr = JArray(JMap.type(JString.type, JString.type), 1)
+ ..releasedBy(arena);
+ expect((arr[0]..releasedBy(arena)).isNull, true);
+ });
+ });
+ testRunner('JArray of JIterator', () {
+ using((arena) {
+ final arr = JArray(JIterator.type(JString.type), 1)..releasedBy(arena);
+ expect((arr[0]..releasedBy(arena)).isNull, true);
+ });
+ });
+}
diff --git a/pkgs/jni/test/jbyte_buffer_test.dart b/pkgs/jni/test/jbyte_buffer_test.dart
new file mode 100644
index 0000000..48f9eaf
--- /dev/null
+++ b/pkgs/jni/test/jbyte_buffer_test.dart
@@ -0,0 +1,229 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:jni/jni.dart';
+import 'package:test/test.dart';
+
+import 'test_util/test_util.dart';
+
+void main() {
+ // Don't forget to initialize JNI.
+ if (!Platform.isAndroid) {
+ checkDylibIsUpToDate();
+ Jni.spawnIfNotExists(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+ }
+ run(testRunner: test);
+}
+
+void run({required TestRunnerCallback testRunner}) {
+ final throwsAJniException = throwsA(isA<JniException>());
+ JByteBuffer testDataBuffer(Arena arena) {
+ final buffer = JByteBuffer.allocate(3)..releasedBy(arena);
+ buffer.nextByte = 1;
+ buffer.nextByte = 2;
+ buffer.nextByte = 3;
+ buffer.position = 0;
+ return buffer;
+ }
+
+ testRunner('wrap whole array', () {
+ using((arena) {
+ final array = JArray(jbyte.type, 3)..releasedBy(arena);
+ array[0] = 1;
+ array[1] = 2;
+ array[2] = 3;
+ final buffer = JByteBuffer.wrap(array)..releasedBy(arena);
+ expect(buffer, testDataBuffer(arena));
+ });
+ });
+
+ testRunner('wrap partial array', () {
+ using((arena) {
+ final array = JArray(jbyte.type, 3)..releasedBy(arena);
+ array[0] = 1;
+ array[1] = 2;
+ array[2] = 3;
+ final buffer = JByteBuffer.wrap(array, 1, 1)..releasedBy(arena);
+ expect(buffer.nextByte, 2);
+ expect(() => buffer.nextByte, throwsAJniException);
+ });
+ });
+
+ testRunner('capacity', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ expect(buffer.capacity, 3);
+ });
+ });
+
+ testRunner('position', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ expect(buffer.position, 0);
+ buffer.position = 2;
+ expect(buffer.position, 2);
+ });
+ });
+
+ testRunner('limit', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ expect(buffer.limit, 3);
+ buffer.limit = 2;
+ expect(buffer.limit, 2);
+ });
+ });
+
+ testRunner('mark and reset', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ buffer.position = 1;
+ buffer.mark();
+ buffer.position = 2;
+ buffer.reset();
+ expect(buffer.position, 1);
+ });
+ });
+
+ testRunner('clear', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ buffer.position = 2;
+ buffer.limit = 2;
+ buffer.clear();
+ expect(buffer.limit, 3);
+ expect(buffer.position, 0);
+ });
+ });
+
+ testRunner('flip', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ buffer.position = 2;
+ buffer.flip();
+ expect(buffer.limit, 2);
+ expect(buffer.position, 0);
+ });
+ });
+
+ testRunner('rewind', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ buffer.mark();
+ buffer.position = 2;
+ buffer.rewind();
+ expect(buffer.position, 0);
+ expect(buffer.reset, throwsAJniException);
+ });
+ });
+
+ testRunner('remaining and hasRemaining', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ buffer.position = 2;
+ expect(buffer.remaining, 1);
+ expect(buffer.hasRemaining, true);
+ buffer.position = 3;
+ expect(buffer.remaining, 0);
+ expect(buffer.hasRemaining, false);
+ });
+ });
+
+ testRunner('isReadOnly and asReadOnlyBuffer', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ expect(buffer.isReadOnly, false);
+ final readOnly = buffer.asReadOnlyBuffer()..releasedBy(arena);
+ expect(readOnly.isReadOnly, true);
+ });
+ });
+
+ testRunner('hasArray, array and arrayOffset', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ expect(buffer.hasArray, true);
+ expect(buffer.arrayOffset, 0);
+ expect(buffer.array.length, 3);
+ final directBuffer = JByteBuffer.allocateDirect(3)..releasedBy(arena);
+ expect(directBuffer.hasArray, false);
+ });
+ });
+
+ testRunner('isDirect', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ expect(buffer.isDirect, false);
+ final directBuffer = JByteBuffer.allocateDirect(3)..releasedBy(arena);
+ expect(directBuffer.isDirect, true);
+ });
+ });
+
+ testRunner('slice', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ buffer.position = 1;
+ buffer.limit = 2;
+ final sliced = buffer.slice()..releasedBy(arena);
+ expect(sliced.capacity, 1);
+ expect(sliced.nextByte, 2);
+ });
+ });
+
+ testRunner('duplicate', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ buffer.position = 1;
+ buffer.limit = 2;
+ final duplicate = buffer.duplicate()..releasedBy(arena);
+ expect(duplicate.capacity, 3);
+ expect(duplicate.position, 1);
+ expect(duplicate.limit, 2);
+ });
+ });
+
+ testRunner('asUint8List', () {
+ using((arena) {
+ final buffer = testDataBuffer(arena);
+ expect(buffer.asUint8List, throwsA(isA<StateError>()));
+ final list = Uint8List.fromList([1, 2, 3]);
+ final directBuffer = list.toJByteBuffer()..releasedBy(arena);
+ expect(directBuffer.asUint8List(), list);
+ });
+ });
+
+ testRunner('type hashCode, ==', () {
+ using((arena) {
+ final a = testDataBuffer(arena);
+ final b = testDataBuffer(arena);
+ expect(a.$type, b.$type);
+ expect(a.$type.hashCode, b.$type.hashCode);
+ final c = JBuffer.fromRef(nullptr);
+ final d = JBuffer.fromRef(nullptr);
+ expect(c.$type, d.$type);
+ expect(c.$type.hashCode, d.$type.hashCode);
+
+ expect(a.$type, isNot(c.$type));
+ expect(a.$type.hashCode, isNot(c.$type.hashCode));
+ });
+ });
+
+ testRunner('asUint8List releasing original', () {
+ using((arena) {
+ // Used as an example in [JByteBuffer].
+ final directBuffer = JByteBuffer.allocateDirect(3);
+ final data1 = directBuffer.asUint8List();
+ directBuffer.nextByte = 42; // No problem!
+ expect(data1[0], 42);
+ final data2 = directBuffer.asUint8List(releaseOriginal: true);
+ expect(
+ () => directBuffer.nextByte = 42,
+ throwsA(isA<UseAfterReleaseError>()),
+ );
+ expect(data2[0], 42);
+ });
+ });
+}
diff --git a/pkgs/jni/test/jfinal_string_test.dart b/pkgs/jni/test/jfinal_string_test.dart
new file mode 100644
index 0000000..c8a9980
--- /dev/null
+++ b/pkgs/jni/test/jfinal_string_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:jni/jni.dart';
+import 'package:jni/src/jfinal_string.dart';
+import 'package:test/test.dart';
+
+import 'test_util/test_util.dart';
+
+void main() {
+ // Don't forget to initialize JNI.
+ if (!Platform.isAndroid) {
+ checkDylibIsUpToDate();
+ Jni.spawnIfNotExists(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+ }
+ run(testRunner: test);
+}
+
+void run({required TestRunnerCallback testRunner}) {
+ testRunner('JFinalString', () {
+ const string = 'abc';
+ var referenceFetchedCount = 0;
+ final finalString = JFinalString(
+ () {
+ ++referenceFetchedCount;
+ return string.toJString().reference;
+ },
+ string,
+ );
+ expect(finalString.toDartString(), string);
+ expect(referenceFetchedCount, 0);
+ expect(finalString.reference, isNot(nullptr));
+ expect(referenceFetchedCount, 1);
+ finalString.reference;
+ expect(referenceFetchedCount, 1);
+ expect(finalString.toDartString(releaseOriginal: true), string);
+ expect(() => finalString.reference, throwsA(isA<UseAfterReleaseError>()));
+ expect(finalString.release, throwsA(isA<DoubleReleaseError>()));
+ });
+}
diff --git a/pkgs/jni/test/jlist_test.dart b/pkgs/jni/test/jlist_test.dart
new file mode 100644
index 0000000..b410525
--- /dev/null
+++ b/pkgs/jni/test/jlist_test.dart
@@ -0,0 +1,216 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:jni/jni.dart';
+import 'package:test/test.dart';
+
+import 'test_util/test_util.dart';
+
+void main() {
+ // Don't forget to initialize JNI.
+ if (!Platform.isAndroid) {
+ checkDylibIsUpToDate();
+ Jni.spawnIfNotExists(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+ }
+ run(testRunner: test);
+}
+
+void run({required TestRunnerCallback testRunner}) {
+ JList<JString> testDataList(Arena arena) {
+ return [
+ "1".toJString()..releasedBy(arena),
+ "2".toJString()..releasedBy(arena),
+ "3".toJString()..releasedBy(arena),
+ ].toJList(JString.type)
+ ..releasedBy(arena);
+ }
+
+ testRunner('length get', () {
+ using((arena) {
+ final list = testDataList(arena);
+ expect(list.length, 3);
+ });
+ });
+ testRunner('length set', () {
+ using((arena) {
+ final list = testDataList(arena);
+ list.length = 2;
+ expect(list.length, 2);
+ list.length = 3;
+ expect(list.length, 3);
+ expect(list.last.isNull, true);
+ });
+ });
+ testRunner('[]', () {
+ using((arena) {
+ final list = testDataList(arena);
+ expect(list[0].toDartString(releaseOriginal: true), "1");
+ expect(list[1].toDartString(releaseOriginal: true), "2");
+ expect(list[2].toDartString(releaseOriginal: true), "3");
+ });
+ });
+ testRunner('[]=', () {
+ using((arena) {
+ final list = testDataList(arena);
+ expect(list[0].toDartString(releaseOriginal: true), "1");
+ list[0] = "2".toJString()..releasedBy(arena);
+ expect(list[0].toDartString(releaseOriginal: true), "2");
+ });
+ });
+ testRunner('add', () {
+ using((arena) {
+ final list = testDataList(arena);
+ list.add("4".toJString()..releasedBy(arena));
+ expect(list.length, 4);
+ expect(list[3].toDartString(releaseOriginal: true), "4");
+ });
+ });
+ testRunner('addAll', () {
+ using((arena) {
+ final list = testDataList(arena);
+ final toAppend = testDataList(arena);
+ list.addAll(toAppend);
+ expect(list.length, 6);
+ list.addAll(["4".toJString()..releasedBy(arena)]);
+ expect(list.length, 7);
+ });
+ });
+ testRunner('clear, isEmpty, isNotEmpty', () {
+ using((arena) {
+ final list = testDataList(arena);
+ expect(list.isNotEmpty, true);
+ expect(list.isEmpty, false);
+ list.clear();
+ expect(list.isNotEmpty, false);
+ expect(list.isEmpty, true);
+ });
+ });
+ testRunner('contains', () {
+ using((arena) {
+ final list = testDataList(arena);
+ // ignore: iterable_contains_unrelated_type
+ expect(list.contains("1"), false);
+ expect(list.contains("1".toJString()..releasedBy(arena)), true);
+ expect(list.contains("4".toJString()..releasedBy(arena)), false);
+ });
+ });
+ testRunner('getRange', () {
+ using((arena) {
+ final list = testDataList(arena);
+ // ignore: iterable_contains_unrelated_type
+ final range = list.getRange(1, 2)..releasedBy(arena);
+ expect(range.length, 1);
+ expect(range.first.toDartString(releaseOriginal: true), "2");
+ });
+ });
+ testRunner('indexOf', () {
+ using((arena) {
+ final list = testDataList(arena);
+ expect(list.indexOf(1), -1);
+ expect(list.indexOf("1".toJString()..toDartString()), 0);
+ expect(list.indexOf("2".toJString()..toDartString()), 1);
+ expect(list.indexOf("1".toJString()..toDartString(), 1), -1);
+ expect(list.indexOf("1".toJString()..toDartString(), -1), 0);
+ });
+ });
+ testRunner('insert', () {
+ using((arena) {
+ final list = testDataList(arena);
+ list.insert(1, "0".toJString()..releasedBy(arena));
+ expect(list.length, 4);
+ expect(list[1].toDartString(releaseOriginal: true), "0");
+ });
+ });
+ testRunner('insertAll', () {
+ using((arena) {
+ final list = testDataList(arena);
+ final toInsert = testDataList(arena);
+ list.insertAll(1, toInsert);
+ expect(list[1].toDartString(releaseOriginal: true), "1");
+ expect(list.length, 6);
+ list.insertAll(1, ["4".toJString()..releasedBy(arena)]);
+ expect(list.length, 7);
+ expect(list[1].toDartString(releaseOriginal: true), "4");
+ });
+ });
+ testRunner('iterator', () {
+ using((arena) {
+ final list = testDataList(arena);
+ final it = list.iterator;
+ expect(it.moveNext(), true);
+ expect(it.current.toDartString(releaseOriginal: true), "1");
+ expect(it.moveNext(), true);
+ expect(it.current.toDartString(releaseOriginal: true), "2");
+ expect(it.moveNext(), true);
+ expect(it.current.toDartString(releaseOriginal: true), "3");
+ expect(it.moveNext(), false);
+ });
+ });
+ testRunner('remove', () {
+ using((arena) {
+ final list = testDataList(arena);
+ expect(list.remove("3".toJString()..releasedBy(arena)), true);
+ expect(list.length, 2);
+ expect(list.remove("4".toJString()..releasedBy(arena)), false);
+ // ignore: list_remove_unrelated_type
+ expect(list.remove(1), false);
+ });
+ });
+ testRunner('removeAt', () {
+ using((arena) {
+ final list = testDataList(arena);
+ expect(list.removeAt(0).toDartString(releaseOriginal: true), "1");
+ expect(list.removeAt(1).toDartString(releaseOriginal: true), "3");
+ });
+ });
+ testRunner('removeRange', () {
+ using((arena) {
+ final list = testDataList(arena);
+ list.removeRange(0, 2);
+ expect(list.single.toDartString(releaseOriginal: true), "3");
+ });
+ });
+ testRunner('==, hashCode', () {
+ using((arena) {
+ final a = testDataList(arena);
+ final b = testDataList(arena);
+ expect(a.hashCode, b.hashCode);
+ expect(a, b);
+ b.add("4".toJString()..releasedBy(arena));
+ expect(a.hashCode, isNot(b.hashCode));
+ expect(a, isNot(b));
+ });
+ });
+ testRunner('toSet', () {
+ using((arena) {
+ final list = testDataList(arena);
+ final set = list.toSet()..releasedBy(arena);
+ expect(set.length, 3);
+ });
+ });
+ testRunner('type hashCode, ==', () {
+ using((arena) {
+ final a = testDataList(arena);
+ final b = testDataList(arena);
+ expect(a.$type, b.$type);
+ expect(a.$type.hashCode, b.$type.hashCode);
+ final c = JList.array(JObject.type)..releasedBy(arena);
+ expect(a.$type, isNot(c.$type));
+ expect(a.$type.hashCode, isNot(c.$type.hashCode));
+ });
+ });
+ testRunner('JIterator type hashCode, ==', () {
+ using((arena) {
+ final a = testDataList(arena);
+ final b = testDataList(arena);
+ expect(a.iterator.$type, b.iterator.$type);
+ expect(a.iterator.$type.hashCode, b.iterator.$type.hashCode);
+ final c = JList.array(JObject.type)..releasedBy(arena);
+ expect(a.iterator.$type, isNot(c.iterator.$type));
+ expect(a.iterator.$type.hashCode, isNot(c.iterator.$type.hashCode));
+ });
+ });
+}
diff --git a/pkgs/jni/test/jmap_test.dart b/pkgs/jni/test/jmap_test.dart
new file mode 100644
index 0000000..4ece751
--- /dev/null
+++ b/pkgs/jni/test/jmap_test.dart
@@ -0,0 +1,170 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:jni/jni.dart';
+import 'package:test/test.dart';
+
+import 'test_util/test_util.dart';
+
+void main() {
+ // Don't forget to initialize JNI.
+ if (!Platform.isAndroid) {
+ Jni.spawnIfNotExists(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+ }
+ run(testRunner: test);
+}
+
+void run({required TestRunnerCallback testRunner}) {
+ JMap<JString, JString> testDataMap(Arena arena) {
+ return {
+ "1".toJString()..releasedBy(arena): "One".toJString()..releasedBy(arena),
+ "2".toJString()..releasedBy(arena): "Two".toJString()..releasedBy(arena),
+ "3".toJString()..releasedBy(arena): "Three".toJString()
+ ..releasedBy(arena),
+ }.toJMap(JString.type, JString.type)
+ ..releasedBy(arena);
+ }
+
+ testRunner('length', () {
+ using((arena) {
+ final map = testDataMap(arena);
+ expect(map.length, 3);
+ });
+ });
+ testRunner('[]', () {
+ using((arena) {
+ final map = testDataMap(arena);
+ // ignore: collection_methods_unrelated_type
+ expect(map[1], null);
+ expect(
+ map["1".toJString()..releasedBy(arena)]
+ ?.toDartString(releaseOriginal: true),
+ "One",
+ );
+ expect(
+ map["4".toJString()..releasedBy(arena)],
+ null,
+ );
+ });
+ });
+ testRunner('[]=', () {
+ using((arena) {
+ final map = testDataMap(arena);
+ map["0".toJString()..releasedBy(arena)] = "Zero".toJString()
+ ..releasedBy(arena);
+ expect(
+ map["0".toJString()..releasedBy(arena)]
+ ?.toDartString(releaseOriginal: true),
+ "Zero",
+ );
+ expect(map.length, 4);
+ map["1".toJString()..releasedBy(arena)] = "one!".toJString()
+ ..releasedBy(arena);
+ expect(
+ map["1".toJString()..releasedBy(arena)]
+ ?.toDartString(releaseOriginal: true),
+ "one!",
+ );
+ expect(map.length, 4);
+ });
+ });
+ testRunner('addAll', () {
+ using((arena) {
+ final map = testDataMap(arena);
+ final toAdd = {
+ "0".toJString()..releasedBy(arena): "Zero".toJString()
+ ..releasedBy(arena),
+ "1".toJString()..releasedBy(arena): "one!".toJString()
+ ..releasedBy(arena),
+ }.toJMap(JString.type, JString.type);
+ map.addAll(toAdd);
+ expect(map.length, 4);
+ expect(
+ map["0".toJString()..releasedBy(arena)]
+ ?.toDartString(releaseOriginal: true),
+ "Zero",
+ );
+ expect(
+ map["1".toJString()..releasedBy(arena)]
+ ?.toDartString(releaseOriginal: true),
+ "one!",
+ );
+ map.addAll({
+ "4".toJString()..releasedBy(arena): "Four".toJString()
+ ..releasedBy(arena)
+ });
+ expect(map.length, 5);
+ });
+ });
+ testRunner('clear, isEmpty, isNotEmpty', () {
+ using((arena) {
+ final map = testDataMap(arena);
+ expect(map.isEmpty, false);
+ expect(map.isNotEmpty, true);
+ map.clear();
+ expect(map.isEmpty, true);
+ expect(map.isNotEmpty, false);
+ });
+ });
+ testRunner('containsKey', () {
+ using((arena) {
+ final map = testDataMap(arena);
+ // ignore: iterable_contains_unrelated_type
+ expect(map.containsKey(1), false);
+ expect(map.containsKey("1".toJString()..releasedBy(arena)), true);
+ expect(map.containsKey("4".toJString()..releasedBy(arena)), false);
+ });
+ });
+ testRunner('containsValue', () {
+ using((arena) {
+ final map = testDataMap(arena);
+ // ignore: iterable_contains_unrelated_type
+ expect(map.containsValue(1), false);
+ expect(map.containsValue("One".toJString()..releasedBy(arena)), true);
+ expect(map.containsValue("Four".toJString()..releasedBy(arena)), false);
+ });
+ });
+ testRunner('keys', () {
+ using((arena) {
+ final map = testDataMap(arena);
+ final keys = map.keys;
+ expect(
+ keys
+ .map((element) => element.toDartString(releaseOriginal: true))
+ .toSet(),
+ {"1", "2", "3"},
+ );
+ });
+ });
+ testRunner('remove', () {
+ using((arena) {
+ final map = testDataMap(arena);
+ // ignore: collection_methods_unrelated_type
+ expect(map.remove(1), null);
+ expect(map.remove("4".toJString()..releasedBy(arena)), null);
+ expect(map.length, 3);
+ expect(
+ map
+ .remove("3".toJString()..releasedBy(arena))
+ ?.toDartString(releaseOriginal: true),
+ "Three",
+ );
+ expect(map.length, 2);
+ });
+ });
+ testRunner('type hashCode, ==', () {
+ using((arena) {
+ final a = testDataMap(arena);
+ final b = testDataMap(arena);
+ expect(a.$type, b.$type);
+ expect(a.$type, b.$type);
+ expect(a.$type.hashCode, b.$type.hashCode);
+ final c = JMap.hash(JObject.type, JObject.type)..releasedBy(arena);
+ expect(a.$type, isNot(c.$type));
+ expect(a.$type.hashCode, isNot(c.$type.hashCode));
+ });
+ });
+}
diff --git a/pkgs/jni/test/jobject_test.dart b/pkgs/jni/test/jobject_test.dart
new file mode 100644
index 0000000..a63828c
--- /dev/null
+++ b/pkgs/jni/test/jobject_test.dart
@@ -0,0 +1,293 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+import 'dart:ffi';
+import 'dart:isolate';
+
+import 'package:test/test.dart';
+
+import 'package:jni/jni.dart';
+
+import 'test_util/test_util.dart';
+
+const maxLongInJava = 9223372036854775807;
+
+void main() {
+ // Don't forget to initialize JNI.
+ if (!Platform.isAndroid) {
+ checkDylibIsUpToDate();
+ Jni.spawnIfNotExists(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+ }
+ run(testRunner: test);
+}
+
+void run({required TestRunnerCallback testRunner}) {
+ // The API based on JniEnv is intended to closely mimic C API of JNI,
+ // And thus can be too verbose for simple experimenting and one-off uses
+ // JObject API provides an easier way to perform some common operations.
+ //
+ // However, if binding generation using jnigen is possible, that should be
+ // the first choice.
+ testRunner("Long.intValue() using JObject", () {
+ // JClass wraps a local class reference, and
+ // provides convenience functions.
+ final longClass = Jni.findJClass("java/lang/Long");
+
+ // looks for a constructor with given signature.
+ // equivalently you can lookup a method with name <init>
+ final longCtor = longClass.getCtorID("(J)V");
+
+ // note that the arguments are just passed as a list.
+ // allowed argument types are primitive types, JObject and its subclasses,
+ // and raw JNI references (JObject). Strings will be automatically converted
+ // to JNI strings.
+ final long = longClass.newInstance(longCtor, [176]);
+
+ final intValue = long.callMethodByName<int>(
+ "intValue",
+ "()I",
+ [],
+ JniCallType.intType,
+ );
+ expect(intValue, equals(176));
+
+ // Release any JObject and JClass instances using `.release()` after use.
+ // This is not strictly required since JNI objects / classes have
+ // a [NativeFinalizer]. But deleting them after use is a good practice.
+ long.release();
+ longClass.release();
+ });
+
+ testRunner("call a static method using JClass APIs", () {
+ final integerClass = Jni.findJClass("java/lang/Integer");
+ final result = integerClass.callStaticMethodByName<JString>(
+ "toHexString", "(I)Ljava/lang/String;", [JValueInt(31)]);
+
+ // If the object is supposed to be a Java string you can call
+ // [toDartString] on it.
+ final resultString = result.toDartString();
+
+ // Dart string is a copy, original object can be released.
+ result.release();
+ expect(resultString, equals("1f"));
+
+ // Also don't forget to release the class.
+ integerClass.release();
+ });
+
+ testRunner("Call method with null argument, expect exception", () {
+ final integerClass = Jni.findJClass("java/lang/Integer");
+ expect(
+ () => integerClass.callStaticMethodByName<int>(
+ "parseInt", "(Ljava/lang/String;)I", [nullptr]),
+ throwsException);
+ integerClass.release();
+ });
+
+ // Skip this test on Android integration test because it fails there, possibly
+ // due to a CheckJNI precondition check.
+ if (!Platform.isAndroid) {
+ testRunner("Try to find a non-exisiting class, expect exception", () {
+ expect(() => Jni.findJClass("java/lang/NotExists"), throwsException);
+ });
+ }
+
+ // [callMethodByName] will be expensive if making same call many times.
+ // Use [getMethodID] to get a method ID and use it in subsequent calls.
+ testRunner("Example for using getMethodID", () {
+ final longClass = Jni.findJClass("java/lang/Long");
+ final bitCountMethod = longClass.getStaticMethodID("bitCount", "(J)I");
+
+ // Use newInstance if you want only one instance.
+ // It finds the class, gets constructor ID and constructs an instance.
+ final random = Jni.newInstance("java/util/Random", "()V", []);
+
+ // You don't need a [JClass] reference to get instance method IDs.
+ final nextIntMethod = random.getMethodID("nextInt", "(I)I");
+
+ for (int i = 0; i < 100; i++) {
+ int r = random.callMethod<int>(
+ nextIntMethod,
+ [JValueInt(256 * 256)],
+ JniCallType.intType,
+ );
+ int bits = 0;
+ final jbc = longClass.callStaticMethod<int>(
+ bitCountMethod,
+ [r],
+ JniCallType.intType,
+ );
+ while (r != 0) {
+ bits += r % 2;
+ r = (r / 2).floor();
+ }
+ expect(jbc, equals(bits));
+ }
+ random.release();
+ longClass.release();
+ });
+
+ // One-off invocation of static method in single call.
+ testRunner("invoke_", () {
+ final m = Jni.invokeStaticMethod<int>(
+ "java/lang/Short",
+ "compare",
+ "(SS)I",
+ [JValueShort(1234), JValueShort(1324)],
+ JniCallType.intType,
+ );
+ expect(m, equals(1234 - 1324));
+ });
+
+ testRunner("Java char from string", () {
+ final m = Jni.invokeStaticMethod<bool>("java/lang/Character", "isLowerCase",
+ "(C)Z", [JValueChar.fromString('X')]);
+ expect(m, isFalse);
+ });
+
+ // One-off access of static field in single call.
+ testRunner("Get static field directly", () {
+ final maxLong = Jni.retrieveStaticField<int>(
+ "java/lang/Short", "MAX_VALUE", "S", JniCallType.shortType);
+ expect(maxLong, equals(32767));
+ });
+
+ // Use [callStringMethod] if all you care about is a string result
+ testRunner("callStaticStringMethod", () {
+ final longClass = Jni.findJClass("java/lang/Long");
+ const n = 1223334444;
+ final strFromJava = longClass.callStaticMethodByName<String>(
+ "toOctalString", "(J)Ljava/lang/String;", [n]);
+ expect(strFromJava, equals(n.toRadixString(8)));
+ longClass.release();
+ });
+
+ // In [JObject], [JClass], and retrieve_/invoke_ methods
+ // you can also pass Dart strings, apart from range of types
+ // allowed by [Jni.jvalues].
+ // They will be converted automatically.
+ testRunner(
+ "Passing strings in arguments",
+ () {
+ final out = Jni.retrieveStaticField<JObject>(
+ "java/lang/System", "out", "Ljava/io/PrintStream;");
+ // uncomment next line to see output
+ // (\n because test runner prints first char at end of the line)
+ //out.callMethodByName<Null>(
+ // "println", "(Ljava/lang/Object;)V", ["\nWorks (Apparently)"]);
+ out.release();
+ },
+ );
+
+ testRunner("Passing strings in arguments 2", () {
+ final twelve = Jni.invokeStaticMethod<int>("java/lang/Byte", "parseByte",
+ "(Ljava/lang/String;)B", ["12"], JniCallType.byteType);
+ expect(twelve, equals(12));
+ });
+
+ // You can use() method on JObject for using once and deleting.
+ testRunner("use() method", () {
+ final randomInt = Jni.newInstance("java/util/Random", "()V", []).use(
+ (random) => random.callMethodByName<int>(
+ "nextInt",
+ "(I)I",
+ [JValueInt(15)],
+ JniCallType.intType,
+ ),
+ );
+ expect(randomInt, lessThan(15));
+ });
+
+ // The JObject and JClass have NativeFinalizer. However, it's possible to
+ // explicitly use `Arena`.
+ testRunner('Using arena', () {
+ final objects = <JObject>[];
+ using((arena) {
+ final r = Jni.findJClass('java/util/Random')..releasedBy(arena);
+ final ctor = r.getCtorID("()V");
+ for (int i = 0; i < 10; i++) {
+ objects.add(r.newInstance(ctor, [])..releasedBy(arena));
+ }
+ });
+ for (var object in objects) {
+ expect(object.isReleased, isTrue);
+ }
+ });
+
+ testRunner("enums", () {
+ // Don't forget to escape $ in nested type names
+ final ordinal = Jni.retrieveStaticField<JObject>(
+ "java/net/Proxy\$Type", "HTTP", "Ljava/net/Proxy\$Type;")
+ .use(
+ (f) => f.callMethodByName<int>(
+ "ordinal",
+ "()I",
+ [],
+ JniCallType.intType,
+ ),
+ );
+ expect(ordinal, equals(1));
+ });
+
+ testRunner("casting", () {
+ using((arena) {
+ final str = "hello".toJString()..releasedBy(arena);
+ final obj = str.castTo(JObject.type)..releasedBy(arena);
+ final backToStr = obj.castTo(JString.type);
+ expect(backToStr.toDartString(), str.toDartString());
+ final _ = backToStr.castTo(JObject.type, releaseOriginal: true)
+ ..releasedBy(arena);
+ expect(backToStr.toDartString, throwsA(isA<UseAfterReleaseError>()));
+ expect(backToStr.release, throwsA(isA<DoubleReleaseError>()));
+ });
+ });
+
+ testRunner("Isolate", () {
+ Isolate.spawn(doSomeWorkInIsolate, null);
+ });
+
+ testRunner("Methods rethrow exceptions in Java as JniException", () {
+ expect(
+ () => Jni.invokeStaticMethod<int>(
+ "java/lang/Integer", "parseInt", "(Ljava/lang/String;)I", ["X"]),
+ throwsA(isA<JniException>()),
+ );
+ });
+
+ testRunner("Passing long integer values to JNI", () {
+ final maxLongStr = Jni.invokeStaticMethod<String>(
+ "java/lang/Long",
+ "toString",
+ "(J)Ljava/lang/String;",
+ [maxLongInJava],
+ );
+ expect(maxLongStr, equals('$maxLongInJava'));
+ });
+
+ testRunner('Returning long integers from JNI', () {
+ final maxLong = Jni.retrieveStaticField<int>(
+ "java/lang/Long",
+ "MAX_VALUE",
+ "J",
+ JniCallType.longType,
+ );
+ expect(maxLong, equals(maxLongInJava));
+ });
+}
+
+void doSomeWorkInIsolate(Void? _) {
+ // On standalone target, make sure to call [setDylibDir] before accessing
+ // any JNI function in a new isolate.
+ //
+ // otherwise subsequent JNI calls will throw a "library not found" exception.
+ Jni.setDylibDir(dylibDir: "build/jni_libs");
+ final random = Jni.newInstance("java/util/Random", "()V", []);
+ // final r = random.callMethodByName<int>("nextInt", "(I)I", [256]);
+ // expect(r, lessThan(256));
+ // Expect throws an [OutsideTestException]
+ // but you can uncomment below print and see it works
+ // print("\n$r");
+ random.release();
+}
diff --git a/pkgs/jni/test/jset_test.dart b/pkgs/jni/test/jset_test.dart
new file mode 100644
index 0000000..2d93e63
--- /dev/null
+++ b/pkgs/jni/test/jset_test.dart
@@ -0,0 +1,202 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:jni/jni.dart';
+import 'package:test/test.dart';
+
+import 'test_util/test_util.dart';
+
+void main() {
+ // Don't forget to initialize JNI.
+ if (!Platform.isAndroid) {
+ checkDylibIsUpToDate();
+ Jni.spawnIfNotExists(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+ }
+ run(testRunner: test);
+}
+
+void run({required TestRunnerCallback testRunner}) {
+ JSet<JString> testDataSet(Arena arena) {
+ return {
+ "1".toJString()..releasedBy(arena),
+ "2".toJString()..releasedBy(arena),
+ "3".toJString()..releasedBy(arena),
+ }.toJSet(JString.type)
+ ..releasedBy(arena);
+ }
+
+ testRunner('length', () {
+ using((arena) {
+ final set = testDataSet(arena);
+ expect(set.length, 3);
+ });
+ });
+ testRunner('add', () {
+ using((arena) {
+ final set = testDataSet(arena);
+ set.add("1".toJString()..releasedBy(arena));
+ expect(set.length, 3);
+ set.add("4".toJString()..releasedBy(arena));
+ expect(set.length, 4);
+ });
+ });
+ testRunner('addAll', () {
+ using((arena) {
+ final set = testDataSet(arena);
+ final toAdd = testDataSet(arena);
+ toAdd.add("4".toJString()..releasedBy(arena));
+ set.addAll(toAdd);
+ expect(set.length, 4);
+ set.addAll([
+ "1".toJString()..releasedBy(arena),
+ "5".toJString()..releasedBy(arena),
+ ]);
+ expect(set.length, 5);
+ });
+ });
+ testRunner('clear, isEmpty, isNotEmpty', () {
+ using((arena) {
+ final set = testDataSet(arena);
+ set.clear();
+ expect(set.isEmpty, true);
+ expect(set.isNotEmpty, false);
+ });
+ });
+ testRunner('contains', () {
+ using((arena) {
+ final set = testDataSet(arena);
+ // ignore: iterable_contains_unrelated_type
+ expect(set.contains(1), false);
+ expect(set.contains("1".toJString()..releasedBy(arena)), true);
+ expect(set.contains("4".toJString()..releasedBy(arena)), false);
+ });
+ });
+ testRunner('containsAll', () {
+ using((arena) {
+ final set = testDataSet(arena);
+ expect(set.containsAll(set), true);
+ expect(
+ set.containsAll([
+ "1".toJString()..releasedBy(arena),
+ "2".toJString()..releasedBy(arena),
+ ]),
+ true,
+ );
+ final testSet = testDataSet(arena);
+ testSet.add("4".toJString()..releasedBy(arena));
+ expect(set.containsAll(testSet), false);
+ expect(set.containsAll(["4".toJString()..releasedBy(arena)]), false);
+ });
+ });
+ testRunner('iterator', () {
+ using((arena) {
+ final set = testDataSet(arena);
+ final it = set.iterator;
+ // There are no order guarantees in a hashset.
+ final dartSet = <String>{};
+ expect(it.moveNext(), true);
+ dartSet.add(it.current.toDartString(releaseOriginal: true));
+ expect(it.moveNext(), true);
+ dartSet.add(it.current.toDartString(releaseOriginal: true));
+ expect(it.moveNext(), true);
+ dartSet.add(it.current.toDartString(releaseOriginal: true));
+ expect(it.moveNext(), false);
+ // So we just check if the elements have appeared in some order.
+ expect(dartSet, {"1", "2", "3"});
+ });
+ });
+ testRunner('remove', () {
+ using((arena) {
+ final set = testDataSet(arena);
+ // ignore: collection_methods_unrelated_type
+ expect(set.remove(1), false);
+ expect(set.remove("4".toJString()..releasedBy(arena)), false);
+ expect(set.length, 3);
+ expect(set.remove("3".toJString()..releasedBy(arena)), true);
+ expect(set.length, 2);
+ });
+ });
+ testRunner('removeAll', () {
+ using((arena) {
+ final set = testDataSet(arena);
+ final toRemoveExclusive = {"4".toJString()..releasedBy(arena)}
+ .toJSet(JString.type)
+ ..releasedBy(arena);
+ set.removeAll(toRemoveExclusive);
+ expect(set.length, 3);
+ final toRemoveInclusive = {
+ "1".toJString()..releasedBy(arena),
+ "4".toJString()..releasedBy(arena),
+ }.toJSet(JString.type)
+ ..releasedBy(arena);
+ set.removeAll(toRemoveInclusive);
+ expect(set.length, 2);
+ set.removeAll(["2".toJString()..releasedBy(arena)]);
+ expect(set.length, 1);
+ });
+ });
+ testRunner('retainAll', () {
+ using((arena) {
+ final set = testDataSet(arena);
+ final toRetain = {
+ "1".toJString()..releasedBy(arena),
+ "3".toJString()..releasedBy(arena),
+ "4".toJString()..releasedBy(arena),
+ };
+ set.retainAll(set);
+ expect(set.length, 3);
+ set.retainAll(toRetain);
+ expect(set.length, 2);
+ final toRetainJSet = toRetain.toJSet(JString.type)..releasedBy(arena);
+ set.retainAll(toRetainJSet);
+ expect(set.length, 2);
+ });
+ });
+ testRunner('==, hashCode', () {
+ using((arena) {
+ final a = testDataSet(arena);
+ final b = testDataSet(arena);
+ expect(a.hashCode, b.hashCode);
+ expect(a, b);
+ b.add("4".toJString()..releasedBy(arena));
+ expect(a.hashCode, isNot(b.hashCode));
+ expect(a, isNot(b));
+ });
+ });
+ testRunner('lookup', () {
+ using((arena) {
+ final set = testDataSet(arena);
+ // ignore: iterable_contains_unrelated_type
+ expect(set.lookup(1), null);
+ expect(
+ set.lookup("1".toJString())?.toDartString(releaseOriginal: true),
+ "1",
+ );
+ expect(set.lookup("4".toJString()..releasedBy(arena)), null);
+ });
+ });
+ testRunner('toSet', () {
+ using((arena) {
+ // Test if the set gets copied.
+ final set = testDataSet(arena);
+ final setCopy = set.toSet()..releasedBy(arena);
+ expect(set, setCopy);
+ set.add("4".toJString()..releasedBy(arena));
+ expect(set, isNot(setCopy));
+ });
+ });
+ testRunner('type hashCode, ==', () {
+ using((arena) {
+ final a = testDataSet(arena);
+ final b = testDataSet(arena);
+ expect(a.$type, b.$type);
+ expect(a.$type.hashCode, b.$type.hashCode);
+ final c = JSet.hash(JObject.type)..releasedBy(arena);
+ expect(a.$type, isNot(c.$type));
+ expect(a.$type.hashCode, isNot(c.$type.hashCode));
+ });
+ });
+}
diff --git a/pkgs/jni/test/jstring_test.dart b/pkgs/jni/test/jstring_test.dart
new file mode 100644
index 0000000..c1a968c
--- /dev/null
+++ b/pkgs/jni/test/jstring_test.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:jni/jni.dart';
+import 'package:test/test.dart';
+
+import 'test_util/test_util.dart';
+
+void main() {
+ // Don't forget to initialize JNI.
+ if (!Platform.isAndroid) {
+ checkDylibIsUpToDate();
+ Jni.spawnIfNotExists(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+ }
+ run(testRunner: test);
+}
+
+void testStringBackAndForth(String str) {
+ final jstring = str.toJString();
+ final dartString = jstring.toDartString(releaseOriginal: true);
+ expect(dartString, str);
+}
+
+void run({required TestRunnerCallback testRunner}) {
+ group("String encoding tests", () {
+ testRunner('Long string back-and-forth', () {
+ testStringBackAndForth('1' * 8096);
+ });
+
+ testRunner('#278 UTF-8 bug', () {
+ testStringBackAndForth('🐬');
+ });
+
+ testRunner('String containing null character', () {
+ final str = 'A${String.fromCharCode(0)}B';
+ testStringBackAndForth(str);
+ });
+
+ testRunner('Zero length string', () {
+ testStringBackAndForth('');
+ });
+ });
+
+ testRunner('Inherited toString', () {
+ final s = 'hello'.toJString();
+ expect(s.toString(), 'hello');
+ });
+}
diff --git a/pkgs/jni/test/load_test.dart b/pkgs/jni/test/load_test.dart
new file mode 100644
index 0000000..d74a5fc
--- /dev/null
+++ b/pkgs/jni/test/load_test.dart
@@ -0,0 +1,135 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+@Tags(['load_test'])
+
+import 'dart:io';
+import 'dart:ffi';
+import 'dart:math';
+
+import 'package:ffi/ffi.dart';
+import 'package:test/test.dart';
+
+import 'package:jni/jni.dart';
+
+import 'test_util/test_util.dart';
+
+const maxLongInJava = 9223372036854775807;
+
+/// Taken from
+/// https://github.com/dart-lang/ffigen/blob/master/test/native_objc_test/automated_ref_count_test.dart
+final executeInternalCommand = DynamicLibrary.process().lookupFunction<
+ Void Function(Pointer<Char>, Pointer<Void>),
+ void Function(Pointer<Char>, Pointer<Void>)>('Dart_ExecuteInternalCommand');
+
+void doGC() {
+ final gcNow = "gc-now".toNativeUtf8();
+ executeInternalCommand(gcNow.cast(), nullptr);
+ calloc.free(gcNow);
+}
+
+void main() {
+ if (!Platform.isAndroid) {
+ checkDylibIsUpToDate();
+ Jni.spawnIfNotExists(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+ }
+ run(testRunner: test);
+}
+
+const k4 = 4 * 1024;
+const k64 = 64 * 1024;
+const k256 = 256 * 1024;
+
+const secureRandomSeedBound = 4294967296;
+
+JObject getSystemOut() => Jni.retrieveStaticField<JObject>(
+ 'System',
+ 'out',
+ 'Ljava/io/PrintStream;',
+ );
+
+final random = Random.secure();
+
+JObject newRandom() => Jni.newInstance(
+ "java/util/Random",
+ "(J)V",
+ [random.nextInt(secureRandomSeedBound)],
+ );
+
+void run({required TestRunnerCallback testRunner}) {
+ testRunner('Test 4K refs can be created in a row', () {
+ final list = <JObject>[];
+ for (int i = 0; i < k4; i++) {
+ list.add(newRandom());
+ }
+ for (final jobject in list) {
+ jobject.release();
+ }
+ });
+
+ testRunner('Create and release 256K references in a loop using arena', () {
+ for (int i = 0; i < k256; i++) {
+ using((arena) {
+ final random = newRandom()..releasedBy(arena);
+ // The actual expect here does not matter. I am just being paranoid
+ // against assigning to `_` because compiler may optimize it. (It has
+ // side effect of calling FFI but still.)
+ expect(random.reference, isNot(nullptr));
+ });
+ }
+ });
+
+ testRunner('Create and release 256K references in a loop (explicit release)',
+ () {
+ for (int i = 0; i < k256; i++) {
+ final random = newRandom();
+ expect(random.reference, isNot(nullptr));
+ random.release();
+ }
+ });
+
+ testRunner('Create and release 64K references, in batches of 256', () {
+ for (int i = 0; i < 64 * 4; i++) {
+ using((arena) {
+ for (int i = 0; i < 256; i++) {
+ final r = newRandom()..releasedBy(arena);
+ expect(r.reference, isNot(nullptr));
+ }
+ });
+ }
+ });
+
+ // We don't have a direct way to check if something creates JNI references.
+ // So we are checking if we can run this for large number of times.
+ testRunner('Verify a call returning primitive can be run any times', () {
+ final random = newRandom();
+ final nextInt = random.getMethodID("nextInt", "()I");
+ for (int i = 0; i < k256; i++) {
+ final rInt = random.callMethod<int>(nextInt, []);
+ expect(rInt, isA<int>());
+ }
+ });
+
+ void testRefValidityAfterGC(int delayInSeconds) {
+ testRunner('Validate reference after GC & ${delayInSeconds}s sleep', () {
+ final random = newRandom();
+ doGC();
+ sleep(Duration(seconds: delayInSeconds));
+ expect(
+ random.callMethodByName<int>("nextInt", "()I", []),
+ isA<int>(),
+ );
+ expect(
+ Jni.env.GetObjectRefType(random.reference),
+ equals(JObjectRefType.JNIGlobalRefType),
+ );
+ });
+ }
+
+ // Dart_ExecuteInternalCommand doesn't exist in Android.
+ if (!Platform.isAndroid) {
+ testRefValidityAfterGC(1);
+ testRefValidityAfterGC(10);
+ }
+}
diff --git a/pkgs/jni/test/test_util/test_util.dart b/pkgs/jni/test/test_util/test_util.dart
new file mode 100644
index 0000000..07e711a
--- /dev/null
+++ b/pkgs/jni/test/test_util/test_util.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:jni/src/build_util/build_util.dart';
+
+typedef TestCaseCallback = void Function();
+typedef TestRunnerCallback = void Function(
+ String description,
+ TestCaseCallback test,
+);
+
+final currentDir = Directory.current.uri;
+final dllSuffix =
+ Platform.isWindows ? "dll" : (Platform.isMacOS ? "dylib" : "so");
+final dllPrefix = Platform.isWindows ? '' : 'lib';
+final dllPath =
+ currentDir.resolve("build/jni_libs/${dllPrefix}dartjni.$dllSuffix");
+final srcPath = currentDir.resolve("src/");
+
+/// Fail if dartjni dll is stale.
+void checkDylibIsUpToDate() {
+ final dllFile = File.fromUri(dllPath);
+ if (needsBuild(File.fromUri(dllPath), Directory.fromUri(srcPath))) {
+ final cause = dllFile.existsSync()
+ ? 'not up-to-date with source modifications'
+ : 'not built';
+ var message = '\nFatal: dartjni.$dllSuffix is $cause. Please run '
+ '`dart run jni:setup` and try again.';
+ if (stderr.supportsAnsiEscapes) {
+ message = ansiRed + message + ansiDefault;
+ }
+ stderr.writeln(message);
+ exit(1);
+ }
+}
diff --git a/pkgs/jni/test/type_test.dart b/pkgs/jni/test/type_test.dart
new file mode 100644
index 0000000..0ad8490
--- /dev/null
+++ b/pkgs/jni/test/type_test.dart
@@ -0,0 +1,327 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi';
+import 'dart:io';
+
+import 'package:jni/jni.dart';
+import 'package:test/test.dart';
+
+import 'test_util/test_util.dart';
+
+// Mocking this type tree:
+// JObject
+// | \
+// A B
+// / \ \
+// C D E
+// /
+// F
+
+class A extends JObject {
+ A.fromRef(super.reference) : super.fromRef();
+ @override
+ JObjType<JObject> get $type => $AType();
+}
+
+final class $AType extends JObjType<A> {
+ @override
+ A fromRef(Pointer<Void> ref) {
+ return A.fromRef(ref);
+ }
+
+ @override
+ String get signature => 'A';
+
+ @override
+ int get superCount => superType.superCount + 1;
+
+ @override
+ JObjType<JObject> get superType => JObject.type;
+
+ @override
+ int get hashCode => ($AType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == $AType && other is $AType;
+ }
+}
+
+class B extends JObject {
+ B.fromRef(super.reference) : super.fromRef();
+ @override
+ JObjType<JObject> get $type => $BType();
+}
+
+final class $BType extends JObjType<B> {
+ @override
+ B fromRef(Pointer<Void> ref) {
+ return B.fromRef(ref);
+ }
+
+ @override
+ String get signature => 'B';
+
+ @override
+ int get superCount => superType.superCount + 1;
+
+ @override
+ JObjType<JObject> get superType => JObject.type;
+
+ @override
+ int get hashCode => ($BType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == $BType && other is $BType;
+ }
+}
+
+class C extends A {
+ C.fromRef(super.reference) : super.fromRef();
+
+ @override
+ JObjType<JObject> get $type => $CType();
+}
+
+final class $CType extends JObjType<C> {
+ @override
+ C fromRef(Pointer<Void> ref) {
+ return C.fromRef(ref);
+ }
+
+ @override
+ String get signature => 'C';
+
+ @override
+ int get superCount => superType.superCount + 1;
+
+ @override
+ JObjType<JObject> get superType => $AType();
+
+ @override
+ int get hashCode => ($CType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == $CType && other is $CType;
+ }
+}
+
+class D extends A {
+ D.fromRef(super.reference) : super.fromRef();
+
+ @override
+ JObjType<JObject> get $type => $DType();
+}
+
+final class $DType extends JObjType<D> {
+ @override
+ D fromRef(Pointer<Void> ref) {
+ return D.fromRef(ref);
+ }
+
+ @override
+ String get signature => 'D';
+
+ @override
+ int get superCount => superType.superCount + 1;
+
+ @override
+ JObjType<JObject> get superType => $AType();
+
+ @override
+ int get hashCode => ($DType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == $DType && other is $DType;
+ }
+}
+
+class E extends B {
+ E.fromRef(super.reference) : super.fromRef();
+
+ @override
+ JObjType<JObject> get $type => $EType();
+}
+
+final class $EType extends JObjType<E> {
+ @override
+ E fromRef(Pointer<Void> ref) {
+ return E.fromRef(ref);
+ }
+
+ @override
+ String get signature => 'E';
+
+ @override
+ int get superCount => superType.superCount + 1;
+
+ @override
+ JObjType<JObject> get superType => $BType();
+
+ @override
+ int get hashCode => ($EType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == $EType && other is $EType;
+ }
+}
+
+class F extends C {
+ F.fromRef(super.reference) : super.fromRef();
+
+ @override
+ JObjType<JObject> get $type => $FType();
+}
+
+final class $FType extends JObjType<F> {
+ @override
+ F fromRef(Pointer<Void> ref) {
+ return F.fromRef(ref);
+ }
+
+ @override
+ String get signature => 'F';
+
+ @override
+ int get superCount => superType.superCount + 1;
+
+ @override
+ JObjType<JObject> get superType => $CType();
+
+ @override
+ int get hashCode => ($FType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == $FType && other is $FType;
+ }
+}
+
+void main() {
+ if (!Platform.isAndroid) {
+ checkDylibIsUpToDate();
+ Jni.spawnIfNotExists(dylibDir: "build/jni_libs", jvmOptions: ["-Xmx128m"]);
+ }
+ run(testRunner: test);
+}
+
+void run({required TestRunnerCallback testRunner}) {
+ testRunner('lowestCommonSuperType', () {
+ expect(lowestCommonSuperType([JObject.type]), JObject.type);
+ expect(lowestCommonSuperType([JString.type]), JString.type);
+ expect(lowestCommonSuperType([JObject.type, JObject.type]), JObject.type);
+ expect(lowestCommonSuperType([JString.type, JString.type]), JString.type);
+ expect(lowestCommonSuperType([JString.type, JArray.type(jlong.type)]),
+ JObject.type);
+ });
+
+ testRunner('Boxed types', () {
+ expect(
+ lowestCommonSuperType([
+ JByte.type,
+ JInteger.type,
+ JLong.type,
+ JShort.type,
+ JDouble.type,
+ JFloat.type,
+ ]),
+ JNumber.type,
+ );
+ expect(lowestCommonSuperType([JByte.type, JBoolean.type]), JObject.type);
+ });
+
+ testRunner('array types', () {
+ using((arena) {
+ expect(
+ lowestCommonSuperType([
+ JArray.type(jint.type),
+ JArray.type(jint.type),
+ ]),
+ JArray.type(jint.type),
+ );
+ expect(
+ lowestCommonSuperType([
+ JArray.type(JObject.type),
+ JArray.type(JObject.type),
+ ]),
+ JArray.type(JObject.type),
+ );
+ expect(
+ lowestCommonSuperType([
+ JArray.type(JObject.type),
+ JArray.type(jint.type),
+ ]),
+ JObject.type,
+ );
+ });
+ });
+
+ testRunner('util types', () {
+ using((arena) {
+ expect(
+ lowestCommonSuperType([
+ JList.type(JObject.type),
+ JList.type(JObject.type),
+ ]),
+ JList.type(JObject.type),
+ );
+ expect(
+ lowestCommonSuperType([
+ JList.type(JObject.type),
+ JList.type(JString.type),
+ ]),
+ JObject.type,
+ );
+ expect(
+ lowestCommonSuperType([
+ JList.type(JObject.type),
+ JMap.type(JObject.type, JObject.type),
+ ]),
+ JObject.type,
+ );
+ expect(
+ lowestCommonSuperType([
+ JSet.type(JObject.type),
+ JIterator.type(JObject.type),
+ ]),
+ JObject.type,
+ );
+ expect(
+ lowestCommonSuperType([
+ JByteBuffer.type,
+ JBuffer.type,
+ ]),
+ JBuffer.type,
+ );
+ });
+ });
+
+ testRunner('Mocked type tree', () {
+ // As a reminder, this is how the type tree looks like:
+ // JObject
+ // | \
+ // A B
+ // / \ \
+ // C D E
+ // /
+ // F
+ expect(lowestCommonSuperType([$AType(), $BType()]), const JObjectType());
+ expect(lowestCommonSuperType([$CType(), $BType()]), const JObjectType());
+ expect(lowestCommonSuperType([$FType(), $BType()]), const JObjectType());
+ expect(lowestCommonSuperType([$EType(), $CType(), $FType()]),
+ const JObjectType());
+
+ expect(lowestCommonSuperType([$CType(), $DType()]), $AType());
+ expect(lowestCommonSuperType([$FType(), $DType()]), $AType());
+ expect(lowestCommonSuperType([$FType(), $CType(), $DType()]), $AType());
+
+ expect(lowestCommonSuperType([$EType(), $BType()]), $BType());
+ expect(lowestCommonSuperType([$BType(), $BType()]), $BType());
+ });
+}
diff --git a/pkgs/jni/third_party/jni.h b/pkgs/jni/third_party/jni.h
new file mode 100644
index 0000000..b71105e
--- /dev/null
+++ b/pkgs/jni/third_party/jni.h
@@ -0,0 +1,1490 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * JNI specification, as defined by Sun:
+ * http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html
+ *
+ * Everything here is expected to be VM-neutral.
+ */
+
+/* ANNOTATED COPY FOR DART JNI LIBRARY */
+
+#pragma once
+
+#include <stdarg.h>
+#include <stdint.h>
+
+/* Primitive types that match up with Java equivalents. */
+typedef uint8_t jboolean; /* unsigned 8 bits */
+typedef int8_t jbyte; /* signed 8 bits */
+typedef uint16_t jchar; /* unsigned 16 bits */
+typedef int16_t jshort; /* signed 16 bits */
+typedef int32_t jint; /* signed 32 bits */
+typedef int64_t jlong; /* signed 64 bits */
+typedef float jfloat; /* 32-bit IEEE 754 */
+typedef double jdouble; /* 64-bit IEEE 754 */
+
+/* "cardinal indices and sizes" */
+typedef jint jsize;
+
+#ifdef __cplusplus
+/*
+ * Reference types, in C++
+ */
+class _jobject
+{
+};
+class _jclass : public _jobject
+{
+};
+class _jstring : public _jobject
+{
+};
+class _jarray : public _jobject
+{
+};
+class _jobjectArray : public _jarray
+{
+};
+class _jbooleanArray : public _jarray
+{
+};
+class _jbyteArray : public _jarray
+{
+};
+class _jcharArray : public _jarray
+{
+};
+class _jshortArray : public _jarray
+{
+};
+class _jintArray : public _jarray
+{
+};
+class _jlongArray : public _jarray
+{
+};
+class _jfloatArray : public _jarray
+{
+};
+class _jdoubleArray : public _jarray
+{
+};
+class _jthrowable : public _jobject
+{
+};
+
+typedef _jobject *jobject;
+typedef _jclass *jclass;
+typedef _jstring *jstring;
+typedef _jarray *jarray;
+typedef _jobjectArray *jobjectArray;
+typedef _jbooleanArray *jbooleanArray;
+typedef _jbyteArray *jbyteArray;
+typedef _jcharArray *jcharArray;
+typedef _jshortArray *jshortArray;
+typedef _jintArray *jintArray;
+typedef _jlongArray *jlongArray;
+typedef _jfloatArray *jfloatArray;
+typedef _jdoubleArray *jdoubleArray;
+typedef _jthrowable *jthrowable;
+typedef _jobject *jweak;
+
+#else /* not __cplusplus */
+
+/*
+ * Reference types, in C.
+ */
+typedef void *jobject;
+typedef jobject jclass;
+typedef jobject jstring;
+typedef jobject jarray;
+typedef jarray jobjectArray;
+typedef jarray jbooleanArray;
+typedef jarray jbyteArray;
+typedef jarray jcharArray;
+typedef jarray jshortArray;
+typedef jarray jintArray;
+typedef jarray jlongArray;
+typedef jarray jfloatArray;
+typedef jarray jdoubleArray;
+typedef jobject jthrowable;
+typedef jobject jweak;
+
+#endif /* not __cplusplus */
+
+struct _jfieldID; /* opaque structure */
+typedef struct _jfieldID *jfieldID; /* field IDs */
+
+struct _jmethodID; /* opaque structure */
+typedef struct _jmethodID *jmethodID; /* method IDs */
+
+struct JNIInvokeInterface;
+
+typedef union jvalue
+{
+ jboolean z;
+ jbyte b;
+ jchar c;
+ jshort s;
+ jint i;
+ jlong j;
+ jfloat f;
+ jdouble d;
+ jobject l;
+} jvalue;
+
+typedef enum jobjectRefType
+{
+ JNIInvalidRefType = 0,
+ JNILocalRefType = 1,
+ JNIGlobalRefType = 2,
+ JNIWeakGlobalRefType = 3
+} jobjectRefType;
+
+typedef struct
+{
+ const char *name;
+ const char *signature;
+ void *fnPtr;
+} JNINativeMethod;
+
+struct _JNIEnv;
+struct _JavaVM;
+typedef const struct JNINativeInterface *C_JNIEnv;
+
+#if defined(__cplusplus)
+typedef _JNIEnv JNIEnv;
+typedef _JavaVM JavaVM;
+#else
+typedef const struct JNINativeInterface *JNIEnv;
+typedef const struct JNIInvokeInterface *JavaVM;
+#endif
+
+/*
+ * Table of interface function pointers.
+ */
+struct JNINativeInterface
+{
+ void *reserved0;
+ void *reserved1;
+ void *reserved2;
+ void *reserved3;
+
+ jint (*GetVersion)(JNIEnv *env);
+ jclass (*DefineClass)(JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
+ jsize bufLen);
+ jclass (*FindClass)(JNIEnv *env, const char *name);
+
+ jmethodID (*FromReflectedMethod)(JNIEnv *env, jobject method);
+ jfieldID (*FromReflectedField)(JNIEnv *env, jobject field);
+
+ /* spec doesn't show jboolean parameter */
+
+ jobject (*ToReflectedMethod)(JNIEnv *env, jclass cls, jmethodID methodId, jboolean isStatic);
+
+ jclass (*GetSuperclass)(JNIEnv *env, jclass clazz);
+ jboolean (*IsAssignableFrom)(JNIEnv *env, jclass clazz1, jclass clazz2);
+
+ /* spec doesn't show jboolean parameter */
+
+ jobject (*ToReflectedField)(JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);
+
+ jint (*Throw)(JNIEnv *env, jthrowable obj);
+ jint (*ThrowNew)(JNIEnv *env, jclass clazz, const char *message);
+ jthrowable (*ExceptionOccurred)(JNIEnv *env);
+ void (*ExceptionDescribe)(JNIEnv *env);
+ void (*ExceptionClear)(JNIEnv *env);
+ void (*FatalError)(JNIEnv *env, const char *msg);
+
+ jint (*PushLocalFrame)(JNIEnv *env, jint capacity);
+ jobject (*PopLocalFrame)(JNIEnv *env, jobject result);
+
+ jobject (*NewGlobalRef)(JNIEnv *env, jobject obj);
+ void (*DeleteGlobalRef)(JNIEnv *env, jobject globalRef);
+ void (*DeleteLocalRef)(JNIEnv *env, jobject localRef);
+ jboolean (*IsSameObject)(JNIEnv *env, jobject ref1, jobject ref2);
+
+ jobject (*NewLocalRef)(JNIEnv *env, jobject obj);
+ jint (*EnsureLocalCapacity)(JNIEnv *env, jint capacity);
+
+ jobject (*AllocObject)(JNIEnv *env, jclass clazz);
+ jobject (*NewObject)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jobject (*NewObjectV)(JNIEnv *, jclass, jmethodID, void *);
+ jobject (*NewObjectA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jclass (*GetObjectClass)(JNIEnv *env, jobject obj);
+ jboolean (*IsInstanceOf)(JNIEnv *env, jobject obj, jclass clazz);
+ jmethodID (*GetMethodID)(JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (*CallObjectMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jobject (*CallObjectMethodV)(JNIEnv *, jobject, jmethodID, void *);
+ jobject (*CallObjectMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+ jboolean (*CallBooleanMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jboolean (*CallBooleanMethodV)(JNIEnv *, jobject, jmethodID, void *);
+ jboolean (*CallBooleanMethodA)(JNIEnv *env, jobject obj, jmethodID methodId, const jvalue *args);
+ jbyte (*CallByteMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jbyte (*CallByteMethodV)(JNIEnv *, jobject, jmethodID, void *);
+ jbyte (*CallByteMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+ jchar (*CallCharMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jchar (*CallCharMethodV)(JNIEnv *, jobject, jmethodID, void *);
+ jchar (*CallCharMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+ jshort (*CallShortMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jshort (*CallShortMethodV)(JNIEnv *, jobject, jmethodID, void *);
+ jshort (*CallShortMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+ jint (*CallIntMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jint (*CallIntMethodV)(JNIEnv *, jobject, jmethodID, void *);
+ jint (*CallIntMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+ jlong (*CallLongMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jlong (*CallLongMethodV)(JNIEnv *, jobject, jmethodID, void *);
+ jlong (*CallLongMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+ jfloat (*CallFloatMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jfloat (*CallFloatMethodV)(JNIEnv *, jobject, jmethodID, void *);
+ jfloat (*CallFloatMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+ jdouble (*CallDoubleMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ jdouble (*CallDoubleMethodV)(JNIEnv *, jobject, jmethodID, void *);
+ jdouble (*CallDoubleMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+ void (*CallVoidMethod)(JNIEnv *env, jobject obj, jmethodID methodID, ...);
+ void (*CallVoidMethodV)(JNIEnv *, jobject, jmethodID, void *);
+ void (*CallVoidMethodA)(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
+
+ jobject (*CallNonvirtualObjectMethod)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...);
+ jobject (*CallNonvirtualObjectMethodV)(JNIEnv *, jobject, jclass,
+ jmethodID, void *);
+ jobject (*CallNonvirtualObjectMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue *args);
+ jboolean (*CallNonvirtualBooleanMethod)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...);
+ jboolean (*CallNonvirtualBooleanMethodV)(JNIEnv *, jobject, jclass,
+ jmethodID, void *);
+ jboolean (*CallNonvirtualBooleanMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue *args);
+ jbyte (*CallNonvirtualByteMethod)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...);
+ jbyte (*CallNonvirtualByteMethodV)(JNIEnv *, jobject, jclass,
+ jmethodID, void *);
+ jbyte (*CallNonvirtualByteMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue *args);
+ jchar (*CallNonvirtualCharMethod)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...);
+ jchar (*CallNonvirtualCharMethodV)(JNIEnv *, jobject, jclass,
+ jmethodID, void *);
+ jchar (*CallNonvirtualCharMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue *args);
+ jshort (*CallNonvirtualShortMethod)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...);
+ jshort (*CallNonvirtualShortMethodV)(JNIEnv *, jobject, jclass,
+ jmethodID, void *);
+ jshort (*CallNonvirtualShortMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue *args);
+ jint (*CallNonvirtualIntMethod)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...);
+ jint (*CallNonvirtualIntMethodV)(JNIEnv *, jobject, jclass,
+ jmethodID, void *);
+ jint (*CallNonvirtualIntMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue *args);
+ jlong (*CallNonvirtualLongMethod)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...);
+ jlong (*CallNonvirtualLongMethodV)(JNIEnv *, jobject, jclass,
+ jmethodID, void *);
+ jlong (*CallNonvirtualLongMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue *args);
+ jfloat (*CallNonvirtualFloatMethod)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...);
+ jfloat (*CallNonvirtualFloatMethodV)(JNIEnv *, jobject, jclass,
+ jmethodID, void *);
+ jfloat (*CallNonvirtualFloatMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue *args);
+ jdouble (*CallNonvirtualDoubleMethod)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...);
+ jdouble (*CallNonvirtualDoubleMethodV)(JNIEnv *, jobject, jclass,
+ jmethodID, void *);
+ jdouble (*CallNonvirtualDoubleMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue *args);
+ void (*CallNonvirtualVoidMethod)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...);
+ void (*CallNonvirtualVoidMethodV)(JNIEnv *, jobject, jclass,
+ jmethodID, void *);
+ void (*CallNonvirtualVoidMethodA)(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue *args);
+
+ jfieldID (*GetFieldID)(JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (*GetObjectField)(JNIEnv *env, jobject obj, jfieldID fieldID);
+ jboolean (*GetBooleanField)(JNIEnv *env, jobject obj, jfieldID fieldID);
+ jbyte (*GetByteField)(JNIEnv *env, jobject obj, jfieldID fieldID);
+ jchar (*GetCharField)(JNIEnv *env, jobject obj, jfieldID fieldID);
+ jshort (*GetShortField)(JNIEnv *env, jobject obj, jfieldID fieldID);
+ jint (*GetIntField)(JNIEnv *env, jobject obj, jfieldID fieldID);
+ jlong (*GetLongField)(JNIEnv *env, jobject obj, jfieldID fieldID);
+ jfloat (*GetFloatField)(JNIEnv *env, jobject obj, jfieldID fieldID);
+ jdouble (*GetDoubleField)(JNIEnv *env, jobject obj, jfieldID fieldID);
+
+ void (*SetObjectField)(JNIEnv *env, jobject obj, jfieldID fieldID, jobject val);
+ void (*SetBooleanField)(JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val);
+ void (*SetByteField)(JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val);
+ void (*SetCharField)(JNIEnv *env, jobject obj, jfieldID fieldID, jchar val);
+ void (*SetShortField)(JNIEnv *env, jobject obj, jfieldID fieldID, jshort val);
+ void (*SetIntField)(JNIEnv *env, jobject obj, jfieldID fieldID, jint val);
+ void (*SetLongField)(JNIEnv *env, jobject obj, jfieldID fieldID, jlong val);
+ void (*SetFloatField)(JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val);
+ void (*SetDoubleField)(JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val);
+
+ jmethodID (*GetStaticMethodID)(JNIEnv *env, jclass clazz, const char *name, const char *sig);
+
+ jobject (*CallStaticObjectMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jobject (*CallStaticObjectMethodV)(JNIEnv *, jclass, jmethodID, void *);
+ jobject (*CallStaticObjectMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+ jboolean (*CallStaticBooleanMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jboolean (*CallStaticBooleanMethodV)(JNIEnv *, jclass, jmethodID,
+ void *);
+ jboolean (*CallStaticBooleanMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+ jbyte (*CallStaticByteMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jbyte (*CallStaticByteMethodV)(JNIEnv *, jclass, jmethodID, void *);
+ jbyte (*CallStaticByteMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+ jchar (*CallStaticCharMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jchar (*CallStaticCharMethodV)(JNIEnv *, jclass, jmethodID, void *);
+ jchar (*CallStaticCharMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+ jshort (*CallStaticShortMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jshort (*CallStaticShortMethodV)(JNIEnv *, jclass, jmethodID, void *);
+ jshort (*CallStaticShortMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+ jint (*CallStaticIntMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jint (*CallStaticIntMethodV)(JNIEnv *, jclass, jmethodID, void *);
+ jint (*CallStaticIntMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+ jlong (*CallStaticLongMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jlong (*CallStaticLongMethodV)(JNIEnv *, jclass, jmethodID, void *);
+ jlong (*CallStaticLongMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+ jfloat (*CallStaticFloatMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jfloat (*CallStaticFloatMethodV)(JNIEnv *, jclass, jmethodID, void *);
+ jfloat (*CallStaticFloatMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+ jdouble (*CallStaticDoubleMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ jdouble (*CallStaticDoubleMethodV)(JNIEnv *, jclass, jmethodID, void *);
+ jdouble (*CallStaticDoubleMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+ void (*CallStaticVoidMethod)(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
+ void (*CallStaticVoidMethodV)(JNIEnv *, jclass, jmethodID, void *);
+ void (*CallStaticVoidMethodA)(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
+
+ jfieldID (*GetStaticFieldID)(JNIEnv *env, jclass clazz, const char *name,
+ const char *sig);
+
+ jobject (*GetStaticObjectField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jboolean (*GetStaticBooleanField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jbyte (*GetStaticByteField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jchar (*GetStaticCharField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jshort (*GetStaticShortField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jint (*GetStaticIntField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jlong (*GetStaticLongField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jfloat (*GetStaticFloatField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
+ jdouble (*GetStaticDoubleField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
+
+ void (*SetStaticObjectField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject val);
+ void (*SetStaticBooleanField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean val);
+ void (*SetStaticByteField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte val);
+ void (*SetStaticCharField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jchar val);
+ void (*SetStaticShortField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jshort val);
+ void (*SetStaticIntField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jint val);
+ void (*SetStaticLongField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jlong val);
+ void (*SetStaticFloatField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat val);
+ void (*SetStaticDoubleField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble val);
+
+ jstring (*NewString)(JNIEnv *env, const jchar *unicodeChars, jsize len);
+ jsize (*GetStringLength)(JNIEnv *env, jstring string);
+ const jchar *(*GetStringChars)(JNIEnv *env, jstring string, jboolean *isCopy);
+ void (*ReleaseStringChars)(JNIEnv *env, jstring string, const jchar *isCopy);
+ jstring (*NewStringUTF)(JNIEnv *env, const char *bytes);
+ jsize (*GetStringUTFLength)(JNIEnv *env, jstring string);
+ const char *(*GetStringUTFChars)(JNIEnv *env, jstring string, jboolean *isCopy);
+ void (*ReleaseStringUTFChars)(JNIEnv *env, jstring string, const char *utf);
+ jsize (*GetArrayLength)(JNIEnv *env, jarray array);
+ jobjectArray (*NewObjectArray)(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement);
+ jobject (*GetObjectArrayElement)(JNIEnv *env, jobjectArray array, jsize index);
+ void (*SetObjectArrayElement)(JNIEnv *env, jobjectArray array, jsize index, jobject val);
+
+ jbooleanArray (*NewBooleanArray)(JNIEnv *env, jsize length);
+ jbyteArray (*NewByteArray)(JNIEnv *env, jsize length);
+ jcharArray (*NewCharArray)(JNIEnv *env, jsize length);
+ jshortArray (*NewShortArray)(JNIEnv *env, jsize length);
+ jintArray (*NewIntArray)(JNIEnv *env, jsize length);
+ jlongArray (*NewLongArray)(JNIEnv *env, jsize length);
+ jfloatArray (*NewFloatArray)(JNIEnv *env, jsize length);
+ jdoubleArray (*NewDoubleArray)(JNIEnv *env, jsize length);
+
+ jboolean *(*GetBooleanArrayElements)(JNIEnv *env, jbooleanArray array, jboolean *isCopy);
+ jbyte *(*GetByteArrayElements)(JNIEnv *env, jbyteArray array, jboolean *isCopy);
+ jchar *(*GetCharArrayElements)(JNIEnv *env, jcharArray array, jboolean *isCopy);
+ jshort *(*GetShortArrayElements)(JNIEnv *env, jshortArray array, jboolean *isCopy);
+ jint *(*GetIntArrayElements)(JNIEnv *env, jintArray array, jboolean *isCopy);
+ jlong *(*GetLongArrayElements)(JNIEnv *env, jlongArray array, jboolean *isCopy);
+ jfloat *(*GetFloatArrayElements)(JNIEnv *env, jfloatArray array, jboolean *isCopy);
+ jdouble *(*GetDoubleArrayElements)(JNIEnv *env, jdoubleArray array, jboolean *isCopy);
+
+ void (*ReleaseBooleanArrayElements)(JNIEnv *env, jbooleanArray array,
+ jboolean *elems, jint mode);
+ void (*ReleaseByteArrayElements)(JNIEnv *env, jbyteArray array,
+ jbyte *elems, jint mode);
+ void (*ReleaseCharArrayElements)(JNIEnv *env, jcharArray array,
+ jchar *elems, jint mode);
+ void (*ReleaseShortArrayElements)(JNIEnv *env, jshortArray array,
+ jshort *elems, jint mode);
+ void (*ReleaseIntArrayElements)(JNIEnv *env, jintArray array,
+ jint *elems, jint mode);
+ void (*ReleaseLongArrayElements)(JNIEnv *env, jlongArray array,
+ jlong *elems, jint mode);
+ void (*ReleaseFloatArrayElements)(JNIEnv *env, jfloatArray array,
+ jfloat *elems, jint mode);
+ void (*ReleaseDoubleArrayElements)(JNIEnv *env, jdoubleArray array,
+ jdouble *elems, jint mode);
+
+ void (*GetBooleanArrayRegion)(JNIEnv *env, jbooleanArray array,
+ jsize start, jsize len, jboolean *buf);
+ void (*GetByteArrayRegion)(JNIEnv *env, jbyteArray array,
+ jsize start, jsize len, jbyte *buf);
+ void (*GetCharArrayRegion)(JNIEnv *env, jcharArray array,
+ jsize start, jsize len, jchar *buf);
+ void (*GetShortArrayRegion)(JNIEnv *env, jshortArray array,
+ jsize start, jsize len, jshort *buf);
+ void (*GetIntArrayRegion)(JNIEnv *env, jintArray array,
+ jsize start, jsize len, jint *buf);
+ void (*GetLongArrayRegion)(JNIEnv *env, jlongArray array,
+ jsize start, jsize len, jlong *buf);
+ void (*GetFloatArrayRegion)(JNIEnv *env, jfloatArray array,
+ jsize start, jsize len, jfloat *buf);
+ void (*GetDoubleArrayRegion)(JNIEnv *env, jdoubleArray array,
+ jsize start, jsize len, jdouble *buf);
+
+ /* spec shows these without const; some jni.h do, some don't */
+ void (*SetBooleanArrayRegion)(JNIEnv *env, jbooleanArray array,
+ jsize start, jsize len, const jboolean *buf);
+ void (*SetByteArrayRegion)(JNIEnv *env, jbyteArray array,
+ jsize start, jsize len, const jbyte *buf);
+ void (*SetCharArrayRegion)(JNIEnv *env, jcharArray array,
+ jsize start, jsize len, const jchar *buf);
+ void (*SetShortArrayRegion)(JNIEnv *env, jshortArray array,
+ jsize start, jsize len, const jshort *buf);
+ void (*SetIntArrayRegion)(JNIEnv *env, jintArray array,
+ jsize start, jsize len, const jint *buf);
+ void (*SetLongArrayRegion)(JNIEnv *env, jlongArray array,
+ jsize start, jsize len, const jlong *buf);
+ void (*SetFloatArrayRegion)(JNIEnv *env, jfloatArray array,
+ jsize start, jsize len, const jfloat *buf);
+ void (*SetDoubleArrayRegion)(JNIEnv *env, jdoubleArray array,
+ jsize start, jsize len, const jdouble *buf);
+
+ jint (*RegisterNatives)(JNIEnv *env, jclass clazz, const JNINativeMethod *methods,
+ jint nMethods);
+ jint (*UnregisterNatives)(JNIEnv *env, jclass clazz);
+ jint (*MonitorEnter)(JNIEnv *env, jobject obj);
+ jint (*MonitorExit)(JNIEnv *env, jobject obj);
+ jint (*GetJavaVM)(JNIEnv *env, JavaVM **vm);
+
+ void (*GetStringRegion)(JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);
+ void (*GetStringUTFRegion)(JNIEnv *env, jstring str, jsize start, jsize len, char *buf);
+
+ void *(*GetPrimitiveArrayCritical)(JNIEnv *env, jarray array, jboolean *isCopy);
+ void (*ReleasePrimitiveArrayCritical)(JNIEnv *env, jarray array, void *carray, jint mode);
+
+ const jchar *(*GetStringCritical)(JNIEnv *env, jstring str, jboolean *isCopy);
+ void (*ReleaseStringCritical)(JNIEnv *env, jstring str, const jchar *carray);
+
+ jweak (*NewWeakGlobalRef)(JNIEnv *env, jobject obj);
+ void (*DeleteWeakGlobalRef)(JNIEnv *env, jweak obj);
+
+ jboolean (*ExceptionCheck)(JNIEnv *env);
+
+ jobject (*NewDirectByteBuffer)(JNIEnv *env, void *address, jlong capacity);
+ void *(*GetDirectBufferAddress)(JNIEnv *env, jobject buf);
+ jlong (*GetDirectBufferCapacity)(JNIEnv *env, jobject buf);
+
+ /* added in JNI 1.6 */
+ jobjectRefType (*GetObjectRefType)(JNIEnv *env, jobject obj);
+};
+
+/*
+ * C++ object wrapper.
+ *
+ * This is usually overlaid on a C struct whose first element is a
+ * JNINativeInterface*. We rely somewhat on compiler behavior.
+ */
+struct _JNIEnv
+{
+ /* do not rename this; it does not seem to be entirely opaque */
+ const struct JNINativeInterface *functions;
+
+#if defined(__cplusplus)
+
+ jint GetVersion()
+ {
+ return functions->GetVersion(this);
+ }
+
+ jclass DefineClass(const char *name, jobject loader, const jbyte *buf,
+ jsize bufLen)
+ {
+ return functions->DefineClass(this, name, loader, buf, bufLen);
+ }
+
+ jclass FindClass(const char *name)
+ {
+ return functions->FindClass(this, name);
+ }
+
+ jmethodID FromReflectedMethod(jobject method)
+ {
+ return functions->FromReflectedMethod(this, method);
+ }
+
+ jfieldID FromReflectedField(jobject field)
+ {
+ return functions->FromReflectedField(this, field);
+ }
+
+ jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic)
+ {
+ return functions->ToReflectedMethod(this, cls, methodID, isStatic);
+ }
+
+ jclass GetSuperclass(jclass clazz)
+ {
+ return functions->GetSuperclass(this, clazz);
+ }
+
+ jboolean IsAssignableFrom(jclass clazz1, jclass clazz2)
+ {
+ return functions->IsAssignableFrom(this, clazz1, clazz2);
+ }
+
+ jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic)
+ {
+ return functions->ToReflectedField(this, cls, fieldID, isStatic);
+ }
+
+ jint Throw(jthrowable obj)
+ {
+ return functions->Throw(this, obj);
+ }
+
+ jint ThrowNew(jclass clazz, const char *message)
+ {
+ return functions->ThrowNew(this, clazz, message);
+ }
+
+ jthrowable ExceptionOccurred()
+ {
+ return functions->ExceptionOccurred(this);
+ }
+
+ void ExceptionDescribe()
+ {
+ functions->ExceptionDescribe(this);
+ }
+
+ void ExceptionClear()
+ {
+ functions->ExceptionClear(this);
+ }
+
+ void FatalError(const char *msg)
+ {
+ functions->FatalError(this, msg);
+ }
+
+ jint PushLocalFrame(jint capacity)
+ {
+ return functions->PushLocalFrame(this, capacity);
+ }
+
+ jobject PopLocalFrame(jobject result)
+ {
+ return functions->PopLocalFrame(this, result);
+ }
+
+ jobject NewGlobalRef(jobject obj)
+ {
+ return functions->NewGlobalRef(this, obj);
+ }
+
+ void DeleteGlobalRef(jobject globalRef)
+ {
+ functions->DeleteGlobalRef(this, globalRef);
+ }
+
+ void DeleteLocalRef(jobject localRef)
+ {
+ functions->DeleteLocalRef(this, localRef);
+ }
+
+ jboolean IsSameObject(jobject ref1, jobject ref2)
+ {
+ return functions->IsSameObject(this, ref1, ref2);
+ }
+
+ jobject NewLocalRef(jobject obj)
+ {
+ return functions->NewLocalRef(this, ref);
+ }
+
+ jint EnsureLocalCapacity(jint capacity)
+ {
+ return functions->EnsureLocalCapacity(this, capacity);
+ }
+
+ jobject AllocObject(jclass clazz)
+ {
+ return functions->AllocObject(this, clazz);
+ }
+
+ jobject NewObject(jclass clazz, jmethodID methodID, ...)
+ {
+ va_list args;
+ va_start(args, methodID);
+ jobject result = functions->NewObjectV(this, clazz, methodID, args);
+ va_end(args);
+ return result;
+ }
+
+ jobject NewObjectV(jclass clazz, jmethodID methodID, va_list args)
+ {
+ return functions->NewObjectV(this, clazz, methodID, args);
+ }
+
+ jobject NewObjectA(jclass clazz, jmethodID methodID, const jvalue *args)
+ {
+ return functions->NewObjectA(this, clazz, methodID, args);
+ }
+
+ jclass GetObjectClass(jobject obj)
+ {
+ return functions->GetObjectClass(this, obj);
+ }
+
+ jboolean IsInstanceOf(jobject obj, jclass clazz)
+ {
+ return functions->IsInstanceOf(this, obj, clazz);
+ }
+
+ jmethodID GetMethodID(jclass clazz, const char *name, const char *sig)
+ {
+ return functions->GetMethodID(this, clazz, name, sig);
+ }
+
+#define CALL_TYPE_METHOD(_jtype, _jname) \
+ _jtype Call##_jname##Method(jobject obj, jmethodID methodID, ...) \
+ { \
+ _jtype result; \
+ va_list args; \
+ va_start(args, methodID); \
+ result = functions->Call##_jname##MethodV(this, obj, methodID, \
+ args); \
+ va_end(args); \
+ return result; \
+ }
+#define CALL_TYPE_METHODV(_jtype, _jname) \
+ _jtype Call##_jname##MethodV(jobject obj, jmethodID methodID, \
+ va_list args) \
+ { \
+ return functions->Call##_jname##MethodV(this, obj, methodID, args); \
+ }
+#define CALL_TYPE_METHODA(_jtype, _jname) \
+ _jtype Call##_jname##MethodA(jobject obj, jmethodID methodID, \
+ const jvalue *args) \
+ { \
+ return functions->Call##_jname##MethodA(this, obj, methodID, args); \
+ }
+
+#define CALL_TYPE(_jtype, _jname) \
+ CALL_TYPE_METHOD(_jtype, _jname) \
+ CALL_TYPE_METHODV(_jtype, _jname) \
+ CALL_TYPE_METHODA(_jtype, _jname)
+
+ CALL_TYPE(jobject, Object)
+ CALL_TYPE(jboolean, Boolean)
+ CALL_TYPE(jbyte, Byte)
+ CALL_TYPE(jchar, Char)
+ CALL_TYPE(jshort, Short)
+ CALL_TYPE(jint, Int)
+ CALL_TYPE(jlong, Long)
+ CALL_TYPE(jfloat, Float)
+ CALL_TYPE(jdouble, Double)
+
+ void CallVoidMethod(jobject obj, jmethodID methodID, ...)
+ {
+ va_list args;
+ va_start(args, methodID);
+ functions->CallVoidMethodV(this, obj, methodID, args);
+ va_end(args);
+ }
+ void CallVoidMethodV(jobject obj, jmethodID methodID, va_list args)
+ {
+ functions->CallVoidMethodV(this, obj, methodID, args);
+ }
+ void CallVoidMethodA(jobject obj, jmethodID methodID, const jvalue *args)
+ {
+ functions->CallVoidMethodA(this, obj, methodID, args);
+ }
+
+#define CALL_NONVIRT_TYPE_METHOD(_jtype, _jname) \
+ _jtype CallNonvirtual##_jname##Method(jobject obj, jclass clazz, \
+ jmethodID methodID, ...) \
+ { \
+ _jtype result; \
+ va_list args; \
+ va_start(args, methodID); \
+ result = functions->CallNonvirtual##_jname##MethodV(this, obj, \
+ clazz, methodID, args); \
+ va_end(args); \
+ return result; \
+ }
+#define CALL_NONVIRT_TYPE_METHODV(_jtype, _jname) \
+ _jtype CallNonvirtual##_jname##MethodV(jobject obj, jclass clazz, \
+ jmethodID methodID, va_list args) \
+ { \
+ return functions->CallNonvirtual##_jname##MethodV(this, obj, clazz, \
+ methodID, args); \
+ }
+#define CALL_NONVIRT_TYPE_METHODA(_jtype, _jname) \
+ _jtype CallNonvirtual##_jname##MethodA(jobject obj, jclass clazz, \
+ jmethodID methodID, const jvalue *args) \
+ { \
+ return functions->CallNonvirtual##_jname##MethodA(this, obj, clazz, \
+ methodID, args); \
+ }
+
+#define CALL_NONVIRT_TYPE(_jtype, _jname) \
+ CALL_NONVIRT_TYPE_METHOD(_jtype, _jname) \
+ CALL_NONVIRT_TYPE_METHODV(_jtype, _jname) \
+ CALL_NONVIRT_TYPE_METHODA(_jtype, _jname)
+
+ CALL_NONVIRT_TYPE(jobject, Object)
+ CALL_NONVIRT_TYPE(jboolean, Boolean)
+ CALL_NONVIRT_TYPE(jbyte, Byte)
+ CALL_NONVIRT_TYPE(jchar, Char)
+ CALL_NONVIRT_TYPE(jshort, Short)
+ CALL_NONVIRT_TYPE(jint, Int)
+ CALL_NONVIRT_TYPE(jlong, Long)
+ CALL_NONVIRT_TYPE(jfloat, Float)
+ CALL_NONVIRT_TYPE(jdouble, Double)
+
+ void CallNonvirtualVoidMethod(jobject obj, jclass clazz,
+ jmethodID methodID, ...)
+ {
+ va_list args;
+ va_start(args, methodID);
+ functions->CallNonvirtualVoidMethodV(this, obj, clazz, methodID, args);
+ va_end(args);
+ }
+ void CallNonvirtualVoidMethodV(jobject obj, jclass clazz,
+ jmethodID methodID, va_list args)
+ {
+ functions->CallNonvirtualVoidMethodV(this, obj, clazz, methodID, args);
+ }
+ void CallNonvirtualVoidMethodA(jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue *args)
+ {
+ functions->CallNonvirtualVoidMethodA(this, obj, clazz, methodID, args);
+ }
+
+ jfieldID GetFieldID(jclass clazz, const char *name, const char *sig)
+ {
+ return functions->GetFieldID(this, clazz, name, sig);
+ }
+
+ jobject GetObjectField(jobject obj, jfieldID fieldID)
+ {
+ return functions->GetObjectField(this, obj, fieldID);
+ }
+ jboolean GetBooleanField(jobject obj, jfieldID fieldID)
+ {
+ return functions->GetBooleanField(this, obj, fieldID);
+ }
+ jbyte GetByteField(jobject obj, jfieldID fieldID)
+ {
+ return functions->GetByteField(this, obj, fieldID);
+ }
+ jchar GetCharField(jobject obj, jfieldID fieldID)
+ {
+ return functions->GetCharField(this, obj, fieldID);
+ }
+ jshort GetShortField(jobject obj, jfieldID fieldID)
+ {
+ return functions->GetShortField(this, obj, fieldID);
+ }
+ jint GetIntField(jobject obj, jfieldID fieldID)
+ {
+ return functions->GetIntField(this, obj, fieldID);
+ }
+ jlong GetLongField(jobject obj, jfieldID fieldID)
+ {
+ return functions->GetLongField(this, obj, fieldID);
+ }
+ jfloat GetFloatField(jobject obj, jfieldID fieldID)
+ {
+ return functions->GetFloatField(this, obj, fieldID);
+ }
+ jdouble GetDoubleField(jobject obj, jfieldID fieldID)
+ {
+ return functions->GetDoubleField(this, obj, fieldID);
+ }
+
+ void SetObjectField(jobject obj, jfieldID fieldID, jobject val)
+ {
+ functions->SetObjectField(this, obj, fieldID, val);
+ }
+ void SetBooleanField(jobject obj, jfieldID fieldID, jboolean val)
+ {
+ functions->SetBooleanField(this, obj, fieldID, val);
+ }
+ void SetByteField(jobject obj, jfieldID fieldID, jbyte val)
+ {
+ functions->SetByteField(this, obj, fieldID, val);
+ }
+ void SetCharField(jobject obj, jfieldID fieldID, jchar val)
+ {
+ functions->SetCharField(this, obj, fieldID, val);
+ }
+ void SetShortField(jobject obj, jfieldID fieldID, jshort val)
+ {
+ functions->SetShortField(this, obj, fieldID, val);
+ }
+ void SetIntField(jobject obj, jfieldID fieldID, jint val)
+ {
+ functions->SetIntField(this, obj, fieldID, val);
+ }
+ void SetLongField(jobject obj, jfieldID fieldID, jlong val)
+ {
+ functions->SetLongField(this, obj, fieldID, val);
+ }
+ void SetFloatField(jobject obj, jfieldID fieldID, jfloat val)
+ {
+ functions->SetFloatField(this, obj, fieldID, val);
+ }
+ void SetDoubleField(jobject obj, jfieldID fieldID, jdouble val)
+ {
+ functions->SetDoubleField(this, obj, fieldID, val);
+ }
+
+ jmethodID GetStaticMethodID(jclass clazz, const char *name, const char *sig)
+ {
+ return functions->GetStaticMethodID(this, clazz, name, sig);
+ }
+
+#define CALL_STATIC_TYPE_METHOD(_jtype, _jname) \
+ _jtype CallStatic##_jname##Method(jclass clazz, jmethodID methodID, \
+ ...) \
+ { \
+ _jtype result; \
+ va_list args; \
+ va_start(args, methodID); \
+ result = functions->CallStatic##_jname##MethodV(this, clazz, \
+ methodID, args); \
+ va_end(args); \
+ return result; \
+ }
+#define CALL_STATIC_TYPE_METHODV(_jtype, _jname) \
+ _jtype CallStatic##_jname##MethodV(jclass clazz, jmethodID methodID, \
+ va_list args) \
+ { \
+ return functions->CallStatic##_jname##MethodV(this, clazz, methodID, \
+ args); \
+ }
+#define CALL_STATIC_TYPE_METHODA(_jtype, _jname) \
+ _jtype CallStatic##_jname##MethodA(jclass clazz, jmethodID methodID, \
+ const jvalue *args) \
+ { \
+ return functions->CallStatic##_jname##MethodA(this, clazz, methodID, \
+ args); \
+ }
+
+#define CALL_STATIC_TYPE(_jtype, _jname) \
+ CALL_STATIC_TYPE_METHOD(_jtype, _jname) \
+ CALL_STATIC_TYPE_METHODV(_jtype, _jname) \
+ CALL_STATIC_TYPE_METHODA(_jtype, _jname)
+
+ CALL_STATIC_TYPE(jobject, Object)
+ CALL_STATIC_TYPE(jboolean, Boolean)
+ CALL_STATIC_TYPE(jbyte, Byte)
+ CALL_STATIC_TYPE(jchar, Char)
+ CALL_STATIC_TYPE(jshort, Short)
+ CALL_STATIC_TYPE(jint, Int)
+ CALL_STATIC_TYPE(jlong, Long)
+ CALL_STATIC_TYPE(jfloat, Float)
+ CALL_STATIC_TYPE(jdouble, Double)
+
+ void CallStaticVoidMethod(jclass clazz, jmethodID methodID, ...)
+ {
+ va_list args;
+ va_start(args, methodID);
+ functions->CallStaticVoidMethodV(this, clazz, methodID, args);
+ va_end(args);
+ }
+ void CallStaticVoidMethodV(jclass clazz, jmethodID methodID, va_list args)
+ {
+ functions->CallStaticVoidMethodV(this, clazz, methodID, args);
+ }
+ void CallStaticVoidMethodA(jclass clazz, jmethodID methodID, const jvalue *args)
+ {
+ functions->CallStaticVoidMethodA(this, clazz, methodID, args);
+ }
+
+ jfieldID GetStaticFieldID(jclass clazz, const char *name, const char *sig)
+ {
+ return functions->GetStaticFieldID(this, clazz, name, sig);
+ }
+
+ jobject GetStaticObjectField(jclass clazz, jfieldID fieldID)
+ {
+ return functions->GetStaticObjectField(this, clazz, fieldID);
+ }
+ jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID)
+ {
+ return functions->GetStaticBooleanField(this, clazz, fieldID);
+ }
+ jbyte GetStaticByteField(jclass clazz, jfieldID fieldID)
+ {
+ return functions->GetStaticByteField(this, clazz, fieldID);
+ }
+ jchar GetStaticCharField(jclass clazz, jfieldID fieldID)
+ {
+ return functions->GetStaticCharField(this, clazz, fieldID);
+ }
+ jshort GetStaticShortField(jclass clazz, jfieldID fieldID)
+ {
+ return functions->GetStaticShortField(this, clazz, fieldID);
+ }
+ jint GetStaticIntField(jclass clazz, jfieldID fieldID)
+ {
+ return functions->GetStaticIntField(this, clazz, fieldID);
+ }
+ jlong GetStaticLongField(jclass clazz, jfieldID fieldID)
+ {
+ return functions->GetStaticLongField(this, clazz, fieldID);
+ }
+ jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID)
+ {
+ return functions->GetStaticFloatField(this, clazz, fieldID);
+ }
+ jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID)
+ {
+ return functions->GetStaticDoubleField(this, clazz, fieldID);
+ }
+
+ void SetStaticObjectField(jclass clazz, jfieldID fieldID, jobject val)
+ {
+ functions->SetStaticObjectField(this, clazz, fieldID, val);
+ }
+ void SetStaticBooleanField(jclass clazz, jfieldID fieldID, jboolean val)
+ {
+ functions->SetStaticBooleanField(this, clazz, fieldID, val);
+ }
+ void SetStaticByteField(jclass clazz, jfieldID fieldID, jbyte val)
+ {
+ functions->SetStaticByteField(this, clazz, fieldID, val);
+ }
+ void SetStaticCharField(jclass clazz, jfieldID fieldID, jchar val)
+ {
+ functions->SetStaticCharField(this, clazz, fieldID, val);
+ }
+ void SetStaticShortField(jclass clazz, jfieldID fieldID, jshort val)
+ {
+ functions->SetStaticShortField(this, clazz, fieldID, val);
+ }
+ void SetStaticIntField(jclass clazz, jfieldID fieldID, jint val)
+ {
+ functions->SetStaticIntField(this, clazz, fieldID, val);
+ }
+ void SetStaticLongField(jclass clazz, jfieldID fieldID, jlong val)
+ {
+ functions->SetStaticLongField(this, clazz, fieldID, val);
+ }
+ void SetStaticFloatField(jclass clazz, jfieldID fieldID, jfloat val)
+ {
+ functions->SetStaticFloatField(this, clazz, fieldID, val);
+ }
+ void SetStaticDoubleField(jclass clazz, jfieldID fieldID, jdouble val)
+ {
+ functions->SetStaticDoubleField(this, clazz, fieldID, val);
+ }
+
+ jstring NewString(const jchar *unicodeChars, jsize len)
+ {
+ return functions->NewString(this, unicodeChars, len);
+ }
+
+ jsize GetStringLength(jstring string)
+ {
+ return functions->GetStringLength(this, string);
+ }
+
+ const jchar *GetStringChars(jstring string, jboolean *isCopy)
+ {
+ return functions->GetStringChars(this, string, isCopy);
+ }
+
+ void ReleaseStringChars(jstring string, const jchar *chars)
+ {
+ functions->ReleaseStringChars(this, string, chars);
+ }
+
+ jstring NewStringUTF(const char *bytes)
+ {
+ return functions->NewStringUTF(this, bytes);
+ }
+
+ jsize GetStringUTFLength(jstring string)
+ {
+ return functions->GetStringUTFLength(this, string);
+ }
+
+ const char *GetStringUTFChars(jstring string, jboolean *isCopy)
+ {
+ return functions->GetStringUTFChars(this, string, isCopy);
+ }
+
+ void ReleaseStringUTFChars(jstring string, const char *utf)
+ {
+ functions->ReleaseStringUTFChars(this, string, utf);
+ }
+
+ jsize GetArrayLength(jarray array)
+ {
+ return functions->GetArrayLength(this, array);
+ }
+
+ jobjectArray NewObjectArray(jsize length, jclass elementClass,
+ jobject initialElement)
+ {
+ return functions->NewObjectArray(this, length, elementClass,
+ initialElement);
+ }
+
+ jobject GetObjectArrayElement(jobjectArray array, jsize index)
+ {
+ return functions->GetObjectArrayElement(this, array, index);
+ }
+
+ void SetObjectArrayElement(jobjectArray array, jsize index, jobject val)
+ {
+ functions->SetObjectArrayElement(this, array, index, val);
+ }
+
+ jbooleanArray NewBooleanArray(jsize length)
+ {
+ return functions->NewBooleanArray(this, length);
+ }
+ jbyteArray NewByteArray(jsize length)
+ {
+ return functions->NewByteArray(this, length);
+ }
+ jcharArray NewCharArray(jsize length)
+ {
+ return functions->NewCharArray(this, length);
+ }
+ jshortArray NewShortArray(jsize length)
+ {
+ return functions->NewShortArray(this, length);
+ }
+ jintArray NewIntArray(jsize length)
+ {
+ return functions->NewIntArray(this, length);
+ }
+ jlongArray NewLongArray(jsize length)
+ {
+ return functions->NewLongArray(this, length);
+ }
+ jfloatArray NewFloatArray(jsize length)
+ {
+ return functions->NewFloatArray(this, length);
+ }
+ jdoubleArray NewDoubleArray(jsize length)
+ {
+ return functions->NewDoubleArray(this, length);
+ }
+
+ jboolean *GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy)
+ {
+ return functions->GetBooleanArrayElements(this, array, isCopy);
+ }
+ jbyte *GetByteArrayElements(jbyteArray array, jboolean *isCopy)
+ {
+ return functions->GetByteArrayElements(this, array, isCopy);
+ }
+ jchar *GetCharArrayElements(jcharArray array, jboolean *isCopy)
+ {
+ return functions->GetCharArrayElements(this, array, isCopy);
+ }
+ jshort *GetShortArrayElements(jshortArray array, jboolean *isCopy)
+ {
+ return functions->GetShortArrayElements(this, array, isCopy);
+ }
+ jint *GetIntArrayElements(jintArray array, jboolean *isCopy)
+ {
+ return functions->GetIntArrayElements(this, array, isCopy);
+ }
+ jlong *GetLongArrayElements(jlongArray array, jboolean *isCopy)
+ {
+ return functions->GetLongArrayElements(this, array, isCopy);
+ }
+ jfloat *GetFloatArrayElements(jfloatArray array, jboolean *isCopy)
+ {
+ return functions->GetFloatArrayElements(this, array, isCopy);
+ }
+ jdouble *GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy)
+ {
+ return functions->GetDoubleArrayElements(this, array, isCopy);
+ }
+
+ void ReleaseBooleanArrayElements(jbooleanArray array, jboolean *elems,
+ jint mode)
+ {
+ functions->ReleaseBooleanArrayElements(this, array, elems, mode);
+ }
+ void ReleaseByteArrayElements(jbyteArray array, jbyte *elems,
+ jint mode)
+ {
+ functions->ReleaseByteArrayElements(this, array, elems, mode);
+ }
+ void ReleaseCharArrayElements(jcharArray array, jchar *elems,
+ jint mode)
+ {
+ functions->ReleaseCharArrayElements(this, array, elems, mode);
+ }
+ void ReleaseShortArrayElements(jshortArray array, jshort *elems,
+ jint mode)
+ {
+ functions->ReleaseShortArrayElements(this, array, elems, mode);
+ }
+ void ReleaseIntArrayElements(jintArray array, jint *elems,
+ jint mode)
+ {
+ functions->ReleaseIntArrayElements(this, array, elems, mode);
+ }
+ void ReleaseLongArrayElements(jlongArray array, jlong *elems,
+ jint mode)
+ {
+ functions->ReleaseLongArrayElements(this, array, elems, mode);
+ }
+ void ReleaseFloatArrayElements(jfloatArray array, jfloat *elems,
+ jint mode)
+ {
+ functions->ReleaseFloatArrayElements(this, array, elems, mode);
+ }
+ void ReleaseDoubleArrayElements(jdoubleArray array, jdouble *elems,
+ jint mode)
+ {
+ functions->ReleaseDoubleArrayElements(this, array, elems, mode);
+ }
+
+ void GetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len,
+ jboolean *buf)
+ {
+ functions->GetBooleanArrayRegion(this, array, start, len, buf);
+ }
+ void GetByteArrayRegion(jbyteArray array, jsize start, jsize len,
+ jbyte *buf)
+ {
+ functions->GetByteArrayRegion(this, array, start, len, buf);
+ }
+ void GetCharArrayRegion(jcharArray array, jsize start, jsize len,
+ jchar *buf)
+ {
+ functions->GetCharArrayRegion(this, array, start, len, buf);
+ }
+ void GetShortArrayRegion(jshortArray array, jsize start, jsize len,
+ jshort *buf)
+ {
+ functions->GetShortArrayRegion(this, array, start, len, buf);
+ }
+ void GetIntArrayRegion(jintArray array, jsize start, jsize len,
+ jint *buf)
+ {
+ functions->GetIntArrayRegion(this, array, start, len, buf);
+ }
+ void GetLongArrayRegion(jlongArray array, jsize start, jsize len,
+ jlong *buf)
+ {
+ functions->GetLongArrayRegion(this, array, start, len, buf);
+ }
+ void GetFloatArrayRegion(jfloatArray array, jsize start, jsize len,
+ jfloat *buf)
+ {
+ functions->GetFloatArrayRegion(this, array, start, len, buf);
+ }
+ void GetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len,
+ jdouble *buf)
+ {
+ functions->GetDoubleArrayRegion(this, array, start, len, buf);
+ }
+
+ void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len,
+ const jboolean *buf)
+ {
+ functions->SetBooleanArrayRegion(this, array, start, len, buf);
+ }
+ void SetByteArrayRegion(jbyteArray array, jsize start, jsize len,
+ const jbyte *buf)
+ {
+ functions->SetByteArrayRegion(this, array, start, len, buf);
+ }
+ void SetCharArrayRegion(jcharArray array, jsize start, jsize len,
+ const jchar *buf)
+ {
+ functions->SetCharArrayRegion(this, array, start, len, buf);
+ }
+ void SetShortArrayRegion(jshortArray array, jsize start, jsize len,
+ const jshort *buf)
+ {
+ functions->SetShortArrayRegion(this, array, start, len, buf);
+ }
+ void SetIntArrayRegion(jintArray array, jsize start, jsize len,
+ const jint *buf)
+ {
+ functions->SetIntArrayRegion(this, array, start, len, buf);
+ }
+ void SetLongArrayRegion(jlongArray array, jsize start, jsize len,
+ const jlong *buf)
+ {
+ functions->SetLongArrayRegion(this, array, start, len, buf);
+ }
+ void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len,
+ const jfloat *buf)
+ {
+ functions->SetFloatArrayRegion(this, array, start, len, buf);
+ }
+ void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len,
+ const jdouble *buf)
+ {
+ functions->SetDoubleArrayRegion(this, array, start, len, buf);
+ }
+
+ jint RegisterNatives(jclass clazz, const JNINativeMethod *methods,
+ jint nMethods)
+ {
+ return functions->RegisterNatives(this, clazz, methods, nMethods);
+ }
+
+ jint UnregisterNatives(jclass clazz)
+ {
+ return functions->UnregisterNatives(this, clazz);
+ }
+
+ jint MonitorEnter(jobject obj)
+ {
+ return functions->MonitorEnter(this, obj);
+ }
+
+ jint MonitorExit(jobject obj)
+ {
+ return functions->MonitorExit(this, obj);
+ }
+
+ jint GetJavaVM(JavaVM **vm)
+ {
+ return functions->GetJavaVM(this, vm);
+ }
+
+ void GetStringRegion(jstring str, jsize start, jsize len, jchar *buf)
+ {
+ functions->GetStringRegion(this, str, start, len, buf);
+ }
+
+ void GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf)
+ {
+ return functions->GetStringUTFRegion(this, str, start, len, buf);
+ }
+
+ void *GetPrimitiveArrayCritical(jarray array, jboolean *isCopy)
+ {
+ return functions->GetPrimitiveArrayCritical(this, array, isCopy);
+ }
+
+ void ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode)
+ {
+ functions->ReleasePrimitiveArrayCritical(this, array, carray, mode);
+ }
+
+ const jchar *GetStringCritical(jstring string, jboolean *isCopy)
+ {
+ return functions->GetStringCritical(this, string, isCopy);
+ }
+
+ void ReleaseStringCritical(jstring string, const jchar *carray)
+ {
+ functions->ReleaseStringCritical(this, string, carray);
+ }
+
+ jweak NewWeakGlobalRef(jobject obj)
+ {
+ return functions->NewWeakGlobalRef(this, obj);
+ }
+
+ void DeleteWeakGlobalRef(jweak obj)
+ {
+ functions->DeleteWeakGlobalRef(this, obj);
+ }
+
+ jboolean ExceptionCheck()
+ {
+ return functions->ExceptionCheck(this);
+ }
+
+ jobject NewDirectByteBuffer(void *address, jlong capacity)
+ {
+ return functions->NewDirectByteBuffer(this, address, capacity);
+ }
+
+ void *GetDirectBufferAddress(jobject buf)
+ {
+ return functions->GetDirectBufferAddress(this, buf);
+ }
+
+ jlong GetDirectBufferCapacity(jobject buf)
+ {
+ return functions->GetDirectBufferCapacity(this, buf);
+ }
+
+ /* added in JNI 1.6 */
+ jobjectRefType GetObjectRefType(jobject obj)
+ {
+ return functions->GetObjectRefType(this, obj);
+ }
+#endif /*__cplusplus*/
+};
+
+/*
+ * JNI invocation interface.
+ */
+struct JNIInvokeInterface
+{
+ void *reserved0;
+ void *reserved1;
+ void *reserved2;
+
+ jint (*DestroyJavaVM)(JavaVM *vm);
+ jint (*AttachCurrentThread)(JavaVM *vm, JNIEnv **p_env, void *thr_args);
+ jint (*DetachCurrentThread)(JavaVM *vm);
+ jint (*GetEnv)(JavaVM *vm, void **p_env, jint version);
+ jint (*AttachCurrentThreadAsDaemon)(JavaVM *vm, JNIEnv **p_env, void *thr_args);
+};
+
+/*
+ * C++ version.
+ */
+struct _JavaVM
+{
+ const struct JNIInvokeInterface *functions;
+
+#if defined(__cplusplus)
+ jint DestroyJavaVM()
+ {
+ return functions->DestroyJavaVM(this);
+ }
+ jint AttachCurrentThread(JNIEnv **p_env, void *thr_args)
+ {
+ return functions->AttachCurrentThread(this, p_env, thr_args);
+ }
+ jint DetachCurrentThread()
+ {
+ return functions->DetachCurrentThread(this);
+ }
+ jint GetEnv(void **env, jint version)
+ {
+ return functions->GetEnv(this, env, version);
+ }
+ jint AttachCurrentThreadAsDaemon(JNIEnv **p_env, void *thr_args)
+ {
+ return functions->AttachCurrentThreadAsDaemon(this, p_env, thr_args);
+ }
+#endif /*__cplusplus*/
+};
+
+struct JavaVMAttachArgs
+{
+ jint version; /* must be >= JNI_VERSION_1_2 */
+ const char *name; /* NULL or name of thread as modified UTF-8 str */
+ jobject group; /* global ref of a ThreadGroup object, or NULL */
+};
+typedef struct JavaVMAttachArgs JavaVMAttachArgs;
+
+/*
+ * JNI 1.2+ initialization. (As of 1.6, the pre-1.2 structures are no
+ * longer supported.)
+ */
+typedef struct JavaVMOption
+{
+ const char *optionString;
+ void *extraInfo;
+} JavaVMOption;
+
+typedef struct JavaVMInitArgs
+{
+ jint version; /* use JNI_VERSION_1_2 or later */
+
+ jint nOptions;
+ JavaVMOption *options;
+ jboolean ignoreUnrecognized;
+} JavaVMInitArgs;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ /*
+ * VM initialization functions.
+ *
+ * Note these are the only symbols exported for JNI by the VM.
+ */
+
+ jint JNI_GetDefaultJavaVMInitArgs(void *);
+ jint JNI_CreateJavaVM(JavaVM **, JNIEnv **, void *);
+ jint JNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *);
+
+#define JNIIMPORT
+#define JNIEXPORT __attribute__((visibility("default")))
+#define JNICALL
+
+ /*
+ * Prototypes for functions exported by loadable shared libs. These are
+ * called by JNI, not provided by JNI.
+ */
+ JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved);
+ JNIEXPORT void JNI_OnUnload(JavaVM *vm, void *reserved);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * Manifest constants.
+ */
+#define JNI_FALSE 0
+#define JNI_TRUE 1
+
+#define JNI_VERSION_1_1 0x00010001
+#define JNI_VERSION_1_2 0x00010002
+#define JNI_VERSION_1_4 0x00010004
+#define JNI_VERSION_1_6 0x00010006
+
+#define JNI_OK (0) /* no error */
+#define JNI_ERR (-1) /* generic error */
+#define JNI_EDETACHED (-2) /* thread detached from the VM */
+#define JNI_EVERSION (-3) /* JNI version error */
+#define JNI_ENOMEM (-4) /* Out of memory */
+#define JNI_EEXIST (-5) /* VM already created */
+#define JNI_EINVAL (-6) /* Invalid argument */
+
+#define JNI_COMMIT 1 /* copy content, do not free buffer */
+#define JNI_ABORT 2 /* free buffer w/o copying back */
diff --git a/pkgs/jni/tool/generate_ffi_bindings.dart b/pkgs/jni/tool/generate_ffi_bindings.dart
new file mode 100644
index 0000000..35b9db2
--- /dev/null
+++ b/pkgs/jni/tool/generate_ffi_bindings.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This script generates all FFIGEN-based bindings we require to use JNI, which
+// includes some C wrappers over `JNIEnv` type and some Dart extension methods.
+
+import 'dart:io';
+
+import 'package:logging/logging.dart';
+import 'package:args/args.dart';
+
+import 'wrapper_generators/logging.dart';
+import 'wrapper_generators/generate_c_extensions.dart';
+import 'wrapper_generators/generate_dart_extensions.dart';
+
+import 'package:ffigen/ffigen.dart' as ffigen;
+
+void main(List<String> args) {
+ final levels = Map.fromEntries(
+ Level.LEVELS.map((l) => MapEntry(l.name.toLowerCase(), l)),
+ );
+ final argParser = ArgParser()
+ ..addOption(
+ 'verbose',
+ defaultsTo: 'severe',
+ help: 'set ffigen log verbosity',
+ allowed: levels.keys,
+ )
+ ..addFlag(
+ 'help',
+ negatable: false,
+ abbr: 'h',
+ defaultsTo: false,
+ help: 'display this help message',
+ );
+
+ final argResults = argParser.parse(args);
+
+ if (argResults['help']) {
+ stderr.writeln('Generates FFI bindings required for package:jni');
+ stderr.writeln(argParser.usage);
+ exitCode = 1;
+ return;
+ }
+
+ hierarchicalLoggingEnabled = true;
+ Logger.root.level = levels[argResults['verbose']]!;
+ logger.level = Level.INFO;
+ Logger.root.onRecord.listen((record) {
+ stderr.writeln('${record.level.name}: ${record.message}');
+ });
+
+ logger.info("Generating C wrappers");
+ final minimalConfig = ffigen.Config.fromFile(File('ffigen_exts.yaml'));
+ final minimalLibrary = ffigen.parse(minimalConfig);
+ generateCWrappers(minimalLibrary);
+
+ logger.info("Generating FFI bindings for package:jni");
+
+ final config = ffigen.Config.fromFile(File('ffigen.yaml'));
+ final library = ffigen.parse(config);
+ final outputFile = File(config.output);
+ library.generateFile(outputFile);
+
+ logger.info("Generating Dart extensions");
+ generateDartExtensions(library);
+}
diff --git a/pkgs/jni/tool/generate_ide_files.dart b/pkgs/jni/tool/generate_ide_files.dart
new file mode 100644
index 0000000..ab44ad8
--- /dev/null
+++ b/pkgs/jni/tool/generate_ide_files.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:args/args.dart';
+
+const makefilesGenerator = 'make';
+const ninjaGenerator = 'ninja';
+
+const cmakeGeneratorNames = {
+ makefilesGenerator: 'Unix Makefiles',
+ ninjaGenerator: 'Ninja',
+};
+
+void runCommand(String exec, List<String> args, String workingDirectory) {
+ stderr.writeln('+ $exec ${args.join(" ")}');
+ final process =
+ Process.runSync(exec, args, workingDirectory: workingDirectory);
+ if (process.exitCode != 0) {
+ stdout.writeln(process.stdout);
+ stderr.writeln(process.stderr);
+ throw "command failed with exit code ${process.exitCode}";
+ }
+}
+
+void main(List<String> arguments) {
+ final argParser = ArgParser()
+ ..addOption(
+ "generator",
+ abbr: 'G',
+ help: 'Generator to pass to CMake. (Either "ninja" or "make").',
+ allowed: [ninjaGenerator, makefilesGenerator],
+ defaultsTo: Platform.isWindows ? ninjaGenerator : makefilesGenerator,
+ )
+ ..addFlag('help', abbr: 'h', help: 'Show this usage information.');
+ final argResults = argParser.parse(arguments);
+ if (argResults.rest.isNotEmpty || argResults['help']) {
+ stderr.writeln('This script generates compile_commands.json for '
+ 'C source files in src/');
+ stderr.writeln(argParser.usage);
+ exitCode = 1;
+ return;
+ }
+ final generator = cmakeGeneratorNames[argResults['generator']];
+ final tempDir = Directory.current.createTempSync("clangd_setup_temp_");
+ final src = Directory.current.uri.resolve("src/");
+ try {
+ runCommand(
+ "cmake",
+ [
+ "-DCMAKE_EXPORT_COMPILE_COMMANDS=1",
+ src.toFilePath(),
+ "-G",
+ generator!,
+ ],
+ tempDir.path);
+ final createdFile = tempDir.uri.resolve("compile_commands.json");
+ final target = src.resolve("compile_commands.json");
+ File.fromUri(createdFile).renameSync(target.toFilePath());
+ } finally {
+ tempDir.deleteSync(recursive: true);
+ }
+}
diff --git a/pkgs/jni/tool/wrapper_generators/ffigen_util.dart b/pkgs/jni/tool/wrapper_generators/ffigen_util.dart
new file mode 100644
index 0000000..2b234f6
--- /dev/null
+++ b/pkgs/jni/tool/wrapper_generators/ffigen_util.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:ffigen/src/code_generator/writer.dart';
+import 'package:ffigen/src/code_generator.dart';
+
+final dummyWriter = Writer(
+ lookUpBindings: [],
+ ffiNativeBindings: [],
+ noLookUpBindings: [],
+ className: 'unused',
+);
+
+/// Find compound having [name] in [library].
+Compound findCompound(library, String name) {
+ return library.bindings.firstWhere((element) => element.name == name)
+ as Compound;
+}
+
+const preamble = '''
+// Auto generated file. Do not edit.
+
+// This is generated from JNI header in Android NDK. License for the same is
+// provided below.
+
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * JNI specification, as defined by Sun:
+ * http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html
+ *
+ * Everything here is expected to be VM-neutral.
+ */
+
+''';
diff --git a/pkgs/jni/tool/wrapper_generators/generate_c_extensions.dart b/pkgs/jni/tool/wrapper_generators/generate_c_extensions.dart
new file mode 100644
index 0000000..f1e15b2
--- /dev/null
+++ b/pkgs/jni/tool/wrapper_generators/generate_c_extensions.dart
@@ -0,0 +1,297 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:ffigen/src/code_generator.dart';
+
+import 'ffigen_util.dart';
+import 'logging.dart';
+
+class Paths {
+ static final currentDir = Directory.current.uri;
+ static final src = currentDir.resolve("src/");
+ static final thirdParty = src.resolve("third_party/");
+ static final globalJniEnvH = thirdParty.resolve("global_jni_env.h");
+ static final globalJniEnvC = thirdParty.resolve("global_jni_env.c");
+ static final bindingsDir = currentDir.resolve("lib/src/third_party/");
+ static final envExtensions = bindingsDir.resolve("env_extensions.dart");
+}
+
+/// Name of variable used in wrappers to hold the result.
+const resultVar = '_result';
+
+/// Name of variable used in wrappers to hold the exception.
+const errorVar = '_exception';
+
+/// Name of JNIEnv struct definition in JNI headers.
+const envType = 'JNINativeInterface';
+
+/// Name of wrapper to JNIEnv
+const wrapperName = 'GlobalJniEnvStruct';
+
+const wrapperIncludes = '''
+#include "global_jni_env.h"
+
+''';
+
+const wrapperDeclIncludes = '''
+#include <stdint.h>
+#include "../dartjni.h"
+
+''';
+
+const wrapperGetter = '''
+FFI_PLUGIN_EXPORT
+$wrapperName* GetGlobalEnv() {
+ if (jni->jvm == NULL) {
+ return NULL;
+ }
+ return &globalJniEnv;
+}
+''';
+
+const wrapperGetterDecl = '''
+FFI_PLUGIN_EXPORT $wrapperName* GetGlobalEnv();
+''';
+
+/// Get C name of a type from its ffigen representation.
+String getCType(Type type) {
+ if (type is PointerType) {
+ return '${getCType(type.child)}*';
+ }
+ final cType = type.getCType(dummyWriter);
+ const specialCaseMappings = {
+ 'JNIEnv1': 'JNIEnv',
+ 'ffi.Char': 'char',
+ 'ffi.Void': 'void',
+ 'ffi.Int': 'int',
+ 'ffi.Int32': 'int32_t',
+ };
+ return specialCaseMappings[cType] ?? cType;
+}
+
+/// Get type of wrapping function for a JNIEnv function.
+FunctionType getGlobalJniEnvFunctionType(FunctionType ft) {
+ return FunctionType(
+ returnType: ft.returnType,
+ parameters: ft.parameters.sublist(1),
+ );
+}
+
+// Returns declaration of function field in GlobalJniEnv struct
+String getFunctionFieldDecl(
+ Member field,
+) {
+ final fieldType = field.type;
+ if (fieldType is PointerType && fieldType.child is NativeFunc) {
+ final nativeFunc = fieldType.child as NativeFunc;
+ final functionType = getGlobalJniEnvFunctionType(nativeFunc.type);
+ final resultWrapper = getResultWrapper(getCType(functionType.returnType));
+ final name = field.name;
+ final params = functionType.parameters
+ .map((param) => '${getCType(param.type)} ${param.name}')
+ .join(', ');
+ return ('${resultWrapper.returnType} (*$name)($params);');
+ } else {
+ return 'void* ${field.name};';
+ }
+}
+
+String getWrapperFuncName(Member field) {
+ return 'globalEnv_${field.name}';
+}
+
+class ResultWrapper {
+ String returnType, onResult, onError;
+ ResultWrapper.withResultAndError(
+ this.returnType, this.onResult, this.onError);
+ ResultWrapper.unionType(
+ String returnType,
+ String defaultValue,
+ ) : this.withResultAndError(
+ returnType,
+ '($returnType){.value = $resultVar, .exception = NULL}',
+ '($returnType){.value = $defaultValue, .exception = $errorVar}',
+ );
+ ResultWrapper.forJValueField(String fieldChar)
+ : this.withResultAndError(
+ 'JniResult',
+ '(JniResult){.value = {.$fieldChar = $resultVar}, .exception = NULL}',
+ '(JniResult){.value = {.j = 0}, .exception = $errorVar}',
+ );
+}
+
+ResultWrapper getResultWrapper(String returnType) {
+ if (returnType.endsWith("*")) {
+ return ResultWrapper.unionType('JniPointerResult', 'NULL');
+ }
+
+ final jobjectWrapper = ResultWrapper.forJValueField('l');
+ if (returnType.endsWith('Array')) {
+ return jobjectWrapper;
+ }
+
+ const jfields = {
+ 'jboolean': 'z',
+ 'jbyte': 'b',
+ 'jshort': 's',
+ 'jchar': 'c',
+ 'jint': 'i',
+ 'jsize': 'i', // jsize is an alias to jint
+ 'jfloat': 'f',
+ 'jlong': 'j',
+ 'jdouble': 'd',
+ 'jobject': 'l',
+ 'jweak': 'l',
+ 'jarray': 'l',
+ 'jstring': 'l',
+ 'jthrowable': 'l',
+ };
+
+ switch (returnType) {
+ case 'void':
+ return ResultWrapper.withResultAndError(
+ 'jthrowable',
+ 'NULL',
+ errorVar,
+ );
+ case 'jmethodID':
+ case 'jfieldID':
+ return ResultWrapper.unionType('JniPointerResult', 'NULL');
+ case 'jclass':
+ return ResultWrapper.unionType('JniClassLookupResult', 'NULL');
+ case 'int32_t':
+ return ResultWrapper.forJValueField('i');
+ default:
+ if (jfields.containsKey(returnType)) {
+ return ResultWrapper.forJValueField(jfields[returnType]!);
+ }
+ throw 'Unknown type $returnType for return type';
+ }
+}
+
+bool isJRefType(String type) {
+ // No need to include jweak here, its only returned by ref-related functions.
+ const refTypes = {
+ 'jclass',
+ 'jobject',
+ 'jstring',
+ 'jthrowable',
+ 'jarray',
+ 'jweak'
+ };
+ return (type.startsWith('j') && type.endsWith('Array')) ||
+ refTypes.contains(type);
+}
+
+const refFunctions = {
+ 'NewGlobalRef',
+ 'DeleteGlobalRef',
+ 'NewLocalRef',
+ 'DeleteLocalRef',
+ 'NewWeakGlobalRef',
+ 'DeleteWeakGlobalRef',
+};
+
+/// These return const ptrs so the assignment statement needs to be
+/// adjusted in the wrapper.
+const constBufferReturningFunctions = {
+ 'GetStringChars',
+ 'GetStringUTFChars',
+ 'GetStringCritical',
+};
+
+/// Methods which do not throw exceptions, and thus not need to be checked
+const _noCheckException = {
+ 'GetVersion',
+ 'GetStringCritical',
+ 'ExceptionClear',
+ 'ExceptionDescribe',
+};
+
+String? getWrapperFunc(Member field) {
+ final fieldType = field.type;
+ if (fieldType is PointerType && fieldType.child is NativeFunc) {
+ final functionType = (fieldType.child as NativeFunc).type;
+ if (functionType.parameters.first.name.isEmpty) {
+ return null;
+ }
+
+ final outerFunctionType = getGlobalJniEnvFunctionType(functionType);
+ final wrapperName = getWrapperFuncName(field);
+ final returnType = getCType(outerFunctionType.returnType);
+ final params = outerFunctionType.parameters
+ .map((param) => '${getCType(param.type)} ${param.name}')
+ .join(', ');
+ var returnCapture = returnType == 'void' ? '' : '$returnType $resultVar =';
+ if (constBufferReturningFunctions.contains(field.name)) {
+ returnCapture = 'const $returnCapture';
+ }
+ final callParams = [
+ 'jniEnv',
+ ...(outerFunctionType.parameters.map((param) => param.name).toList())
+ ].join(', ');
+ final resultWrapper = getResultWrapper(returnType);
+
+ var convertRef = '';
+ if (isJRefType(returnType) && !refFunctions.contains(field.name)) {
+ convertRef = ' $resultVar = to_global_ref($resultVar);\n';
+ }
+ final exceptionCheck = _noCheckException.contains(field.name)
+ ? ''
+ : ' jthrowable $errorVar = check_exception();\n'
+ ' if ($errorVar != NULL) {\n'
+ ' return ${resultWrapper.onError};\n'
+ ' }\n';
+ return '${resultWrapper.returnType} $wrapperName($params) {\n'
+ ' attach_thread();\n'
+ ' $returnCapture (*jniEnv)->${field.name}($callParams);\n'
+ '$exceptionCheck'
+ '$convertRef'
+ ' return ${resultWrapper.onResult};\n'
+ '}\n';
+ }
+ return null;
+}
+
+void writeGlobalJniEnvWrapper(Library library) {
+ final jniEnvType = findCompound(library, envType);
+
+ final fieldDecls = jniEnvType.members.map(getFunctionFieldDecl).join('\n');
+ final structDecl =
+ 'typedef struct $wrapperName {\n$fieldDecls\n} $wrapperName;\n';
+ File.fromUri(Paths.globalJniEnvH).writeAsStringSync(
+ '$preamble$wrapperDeclIncludes$structDecl$wrapperGetterDecl');
+
+ final functionWrappers = StringBuffer();
+ final structInst = StringBuffer('$wrapperName globalJniEnv = {\n');
+ for (final member in jniEnvType.members) {
+ final wrapper = getWrapperFunc(member);
+ if (wrapper == null) {
+ structInst.write('.${member.name} = NULL,\n');
+ } else {
+ structInst.write('.${member.name} = ${getWrapperFuncName(member)},\n');
+ functionWrappers.write('$wrapper\n');
+ }
+ }
+ structInst.write('};');
+ File.fromUri(Paths.globalJniEnvC).writeAsStringSync(
+ '$preamble$wrapperIncludes$functionWrappers$structInst$wrapperGetter');
+}
+
+void executeClangFormat(List<Uri> files) {
+ final paths = files.map((u) => u.toFilePath()).toList();
+ logger.info('execute clang-format -i ${paths.join(" ")}');
+ final format = Process.runSync('clang-format', ['-i', ...paths]);
+ if (format.exitCode != 0) {
+ stderr.writeln('clang-format exited with ${format.exitCode}');
+ stderr.writeln(format.stderr);
+ }
+}
+
+void generateCWrappers(Library minimalLibrary) {
+ writeGlobalJniEnvWrapper(minimalLibrary);
+ executeClangFormat([Paths.globalJniEnvC, Paths.globalJniEnvH]);
+}
diff --git a/pkgs/jni/tool/wrapper_generators/generate_dart_extensions.dart b/pkgs/jni/tool/wrapper_generators/generate_dart_extensions.dart
new file mode 100644
index 0000000..c78b883
--- /dev/null
+++ b/pkgs/jni/tool/wrapper_generators/generate_dart_extensions.dart
@@ -0,0 +1,253 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:collection/collection.dart';
+import 'package:ffigen/src/code_generator.dart';
+
+import 'ffigen_util.dart';
+import 'logging.dart';
+
+class Paths {
+ static final currentDir = Directory.current.uri;
+ static final bindingsDir = currentDir.resolve("lib/src/third_party/");
+ // Contains extensions for our C wrapper types.
+ static final globalEnvExts =
+ bindingsDir.resolve("global_env_extensions.dart");
+ // Contains extensions for JNI's struct types.
+ static final localEnvExts =
+ bindingsDir.resolve("jnienv_javavm_extensions.dart");
+}
+
+const writeLocalEnvExtensions = false;
+
+void executeDartFormat(List<Uri> files) {
+ final paths = files.map((u) => u.toFilePath()).toList();
+ logger.info('execute dart format ${paths.join(" ")}');
+ final format = Process.runSync('dart', ['format', ...paths]);
+ if (format.exitCode != 0) {
+ logger.severe('dart format exited with ${format.exitCode}');
+ stderr.writeln(format.stderr);
+ }
+}
+
+const globalEnvType = 'GlobalJniEnvStruct';
+const localEnvType = 'JNINativeInterface';
+const jvmType = 'JNIInvokeInterface';
+
+String getCheckedGetter(Type returnType) {
+ if (returnType is PointerType) {
+ final child = returnType.child.getCType(dummyWriter);
+ return 'getPointer<$child>()';
+ }
+ final cType = returnType.getCType(dummyWriter);
+ if (cType.endsWith("ArrayPtr")) {
+ return 'object';
+ }
+ const mappings = {
+ 'JBooleanMarker': 'boolean',
+ 'JByteMarker': 'byte',
+ 'JShortMarker': 'short',
+ 'JCharMarker': 'char',
+ 'JIntMarker': 'integer',
+ 'JSizeMarker': 'integer', // jsize is aliased to jint
+ 'JLongMarker': 'long',
+ 'JFloatMarker': 'float',
+ 'JDoubleMarker': 'doubleFloat',
+ 'JObjectPtr': 'object',
+ 'JThrowablePtr': 'object',
+ 'JStringPtr': 'object',
+ 'JClassPtr': 'value',
+ 'JFieldIDPtr': 'fieldID',
+ 'JMethodIDPtr': 'methodID',
+ 'ffi.Int32': 'integer',
+ 'ffi.Void': 'check()',
+ 'JWeakPtr': 'object',
+ };
+ if (mappings.containsKey(cType)) {
+ return mappings[cType]!;
+ }
+ throw 'Unknown return type: $cType';
+}
+
+String? getGlobalEnvExtensionFunction(Member field, Type? checkedReturnType) {
+ final fieldType = field.type;
+ if (fieldType is PointerType && fieldType.child is NativeFunc) {
+ final nativeFunc = fieldType.child as NativeFunc;
+ final functionType = nativeFunc.type;
+ final returnType = functionType.returnType;
+ var params = functionType.parameters;
+ if (params.first.name.isEmpty) {
+ return null;
+ }
+
+ // Remove env parameter
+ params = params.sublist(1);
+
+ final signature = params
+ .map((p) => '${p.type.getDartType(dummyWriter)} ${p.name}')
+ .join(', ');
+
+ final dartType =
+ FunctionType(returnType: checkedReturnType!, parameters: params)
+ .getDartType(dummyWriter);
+ final callArgs = params.map((p) => p.name).join(', ');
+ final checkedGetter = getCheckedGetter(returnType);
+ var returns = returnType.getDartType(dummyWriter);
+ if (checkedGetter == 'boolean') {
+ returns = 'bool';
+ }
+ return '''
+late final _${field.name} =
+ ptr.ref.${field.name}.asFunction<$dartType>();\n
+$returns ${field.name}($signature) =>
+ _${field.name}($callArgs).$checkedGetter;
+
+''';
+ }
+ return null;
+}
+
+void writeDartExtensions(Library library) {
+ const header = '''
+// ignore_for_file: non_constant_identifier_names
+// coverage:ignore-file
+
+import "dart:ffi" as ffi;\n
+import "jni_bindings_generated.dart";
+
+''';
+ const importAccessors = '''
+import "../accessors.dart";
+
+''';
+
+ final globalEnvExtension = getGlobalEnvExtension(library);
+ final accessorExtension = getFunctionPointerExtension(
+ library,
+ 'JniAccessorsStruct',
+ 'JniAccessors',
+ );
+ File.fromUri(Paths.globalEnvExts).writeAsStringSync(preamble +
+ header +
+ importAccessors +
+ globalEnvExtension +
+ accessorExtension);
+ final localEnvExtsFile = File.fromUri(Paths.localEnvExts);
+ if (localEnvExtsFile.existsSync()) {
+ localEnvExtsFile.deleteSync();
+ }
+ if (!writeLocalEnvExtensions) {
+ return;
+ }
+ final envExtension = getFunctionPointerExtension(
+ library,
+ 'JniEnv',
+ 'LocalJniEnv',
+ indirect: true,
+ implicitThis: true,
+ );
+ final jvmExtension = getFunctionPointerExtension(
+ library,
+ 'JavaVM',
+ 'JniJavaVM',
+ indirect: true,
+ implicitThis: true,
+ );
+ localEnvExtsFile
+ .writeAsStringSync(preamble + header + envExtension + jvmExtension);
+}
+
+String getGlobalEnvExtension(
+ Library library,
+) {
+ final env = findCompound(library, localEnvType);
+ final globalEnv = findCompound(library, globalEnvType);
+ final checkedReturnTypes = {};
+ for (var field in globalEnv.members) {
+ final fieldType = field.type;
+ if (fieldType is PointerType && fieldType.child is NativeFunc) {
+ checkedReturnTypes[field.name] =
+ (fieldType.child as NativeFunc).type.returnType;
+ }
+ }
+ final extensionFunctions = env.members
+ .map((m) => getGlobalEnvExtensionFunction(m, checkedReturnTypes[m.name]))
+ .whereNotNull()
+ .join('\n');
+ return '''
+/// Wraps over Pointer<GlobalJniEnvStruct> and exposes function pointer fields
+/// as methods.
+class GlobalJniEnv {
+ final ffi.Pointer<GlobalJniEnvStruct> ptr;
+ GlobalJniEnv(this.ptr);
+ $extensionFunctions
+}
+''';
+}
+
+String? getFunctionPointerExtensionFunction(Member field,
+ {bool indirect = false, bool implicitThis = false}) {
+ final fieldType = field.type;
+ if (fieldType is PointerType && fieldType.child is NativeFunc) {
+ final nativeFunc = fieldType.child as NativeFunc;
+ final functionType = nativeFunc.type;
+ final returnType = functionType.returnType;
+ final params = functionType.parameters;
+ if (params.first.name.isEmpty) {
+ return null;
+ }
+
+ final visibleParams = implicitThis ? params.sublist(1) : params;
+
+ final signature = visibleParams
+ .map((p) => '${p.type.getDartType(dummyWriter)} ${p.name}')
+ .join(', ');
+
+ final dartType = FunctionType(returnType: returnType, parameters: params)
+ .getDartType(dummyWriter);
+ final callArgs = [
+ if (implicitThis) 'ptr',
+ ...visibleParams.map((p) => p.name)
+ ].join(', ');
+ final returns = returnType.getDartType(dummyWriter);
+ final dereference = indirect ? 'value.ref' : 'ref';
+ return '''
+late final _${field.name} =
+ ptr.$dereference.${field.name}.asFunction<$dartType>();
+$returns ${field.name}($signature) => _${field.name}($callArgs);
+
+''';
+ }
+ return null;
+}
+
+String getFunctionPointerExtension(
+ Library library, String type, String wrapperClassName,
+ {bool indirect = false, bool implicitThis = false}) {
+ final typeBinding =
+ library.bindings.firstWhere((b) => b.name == type) as Type;
+ final compound = typeBinding.typealiasType.baseType as Compound;
+ final extensionFunctions = compound.members
+ .map((f) => getFunctionPointerExtensionFunction(f,
+ indirect: indirect, implicitThis: implicitThis))
+ .whereNotNull()
+ .join('\n');
+ return '''
+/// Wraps over the function pointers in $type and exposes them as methods.
+class $wrapperClassName {
+ final ffi.Pointer<$type> ptr;
+ $wrapperClassName(this.ptr);
+
+ $extensionFunctions
+}
+
+''';
+}
+
+void generateDartExtensions(Library library) {
+ writeDartExtensions(library);
+ executeDartFormat([Paths.globalEnvExts, Paths.localEnvExts]);
+}
diff --git a/pkgs/jni/tool/wrapper_generators/logging.dart b/pkgs/jni/tool/wrapper_generators/logging.dart
new file mode 100644
index 0000000..386f5c6
--- /dev/null
+++ b/pkgs/jni/tool/wrapper_generators/logging.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:logging/logging.dart';
+
+final logger = Logger('ffi_wrappers_generator');
diff --git a/pkgs/jni/windows/.gitignore b/pkgs/jni/windows/.gitignore
new file mode 100644
index 0000000..b3eb2be
--- /dev/null
+++ b/pkgs/jni/windows/.gitignore
@@ -0,0 +1,17 @@
+flutter/
+
+# Visual Studio user-specific files.
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# Visual Studio build-related files.
+x64/
+x86/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
diff --git a/pkgs/jni/windows/CMakeLists.txt b/pkgs/jni/windows/CMakeLists.txt
new file mode 100644
index 0000000..67bbdc6
--- /dev/null
+++ b/pkgs/jni/windows/CMakeLists.txt
@@ -0,0 +1,23 @@
+# The Flutter tooling requires that developers have a version of Visual Studio
+# installed that includes CMake 3.14 or later. 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.14)
+
+# Project-level configuration.
+set(PROJECT_NAME "jni")
+project(${PROJECT_NAME} LANGUAGES CXX)
+
+# Invoke the build for native code shared with the other target platforms.
+# This can be changed to accomodate different builds.
+add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared")
+
+# 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.
+set(jni_bundled_libraries
+ # Defined in ../src/CMakeLists.txt.
+ # This can be changed to accomodate different builds.
+ $<TARGET_FILE:jni>
+ PARENT_SCOPE
+)
diff --git a/pkgs/jnigen/.gitignore b/pkgs/jnigen/.gitignore
new file mode 100644
index 0000000..a63fd72
--- /dev/null
+++ b/pkgs/jnigen/.gitignore
@@ -0,0 +1,48 @@
+# See https://www.dartlang.org/guides/libraries/private-files
+
+# Files and directories created by pub.
+.dart_tool/
+.packages
+build/
+pubspec.lock
+.flutter-plugins
+.flutter-plugins-dependencies
+
+# created by maven
+/target/
+
+# Directory created by dartdoc.
+doc/api/
+
+# Avoid committing generated Javascript files:
+*.dart.js
+*.info.json # Produced by the --dump-info flag.
+*.js # When generated by dart2js. Don't specify *.js if your
+ # project includes source files written in JavaScript.
+*.js_
+*.js.deps
+*.js.map
+
+# IDE and debugger files.
+.clangd
+.gdb_history
+.history
+.vscode
+compile_commands.json
+
+# IntelliJ
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# Mac
+.DS_Store
+
+# Vim
+.*.swp
+
+## Downloaded files and build artifacts
+*.jar
+*.class
+*.exe
diff --git a/pkgs/jnigen/CHANGELOG.md b/pkgs/jnigen/CHANGELOG.md
new file mode 100644
index 0000000..0056f41
--- /dev/null
+++ b/pkgs/jnigen/CHANGELOG.md
@@ -0,0 +1,79 @@
+## 0.8.0-wip
+
+- **Breaking Change**: The generated impl class for interfaces is now an
+ `interface`.
+
+## 0.7.0
+
+- **Breaking Change** ([#387](https://github.com/dart-lang/jnigen/issues/387)):
+ Added `JBuffer` and `JByteBuffer` classes as default classes for
+ `java.nio.Buffer` and `java.nio.ByteBuffer` respectively.
+- **Breaking Change**: Made the type classes `final`.
+- Added `ignore_for_file: lines_longer_than_80_chars` to the generated file
+ preamble.
+- Added an explicit cast in generated `<Interface>.implement` code to allow
+ `dart analyze` to pass when `strict-casts` is set.
+
+## 0.6.0
+
+- **Breaking Change** ([#131](https://github.com/dart-lang/jnigen/issues/131)):
+ Renamed `delete*` to `release*`.
+- **Breaking Change** ([#354](https://github.com/dart-lang/jnigen/issues/354)):
+ Renamed constructors from `ctor1`, `ctor2`, ... to `new1`, `new2`, ...
+- **Breaking Change**: Specifying a class always pulls in nested classes by
+ default. If a nested class is specified in config, it will be an error.
+- **Breaking Change**: Removed `suspend_fun_to_async` flag from the config. It's
+ now happening by default since we read the Kotlin's metadata and reliably
+ identify the `suspend fun`s.
+- Fixed a bug where the nested classes would be generated incorrectly depending
+ on the backend used for generation.
+- Fixed a bug where ASM backend would produce the incorrect parent for
+ multi-level nested classes.
+- Fixed a bug where the backends would produce different descriptors for the
+ same method.
+- Added `enable_experiment` option to config.
+- Created an experiment called `interface_implementation` which creates a
+ `.implement` method for interfaces, so you can implement them using Dart.
+- Save all `jnigen` logs to a file in `.dart_tool/jnigen/logs/`. This is useful
+ for debugging.
+
+## 0.5.0
+
+- **Breaking Change** ([#72](https://github.com/dart-lang/jnigen/issues/72)):
+ Removed support for `importMap` in favor of the newly added interop mechanism
+ with importing yaml files.
+- **Breaking Change** ([#72](https://github.com/dart-lang/jnigen/issues/72)):
+ `java.util.Set`, `java.util.Map`, `java.util.List`, `java.util.Iterator` and
+ the boxed types like `java.lang.Integer`, `java.lang.Double`, ... will be
+ generated as their corresponding classes in `package:jni`.
+- Strings now use UTF16.
+
+## 0.4.0
+
+- **Breaking Change** ([#145](https://github.com/dart-lang/jnigen/issues/145)):
+ Type arguments are now named instead of positional.
+- Type parameters can now be inferred when possible.
+- Fixed a bug where passing a `long` argument truncated it to `int` in pure dart
+ bindings.
+- Removed array extensions from the generated code.
+- Added the ability to use source dependencies from Gradle.
+- Fixed an issue with the field setter.
+- Fixed an issue where exceptions were not properly thrown in pure Dart
+ bindings.
+
+## 0.3.0
+
+- Added the option to convert Kotlin `suspend fun` to Dart async methods. Add
+ `suspend_fun_to_async: true` to `jnigen.yaml`.
+
+## 0.2.0
+
+- Support generating bindings for generics.
+
+## 0.1.1
+
+- Windows support for running tests and examples on development machines.
+
+## 0.1.0
+
+- Initial version: Basic bindings generation, maven and android utilities
diff --git a/pkgs/jnigen/LICENSE b/pkgs/jnigen/LICENSE
new file mode 100644
index 0000000..f0604ef
--- /dev/null
+++ b/pkgs/jnigen/LICENSE
@@ -0,0 +1,32 @@
+Copyright 2022, the Dart project authors.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of Google LLC nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Code generated by JNIgen is owned by the owner of the input file used
+when generating it. This code is not standalone and requires a
+support library to be linked with it. This support library is itself
+covered by the above license.
diff --git a/pkgs/jnigen/README.md b/pkgs/jnigen/README.md
new file mode 100644
index 0000000..eaffeaa
--- /dev/null
+++ b/pkgs/jnigen/README.md
@@ -0,0 +1,285 @@
+[](https://github.com/dart-lang/jnigen/actions?query=workflow%3A%22Dart+CI%22+branch%3Amain)
+[](https://coveralls.io/github/dart-lang/jnigen?branch=main)
+
+## Introduction
+Experimental bindings generator for Java bindings through dart:ffi and JNI.
+
+`jnigen` scans compiled JAR files or Java source code to generate a description of the API, then uses it to generate Dart annd C bindings. The Dart bindings call the C bindings, which in-turn call the Java functions through JNI. Shared functionality and base classes are provided through the support library, `package:jni`.
+
+The configuration for binding generation is usually provided through YAML.
+
+Three configuration details are needed to generate the bindings. Everything else is optional:
+
+* _Inputs_: input can be Java source files (`source_path`), or compiled classes / JARs (`class_path`). Some maven / gradle based tooling is also provided to simplify obtaining dependencies.
+
+* _Outputs_: Output can be generated in package-structured (one file per class) or single file bindings. Target path to write C and Dart bindings needs to be specified.
+
+* _Classes_: Specify which classes or packages you need bindings for. Specifying a package includes all classes inside it recursively.
+
+Check out the [examples](jnigen/example/) to see some sample configurations.
+
+C code is always generated into a directory with it's own build configuration. It's built as a separate dynamic library.
+
+Lastly, [dart_only bindings](#pure-dart-bindings) mode is also available as a proof-of-concept. It does not need intermediate C bindings, only a dependency on the support library `package:jni`.
+
+## Example
+It's possible to generate bindings for JAR libraries, or Java source files.
+
+Here's a simple example Java file, in a Flutter Android app.
+
+```java
+package com.example.in_app_java;
+
+import android.app.Activity;
+import android.widget.Toast;
+import androidx.annotation.Keep;
+
+@Keep
+public abstract class AndroidUtils {
+ // Hide constructor
+ private AndroidUtils() {}
+
+ public static void showToast(Activity mainActivity, CharSequence text, int duration) {
+ mainActivity.runOnUiThread(() -> Toast.makeText(mainActivity, text, duration).show());
+ }
+}
+```
+
+This produces the following boilerplate:
+
+#### Dart Bindings:
+
+```dart
+/// Some boilerplate is omitted for clarity.
+final ffi.Pointer<T> Function<T extends ffi.NativeType>(String sym) jniLookup =
+ ProtectedJniExtensions.initGeneratedLibrary("android_utils");
+
+/// from: com.example.in_app_java.AndroidUtils
+class AndroidUtils extends jni.JObject {
+ AndroidUtils.fromRef(ffi.Pointer<ffi.Void> ref) : super.fromRef(ref);
+
+ static final _showToast = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Int32)>>("AndroidUtils__showToast")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: static public void showToast(android.app.Activity mainActivity, java.lang.CharSequence text, int duration)
+ static void showToast(
+ jni.JObject mainActivity, jni.JObject text, int duration) =>
+ _showToast(mainActivity.reference, text.reference, duration).check();
+}
+```
+
+#### C Bindings:
+
+```c
+// Some boilerplate is omitted for clarity.
+
+// com.example.in_app_java.AndroidUtils
+jclass _c_AndroidUtils = NULL;
+
+jmethodID _m_AndroidUtils__showToast = NULL;
+FFI_PLUGIN_EXPORT
+JniResult AndroidUtils__showToast(jobject mainActivity,
+ jobject text,
+ int32_t duration) {
+ load_env();
+ load_class_gr(&_c_AndroidUtils, "com/example/in_app_java/AndroidUtils");
+ if (_c_AndroidUtils == NULL)
+ return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_AndroidUtils, &_m_AndroidUtils__showToast, "showToast",
+ "(Landroid/app/Activity;Ljava/lang/CharSequence;I)V");
+ if (_m_AndroidUtils__showToast == NULL)
+ return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallStaticVoidMethod(jniEnv, _c_AndroidUtils,
+ _m_AndroidUtils__showToast, mainActivity,
+ text, duration);
+ return (JniResult){.result = {.j = 0}, .exception = check_exception()};
+}
+```
+
+The YAML configuration used to generate the above code looks like this:
+
+```yaml
+android_sdk_config:
+ add_gradle_deps: true
+
+output:
+ c:
+ library_name: android_utils
+ path: src/android_utils/
+ dart:
+ path: lib/android_utils.dart
+ structure: single_file
+
+source_path:
+ - 'android/app/src/main/java'
+classes:
+ - 'com.example.in_app_java.AndroidUtils'
+```
+
+The complete example can be found in [jnigen/example/in_app_java](jnigen/example/in_app_java), which adds few more classes to demonstrate using classes from gradle JAR and source dependencies.
+
+## Supported platforms
+| Platform | Dart Standalone | Flutter |
+| -------- | --------------- | ------------- |
+| Android | n/a | Supported |
+| Linux | Supported | Supported |
+| Windows | Supported | Supported |
+| MacOS | Supported | Not Yet |
+
+On Android, the flutter application runs embedded in Android JVM. On other platforms, a JVM needs to be explicitly spawned using `Jni.spawn`. `package:jni` provides the infrastructure for initializing and managing the JNI on both Android and Non-Android platforms.
+
+## Java features support
+Currently basic features of the Java language are supported in the bindings. Each Java class is mapped to a Dart class. Bindings are generated for methods, constructors and fields. Exceptions thrown in Java are rethrown in Dart with stack trace from Java.
+
+More advanced features such as callbacks are not supported yet. Support for these features is tracked in the [issue tracker](https://github.com/dart-lang/jnigen/issues).
+
+## Note on Dart (standalone) target
+`package:jni` is an FFI plugin containing native code, and any bindings generated from jnigen contains native code too.
+
+On Flutter targets, native libraries are built automatically and bundled. On standalone platforms, no such infrastructure exists yet. As a stopgap solution, running `dart run jni:setup` in a target directory builds all JNI native dependencies of the package into `build/jni_libs`.
+
+By default `jni:setup` goes through pubspec configuration and builds all JNI dependencies of the project. It can be overridden to build a custom directory using `-s` switch, which can be useful when output configuration for C bindings does not follow standard FFI plugin layout.
+
+The build directory has to be passed to `Jni.spawn` call. It's assumed that all dependencies are built into the same target directory, so that once JNI is initialized, generated bindings can load their respective C libraries automatically.
+
+## Requirements
+### SDK
+Flutter SDK is required.
+
+Dart standalone target is supported, but due to some problems with pubspec format, the `dart` command must be from Flutter SDK and not Dart SDK. See [dart-lang/pub#3563](https://github.com/dart-lang/pub/issues/3563).
+
+### Java tooling
+
+**Use JDK versions 11 to 17. The newer versions will not work because of their lack of [compatibility](https://docs.gradle.org/current/userguide/compatibility.html) with Gradle.**
+
+Along with JDK, maven (`mvn` command) is required. On windows, it can be installed using a package manager such as [chocolatey](https://community.chocolatey.org/packages/maven) or [scoop](https://scoop.sh/#/apps?q=maven).
+
+__On windows, append the path of `jvm.dll` in your JDK installation to PATH.__
+
+For example, on Powershell:
+
+```powershell
+$env:Path += ";${env:JAVA_HOME}\bin\server".
+```
+
+If JAVA_HOME not set, find the `java.exe` executable and set the environment variable in Control Panel. If java is installed through a package manager, there may be a more automatic way to do this. (Eg: `scoop reset`).
+
+### C/C++ tooling
+CMake and a standard C toolchain are required to build `package:jni` and C bindings generated by `jnigen`.
+
+It's recommended to have `clang-format` installed for formatting the generated C bindings. On Windows, it's part of LLVM installation. On most Linux distributions it is available as a separate package. On MacOS, it can be installed using Homebrew.
+
+## FAQs
+
+#### I am getting ClassNotFoundError at runtime.
+`jnigen` does not handle getting the classes into application. It has to be done by target-specific mechanism. Such as adding a gradle dependency on Android, or manually providing classpath to `Jni.spawn` on desktop / standalone targets.
+
+On Android, `proguard` prunes classes which it deems inaccessible. Since JNI class lookup happens in runtime, this leads to ClassNotFound errors in release mode even if the dependency is included in gradle. [in_app_java example](jnigen/example/in_app_java/) discusses two mechanisms to prevent this: using `Keep` annotation (`androidx.annotation.Keep`) for the code written in the application itself, and [proguard-rules file](jnigen/example/in_app_java/android/app/proguard-rules.pro) for external libraries.
+
+Lastly, some libraries such as `java.awt` do not exist in android. Attempting to use libraries which depend on them can also lead to ClassNotFound errors.
+
+#### `jnigen` is not finding classes.
+Ensure you are providing correct source and class paths, and they follow standard directory structure. If your class name is `com.abc.MyClass`, `MyClass` must be in `com/abc/MyClass.java` relative to one of the source paths, or `com/abc/MyClass.class` relative to one of the class paths specified in YAML.
+
+If the classes are in JAR file, make sure to provide path to JAR file itself, and not the containing directory.
+
+#### `jnigen` is unable to parse sources.
+If the errors are similar to `symbol not found`, ensure all dependencies of the source are available. If such dependency is compiled, it can be included in `class_path`.
+
+#### How are classes mapped into bindings?
+Each Java class generates a subclass of `JObject` class, which wraps a `jobject` reference in JNI. Nested classes use `_` as separator, `Example.NestedClass` will be mapped to `Example_NestedClass`.
+
+#### Does `JObject` hold a local or global reference? Does it need to be manually released?
+Each Java object returned into Dart creates a JNI global reference. Reference deletion is taken care of by `NativeFinalizer` and that's usually sufficient.
+
+It's a good practice to keep the interface between languages sparse. However, if there's a need to create several references (Eg: in a loop), you can use FFI Arena mechanism (`using` function) and `releasedBy` method, or manually release the object using `release` method.
+
+#### Should I use `jnigen` over Method channels?
+This is currently an experimental package. Many features are missing, and it's rough around the edges. You're welcome to try it and give feedback.
+
+## YAML Configuration Reference
+Keys ending with a colon (`:`) denote subsections.
+
+The typical invocation with YAML configuration is
+
+```
+dart run jnigen --config jnigen.yaml
+```
+
+Any configuration can be overridden through command line using `-D` or `--override` switch. For example `-Dlog_level=warning` or `-Dsummarizer.backend=asm`. (Use `.` to separate subsection and property name).
+
+A `*` denotes required configuration.
+
+| Configuration property | Type / Values | Description |
+| ---------------------- | ------------- | ----------------------------------------------------------------------- |
+| `preamble` | Text | Text to be pasted in the start of each generated file. |
+| `source_path` | List of directory paths | Directories to search for source files. Note: source_path for dependencies downloaded using `maven_downloads` configuration is added automatically without the need to specify here. |
+| `class_path` | List of directory / JAR paths | Classpath for API summary generation. This should include any JAR dependencies of the source files in `source_path`. |
+| `classes` * | List of qualified class / package names | List of qualified class / package names. `source_path` will be scanned assuming the sources follow standard java-ish hierarchy. That is a.b.c either maps to a directory `a/b/c` or a class file `a/b/c.java`. |
+| `enable_experiment` | List of experiment names:<br><ul><li>`interface_implementation`</li></ul> | List of enabled experiments. These features are still in development and their API might break. |
+| `output:` | (Subsection) | This subsection will contain configuration related to output files. |
+| `output:` >> `bindings_type` | `c_based` (default) or `dart_only` | Binding generation strategy. [Trade-offs](#pure-dart-bindings) are explained at the end of this document. |
+| `output:` >> `c:` | (Subsection) | This subsection specified C output configuration. Required if `bindings_type` is `c_based`. |
+| `output:` >> `c:` >> path * | Directory path | Directory to write C bindings. Usually `src/` in case of an FFI plugin template. |
+| `output:` >> `c:` >> subdir | Directory path | If specified, C bindings will be written to `subdir` resolved relative to `path`. This is useful when bindings are supposed to be under source's license, and written to a subdirectory such as `third_party`. |
+| `output:` >> `c:` >> `library_name` *| Identifier (snake_case) | Name for generated C library.
+| `output:` >> `dart:` | (Subsection) | This subsection specifies Dart output configuration. |
+| `output:` >> `dart:` >> `structure` | `package_structure` / `single_file` | Whether to map resulting dart bindings to file-per-class source layout, or write all bindings to single file.
+| `output:` >> `dart:` >> `path` * | Directory path or File path | Path to write Dart bindings. Should end in `.dart` for `single_file` configurations, and end in `/` for `package_structure` (default) configuration. |
+| `maven_downloads:` | (Subsection) | This subsection will contain configuration for automatically downloading Java dependencies (source and JAR) through maven. |
+| `maven_downloads:` >> `source_deps` | List of maven package coordinates | Source packages to download and unpack using maven. The names should be valid maven artifact coordinates. (Eg: `org.apache.pdfbox:pdfbox:2.0.26`). The downloads do not include transitive dependencies. |
+| `maven_downloads:` >> `source_dir` | Path | Directory in which maven sources are extracted. Defaults to `mvn_java`. It's not required to list this explicitly in source_path. |
+| `maven_downloads:` >> `jar_only_deps` | List of maven package coordinates | JAR dependencies to download which are not mandatory transitive dependencies of `source_deps`. Often, it's required to find and include optional dependencies so that entire source is valid for further processing. |
+| `maven_downloads:` >> `jar_dir` | Path | Directory to store downloaded JARs. Defaults to `mvn_jar`. |
+| `log_level` | Logging level | Configure logging level. Defaults to `info`. |
+| `android_sdk_config:` | (Subsection) | Configuration for autodetection of Android dependencies and SDK. Note that this is more experimental than others, and very likely subject to change. |
+| `android_sdk_config:` >> `add_gradle_deps` | Boolean | If true, run a gradle stub during `jnigen` invocation, and add Android compile classpath to the classpath of jnigen. This requires a release build to have happened before, so that all dependencies are cached appropriately. |
+| `android_sdk_config:` >> `android_example` | Directory path | In case of an Android plugin project, the plugin itself cannot be built and `add_gradle_deps` is not directly feasible. This property can be set to relative path of package example app (usually `example/` so that gradle dependencies can be collected by running a stub in this directory. See [notification_plugin example](jnigen/example/notification_plugin/jnigen.yaml) for an example. |
+| `summarizer:` | (Subsection) | Configuration specific to summarizer component, which builds API descriptions from Java sources or JAR files. |
+| `summarizer:` >> `backend` | `auto`, `doclet` or `asm` | Specifies the backend to use in API summary generation. `doclet` uses OpenJDK Doclet API to build summary from sources. `asm` uses ASM library to build summary from classes in `class_path` JARs. `auto` attempts to find the class in sources, and falls back to using ASM. |
+| `summarizer:` >> `extra_args` (DEV) | List of CLI arguments | Extra arguments to pass to summarizer JAR. |
+| `exclude:` | (Subsection) | Exclude methods or fields using regex filters. It's generally useful to exclude problematic fields or methods which, with current binding generation, can lead to syntax errors |
+| `exclude:` >> `methods`| List of methods in `classBinaryName#methodName` format where classBinaryName is same as qualified name, but `$` preceding a nested class instead of `.`. Example: `com.example.MyClass` or `com.example.MyClass$NestedClass` | Methods to exclude.
+| `exclude:` >> `fields` | List of fields in `classBinaryName#fieldName` format | Fields to exclude.
+
+It's possible to use the programmatic API instead of YAML.
+
+* Create a tool script. (Eg: `tool/generate_jni_bindings.dart`)
+* import `package:jnigen/jnigen.dart`
+* construct a `Config` object and pass it to `generateJniBindings` function. The parameters are similar to the ones described above.
+
+## Pure dart Bindings
+It's possible to generate bindings that do not rely on an intermediate layer of C code. Bindings will still depend on `package:jni` and its support library written in C. But this approach avoids large C bindings.
+
+To enable pure dart bindings, specify
+```
+output:
+ bindings_type: dart_only
+```
+
+Any C output configuration will be ignored.
+
+However, pure dart bindings will require additional allocations and check runtimeType of the arguments. This will be the case until Variadic arguments land in Dart FFI.
+
+## Android core libraries
+These days, Android projects depend heavily on AndroidX and other libraries downloaded via gradle. We have a tracking issue to improve detection of android SDK and dependencies. (#31). Currently we can fetch the JAR dependencies of an android project, by running a gradle stub, if `android_sdk_config` >> `add_gradle_deps` is specified.
+
+But core libraries (the `android.**` namespace) are not downloaded through gradle. The core libraries are shipped as stub JARs with the Android SDK. (`$SDK_ROOT/platforms/android-$VERSION/android-stubs-src.jar`).
+
+Currently we don't have an automatic mechanism for using these. You can unpack this JAR manually into some directory and provide it as a source path.
+
+However there are 2 caveats to this caveat.
+
+* SDK stubs after version 28 are incomplete. OpenJDK Doclet API we use to generate API summaries will error on incomplete sources.
+* The API can't process the `java.**` namespaces in the Android SDK stubs, because it expects a module layout. So if you want to generate bindings for, say, `java.lang.Math`, you cannot use the Android SDK stubs. OpenJDK sources can be used instead.
+
+The JAR files (`$SDK_ROOT/platforms/android-$VERSION/android.jar`) can be used instead. But compiled JARs do not include JavaDoc and method parameter names. This JAR is automatically included by Gradle when `android_sdk_config` >> `add_gradle_deps` is specified.
+
+## Contributing
+See the wiki for architecture-related documents.
+
diff --git a/pkgs/jnigen/analysis_options.yaml b/pkgs/jnigen/analysis_options.yaml
new file mode 100644
index 0000000..4bebf0e
--- /dev/null
+++ b/pkgs/jnigen/analysis_options.yaml
@@ -0,0 +1,19 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+include: package:lints/recommended.yaml
+
+analyzer:
+ exclude: [build/**, example/**]
+ language:
+ strict-raw-types: true
+ strict-inference: true
+
+linter:
+ rules:
+ - prefer_final_locals
+ - prefer_const_declarations
+ - unawaited_futures
+ - prefer_const_constructors
+ - prefer_relative_imports
diff --git a/pkgs/jnigen/android_test_runner/.gitignore b/pkgs/jnigen/android_test_runner/.gitignore
new file mode 100644
index 0000000..24476c5
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/.gitignore
@@ -0,0 +1,44 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
diff --git a/pkgs/jnigen/android_test_runner/.metadata b/pkgs/jnigen/android_test_runner/.metadata
new file mode 100644
index 0000000..957ea81
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/.metadata
@@ -0,0 +1,30 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled.
+
+version:
+ revision: f72efea43c3013323d1b95cff571f3c1caa37583
+ channel: stable
+
+project_type: app
+
+# Tracks metadata for the flutter migrate command
+migration:
+ platforms:
+ - platform: root
+ create_revision: f72efea43c3013323d1b95cff571f3c1caa37583
+ base_revision: f72efea43c3013323d1b95cff571f3c1caa37583
+ - platform: android
+ create_revision: f72efea43c3013323d1b95cff571f3c1caa37583
+ base_revision: f72efea43c3013323d1b95cff571f3c1caa37583
+
+ # User provided section
+
+ # List of Local paths (relative to this file) that should be
+ # ignored by the migrate tool.
+ #
+ # Files that are not part of the templates will be ignored by default.
+ unmanaged_files:
+ - 'lib/main.dart'
+ - 'ios/Runner.xcodeproj/project.pbxproj'
diff --git a/pkgs/jnigen/android_test_runner/README.md b/pkgs/jnigen/android_test_runner/README.md
new file mode 100644
index 0000000..cd85e19
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/README.md
@@ -0,0 +1,17 @@
+## What's this?
+
+This is Flutter app project which serves as a skeleton for running binding runtime tests on android, using Flutter's integration testing mechanism.
+
+## How to run tests?
+
+Generate runtime test files, by running the following in parent (jnigen) directory.
+
+```bash
+dart run tool/generate_runtime_tests.dart
+```
+
+This will generate integration_test/runtime_test.dart in this directory, along with other runtime tests for `jnigen`. This can be run with regular integration test mechanism.
+
+```bash
+flutter test integration_test/
+```
\ No newline at end of file
diff --git a/pkgs/jnigen/android_test_runner/analysis_options.yaml b/pkgs/jnigen/android_test_runner/analysis_options.yaml
new file mode 100644
index 0000000..61b6c4d
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/analysis_options.yaml
@@ -0,0 +1,29 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+ # The lint rules applied to this project can be customized in the
+ # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+ # included above or to enable additional rules. A list of all available lints
+ # and their documentation is published at
+ # https://dart-lang.github.io/linter/lints/index.html.
+ #
+ # Instead of disabling a lint rule for the entire project in the
+ # section below, it can also be suppressed for a single line of code
+ # or a specific dart file by using the `// ignore: name_of_lint` and
+ # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+ # producing the lint.
+ rules:
+ # avoid_print: false # Uncomment to disable the `avoid_print` rule
+ # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/pkgs/jnigen/android_test_runner/android/.gitignore b/pkgs/jnigen/android_test_runner/android/.gitignore
new file mode 100644
index 0000000..6f56801
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/.gitignore
@@ -0,0 +1,13 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/pkgs/jnigen/android_test_runner/android/app/.gitignore b/pkgs/jnigen/android_test_runner/android/app/.gitignore
new file mode 100644
index 0000000..df2fa17
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/app/.gitignore
@@ -0,0 +1 @@
+.cxx
\ No newline at end of file
diff --git a/pkgs/jnigen/android_test_runner/android/app/CMakeLists.txt b/pkgs/jnigen/android_test_runner/android/app/CMakeLists.txt
new file mode 100644
index 0000000..7bc2474
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/app/CMakeLists.txt
@@ -0,0 +1,10 @@
+## Parent CMake for Android native build target. This will build
+## all C bindings from tests.
+
+cmake_minimum_required(VERSION 3.10)
+
+project(simple_package VERSION 0.0.1 LANGUAGES C)
+
+add_subdirectory(../../../test/jackson_core_test/third_party/c_based/c_bindings jackson_core_test_build)
+add_subdirectory(../../../test/simple_package_test/c_based/c_bindings simple_package_test_build)
+add_subdirectory(../../../test/kotlin_test/c_based/c_bindings kotlin_test_build)
diff --git a/pkgs/jnigen/android_test_runner/android/app/build.gradle b/pkgs/jnigen/android_test_runner/android/app/build.gradle
new file mode 100644
index 0000000..58cd27a
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/app/build.gradle
@@ -0,0 +1,79 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+ localPropertiesFile.withReader('UTF-8') { reader ->
+ localProperties.load(reader)
+ }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+ throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+ flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+ flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+ compileSdkVersion flutter.compileSdkVersion
+ ndkVersion flutter.ndkVersion
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_11
+ targetCompatibility JavaVersion.VERSION_11
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ main.java.srcDirs += '../../../test/simple_package_test/java'
+ main.java.srcDirs += '../../../test/kotlin_test/kotlin/src/main'
+ }
+
+ defaultConfig {
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId "com.github.dart_lang.jnigen.android_integration_test"
+ // You can update the following values to match your application needs.
+ // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
+ minSdkVersion flutter.minSdkVersion
+ targetSdkVersion flutter.targetSdkVersion
+ versionCode flutterVersionCode.toInteger()
+ versionName flutterVersionName
+ }
+
+ buildTypes {
+ release {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig signingConfigs.debug
+ }
+ }
+ externalNativeBuild {
+ cmake {
+ path 'CMakeLists.txt'
+ }
+ }
+}
+
+flutter {
+ source '../..'
+}
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation "com.fasterxml.jackson.core:jackson-core:2.13.4"
+}
diff --git a/pkgs/jnigen/android_test_runner/android/app/src/debug/AndroidManifest.xml b/pkgs/jnigen/android_test_runner/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..fc7efb6
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.github.dart_lang.jnigen.android_integration_test">
+ <!-- The INTERNET permission is required for development. Specifically,
+ the Flutter tool needs it to communicate with the running application
+ to allow setting breakpoints, to provide hot reload, etc.
+ -->
+ <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/pkgs/jnigen/android_test_runner/android/app/src/main/AndroidManifest.xml b/pkgs/jnigen/android_test_runner/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..84209fb
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.github.dart_lang.jnigen.android_integration_test">
+ <application
+ android:label="android_integration_test"
+ android:name="${applicationName}"
+ android:icon="@mipmap/ic_launcher">
+ <activity
+ android:name=".MainActivity"
+ android:exported="true"
+ android:launchMode="singleTop"
+ android:theme="@style/LaunchTheme"
+ android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
+ android:hardwareAccelerated="true"
+ android:windowSoftInputMode="adjustResize">
+ <!-- Specifies an Android theme to apply to this Activity as soon as
+ the Android process has started. This theme is visible to the user
+ while the Flutter UI initializes. After that, this theme continues
+ to determine the Window background behind the Flutter UI. -->
+ <meta-data
+ android:name="io.flutter.embedding.android.NormalTheme"
+ android:resource="@style/NormalTheme"
+ />
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <!-- Don't delete the meta-data below.
+ This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
+ <meta-data
+ android:name="flutterEmbedding"
+ android:value="2" />
+ </application>
+</manifest>
diff --git a/pkgs/jnigen/android_test_runner/android/app/src/main/kotlin/com/github/dart_lang/jnigen/android_integration_test/MainActivity.kt b/pkgs/jnigen/android_test_runner/android/app/src/main/kotlin/com/github/dart_lang/jnigen/android_integration_test/MainActivity.kt
new file mode 100644
index 0000000..5197ccc
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/app/src/main/kotlin/com/github/dart_lang/jnigen/android_integration_test/MainActivity.kt
@@ -0,0 +1,6 @@
+package com.github.dart_lang.jnigen.android_integration_test
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}
diff --git a/pkgs/jnigen/android_test_runner/android/app/src/main/res/drawable-v21/launch_background.xml b/pkgs/jnigen/android_test_runner/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="?android:colorBackground" />
+
+ <!-- You can insert your own image assets here -->
+ <!-- <item>
+ <bitmap
+ android:gravity="center"
+ android:src="@mipmap/launch_image" />
+ </item> -->
+</layer-list>
diff --git a/pkgs/jnigen/android_test_runner/android/app/src/main/res/drawable/launch_background.xml b/pkgs/jnigen/android_test_runner/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..304732f
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@android:color/white" />
+
+ <!-- You can insert your own image assets here -->
+ <!-- <item>
+ <bitmap
+ android:gravity="center"
+ android:src="@mipmap/launch_image" />
+ </item> -->
+</layer-list>
diff --git a/pkgs/jnigen/android_test_runner/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/pkgs/jnigen/android_test_runner/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..db77bb4
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/android_test_runner/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/pkgs/jnigen/android_test_runner/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..17987b7
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/android_test_runner/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/pkgs/jnigen/android_test_runner/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..09d4391
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/android_test_runner/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/pkgs/jnigen/android_test_runner/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d5f1c8d
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/android_test_runner/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/pkgs/jnigen/android_test_runner/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d6372e
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/android_test_runner/android/app/src/main/res/values-night/styles.xml b/pkgs/jnigen/android_test_runner/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..06952be
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
+ <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
+ <!-- Show a splash screen on the activity. Automatically removed when
+ the Flutter engine draws its first frame -->
+ <item name="android:windowBackground">@drawable/launch_background</item>
+ </style>
+ <!-- Theme applied to the Android Window as soon as the process has started.
+ This theme determines the color of the Android Window while your
+ Flutter UI initializes, as well as behind your Flutter UI while its
+ running.
+
+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
+ <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
+ <item name="android:windowBackground">?android:colorBackground</item>
+ </style>
+</resources>
diff --git a/pkgs/jnigen/android_test_runner/android/app/src/main/res/values/styles.xml b/pkgs/jnigen/android_test_runner/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..cb1ef88
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
+ <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
+ <!-- Show a splash screen on the activity. Automatically removed when
+ the Flutter engine draws its first frame -->
+ <item name="android:windowBackground">@drawable/launch_background</item>
+ </style>
+ <!-- Theme applied to the Android Window as soon as the process has started.
+ This theme determines the color of the Android Window while your
+ Flutter UI initializes, as well as behind your Flutter UI while its
+ running.
+
+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
+ <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
+ <item name="android:windowBackground">?android:colorBackground</item>
+ </style>
+</resources>
diff --git a/pkgs/jnigen/android_test_runner/android/app/src/profile/AndroidManifest.xml b/pkgs/jnigen/android_test_runner/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..fc7efb6
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.github.dart_lang.jnigen.android_integration_test">
+ <!-- The INTERNET permission is required for development. Specifically,
+ the Flutter tool needs it to communicate with the running application
+ to allow setting breakpoints, to provide hot reload, etc.
+ -->
+ <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/pkgs/jnigen/android_test_runner/android/build.gradle b/pkgs/jnigen/android_test_runner/android/build.gradle
new file mode 100644
index 0000000..58a8c74
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/build.gradle
@@ -0,0 +1,31 @@
+buildscript {
+ ext.kotlin_version = '1.7.10'
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:7.2.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+ project.evaluationDependsOn(':app')
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/pkgs/jnigen/android_test_runner/android/gradle.properties b/pkgs/jnigen/android_test_runner/android/gradle.properties
new file mode 100644
index 0000000..94adc3a
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/pkgs/jnigen/android_test_runner/android/gradle/wrapper/gradle-wrapper.properties b/pkgs/jnigen/android_test_runner/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..3c472b9
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
diff --git a/pkgs/jnigen/android_test_runner/android/settings.gradle b/pkgs/jnigen/android_test_runner/android/settings.gradle
new file mode 100644
index 0000000..44e62bc
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/android/settings.gradle
@@ -0,0 +1,11 @@
+include ':app'
+
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
+
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/pkgs/jnigen/android_test_runner/integration_test/.gitignore b/pkgs/jnigen/android_test_runner/integration_test/.gitignore
new file mode 100644
index 0000000..af7c365
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/integration_test/.gitignore
@@ -0,0 +1 @@
+runtime_test.dart
\ No newline at end of file
diff --git a/pkgs/jnigen/android_test_runner/lib/main.dart b/pkgs/jnigen/android_test_runner/lib/main.dart
new file mode 100644
index 0000000..da07cdd
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/lib/main.dart
@@ -0,0 +1,52 @@
+import 'package:flutter/material.dart';
+
+void main() {
+ runApp(const MyApp());
+}
+
+class MyApp extends StatelessWidget {
+ const MyApp({super.key});
+
+ // This widget is the root of your application.
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ title: 'Flutter Demo',
+ theme: ThemeData(
+ // This is the theme of your application.
+ //
+ // Try running your application with "flutter run". You'll see the
+ // application has a blue toolbar. Then, without quitting the app, try
+ // changing the primarySwatch below to Colors.green and then invoke
+ // "hot reload" (press "r" in the console where you ran "flutter run",
+ // or simply save your changes to "hot reload" in a Flutter IDE).
+ // Notice that the counter didn't reset back to zero; the application
+ // is not restarted.
+ primarySwatch: Colors.blue,
+ ),
+ home: const MyHomePage(),
+ );
+ }
+}
+
+class MyHomePage extends StatelessWidget {
+ const MyHomePage({super.key});
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text("Integration test runner"),
+ ),
+ body: const Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text(
+ 'This app should be run as flutter integration test',
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/pkgs/jnigen/android_test_runner/pubspec.yaml b/pkgs/jnigen/android_test_runner/pubspec.yaml
new file mode 100644
index 0000000..fccc86e
--- /dev/null
+++ b/pkgs/jnigen/android_test_runner/pubspec.yaml
@@ -0,0 +1,94 @@
+name: android_integration_test
+description: jnigen integration test runner for android
+# The following line prevents the package from being accidentally published to
+# pub.dev using `flutter pub publish`. This is preferred for private packages.
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+# The following defines the version and build number for your application.
+# A version number is three numbers separated by dots, like 1.2.43
+# followed by an optional build number separated by a +.
+# Both the version and the builder number may be overridden in flutter
+# build by specifying --build-name and --build-number, respectively.
+# In Android, build-name is used as versionName while build-number used as versionCode.
+# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
+# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
+# Read more about iOS versioning at
+# 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.0+1
+
+environment:
+ sdk: '>=3.1.0 <4.0.0'
+
+# Dependencies specify other packages that your package needs in order to work.
+# To automatically upgrade your package dependencies to the latest versions
+# consider running `flutter pub upgrade --major-versions`. Alternatively,
+# dependencies can be manually updated by changing the version numbers below to
+# the latest version available on pub.dev. To see which dependencies have newer
+# versions available, run `flutter pub outdated`.
+dependencies:
+ jni:
+ path: ../../jni/
+ ffi: any
+ flutter:
+ sdk: flutter
+
+ # The following adds the Cupertino Icons font to your application.
+ # Use with the CupertinoIcons class for iOS style icons.
+ cupertino_icons: ^1.0.2
+
+dev_dependencies:
+ test: any
+ flutter_test:
+ sdk: flutter
+ integration_test:
+ sdk: flutter
+
+ # The "flutter_lints" package below contains a set of recommended lints to
+ # encourage good coding practices. The lint set provided by the package is
+ # activated in the `analysis_options.yaml` file located at the root of your
+ # package. See that file for information about deactivating specific lint
+ # rules and activating additional ones.
+ flutter_lints: ^2.0.0
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter packages.
+flutter:
+ # The following line ensures that the Material Icons font is
+ # included with your application, so that you can use the icons in
+ # the material Icons class.
+ uses-material-design: true
+
+ # To add assets to your application, add an assets section, like this:
+ # assets:
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
+
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/assets-and-images/#resolution-aware
+
+ # For details regarding adding assets from package dependencies, see
+ # https://flutter.dev/assets-and-images/#from-packages
+
+ # To add custom fonts to your application, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts from package dependencies,
+ # see https://flutter.dev/custom-fonts/#from-packages
diff --git a/pkgs/jnigen/bin/download_maven_jars.dart b/pkgs/jnigen/bin/download_maven_jars.dart
new file mode 100644
index 0000000..6e5b4b0
--- /dev/null
+++ b/pkgs/jnigen/bin/download_maven_jars.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:jnigen/jnigen.dart';
+import 'package:jnigen/tools.dart';
+
+/// Downloads maven dependencies downloaded by equivalent jnigen invocation.
+///
+/// Useful for running standalone examples on already generated sources.
+void main(List<String> args) async {
+ final config = Config.parseArgs(args);
+ final mavenDownloads = config.mavenDownloads;
+ if (mavenDownloads != null) {
+ await MavenTools.downloadMavenJars(
+ MavenTools.deps(mavenDownloads.jarOnlyDeps + mavenDownloads.sourceDeps),
+ mavenDownloads.jarDir);
+ await Directory(mavenDownloads.jarDir)
+ .list()
+ .map((entry) => entry.path)
+ .where((path) => path.endsWith('.jar'))
+ .forEach(stdout.writeln);
+ } else {
+ stderr.writeln('No maven dependencies found in config.');
+ exitCode = 2;
+ }
+}
diff --git a/pkgs/jnigen/bin/jnigen.dart b/pkgs/jnigen/bin/jnigen.dart
new file mode 100644
index 0000000..8dc69e3
--- /dev/null
+++ b/pkgs/jnigen/bin/jnigen.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:jnigen/jnigen.dart';
+import 'package:jnigen/src/logging/logging.dart';
+
+void main(List<String> args) async {
+ enableLoggingToFile();
+ Config config;
+ try {
+ config = Config.parseArgs(args);
+ } on ConfigException catch (e) {
+ log.fatal(e);
+ } on FormatException catch (e) {
+ log.fatal(e);
+ }
+ await generateJniBindings(config);
+}
diff --git a/pkgs/jnigen/bin/setup.dart b/pkgs/jnigen/bin/setup.dart
new file mode 100644
index 0000000..54df277
--- /dev/null
+++ b/pkgs/jnigen/bin/setup.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:jnigen/src/logging/logging.dart';
+import 'package:jnigen/src/tools/tools.dart';
+import 'package:logging/logging.dart';
+
+void main(List<String> args) async {
+ bool force = false;
+ setLoggingLevel(Level.INFO);
+ if (args.isNotEmpty) {
+ if (args.length != 1 || args[0] != '-f') {
+ stderr.writeln('usage: dart run jnigen:setup [-f]');
+ stderr.writeln('* -f\trebuild ApiSummarizer jar even if it already '
+ 'exists.');
+ } else {
+ force = true;
+ }
+ }
+ await buildSummarizerIfNotExists(force: force);
+}
diff --git a/pkgs/jnigen/cmake/CMakeLists.txt.tmpl b/pkgs/jnigen/cmake/CMakeLists.txt.tmpl
new file mode 100644
index 0000000..d0b8a73
--- /dev/null
+++ b/pkgs/jnigen/cmake/CMakeLists.txt.tmpl
@@ -0,0 +1,32 @@
+# jni_native_build (Build with jni:setup. Do not delete this line.)
+
+# 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)
+
+project({{LIBRARY_NAME}} VERSION 0.0.1 LANGUAGES C)
+
+add_library({{LIBRARY_NAME}} SHARED
+ "{{SUBDIR}}/{{LIBRARY_NAME}}.c"
+)
+
+set_target_properties({{LIBRARY_NAME}} PROPERTIES
+ OUTPUT_NAME "{{LIBRARY_NAME}}"
+)
+
+target_compile_definitions({{LIBRARY_NAME}} PUBLIC DART_SHARED_LIB)
+
+if(WIN32)
+ set_target_properties(${TARGET_NAME} PROPERTIES
+ LINK_FLAGS "/DELAYLOAD:jvm.dll")
+endif()
+
+if (ANDROID)
+ target_link_libraries({{LIBRARY_NAME}} log)
+else()
+ find_package(Java REQUIRED)
+ find_package(JNI REQUIRED)
+ include_directories(${JNI_INCLUDE_DIRS})
+ target_link_libraries({{LIBRARY_NAME}} ${JNI_LIBRARIES})
+endif()
diff --git a/pkgs/jnigen/cmake/README.md b/pkgs/jnigen/cmake/README.md
new file mode 100644
index 0000000..65f9951
--- /dev/null
+++ b/pkgs/jnigen/cmake/README.md
@@ -0,0 +1,3 @@
+This directory contains a CMakeLists.txt.tmpl file which will be used to generate build configuration for generated C code.
+
+`{{LIBRARY_NAME}}` in this template will be replaced by `library_name` configuration parameter.
\ No newline at end of file
diff --git a/pkgs/jnigen/dart_test.yaml b/pkgs/jnigen/dart_test.yaml
new file mode 100644
index 0000000..fdd1587
--- /dev/null
+++ b/pkgs/jnigen/dart_test.yaml
@@ -0,0 +1,14 @@
+## Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+## for details. All rights reserved. Use of this source code is governed by a
+## BSD-style license that can be found in the LICENSE file.
+
+## This file defines test groups for jnigen. This will be helpful to exclude
+## lengthy tests by using -x flag.
+
+tags:
+ large_test:
+ timeout: 2x
+ summarizer_test:
+ timeout: 1x
+ runtime_test:
+ timeout: 1x
diff --git a/pkgs/jnigen/example/README.md b/pkgs/jnigen/example/README.md
new file mode 100644
index 0000000..dce00fb
--- /dev/null
+++ b/pkgs/jnigen/example/README.md
@@ -0,0 +1,51 @@
+## jnigen examples
+
+This directory contains examples on how to use jnigen.
+
+| Directory | Description |
+| ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
+| [in_app_java](https://github.com/dart-lang/jnigen/tree/main/jnigen/example/in_app_java/) | Demonstrates how to include custom Java code in Flutter application and call that using jnigen |
+| [pdfbox_plugin](https://github.com/dart-lang/jnigen/tree/main/jnigen/example/pdfbox_plugin/) | Example of a flutter plugin which provides bindings to Apache PDFBox library. Currently works on Flutter desktop and Dart standalone on linux. |
+| [notification_plugin](https://github.com/dart-lang/jnigen/tree/main/jnigen/example/notification_plugin/) | Example of a reusable Flutter plugin with custom Java code which uses Android libraries. |
+| [kotlin_plugin](https://github.com/dart-lang/jnigen/tree/main/jnigen/example/kotlin_plugin) | Example of using jnigen to generate bindings for Kotlin. |
+
+We intend to cover few more use cases in future.
+
+## Creating a jnigen-based plugin from scratch
+
+### Dart package (Standalone only)
+
+- Create dart package, add `jni` as dependency and `jnigen` as dev dependency.
+- Write the jnigen config similar to [the one in pdfbox_plugin](https://github.com/dart-lang/jnigen/tree/main/jnigen/example/pdfbox_plugin/jnigen.yaml).
+- Generate JNI bindings by running `dart run jnigen --config jnigen.yaml`.
+
+- In the CLI project which uses this package, add this package, and `jni` as a dependency.
+- Run `dart run jni:setup` to build native libraries for JNI base library and jnigen generated package.
+- Import the package. See [pdf_info.dart](https://github.com/dart-lang/jnigen/tree/main/jnigen/example/pdfbox_plugin/dart_example/bin/pdf_info.dart) for an example of using JNI from dart standalone.
+
+### Flutter FFI plugin
+
+Flutter FFI plugin has the advantage of bundling the required native libraries along with Android / Linux Desktop app.
+
+To create an FFI plugin with JNI bindings:
+
+- Create a plugin using `plugin_ffi` template.
+- Remove ffigen-specific files and stubs.
+- Follow the above steps to generate JNI bindings. The plugin can be used from a flutter project.
+
+- It may be desirable to generate the bindings into a private directory (Eg: `lib/src/third_party`) and re-export the classes from the top level dart file.
+
+- To use the plugin from Dart projects as well, comment-out or remove flutter SDK requirements from the pubspec. This is however problematic if you want to publish the package.
+
+### Android plugin with custom Java code
+
+- Create an FFI plugin with Android as the only platform.
+- Build the example/ Android project using command `flutter build apk`. After a release build is done, jnigen can use a gradle stub to collect compile classpaths.
+- Write your custom Java code in `android/src/main/java` hierarchy of the plugin.
+- Generate JNI bindings as described above. See [notification_plugin/jnigen.yaml](https://github.com/dart-lang/jnigen/tree/main/jnigen/example/notification_plugin/jnigen.yaml) for example configuration.
+
+### Pure dart bindings
+
+With Pure dart bindings PoC, most of the FFI setup steps are not required. For example, a simple flutter package can be created instead of an FFI plugin, since there are no native artifacts to bundle.
+
+The generated bindings still depend on `package:jni`, therefore running `dart run jni:setup` is still a requirement on standalone target.
diff --git a/pkgs/jnigen/example/in_app_java/.gitignore b/pkgs/jnigen/example/in_app_java/.gitignore
new file mode 100644
index 0000000..8c64048
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/.gitignore
@@ -0,0 +1,50 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Web related
+lib/generated_plugin_registrant.dart
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
+
+## Generated by build process
+android/app/.cxx
diff --git a/pkgs/jnigen/example/in_app_java/.metadata b/pkgs/jnigen/example/in_app_java/.metadata
new file mode 100644
index 0000000..2544bab
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/.metadata
@@ -0,0 +1,30 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled.
+
+version:
+ revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+ channel: stable
+
+project_type: app
+
+# Tracks metadata for the flutter migrate command
+migration:
+ platforms:
+ - platform: root
+ create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+ base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+ - platform: android
+ create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+ base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+
+ # User provided section
+
+ # List of Local paths (relative to this file) that should be
+ # ignored by the migrate tool.
+ #
+ # Files that are not part of the templates will be ignored by default.
+ unmanaged_files:
+ - 'lib/main.dart'
+ - 'ios/Runner.xcodeproj/project.pbxproj'
diff --git a/pkgs/jnigen/example/in_app_java/README.md b/pkgs/jnigen/example/in_app_java/README.md
new file mode 100644
index 0000000..13813a8
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/README.md
@@ -0,0 +1,24 @@
+# In-App Java Example
+
+This example shows how to write custom java code in `android/app/src` and call it using `jnigen` generated bindings.
+
+#### How to run this example:
+* Run `flutter run` to run the app.
+
+* To regenerate bindings after changing Java code, run `flutter pub run jnigen --config jnigen.yaml`. This requires at least one APK build to have been run before, so that it's possible for `jnigen` to obtain classpaths of Android Gradle libraries. Therefore, once run `flutter build apk` before generating bindings for the first time, or after a `flutter clean`.
+
+#### General steps
+These are general steps to integrate Java code into a flutter project using `jnigen`.
+
+* Write Java code in suitable package folder, under `android/` subproject of the flutter app.
+
+* Create A jnigen config like `jnigen.yaml` in this example.
+
+* Generate bindings using jnigen config.
+
+* Add an `externalNativeBuild` to gradle script (see `android/app/build.gradle` in this example).
+
+* Add proguard rules to exclude your custom classes from tree shaking, since they are always accessed reflectively in JNI.
+
+* Build and run the app.
+
diff --git a/pkgs/jnigen/example/in_app_java/analysis_options.yaml b/pkgs/jnigen/example/in_app_java/analysis_options.yaml
new file mode 100644
index 0000000..61b6c4d
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/analysis_options.yaml
@@ -0,0 +1,29 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+ # The lint rules applied to this project can be customized in the
+ # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+ # included above or to enable additional rules. A list of all available lints
+ # and their documentation is published at
+ # https://dart-lang.github.io/linter/lints/index.html.
+ #
+ # Instead of disabling a lint rule for the entire project in the
+ # section below, it can also be suppressed for a single line of code
+ # or a specific dart file by using the `// ignore: name_of_lint` and
+ # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+ # producing the lint.
+ rules:
+ # avoid_print: false # Uncomment to disable the `avoid_print` rule
+ # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/pkgs/jnigen/example/in_app_java/android/.gitignore b/pkgs/jnigen/example/in_app_java/android/.gitignore
new file mode 100644
index 0000000..6f56801
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/.gitignore
@@ -0,0 +1,13 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/pkgs/jnigen/example/in_app_java/android/app/build.gradle b/pkgs/jnigen/example/in_app_java/android/app/build.gradle
new file mode 100644
index 0000000..59ebf16
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/app/build.gradle
@@ -0,0 +1,82 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+ localPropertiesFile.withReader('UTF-8') { reader ->
+ localProperties.load(reader)
+ }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+ throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+ flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+ flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+ compileSdkVersion flutter.compileSdkVersion
+ ndkVersion flutter.ndkVersion
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+
+ defaultConfig {
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId "com.example.in_app_java"
+ // You can update the following values to match your application needs.
+ // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
+ minSdkVersion flutter.minSdkVersion
+ targetSdkVersion flutter.targetSdkVersion
+ versionCode flutterVersionCode.toInteger()
+ versionName flutterVersionName
+ }
+
+ buildTypes {
+ release {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig signingConfigs.debug
+ }
+ }
+
+ externalNativeBuild {
+ cmake {
+ path "../../src/android_utils/CMakeLists.txt"
+ }
+ }
+}
+
+flutter {
+ source '../..'
+}
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+
+ /// Add AndroidX emoji2 library as dependency.
+ /// We will be using EmojiCompat's GlyphChecker in our flutter example.
+ def emoji2_version = "1.3.0"
+ implementation "androidx.emoji2:emoji2:$emoji2_version"
+}
diff --git a/pkgs/jnigen/example/in_app_java/android/app/proguard-rules.pro b/pkgs/jnigen/example/in_app_java/android/app/proguard-rules.pro
new file mode 100644
index 0000000..8eecc4c
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/app/proguard-rules.pro
@@ -0,0 +1,17 @@
+# This is the rules file which prevents `proguard` from aggressively
+# removing the classes which appear to be unused, in release mode.
+#
+# Since JNI is based on runtime lookup for classes, proguard will not have
+# a way to know EmojiCompat class in our example is actually used. Therefore
+# we have to explicitly list it in this file to prevent the application from
+# crashing with ClassNotFoundException.
+#
+# This doesn't apply to builtin classes, eg: those in `android.` namespace Since
+# they are already present on the device.
+# For the Java code which is written by yourself, you can add `androidx.annotation.Keep`
+# instead. (As done in `AndroidUtils.java`).
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+-keep class androidx.emoji2.text.EmojiCompat { public *; }
diff --git a/pkgs/jnigen/example/in_app_java/android/app/src/debug/AndroidManifest.xml b/pkgs/jnigen/example/in_app_java/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..a096030
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.in_app_java">
+ <!-- The INTERNET permission is required for development. Specifically,
+ the Flutter tool needs it to communicate with the running application
+ to allow setting breakpoints, to provide hot reload, etc.
+ -->
+ <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/pkgs/jnigen/example/in_app_java/android/app/src/main/AndroidManifest.xml b/pkgs/jnigen/example/in_app_java/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..e674e57
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.in_app_java">
+ <application
+ android:label="in_app_java"
+ android:name="${applicationName}"
+ android:icon="@mipmap/ic_launcher">
+ <activity
+ android:name=".MainActivity"
+ android:exported="true"
+ android:launchMode="singleTop"
+ android:theme="@style/LaunchTheme"
+ android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
+ android:hardwareAccelerated="true"
+ android:windowSoftInputMode="adjustResize">
+ <!-- Specifies an Android theme to apply to this Activity as soon as
+ the Android process has started. This theme is visible to the user
+ while the Flutter UI initializes. After that, this theme continues
+ to determine the Window background behind the Flutter UI. -->
+ <meta-data
+ android:name="io.flutter.embedding.android.NormalTheme"
+ android:resource="@style/NormalTheme"
+ />
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <!-- Don't delete the meta-data below.
+ This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
+ <meta-data
+ android:name="flutterEmbedding"
+ android:value="2" />
+ </application>
+</manifest>
diff --git a/pkgs/jnigen/example/in_app_java/android/app/src/main/java/com/example/in_app_java/AndroidUtils.java b/pkgs/jnigen/example/in_app_java/android/app/src/main/java/com/example/in_app_java/AndroidUtils.java
new file mode 100644
index 0000000..84be6f1
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/app/src/main/java/com/example/in_app_java/AndroidUtils.java
@@ -0,0 +1,19 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.example.in_app_java;
+
+import android.app.Activity;
+import android.widget.Toast;
+import androidx.annotation.Keep;
+
+@Keep
+public abstract class AndroidUtils {
+ // Hide constructor
+ private AndroidUtils() {}
+
+ public static void showToast(Activity mainActivity, CharSequence text, int duration) {
+ mainActivity.runOnUiThread(() -> Toast.makeText(mainActivity, text, duration).show());
+ }
+}
diff --git a/pkgs/jnigen/example/in_app_java/android/app/src/main/kotlin/com/example/in_app_java/MainActivity.kt b/pkgs/jnigen/example/in_app_java/android/app/src/main/kotlin/com/example/in_app_java/MainActivity.kt
new file mode 100644
index 0000000..c8fde0c
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/app/src/main/kotlin/com/example/in_app_java/MainActivity.kt
@@ -0,0 +1,6 @@
+package com.example.in_app_java
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}
diff --git a/pkgs/jnigen/example/in_app_java/android/app/src/main/res/drawable-v21/launch_background.xml b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="?android:colorBackground" />
+
+ <!-- You can insert your own image assets here -->
+ <!-- <item>
+ <bitmap
+ android:gravity="center"
+ android:src="@mipmap/launch_image" />
+ </item> -->
+</layer-list>
diff --git a/pkgs/jnigen/example/in_app_java/android/app/src/main/res/drawable/launch_background.xml b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..304732f
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@android:color/white" />
+
+ <!-- You can insert your own image assets here -->
+ <!-- <item>
+ <bitmap
+ android:gravity="center"
+ android:src="@mipmap/launch_image" />
+ </item> -->
+</layer-list>
diff --git a/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..db77bb4
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..17987b7
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..09d4391
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d5f1c8d
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d6372e
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/in_app_java/android/app/src/main/res/values-night/styles.xml b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..06952be
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
+ <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
+ <!-- Show a splash screen on the activity. Automatically removed when
+ the Flutter engine draws its first frame -->
+ <item name="android:windowBackground">@drawable/launch_background</item>
+ </style>
+ <!-- Theme applied to the Android Window as soon as the process has started.
+ This theme determines the color of the Android Window while your
+ Flutter UI initializes, as well as behind your Flutter UI while its
+ running.
+
+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
+ <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
+ <item name="android:windowBackground">?android:colorBackground</item>
+ </style>
+</resources>
diff --git a/pkgs/jnigen/example/in_app_java/android/app/src/main/res/values/styles.xml b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..cb1ef88
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
+ <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
+ <!-- Show a splash screen on the activity. Automatically removed when
+ the Flutter engine draws its first frame -->
+ <item name="android:windowBackground">@drawable/launch_background</item>
+ </style>
+ <!-- Theme applied to the Android Window as soon as the process has started.
+ This theme determines the color of the Android Window while your
+ Flutter UI initializes, as well as behind your Flutter UI while its
+ running.
+
+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
+ <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
+ <item name="android:windowBackground">?android:colorBackground</item>
+ </style>
+</resources>
diff --git a/pkgs/jnigen/example/in_app_java/android/app/src/profile/AndroidManifest.xml b/pkgs/jnigen/example/in_app_java/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..a096030
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.in_app_java">
+ <!-- The INTERNET permission is required for development. Specifically,
+ the Flutter tool needs it to communicate with the running application
+ to allow setting breakpoints, to provide hot reload, etc.
+ -->
+ <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/pkgs/jnigen/example/in_app_java/android/build.gradle b/pkgs/jnigen/example/in_app_java/android/build.gradle
new file mode 100644
index 0000000..2fbab80
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/build.gradle
@@ -0,0 +1,32 @@
+buildscript {
+ ext.kotlin_version = '1.6.10'
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:7.1.2'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+
+subprojects {
+ project.evaluationDependsOn(':app')
+}
+
+tasks.register("clean", Delete) {
+ delete rootProject.buildDir
+}
diff --git a/pkgs/jnigen/example/in_app_java/android/gradle.properties b/pkgs/jnigen/example/in_app_java/android/gradle.properties
new file mode 100644
index 0000000..94adc3a
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/pkgs/jnigen/example/in_app_java/android/gradle/wrapper/gradle-wrapper.properties b/pkgs/jnigen/example/in_app_java/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..cc5527d
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jun 23 08:50:38 CEST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
diff --git a/pkgs/jnigen/example/in_app_java/android/settings.gradle b/pkgs/jnigen/example/in_app_java/android/settings.gradle
new file mode 100644
index 0000000..44e62bc
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/android/settings.gradle
@@ -0,0 +1,11 @@
+include ':app'
+
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
+
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/pkgs/jnigen/example/in_app_java/jnigen.yaml b/pkgs/jnigen/example/in_app_java/jnigen.yaml
new file mode 100644
index 0000000..e588f4a
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/jnigen.yaml
@@ -0,0 +1,23 @@
+android_sdk_config:
+ add_gradle_deps: true
+ add_gradle_sources: true
+
+output:
+ c:
+ library_name: android_utils
+ path: src/android_utils/
+ dart:
+ path: lib/android_utils.dart
+ structure: single_file
+
+source_path:
+ - 'android/app/src/main/java'
+classes:
+ - 'com.example.in_app_java.AndroidUtils' # from source_path
+ - 'androidx.emoji2.text.EmojiCompat' # From gradle's source path
+ - 'androidx.emoji2.text.DefaultEmojiCompatConfig' # From gradle's source path
+ - 'android.os.Build' # from gradle's compile classpath
+ - 'java.util.HashMap' # from gradle's compile classpath
+exclude:
+ fields:
+ - 'android.os.Build\$VERSION_CODES#UPSIDE_DOWN_CAKE'
diff --git a/pkgs/jnigen/example/in_app_java/lib/android_utils.dart b/pkgs/jnigen/example/in_app_java/lib/android_utils.dart
new file mode 100644
index 0000000..6e677a9
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/lib/android_utils.dart
@@ -0,0 +1,3656 @@
+// Autogenerated by jnigen. DO NOT EDIT!
+
+// ignore_for_file: annotate_overrides
+// ignore_for_file: camel_case_extensions
+// ignore_for_file: camel_case_types
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: doc_directive_unknown
+// ignore_for_file: file_names
+// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: overridden_fields
+// ignore_for_file: unnecessary_cast
+// ignore_for_file: unused_element
+// ignore_for_file: unused_field
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: unused_shown_name
+
+import "dart:isolate" show ReceivePort;
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+import "package:jni/jni.dart" as jni;
+
+// Auto-generated initialization code.
+
+final ffi.Pointer<T> Function<T extends ffi.NativeType>(String sym) jniLookup =
+ ProtectedJniExtensions.initGeneratedLibrary("android_utils");
+
+/// from: com.example.in_app_java.AndroidUtils
+class AndroidUtils extends jni.JObject {
+ @override
+ late final jni.JObjType<AndroidUtils> $type = type;
+
+ AndroidUtils.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $AndroidUtilsType();
+ static final _showToast = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Int32)>>("AndroidUtils__showToast")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: static public void showToast(android.app.Activity mainActivity, java.lang.CharSequence text, int duration)
+ static void showToast(
+ jni.JObject mainActivity,
+ jni.JObject text,
+ int duration,
+ ) {
+ return _showToast(mainActivity.reference, text.reference, duration).check();
+ }
+}
+
+final class $AndroidUtilsType extends jni.JObjType<AndroidUtils> {
+ const $AndroidUtilsType();
+
+ @override
+ String get signature => r"Lcom/example/in_app_java/AndroidUtils;";
+
+ @override
+ AndroidUtils fromRef(jni.JObjectPtr ref) => AndroidUtils.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($AndroidUtilsType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($AndroidUtilsType) &&
+ other is $AndroidUtilsType;
+ }
+}
+
+/// from: androidx.emoji2.text.EmojiCompat
+///
+/// Main class to keep Android devices up to date with the newest emojis by adding EmojiSpans
+/// to a given CharSequence.
+/// <p/>
+/// By default, EmojiCompat is initialized by EmojiCompatInitializer, which performs
+/// deferred font loading to avoid potential app startup delays. The default behavior is to load
+/// the font shortly after the first Activity resumes. EmojiCompatInitializer will configure
+/// EmojiCompat to use the system emoji font provider via DefaultEmojiCompatConfig and
+/// always creates a new background thread for font loading.
+/// <p/>
+/// EmojiCompat will only allow one instance to be initialized and any calls to
+/// \#init(Config) after the first one will have no effect. As a result, configuration options
+/// may not be provided when using EmojiCompatInitializer. To provide a custom configuration,
+/// disable EmojiCompatInitializer in the manifest with:
+///
+/// <pre>
+/// <provider
+/// android:name="androidx.startup.InitializationProvider"
+/// android:authorities="${applicationId}.androidx-startup"
+/// android:exported="false"
+/// tools:node="merge">
+/// <meta-data android:name="androidx.emoji2.text.EmojiCompatInitializer"
+/// tools:node="remove" />
+/// </provider>
+/// </pre>
+///
+/// When not using EmojiCompatInitializer, EmojiCompat must to be initialized manually using
+/// \#init(EmojiCompat.Config). It is recommended to make the initialization as early as
+/// possible in your app, such as from Application\#onCreate().
+/// <p/>
+/// \#init(Config) is fast and may be called from the main thread on the path to
+/// displaying the first activity. However, loading the emoji font takes significant resources on a
+/// background thread, so it is suggested to use \#LOAD_STRATEGY_MANUAL in all manual
+/// configurations to defer font loading until after the first screen displays. Font loading may
+/// be started by calling \#load()}. See the implementation EmojiCompatInitializer
+/// for ideas when building a manual configuration.
+/// <p/>
+/// After initialization the \#get() function can be used to get the configured instance and
+/// the \#process(CharSequence) function can be used to update a CharSequence with emoji
+/// EmojiSpans.
+/// <p/>
+/// <pre><code>CharSequence processedSequence = EmojiCompat.get().process("some string")</pre>
+/// <p/>
+/// During loading information about emojis is not available. Before the
+/// EmojiCompat instance has finished loading, calls to functions such as EmojiCompat\#process(CharSequence) will throw an exception. It is safe to call process when
+/// \#getLoadState() returns \#LOAD_STATE_SUCCEEDED. To register a callback when
+/// loading completes use InitCallback.
+/// <p/>
+class EmojiCompat extends jni.JObject {
+ @override
+ late final jni.JObjType<EmojiCompat> $type = type;
+
+ EmojiCompat.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $EmojiCompatType();
+
+ /// from: static public final java.lang.String EDITOR_INFO_METAVERSION_KEY
+ ///
+ /// Key in EditorInfo\#extras that represents the emoji metadata version used by the
+ /// widget. The existence of the value means that the widget is using EmojiCompat.
+ /// <p/>
+ /// If exists, the value for the key is an {@code int} and can be used to query EmojiCompat to
+ /// see whether the widget has the ability to display a certain emoji using
+ /// \#hasEmojiGlyph(CharSequence, int).
+ static const EDITOR_INFO_METAVERSION_KEY =
+ r"""android.support.text.emoji.emojiCompat_metadataVersion""";
+
+ /// from: static public final java.lang.String EDITOR_INFO_REPLACE_ALL_KEY
+ ///
+ /// Key in EditorInfo\#extras that represents EmojiCompat.Config\#setReplaceAll(boolean) configuration parameter. The key is added only if
+ /// EmojiCompat is used by the widget. If exists, the value is a boolean.
+ static const EDITOR_INFO_REPLACE_ALL_KEY =
+ r"""android.support.text.emoji.emojiCompat_replaceAll""";
+
+ /// from: static public final int LOAD_STATE_DEFAULT
+ ///
+ /// EmojiCompat instance is constructed, however the initialization did not start yet.
+ ///@see \#getLoadState()
+ static const LOAD_STATE_DEFAULT = 3;
+
+ /// from: static public final int LOAD_STATE_LOADING
+ ///
+ /// EmojiCompat is initializing.
+ ///@see \#getLoadState()
+ static const LOAD_STATE_LOADING = 0;
+
+ /// from: static public final int LOAD_STATE_SUCCEEDED
+ ///
+ /// EmojiCompat successfully initialized.
+ ///@see \#getLoadState()
+ static const LOAD_STATE_SUCCEEDED = 1;
+
+ /// from: static public final int LOAD_STATE_FAILED
+ ///
+ /// An unrecoverable error occurred during initialization of EmojiCompat. Calls to functions
+ /// such as \#process(CharSequence) will fail.
+ ///@see \#getLoadState()
+ static const LOAD_STATE_FAILED = 2;
+
+ /// from: static public final int REPLACE_STRATEGY_DEFAULT
+ ///
+ /// Replace strategy that uses the value given in EmojiCompat.Config.
+ ///@see \#process(CharSequence, int, int, int, int)
+ static const REPLACE_STRATEGY_DEFAULT = 0;
+
+ /// from: static public final int REPLACE_STRATEGY_ALL
+ ///
+ /// Replace strategy to add EmojiSpans for all emoji that were found.
+ ///@see \#process(CharSequence, int, int, int, int)
+ static const REPLACE_STRATEGY_ALL = 1;
+
+ /// from: static public final int REPLACE_STRATEGY_NON_EXISTENT
+ ///
+ /// Replace strategy to add EmojiSpans only for emoji that do not exist in the system.
+ static const REPLACE_STRATEGY_NON_EXISTENT = 2;
+
+ /// from: static public final int LOAD_STRATEGY_DEFAULT
+ ///
+ /// EmojiCompat will start loading metadata when \#init(Config) is called.
+ ///@see Config\#setMetadataLoadStrategy(int)
+ static const LOAD_STRATEGY_DEFAULT = 0;
+
+ /// from: static public final int LOAD_STRATEGY_MANUAL
+ ///
+ /// EmojiCompat will wait for \#load() to be called by developer in order to
+ /// start loading metadata.
+ ///@see Config\#setMetadataLoadStrategy(int)
+ static const LOAD_STRATEGY_MANUAL = 1;
+
+ /// from: static public final int EMOJI_UNSUPPORTED
+ ///
+ /// Result of \#getEmojiMatch(CharSequence, int) that means no part of this codepoint
+ /// sequence will ever generate an EmojiSpan at the requested metadata level.
+ ///
+ /// This return value implies:
+ /// - EmojiCompat will always defer to system emoji font
+ /// - System emoji font may or may not support this emoji
+ /// - This application MAY render this emoji
+ ///
+ /// This can be used by keyboards to learn that EmojiCompat does not support this codepoint
+ /// sequence at this metadata version. The system emoji font is not checked by this method,
+ /// and this result will be returned even if the system emoji font supports the emoji. This may
+ /// happen if the application is using an older version of the emoji compat font than the
+ /// system emoji font.
+ ///
+ /// Keyboards may optionally determine that the system emoji font will support the emoji, for
+ /// example by building a internal lookup table or calling
+ /// androidx.core.graphics.PaintCompat\#hasGlyph(Paint, String) to query the system
+ /// emoji font. Keyboards may use a lookup table to optimize this check, however they should be
+ /// aware that OEMs may add or remove emoji from the system emoji font.
+ ///
+ /// Keyboards may finally decide:
+ /// - If the system emoji font DOES NOT support the emoji, then the emoji IS NOT supported by
+ /// this application.
+ /// - If the system emoji font DOES support the emoji, then the emoji IS supported by this
+ /// application.
+ /// - If system emoji font is support is UNKNOWN, then assume the emoji IS NOT supported by
+ /// this application.
+ static const EMOJI_UNSUPPORTED = 0;
+
+ /// from: static public final int EMOJI_SUPPORTED
+ ///
+ /// Result of \#getEmojiMatch(CharSequence, int) that means this codepoint can be drawn
+ /// by an EmojiSpan at this metadata level.
+ ///
+ /// No further checks are required by keyboards for this result. The emoji is always supported
+ /// by this application.
+ ///
+ /// This return value implies:
+ /// - EmojiCompat can draw this emoji
+ /// - System emoji font may or may not support this emoji
+ /// - This application WILL render this emoji
+ ///
+ /// This result implies that EmojiCompat can successfully display this emoji. The system emoji
+ /// font is not checked by this method, and this result may be returned even if the platform
+ /// also supports the emoji sequence.
+ ///
+ /// If the application passes EmojiCompat\#REPLACE_STRATEGY_ALL of true, then an
+ /// EmojiSpan will always be generated for this emoji.
+ ///
+ /// If the application passes EmojiCompat\#REPLACE_STRATEGY_ALL of false, then an
+ /// EmojiSpan will only be generated if
+ /// androidx.core.graphics.PaintCompat\#hasGlyph(Paint, String)
+ /// returns false for this emoji.
+ static const EMOJI_SUPPORTED = 1;
+
+ /// from: static public final int EMOJI_FALLBACK
+ ///
+ /// Result of \#getEmojiMatch(CharSequence, int) that means the full codepoint sequence
+ /// is not known to emojicompat, but at least one subsequence is an emoji that is known at
+ /// this metadata level.
+ ///
+ /// Keyboards may decide that this emoji is not supported by the application when this result is
+ /// returned, with no further processing.
+ ///
+ /// This return value implies:
+ /// - EmojiCompat will decompose this ZWJ sequence into multiple glyphs when replaceAll=true
+ /// - EmojiCompat MAY defer to platform when replaceAll=false
+ /// - System emoji font may or may not support this emoji
+ /// - This application MAY render this emoji
+ ///
+ /// This return value is only ever returned for ZWJ sequences. To understand this result
+ /// consider when it may be returned for the multi-skin-tone handshake introduced in emoji 14.
+ ///
+ /// <pre>
+ /// U+1FAF1 // unknown @ requested metadata level
+ /// U+1F3FB // metadata level 1
+ /// U+200D // not displayed (ZWJ)
+ /// U+1FAF2 // unknown @ requested metadata level
+ /// U+1F3FD // metadata level 1
+ /// </pre>
+ ///
+ /// In this codepoint sequence, U+1F3FB and U+1F3FD are known from metadata level 1. When an
+ /// application is using a metadata level that doesn't understand this ZWJ and provides
+ /// EmojiCompat\#REPLACE_STRATEGY_ALL true, the color emoji are matched and replaced
+ /// with EmojiSpan. The system emoji font, even if it supports this ZWJ sequence, is
+ /// never queried and the added EmojiSpans force fallback rendering for the ZWJ sequence.
+ ///
+ /// The glyph will only display correctly for this application if ALL of the following
+ /// requirements are met:
+ /// - EmojiCompat\#REPLACE_STRATEGY_ALL is false
+ /// - androidx.core.graphics.PaintCompat\#hasGlyph(Paint, String) returns true for each
+ /// emoji subsequence known at this metadata level
+ /// - androidx.core.graphics.PaintCompat\#hasGlyph(Paint, String) returns true for the
+ /// full sequence
+ ///
+ /// Given this return value for the multi-skin-tone handshake above, if
+ /// EmojiCompat\#REPLACE_STRATEGY_ALL is false then the emoji will display if the
+ /// entire emoji sequence is matched by
+ /// androidx.core.graphics.PaintCompat\#hasGlyph(Paint, String) because U+1F3FB and
+ /// U+1F3FD are both in the system emoji font.
+ ///
+ /// Keyboards that wish to determine if the glyph will display correctly by the application in
+ /// response to this return value should consider building an internal lookup for new ZWJ
+ /// sequences instead of repeatedly calling
+ /// androidx.core.graphics.PaintCompat\#hasGlyph(Paint, String) for each emoji
+ /// subsequence.
+ static const EMOJI_FALLBACK = 2;
+
+ static final _init = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat__init")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public androidx.emoji2.text.EmojiCompat init(android.content.Context context)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Initialize the singleton instance with the default system-provided configuration.
+ ///
+ /// This is the recommended configuration for most applications. For more details see
+ /// DefaultEmojiCompatConfig.
+ ///
+ ///
+ /// This call will use DefaultEmojiCompatConfig to lookup the default emoji font
+ /// provider installed on the system and use that, if present. If there is no default font
+ /// provider onthe system, this call will have no effect.
+ ///
+ ///
+ /// Note: EmojiCompat may only be initialized once, and will return the same instance
+ /// afterwords.
+ ///
+ ///@return Default EmojiCompat for this device, or null if there is no provider on the system.
+ static EmojiCompat init(
+ jni.JObject context,
+ ) {
+ return const $EmojiCompatType().fromRef(_init(context.reference).object);
+ }
+
+ static final _init1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("EmojiCompat__init1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public androidx.emoji2.text.EmojiCompat init(android.content.Context context, androidx.emoji2.text.DefaultEmojiCompatConfig.DefaultEmojiCompatConfigFactory defaultFactory)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// @hide
+ static EmojiCompat init1(
+ jni.JObject context,
+ DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory defaultFactory,
+ ) {
+ return const $EmojiCompatType()
+ .fromRef(_init1(context.reference, defaultFactory.reference).object);
+ }
+
+ static final _init2 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat__init2")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public androidx.emoji2.text.EmojiCompat init(androidx.emoji2.text.EmojiCompat.Config config)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Initialize the singleton instance with a configuration. When used on devices running API 18
+ /// or below, the singleton instance is immediately moved into \#LOAD_STATE_SUCCEEDED
+ /// state without loading any metadata. When called for the first time, the library will create
+ /// the singleton instance and any call after that will not create a new instance and return
+ /// immediately.
+ ///@see EmojiCompat.Config
+ static EmojiCompat init2(
+ EmojiCompat_Config config,
+ ) {
+ return const $EmojiCompatType().fromRef(_init2(config.reference).object);
+ }
+
+ static final _isConfigured =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "EmojiCompat__isConfigured")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public boolean isConfigured()
+ ///
+ /// Return true if EmojiCompat has been configured by a successful call to
+ /// EmojiCompat\#init.
+ ///
+ /// You can use this to check if EmojiCompat\#get() will return a valid EmojiCompat
+ /// instance.
+ ///
+ /// This function does not check the \#getLoadState() and will return true even if the
+ /// font is still loading, or has failed to load.
+ ///@return true if EmojiCompat has been successfully initialized.
+ static bool isConfigured() {
+ return _isConfigured().boolean;
+ }
+
+ static final _reset = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat__reset")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public androidx.emoji2.text.EmojiCompat reset(androidx.emoji2.text.EmojiCompat.Config config)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Used by the tests to reset EmojiCompat with a new configuration. Every time it is called a
+ /// new instance is created with the new configuration.
+ ///@hide
+ static EmojiCompat reset(
+ EmojiCompat_Config config,
+ ) {
+ return const $EmojiCompatType().fromRef(_reset(config.reference).object);
+ }
+
+ static final _reset1 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat__reset1")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public androidx.emoji2.text.EmojiCompat reset(androidx.emoji2.text.EmojiCompat emojiCompat)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Used by the tests to reset EmojiCompat with a new singleton instance.
+ ///@hide
+ static EmojiCompat reset1(
+ EmojiCompat emojiCompat,
+ ) {
+ return const $EmojiCompatType()
+ .fromRef(_reset1(emojiCompat.reference).object);
+ }
+
+ static final _skipDefaultConfigurationLookup =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Uint8)>>(
+ "EmojiCompat__skipDefaultConfigurationLookup")
+ .asFunction<jni.JniResult Function(int)>();
+
+ /// from: static public void skipDefaultConfigurationLookup(boolean shouldSkip)
+ ///
+ /// Reset default configuration lookup flag, for tests.
+ ///@hide
+ static void skipDefaultConfigurationLookup(
+ bool shouldSkip,
+ ) {
+ return _skipDefaultConfigurationLookup(shouldSkip ? 1 : 0).check();
+ }
+
+ static final _get0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "EmojiCompat__get0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public androidx.emoji2.text.EmojiCompat get()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Return singleton EmojiCompat instance. Should be called after
+ /// \#init(EmojiCompat.Config) is called to initialize the singleton instance.
+ ///@return EmojiCompat instance
+ ///@throws IllegalStateException if called before \#init(EmojiCompat.Config)
+ static EmojiCompat get0() {
+ return const $EmojiCompatType().fromRef(_get0().object);
+ }
+
+ static final _load = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat__load")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void load()
+ ///
+ /// When Config\#setMetadataLoadStrategy(int) is set to \#LOAD_STRATEGY_MANUAL,
+ /// this function starts loading the metadata. Calling the function when
+ /// Config\#setMetadataLoadStrategy(int) is {@code not} set to
+ /// \#LOAD_STRATEGY_MANUAL will throw an exception. The load will {@code not} start if:
+ /// <ul>
+ /// <li>the metadata is already loaded successfully and \#getLoadState() is
+ /// \#LOAD_STATE_SUCCEEDED.
+ /// </li>
+ /// <li>a previous load attempt is not finished yet and \#getLoadState() is
+ /// \#LOAD_STATE_LOADING.</li>
+ /// </ul>
+ ///@throws IllegalStateException when Config\#setMetadataLoadStrategy(int) is not set
+ /// to \#LOAD_STRATEGY_MANUAL
+ void load() {
+ return _load(reference).check();
+ }
+
+ static final _registerInitCallback = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("EmojiCompat__registerInitCallback")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void registerInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback initCallback)
+ ///
+ /// Registers an initialization callback. If the initialization is already completed by the time
+ /// the listener is added, the callback functions are called immediately. Callbacks are called on
+ /// the main looper.
+ /// <p/>
+ /// When used on devices running API 18 or below, InitCallback\#onInitialized() is called
+ /// without loading any metadata. In such cases InitCallback\#onFailed(Throwable) is never
+ /// called.
+ ///@param initCallback the initialization callback to register, cannot be {@code null}
+ ///@see \#unregisterInitCallback(InitCallback)
+ void registerInitCallback(
+ EmojiCompat_InitCallback initCallback,
+ ) {
+ return _registerInitCallback(reference, initCallback.reference).check();
+ }
+
+ static final _unregisterInitCallback = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat__unregisterInitCallback")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void unregisterInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback initCallback)
+ ///
+ /// Unregisters a callback that was added before.
+ ///@param initCallback the callback to be removed, cannot be {@code null}
+ void unregisterInitCallback(
+ EmojiCompat_InitCallback initCallback,
+ ) {
+ return _unregisterInitCallback(reference, initCallback.reference).check();
+ }
+
+ static final _getLoadState = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat__getLoadState")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int getLoadState()
+ ///
+ /// Returns loading state of the EmojiCompat instance. When used on devices running API 18 or
+ /// below always returns \#LOAD_STATE_SUCCEEDED.
+ ///@return one of \#LOAD_STATE_DEFAULT, \#LOAD_STATE_LOADING,
+ /// \#LOAD_STATE_SUCCEEDED, \#LOAD_STATE_FAILED
+ int getLoadState() {
+ return _getLoadState(reference).integer;
+ }
+
+ static final _isEmojiSpanIndicatorEnabled = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat__isEmojiSpanIndicatorEnabled")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean isEmojiSpanIndicatorEnabled()
+ ///
+ /// @return whether a background should be drawn for the emoji for debugging
+ ///@hide
+ bool isEmojiSpanIndicatorEnabled() {
+ return _isEmojiSpanIndicatorEnabled(reference).boolean;
+ }
+
+ static final _getEmojiSpanIndicatorColor = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat__getEmojiSpanIndicatorColor")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int getEmojiSpanIndicatorColor()
+ ///
+ /// @return color of background drawn if EmojiCompat\#isEmojiSpanIndicatorEnabled is true
+ ///@hide
+ int getEmojiSpanIndicatorColor() {
+ return _getEmojiSpanIndicatorColor(reference).integer;
+ }
+
+ static final _getEmojiStart = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32)>>("EmojiCompat__getEmojiStart")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public int getEmojiStart(java.lang.CharSequence charSequence, int offset)
+ ///
+ /// Together with \#getEmojiEnd(CharSequence, int), if the character at {@code offset} is
+ /// part of an emoji, returns the index range of that emoji, start index inclusively/end index
+ /// exclusively so that {@code charSequence.subSequence(start, end)} will return that emoji.
+ /// E.g., getEmojiStart/End("AB\ud83d\ude00", 1) will return (-1,-1) since 'B' is not part an emoji;
+ /// getEmojiStart/End("AB\ud83d\ude00", 3) will return [2,4), note that "\ud83d\ude00" contains 2 Chars.
+ /// Returns -1 otherwise.
+ ///@param charSequence the whole sequence
+ ///@param offset index of the emoji to look up
+ ///@return the start index inclusively/end index exclusively
+ int getEmojiStart(
+ jni.JObject charSequence,
+ int offset,
+ ) {
+ return _getEmojiStart(reference, charSequence.reference, offset).integer;
+ }
+
+ static final _getEmojiEnd = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32)>>("EmojiCompat__getEmojiEnd")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public int getEmojiEnd(java.lang.CharSequence charSequence, int offset)
+ ///
+ /// see \#getEmojiStart(CharSequence, int).
+ int getEmojiEnd(
+ jni.JObject charSequence,
+ int offset,
+ ) {
+ return _getEmojiEnd(reference, charSequence.reference, offset).integer;
+ }
+
+ static final _handleOnKeyDown = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Int32,
+ ffi.Pointer<ffi.Void>)>>("EmojiCompat__handleOnKeyDown")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, int, ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public boolean handleOnKeyDown(android.text.Editable editable, int keyCode, android.view.KeyEvent event)
+ ///
+ /// Handles onKeyDown commands from a KeyListener and if {@code keyCode} is one of
+ /// KeyEvent\#KEYCODE_DEL or KeyEvent\#KEYCODE_FORWARD_DEL it tries to delete an
+ /// EmojiSpan from an Editable. Returns {@code true} if an EmojiSpan is
+ /// deleted with the characters it covers.
+ /// <p/>
+ /// If there is a selection where selection start is not equal to selection end, does not
+ /// delete.
+ /// <p/>
+ /// When used on devices running API 18 or below, always returns {@code false}.
+ ///@param editable Editable instance passed to KeyListener\#onKeyDown(android.view.View,
+ /// Editable, int, KeyEvent)
+ ///@param keyCode keyCode passed to KeyListener\#onKeyDown(android.view.View, Editable,
+ /// int, KeyEvent)
+ ///@param event KeyEvent passed to KeyListener\#onKeyDown(android.view.View, Editable,
+ /// int, KeyEvent)
+ ///@return {@code true} if an EmojiSpan is deleted
+ static bool handleOnKeyDown(
+ jni.JObject editable,
+ int keyCode,
+ jni.JObject event,
+ ) {
+ return _handleOnKeyDown(editable.reference, keyCode, event.reference)
+ .boolean;
+ }
+
+ static final _handleDeleteSurroundingText = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32,
+ ffi.Int32,
+ ffi.Uint8)>>("EmojiCompat__handleDeleteSurroundingText")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int, int, int)>();
+
+ /// from: static public boolean handleDeleteSurroundingText(android.view.inputmethod.InputConnection inputConnection, android.text.Editable editable, int beforeLength, int afterLength, boolean inCodePoints)
+ ///
+ /// Handles deleteSurroundingText commands from InputConnection and tries to delete an
+ /// EmojiSpan from an Editable. Returns {@code true} if an EmojiSpan is
+ /// deleted.
+ /// <p/>
+ /// If there is a selection where selection start is not equal to selection end, does not
+ /// delete.
+ /// <p/>
+ /// When used on devices running API 18 or below, always returns {@code false}.
+ ///@param inputConnection InputConnection instance
+ ///@param editable TextView.Editable instance
+ ///@param beforeLength the number of characters before the cursor to be deleted
+ ///@param afterLength the number of characters after the cursor to be deleted
+ ///@param inCodePoints {@code true} if length parameters are in codepoints
+ ///@return {@code true} if an EmojiSpan is deleted
+ static bool handleDeleteSurroundingText(
+ jni.JObject inputConnection,
+ jni.JObject editable,
+ int beforeLength,
+ int afterLength,
+ bool inCodePoints,
+ ) {
+ return _handleDeleteSurroundingText(inputConnection.reference,
+ editable.reference, beforeLength, afterLength, inCodePoints ? 1 : 0)
+ .boolean;
+ }
+
+ static final _hasEmojiGlyph = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("EmojiCompat__hasEmojiGlyph")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean hasEmojiGlyph(java.lang.CharSequence sequence)
+ ///
+ /// Returns {@code true} if EmojiCompat is capable of rendering an emoji. When used on devices
+ /// running API 18 or below, always returns {@code false}.
+ ///@deprecated use getEmojiMatch which returns more accurate lookup information.
+ ///@param sequence CharSequence representing the emoji
+ ///@return {@code true} if EmojiCompat can render given emoji, cannot be {@code null}
+ ///@throws IllegalStateException if not initialized yet
+ bool hasEmojiGlyph(
+ jni.JObject sequence,
+ ) {
+ return _hasEmojiGlyph(reference, sequence.reference).boolean;
+ }
+
+ static final _hasEmojiGlyph1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32)>>("EmojiCompat__hasEmojiGlyph1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public boolean hasEmojiGlyph(java.lang.CharSequence sequence, int metadataVersion)
+ ///
+ /// Returns {@code true} if EmojiCompat is capable of rendering an emoji at the given metadata
+ /// version. When used on devices running API 18 or below, always returns {@code false}.
+ ///@deprecated use getEmojiMatch which returns more accurate lookup information.
+ ///@param sequence CharSequence representing the emoji
+ ///@param metadataVersion the metadata version to check against, should be greater than or
+ /// equal to {@code 0},
+ ///@return {@code true} if EmojiCompat can render given emoji, cannot be {@code null}
+ ///@throws IllegalStateException if not initialized yet
+ bool hasEmojiGlyph1(
+ jni.JObject sequence,
+ int metadataVersion,
+ ) {
+ return _hasEmojiGlyph1(reference, sequence.reference, metadataVersion)
+ .boolean;
+ }
+
+ static final _getEmojiMatch = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32)>>("EmojiCompat__getEmojiMatch")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public int getEmojiMatch(java.lang.CharSequence sequence, int metadataVersion)
+ ///
+ /// Attempts to lookup the entire sequence at the specified metadata version and returns what
+ /// the runtime match behavior would be.
+ ///
+ /// To be used by keyboards to show or hide emoji in response to specific metadata support.
+ ///@see \#EMOJI_SUPPORTED
+ ///@see \#EMOJI_UNSUPPORTED
+ ///@see \#EMOJI_FALLBACK
+ ///@param sequence CharSequence representing an emoji
+ ///@param metadataVersion the metada version to check against, should be greater than or
+ /// equal to {@code 0},
+ ///@return A match result, or decomposes if replaceAll would cause partial subsequence matches.
+ int getEmojiMatch(
+ jni.JObject sequence,
+ int metadataVersion,
+ ) {
+ return _getEmojiMatch(reference, sequence.reference, metadataVersion)
+ .integer;
+ }
+
+ static final _process = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("EmojiCompat__process")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.CharSequence process(java.lang.CharSequence charSequence)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Checks a given CharSequence for emojis, and adds EmojiSpans if any emojis are found. When
+ /// used on devices running API 18 or below, returns the given {@code charSequence} without
+ /// processing it.
+ ///@param charSequence CharSequence to add the EmojiSpans
+ ///@throws IllegalStateException if not initialized yet
+ ///@see \#process(CharSequence, int, int)
+ jni.JObject process(
+ jni.JObject charSequence,
+ ) {
+ return const jni.JObjectType()
+ .fromRef(_process(reference, charSequence.reference).object);
+ }
+
+ static final _process1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32,
+ ffi.Int32)>>("EmojiCompat__process1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int, int)>();
+
+ /// from: public java.lang.CharSequence process(java.lang.CharSequence charSequence, int start, int end)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Checks a given CharSequence for emojis, and adds EmojiSpans if any emojis are found.
+ ///
+ /// <ul>
+ /// <li>If no emojis are found, {@code charSequence} given as the input is returned without
+ /// any changes. i.e. charSequence is a String, and no emojis are found, the same String is
+ /// returned.</li>
+ /// <li>If the given input is not a Spannable (such as String), and at least one emoji is found
+ /// a new android.text.Spannable instance is returned. </li>
+ /// <li>If the given input is a Spannable, the same instance is returned. </li>
+ /// </ul>
+ /// When used on devices running API 18 or below, returns the given {@code charSequence} without
+ /// processing it.
+ ///@param charSequence CharSequence to add the EmojiSpans, cannot be {@code null}
+ ///@param start start index in the charSequence to look for emojis, should be greater than or
+ /// equal to {@code 0}, also less than or equal to {@code charSequence.length()}
+ ///@param end end index in the charSequence to look for emojis, should be greater than or equal
+ /// to {@code start} parameter, also less than or equal to
+ /// {@code charSequence.length()}
+ ///@throws IllegalStateException if not initialized yet
+ ///@throws IllegalArgumentException in the following cases:
+ /// {@code start < 0}, {@code end < 0}, {@code end < start},
+ /// {@code start > charSequence.length()},
+ /// {@code end > charSequence.length()}
+ jni.JObject process1(
+ jni.JObject charSequence,
+ int start,
+ int end,
+ ) {
+ return const jni.JObjectType().fromRef(
+ _process1(reference, charSequence.reference, start, end).object);
+ }
+
+ static final _process2 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32,
+ ffi.Int32,
+ ffi.Int32)>>("EmojiCompat__process2")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int, int, int)>();
+
+ /// from: public java.lang.CharSequence process(java.lang.CharSequence charSequence, int start, int end, int maxEmojiCount)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Checks a given CharSequence for emojis, and adds EmojiSpans if any emojis are found.
+ ///
+ /// <ul>
+ /// <li>If no emojis are found, {@code charSequence} given as the input is returned without
+ /// any changes. i.e. charSequence is a String, and no emojis are found, the same String is
+ /// returned.</li>
+ /// <li>If the given input is not a Spannable (such as String), and at least one emoji is found
+ /// a new android.text.Spannable instance is returned. </li>
+ /// <li>If the given input is a Spannable, the same instance is returned. </li>
+ /// </ul>
+ /// When used on devices running API 18 or below, returns the given {@code charSequence} without
+ /// processing it.
+ ///@param charSequence CharSequence to add the EmojiSpans, cannot be {@code null}
+ ///@param start start index in the charSequence to look for emojis, should be greater than or
+ /// equal to {@code 0}, also less than or equal to {@code charSequence.length()}
+ ///@param end end index in the charSequence to look for emojis, should be greater than or
+ /// equal to {@code start} parameter, also less than or equal to
+ /// {@code charSequence.length()}
+ ///@param maxEmojiCount maximum number of emojis in the {@code charSequence}, should be greater
+ /// than or equal to {@code 0}
+ ///@throws IllegalStateException if not initialized yet
+ ///@throws IllegalArgumentException in the following cases:
+ /// {@code start < 0}, {@code end < 0}, {@code end < start},
+ /// {@code start > charSequence.length()},
+ /// {@code end > charSequence.length()}
+ /// {@code maxEmojiCount < 0}
+ jni.JObject process2(
+ jni.JObject charSequence,
+ int start,
+ int end,
+ int maxEmojiCount,
+ ) {
+ return const jni.JObjectType().fromRef(
+ _process2(reference, charSequence.reference, start, end, maxEmojiCount)
+ .object);
+ }
+
+ static final _process3 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32,
+ ffi.Int32,
+ ffi.Int32,
+ ffi.Int32)>>("EmojiCompat__process3")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ int, int, int, int)>();
+
+ /// from: public java.lang.CharSequence process(java.lang.CharSequence charSequence, int start, int end, int maxEmojiCount, int replaceStrategy)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Checks a given CharSequence for emojis, and adds EmojiSpans if any emojis are found.
+ ///
+ /// <ul>
+ /// <li>If no emojis are found, {@code charSequence} given as the input is returned without
+ /// any changes. i.e. charSequence is a String, and no emojis are found, the same String is
+ /// returned.</li>
+ /// <li>If the given input is not a Spannable (such as String), and at least one emoji is found
+ /// a new android.text.Spannable instance is returned. </li>
+ /// <li>If the given input is a Spannable, the same instance is returned. </li>
+ /// </ul>
+ /// When used on devices running API 18 or below, returns the given {@code charSequence} without
+ /// processing it.
+ ///@param charSequence CharSequence to add the EmojiSpans, cannot be {@code null}
+ ///@param start start index in the charSequence to look for emojis, should be greater than or
+ /// equal to {@code 0}, also less than or equal to {@code charSequence.length()}
+ ///@param end end index in the charSequence to look for emojis, should be greater than or
+ /// equal to {@code start} parameter, also less than or equal to
+ /// {@code charSequence.length()}
+ ///@param maxEmojiCount maximum number of emojis in the {@code charSequence}, should be greater
+ /// than or equal to {@code 0}
+ ///@param replaceStrategy whether to replace all emoji with EmojiSpans, should be one of
+ /// \#REPLACE_STRATEGY_DEFAULT,
+ /// \#REPLACE_STRATEGY_NON_EXISTENT,
+ /// \#REPLACE_STRATEGY_ALL
+ ///@throws IllegalStateException if not initialized yet
+ ///@throws IllegalArgumentException in the following cases:
+ /// {@code start < 0}, {@code end < 0}, {@code end < start},
+ /// {@code start > charSequence.length()},
+ /// {@code end > charSequence.length()}
+ /// {@code maxEmojiCount < 0}
+ jni.JObject process3(
+ jni.JObject charSequence,
+ int start,
+ int end,
+ int maxEmojiCount,
+ int replaceStrategy,
+ ) {
+ return const jni.JObjectType().fromRef(_process3(reference,
+ charSequence.reference, start, end, maxEmojiCount, replaceStrategy)
+ .object);
+ }
+
+ static final _getAssetSignature = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat__getAssetSignature")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getAssetSignature()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Returns signature for the currently loaded emoji assets. The signature is a SHA that is
+ /// constructed using emoji assets. Can be used to detect if currently loaded asset is different
+ /// then previous executions. When used on devices running API 18 or below, returns empty string.
+ ///@throws IllegalStateException if not initialized yet
+ jni.JString getAssetSignature() {
+ return const jni.JStringType()
+ .fromRef(_getAssetSignature(reference).object);
+ }
+
+ static final _updateEditorInfo = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("EmojiCompat__updateEditorInfo")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void updateEditorInfo(android.view.inputmethod.EditorInfo outAttrs)
+ ///
+ /// Updates the EditorInfo attributes in order to communicate information to Keyboards. When
+ /// used on devices running API 18 or below, does not update EditorInfo attributes.
+ ///
+ /// This is called from EditText integrations that use EmojiEditTextHelper. Custom
+ /// widgets that allow IME not subclassing EditText should call this method when creating an
+ /// input connection.
+ ///
+ /// When EmojiCompat is not in \#LOAD_STATE_SUCCEEDED, this method has no effect.
+ ///
+ /// Calling this method on API levels below API 19 will have no effect, as EmojiCompat may
+ /// never be configured. However, it is always safe to call, even on older API levels.
+ ///@param outAttrs EditorInfo instance passed to
+ /// android.widget.TextView\#onCreateInputConnection(EditorInfo)
+ ///@see \#EDITOR_INFO_METAVERSION_KEY
+ ///@see \#EDITOR_INFO_REPLACE_ALL_KEY
+ void updateEditorInfo(
+ jni.JObject outAttrs,
+ ) {
+ return _updateEditorInfo(reference, outAttrs.reference).check();
+ }
+}
+
+final class $EmojiCompatType extends jni.JObjType<EmojiCompat> {
+ const $EmojiCompatType();
+
+ @override
+ String get signature => r"Landroidx/emoji2/text/EmojiCompat;";
+
+ @override
+ EmojiCompat fromRef(jni.JObjectPtr ref) => EmojiCompat.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($EmojiCompatType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($EmojiCompatType) && other is $EmojiCompatType;
+ }
+}
+
+/// from: androidx.emoji2.text.EmojiCompat$Config
+///
+/// Configuration class for EmojiCompat. Changes to the values will be ignored after
+/// \#init(Config) is called.
+///@see \#init(EmojiCompat.Config)
+class EmojiCompat_Config extends jni.JObject {
+ @override
+ late final jni.JObjType<EmojiCompat_Config> $type = type;
+
+ EmojiCompat_Config.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $EmojiCompat_ConfigType();
+ static final _new0 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat_Config__new0")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void <init>(androidx.emoji2.text.EmojiCompat.MetadataRepoLoader metadataLoader)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Default constructor.
+ ///@param metadataLoader MetadataRepoLoader instance, cannot be {@code null}
+ factory EmojiCompat_Config(
+ EmojiCompat_MetadataRepoLoader metadataLoader,
+ ) {
+ return EmojiCompat_Config.fromRef(_new0(metadataLoader.reference).object);
+ }
+
+ static final _registerInitCallback = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat_Config__registerInitCallback")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public androidx.emoji2.text.EmojiCompat.Config registerInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback initCallback)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Registers an initialization callback.
+ ///@param initCallback the initialization callback to register, cannot be {@code null}
+ ///@return EmojiCompat.Config instance
+ EmojiCompat_Config registerInitCallback(
+ EmojiCompat_InitCallback initCallback,
+ ) {
+ return const $EmojiCompat_ConfigType().fromRef(
+ _registerInitCallback(reference, initCallback.reference).object);
+ }
+
+ static final _unregisterInitCallback = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat_Config__unregisterInitCallback")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public androidx.emoji2.text.EmojiCompat.Config unregisterInitCallback(androidx.emoji2.text.EmojiCompat.InitCallback initCallback)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Unregisters a callback that was added before.
+ ///@param initCallback the initialization callback to be removed, cannot be {@code null}
+ ///@return EmojiCompat.Config instance
+ EmojiCompat_Config unregisterInitCallback(
+ EmojiCompat_InitCallback initCallback,
+ ) {
+ return const $EmojiCompat_ConfigType().fromRef(
+ _unregisterInitCallback(reference, initCallback.reference).object);
+ }
+
+ static final _setReplaceAll = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Uint8)>>("EmojiCompat_Config__setReplaceAll")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public androidx.emoji2.text.EmojiCompat.Config setReplaceAll(boolean replaceAll)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Determines whether EmojiCompat should replace all the emojis it finds with the
+ /// EmojiSpans. By default EmojiCompat tries its best to understand if the system already
+ /// can render an emoji and do not replace those emojis.
+ ///@param replaceAll replace all emojis found with EmojiSpans
+ ///@return EmojiCompat.Config instance
+ EmojiCompat_Config setReplaceAll(
+ bool replaceAll,
+ ) {
+ return const $EmojiCompat_ConfigType()
+ .fromRef(_setReplaceAll(reference, replaceAll ? 1 : 0).object);
+ }
+
+ static final _setUseEmojiAsDefaultStyle = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Uint8)>>("EmojiCompat_Config__setUseEmojiAsDefaultStyle")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public androidx.emoji2.text.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean useEmojiAsDefaultStyle)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Determines whether EmojiCompat should use the emoji presentation style for emojis
+ /// that have text style as default. By default, the text style would be used, unless these
+ /// are followed by the U+FE0F variation selector.
+ /// Details about emoji presentation and text presentation styles can be found here:
+ /// http://unicode.org/reports/tr51/\#Presentation_Style
+ /// If useEmojiAsDefaultStyle is true, the emoji presentation style will be used for all
+ /// emojis, including potentially unexpected ones (such as digits or other keycap emojis). If
+ /// this is not the expected behaviour, method
+ /// \#setUseEmojiAsDefaultStyle(boolean, List) can be used to specify the
+ /// exception emojis that should be still presented as text style.
+ ///@param useEmojiAsDefaultStyle whether to use the emoji style presentation for all emojis
+ /// that would be presented as text style by default
+ EmojiCompat_Config setUseEmojiAsDefaultStyle(
+ bool useEmojiAsDefaultStyle,
+ ) {
+ return const $EmojiCompat_ConfigType().fromRef(
+ _setUseEmojiAsDefaultStyle(reference, useEmojiAsDefaultStyle ? 1 : 0)
+ .object);
+ }
+
+ static final _setUseEmojiAsDefaultStyle1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Uint8,
+ ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat_Config__setUseEmojiAsDefaultStyle1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, int, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public androidx.emoji2.text.EmojiCompat.Config setUseEmojiAsDefaultStyle(boolean useEmojiAsDefaultStyle, java.util.List<java.lang.Integer> emojiAsDefaultStyleExceptions)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// @see \#setUseEmojiAsDefaultStyle(boolean)
+ ///@param emojiAsDefaultStyleExceptions Contains the exception emojis which will be still
+ /// presented as text style even if the
+ /// useEmojiAsDefaultStyle flag is set to {@code true}.
+ /// This list will be ignored if useEmojiAsDefaultStyle
+ /// is {@code false}. Note that emojis with default
+ /// emoji style presentation will remain emoji style
+ /// regardless the value of useEmojiAsDefaultStyle or
+ /// whether they are included in the exceptions list or
+ /// not. When no exception is wanted, the method
+ /// \#setUseEmojiAsDefaultStyle(boolean) should
+ /// be used instead.
+ EmojiCompat_Config setUseEmojiAsDefaultStyle1(
+ bool useEmojiAsDefaultStyle,
+ jni.JList<jni.JInteger> emojiAsDefaultStyleExceptions,
+ ) {
+ return const $EmojiCompat_ConfigType().fromRef(_setUseEmojiAsDefaultStyle1(
+ reference,
+ useEmojiAsDefaultStyle ? 1 : 0,
+ emojiAsDefaultStyleExceptions.reference)
+ .object);
+ }
+
+ static final _setEmojiSpanIndicatorEnabled = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
+ "EmojiCompat_Config__setEmojiSpanIndicatorEnabled")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public androidx.emoji2.text.EmojiCompat.Config setEmojiSpanIndicatorEnabled(boolean emojiSpanIndicatorEnabled)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Determines whether a background will be drawn for the emojis that are found and
+ /// replaced by EmojiCompat. Should be used only for debugging purposes. The indicator color
+ /// can be set using \#setEmojiSpanIndicatorColor(int).
+ ///@param emojiSpanIndicatorEnabled when {@code true} a background is drawn for each emoji
+ /// that is replaced
+ EmojiCompat_Config setEmojiSpanIndicatorEnabled(
+ bool emojiSpanIndicatorEnabled,
+ ) {
+ return const $EmojiCompat_ConfigType().fromRef(
+ _setEmojiSpanIndicatorEnabled(
+ reference, emojiSpanIndicatorEnabled ? 1 : 0)
+ .object);
+ }
+
+ static final _setEmojiSpanIndicatorColor = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Int32)>>("EmojiCompat_Config__setEmojiSpanIndicatorColor")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public androidx.emoji2.text.EmojiCompat.Config setEmojiSpanIndicatorColor(int color)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Sets the color used as emoji span indicator. The default value is
+ /// Color\#GREEN Color.GREEN.
+ ///@see \#setEmojiSpanIndicatorEnabled(boolean)
+ EmojiCompat_Config setEmojiSpanIndicatorColor(
+ int color,
+ ) {
+ return const $EmojiCompat_ConfigType()
+ .fromRef(_setEmojiSpanIndicatorColor(reference, color).object);
+ }
+
+ static final _setMetadataLoadStrategy = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Int32)>>("EmojiCompat_Config__setMetadataLoadStrategy")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public androidx.emoji2.text.EmojiCompat.Config setMetadataLoadStrategy(int strategy)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Determines the strategy to start loading the metadata. By default EmojiCompat
+ /// will start loading the metadata during EmojiCompat\#init(Config). When set to
+ /// EmojiCompat\#LOAD_STRATEGY_MANUAL, you should call EmojiCompat\#load() to
+ /// initiate metadata loading.
+ /// <p/>
+ /// Default implementations of EmojiCompat.MetadataRepoLoader start a thread
+ /// during their EmojiCompat.MetadataRepoLoader\#load functions. Just instantiating
+ /// and starting a thread might take time especially in older devices. Since
+ /// EmojiCompat\#init(Config) has to be called before any EmojiCompat widgets are
+ /// inflated, this results in time spent either on your Application.onCreate or Activity
+ /// .onCreate. If you'd like to gain more control on when to start loading the metadata
+ /// and be able to call EmojiCompat\#init(Config) with absolute minimum time cost you
+ /// can use EmojiCompat\#LOAD_STRATEGY_MANUAL.
+ /// <p/>
+ /// When set to EmojiCompat\#LOAD_STRATEGY_MANUAL, EmojiCompat will wait
+ /// for \#load() to be called by the developer in order to start loading metadata,
+ /// therefore you should call EmojiCompat\#load() to initiate metadata loading.
+ /// \#load() can be called from any thread.
+ /// <pre>
+ /// EmojiCompat.Config config = new FontRequestEmojiCompatConfig(context, fontRequest)
+ /// .setMetadataLoadStrategy(EmojiCompat.LOAD_STRATEGY_MANUAL);
+ ///
+ /// // EmojiCompat will not start loading metadata and MetadataRepoLoader\#load(...)
+ /// // will not be called
+ /// EmojiCompat.init(config);
+ ///
+ /// // At any time (i.e. idle time or executorService is ready)
+ /// // call EmojiCompat\#load() to start loading metadata.
+ /// executorService.execute(() -> EmojiCompat.get().load());
+ /// </pre>
+ ///@param strategy one of EmojiCompat\#LOAD_STRATEGY_DEFAULT,
+ /// EmojiCompat\#LOAD_STRATEGY_MANUAL
+ EmojiCompat_Config setMetadataLoadStrategy(
+ int strategy,
+ ) {
+ return const $EmojiCompat_ConfigType()
+ .fromRef(_setMetadataLoadStrategy(reference, strategy).object);
+ }
+
+ static final _setSpanFactory = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("EmojiCompat_Config__setSpanFactory")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public androidx.emoji2.text.EmojiCompat.Config setSpanFactory(androidx.emoji2.text.EmojiCompat.SpanFactory factory)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Set the span factory used to actually draw emoji replacements.
+ ///@param factory custum span factory that can draw the emoji replacements
+ ///@return this
+ EmojiCompat_Config setSpanFactory(
+ EmojiCompat_SpanFactory factory0,
+ ) {
+ return const $EmojiCompat_ConfigType()
+ .fromRef(_setSpanFactory(reference, factory0.reference).object);
+ }
+
+ static final _setGlyphChecker = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat_Config__setGlyphChecker")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public androidx.emoji2.text.EmojiCompat.Config setGlyphChecker(androidx.emoji2.text.EmojiCompat.GlyphChecker glyphChecker)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// The interface that is used by EmojiCompat in order to check if a given emoji can be
+ /// rendered by the system.
+ ///@param glyphChecker GlyphChecker instance to be used.
+ EmojiCompat_Config setGlyphChecker(
+ EmojiCompat_GlyphChecker glyphChecker,
+ ) {
+ return const $EmojiCompat_ConfigType()
+ .fromRef(_setGlyphChecker(reference, glyphChecker.reference).object);
+ }
+
+ static final _getMetadataRepoLoader = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat_Config__getMetadataRepoLoader")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected final androidx.emoji2.text.EmojiCompat.MetadataRepoLoader getMetadataRepoLoader()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Returns the MetadataRepoLoader.
+ EmojiCompat_MetadataRepoLoader getMetadataRepoLoader() {
+ return const $EmojiCompat_MetadataRepoLoaderType()
+ .fromRef(_getMetadataRepoLoader(reference).object);
+ }
+}
+
+final class $EmojiCompat_ConfigType extends jni.JObjType<EmojiCompat_Config> {
+ const $EmojiCompat_ConfigType();
+
+ @override
+ String get signature => r"Landroidx/emoji2/text/EmojiCompat$Config;";
+
+ @override
+ EmojiCompat_Config fromRef(jni.JObjectPtr ref) =>
+ EmojiCompat_Config.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($EmojiCompat_ConfigType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($EmojiCompat_ConfigType) &&
+ other is $EmojiCompat_ConfigType;
+ }
+}
+
+/// from: androidx.emoji2.text.EmojiCompat$MetadataRepoLoaderCallback
+///
+/// Callback to inform EmojiCompat about the state of the metadata load. Passed to
+/// MetadataRepoLoader during MetadataRepoLoader\#load(MetadataRepoLoaderCallback) call.
+class EmojiCompat_MetadataRepoLoaderCallback extends jni.JObject {
+ @override
+ late final jni.JObjType<EmojiCompat_MetadataRepoLoaderCallback> $type = type;
+
+ EmojiCompat_MetadataRepoLoaderCallback.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $EmojiCompat_MetadataRepoLoaderCallbackType();
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "EmojiCompat_MetadataRepoLoaderCallback__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory EmojiCompat_MetadataRepoLoaderCallback() {
+ return EmojiCompat_MetadataRepoLoaderCallback.fromRef(_new0().object);
+ }
+
+ static final _onLoaded = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat_MetadataRepoLoaderCallback__onLoaded")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract void onLoaded(androidx.emoji2.text.MetadataRepo metadataRepo)
+ ///
+ /// Called by MetadataRepoLoader when metadata is loaded successfully.
+ ///@param metadataRepo MetadataRepo instance, cannot be {@code null}
+ void onLoaded(
+ jni.JObject metadataRepo,
+ ) {
+ return _onLoaded(reference, metadataRepo.reference).check();
+ }
+
+ static final _onFailed = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat_MetadataRepoLoaderCallback__onFailed")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract void onFailed(java.lang.Throwable throwable)
+ ///
+ /// Called by MetadataRepoLoader if an error occurs while loading the metadata.
+ ///@param throwable the exception that caused the failure, {@code nullable}
+ void onFailed(
+ jni.JObject throwable,
+ ) {
+ return _onFailed(reference, throwable.reference).check();
+ }
+}
+
+final class $EmojiCompat_MetadataRepoLoaderCallbackType
+ extends jni.JObjType<EmojiCompat_MetadataRepoLoaderCallback> {
+ const $EmojiCompat_MetadataRepoLoaderCallbackType();
+
+ @override
+ String get signature =>
+ r"Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback;";
+
+ @override
+ EmojiCompat_MetadataRepoLoaderCallback fromRef(jni.JObjectPtr ref) =>
+ EmojiCompat_MetadataRepoLoaderCallback.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($EmojiCompat_MetadataRepoLoaderCallbackType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($EmojiCompat_MetadataRepoLoaderCallbackType) &&
+ other is $EmojiCompat_MetadataRepoLoaderCallbackType;
+ }
+}
+
+/// from: androidx.emoji2.text.EmojiCompat$GlyphChecker
+///
+/// Interface to check if a given emoji exists on the system.
+class EmojiCompat_GlyphChecker extends jni.JObject {
+ @override
+ late final jni.JObjType<EmojiCompat_GlyphChecker> $type = type;
+
+ EmojiCompat_GlyphChecker.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $EmojiCompat_GlyphCheckerType();
+ static final _hasGlyph = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32,
+ ffi.Int32,
+ ffi.Int32)>>("EmojiCompat_GlyphChecker__hasGlyph")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int, int, int)>();
+
+ /// from: public abstract boolean hasGlyph(java.lang.CharSequence charSequence, int start, int end, int sdkAdded)
+ ///
+ /// Return {@code true} if the emoji that is in {@code charSequence} between
+ /// {@code start}(inclusive) and {@code end}(exclusive) can be rendered on the system
+ /// using the default Typeface.
+ ///
+ /// This function is called after an emoji is identified in the given {@code charSequence}
+ /// and EmojiCompat wants to know if that emoji can be rendered on the system. The result
+ /// of this call will be cached and the same emoji sequence won't be asked for the same
+ /// EmojiCompat instance.
+ ///
+ /// When the function returns {@code true}, it will mean that the system can render the
+ /// emoji. In that case if Config\#setReplaceAll is set to {@code false}, then no
+ /// EmojiSpan will be added in the final emoji processing result.
+ ///
+ /// When the function returns {@code false}, it will mean that the system cannot render
+ /// the given emoji, therefore an EmojiSpan will be added to the final emoji
+ /// processing result.
+ ///
+ /// The default implementation of this class uses
+ /// androidx.core.graphics.PaintCompat\#hasGlyph(Paint, String) function to check
+ /// if the emoji can be rendered on the system. This is required even if EmojiCompat
+ /// knows about the SDK Version that the emoji was added on AOSP. Just the {@code sdkAdded}
+ /// information is not enough to reliably decide if emoji can be rendered since this
+ /// information may not be consistent across all the OEMs and all the Android versions.
+ ///
+ /// With this interface you can apply your own heuristics to check if the emoji can be
+ /// rendered on the system. For example, if you'd like to rely on the {@code sdkAdded}
+ /// information, and some predefined OEMs, it is possible to write the following code
+ /// snippet.
+ ///
+ /// {@sample frameworks/support/samples/SupportEmojiDemos/src/main/java/com/example/android/support/text/emoji/sample/GlyphCheckerSample.java glyphchecker}
+ ///@param charSequence the CharSequence that is being processed
+ ///@param start the inclusive starting offset for the emoji in the {@code charSequence}
+ ///@param end the exclusive end offset for the emoji in the {@code charSequence}
+ ///@param sdkAdded the API version that the emoji was added in AOSP
+ ///@return true if the given sequence can be rendered as a single glyph, otherwise false.
+ bool hasGlyph(
+ jni.JObject charSequence,
+ int start,
+ int end,
+ int sdkAdded,
+ ) {
+ return _hasGlyph(reference, charSequence.reference, start, end, sdkAdded)
+ .boolean;
+ }
+}
+
+final class $EmojiCompat_GlyphCheckerType
+ extends jni.JObjType<EmojiCompat_GlyphChecker> {
+ const $EmojiCompat_GlyphCheckerType();
+
+ @override
+ String get signature => r"Landroidx/emoji2/text/EmojiCompat$GlyphChecker;";
+
+ @override
+ EmojiCompat_GlyphChecker fromRef(jni.JObjectPtr ref) =>
+ EmojiCompat_GlyphChecker.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($EmojiCompat_GlyphCheckerType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($EmojiCompat_GlyphCheckerType) &&
+ other is $EmojiCompat_GlyphCheckerType;
+ }
+}
+
+/// from: androidx.emoji2.text.EmojiCompat$MetadataRepoLoader
+///
+/// Interface to load emoji metadata.
+class EmojiCompat_MetadataRepoLoader extends jni.JObject {
+ @override
+ late final jni.JObjType<EmojiCompat_MetadataRepoLoader> $type = type;
+
+ EmojiCompat_MetadataRepoLoader.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $EmojiCompat_MetadataRepoLoaderType();
+ static final _load = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat_MetadataRepoLoader__load")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract void load(androidx.emoji2.text.EmojiCompat.MetadataRepoLoaderCallback loaderCallback)
+ ///
+ /// Start loading the metadata. When the loading operation is finished MetadataRepoLoaderCallback\#onLoaded(MetadataRepo) or
+ /// MetadataRepoLoaderCallback\#onFailed(Throwable) should be called. When used on
+ /// devices running API 18 or below, this function is never called.
+ ///@param loaderCallback callback to signal the loading state
+ void load(
+ EmojiCompat_MetadataRepoLoaderCallback loaderCallback,
+ ) {
+ return _load(reference, loaderCallback.reference).check();
+ }
+}
+
+final class $EmojiCompat_MetadataRepoLoaderType
+ extends jni.JObjType<EmojiCompat_MetadataRepoLoader> {
+ const $EmojiCompat_MetadataRepoLoaderType();
+
+ @override
+ String get signature =>
+ r"Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoader;";
+
+ @override
+ EmojiCompat_MetadataRepoLoader fromRef(jni.JObjectPtr ref) =>
+ EmojiCompat_MetadataRepoLoader.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($EmojiCompat_MetadataRepoLoaderType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($EmojiCompat_MetadataRepoLoaderType) &&
+ other is $EmojiCompat_MetadataRepoLoaderType;
+ }
+}
+
+/// from: androidx.emoji2.text.EmojiCompat$InitCallback
+///
+/// Listener class for the initialization of the EmojiCompat.
+class EmojiCompat_InitCallback extends jni.JObject {
+ @override
+ late final jni.JObjType<EmojiCompat_InitCallback> $type = type;
+
+ EmojiCompat_InitCallback.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $EmojiCompat_InitCallbackType();
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "EmojiCompat_InitCallback__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory EmojiCompat_InitCallback() {
+ return EmojiCompat_InitCallback.fromRef(_new0().object);
+ }
+
+ static final _onInitialized = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat_InitCallback__onInitialized")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void onInitialized()
+ ///
+ /// Called when EmojiCompat is initialized and the emoji data is loaded. When used on devices
+ /// running API 18 or below, this function is always called.
+ void onInitialized() {
+ return _onInitialized(reference).check();
+ }
+
+ static final _onFailed = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("EmojiCompat_InitCallback__onFailed")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void onFailed(java.lang.Throwable throwable)
+ ///
+ /// Called when an unrecoverable error occurs during EmojiCompat initialization. When used on
+ /// devices running API 18 or below, this function is never called.
+ void onFailed(
+ jni.JObject throwable,
+ ) {
+ return _onFailed(reference, throwable.reference).check();
+ }
+}
+
+final class $EmojiCompat_InitCallbackType
+ extends jni.JObjType<EmojiCompat_InitCallback> {
+ const $EmojiCompat_InitCallbackType();
+
+ @override
+ String get signature => r"Landroidx/emoji2/text/EmojiCompat$InitCallback;";
+
+ @override
+ EmojiCompat_InitCallback fromRef(jni.JObjectPtr ref) =>
+ EmojiCompat_InitCallback.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($EmojiCompat_InitCallbackType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($EmojiCompat_InitCallbackType) &&
+ other is $EmojiCompat_InitCallbackType;
+ }
+}
+
+/// from: androidx.emoji2.text.EmojiCompat$DefaultSpanFactory
+///
+/// @hide
+class EmojiCompat_DefaultSpanFactory extends jni.JObject {
+ @override
+ late final jni.JObjType<EmojiCompat_DefaultSpanFactory> $type = type;
+
+ EmojiCompat_DefaultSpanFactory.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $EmojiCompat_DefaultSpanFactoryType();
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "EmojiCompat_DefaultSpanFactory__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory EmojiCompat_DefaultSpanFactory() {
+ return EmojiCompat_DefaultSpanFactory.fromRef(_new0().object);
+ }
+
+ static final _createSpan = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat_DefaultSpanFactory__createSpan")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public androidx.emoji2.text.EmojiSpan createSpan(androidx.emoji2.text.TypefaceEmojiRasterizer rasterizer)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Returns a TypefaceEmojiSpan.
+ ///@param rasterizer TypefaceEmojiRasterizer instance, which can draw the emoji onto a
+ /// Canvas.
+ ///@return TypefaceEmojiSpan
+ jni.JObject createSpan(
+ jni.JObject rasterizer,
+ ) {
+ return const jni.JObjectType()
+ .fromRef(_createSpan(reference, rasterizer.reference).object);
+ }
+}
+
+final class $EmojiCompat_DefaultSpanFactoryType
+ extends jni.JObjType<EmojiCompat_DefaultSpanFactory> {
+ const $EmojiCompat_DefaultSpanFactoryType();
+
+ @override
+ String get signature =>
+ r"Landroidx/emoji2/text/EmojiCompat$DefaultSpanFactory;";
+
+ @override
+ EmojiCompat_DefaultSpanFactory fromRef(jni.JObjectPtr ref) =>
+ EmojiCompat_DefaultSpanFactory.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($EmojiCompat_DefaultSpanFactoryType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($EmojiCompat_DefaultSpanFactoryType) &&
+ other is $EmojiCompat_DefaultSpanFactoryType;
+ }
+}
+
+/// from: androidx.emoji2.text.EmojiCompat$SpanFactory
+///
+/// Factory class that creates the EmojiSpans.
+///
+/// By default it creates TypefaceEmojiSpan.
+///
+/// Apps should use this only if they want to control the drawing of EmojiSpans for non-standard
+/// emoji display (for example, resizing or repositioning emoji).
+class EmojiCompat_SpanFactory extends jni.JObject {
+ @override
+ late final jni.JObjType<EmojiCompat_SpanFactory> $type = type;
+
+ EmojiCompat_SpanFactory.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $EmojiCompat_SpanFactoryType();
+ static final _createSpan = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "EmojiCompat_SpanFactory__createSpan")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract androidx.emoji2.text.EmojiSpan createSpan(androidx.emoji2.text.TypefaceEmojiRasterizer rasterizer)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Create EmojiSpan instance.
+ ///@param rasterizer TypefaceEmojiRasterizer instance, which can draw the emoji onto a
+ /// Canvas.
+ ///@return EmojiSpan instance that can use TypefaceEmojiRasterizer to draw emoji.
+ jni.JObject createSpan(
+ jni.JObject rasterizer,
+ ) {
+ return const jni.JObjectType()
+ .fromRef(_createSpan(reference, rasterizer.reference).object);
+ }
+}
+
+final class $EmojiCompat_SpanFactoryType
+ extends jni.JObjType<EmojiCompat_SpanFactory> {
+ const $EmojiCompat_SpanFactoryType();
+
+ @override
+ String get signature => r"Landroidx/emoji2/text/EmojiCompat$SpanFactory;";
+
+ @override
+ EmojiCompat_SpanFactory fromRef(jni.JObjectPtr ref) =>
+ EmojiCompat_SpanFactory.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($EmojiCompat_SpanFactoryType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($EmojiCompat_SpanFactoryType) &&
+ other is $EmojiCompat_SpanFactoryType;
+ }
+}
+
+/// from: androidx.emoji2.text.DefaultEmojiCompatConfig
+///
+/// The default config will use downloadable fonts to fetch the emoji compat font file.
+///
+/// It will automatically fetch the emoji compat font from a {@code ContentProvider} that is
+/// installed on the devices system image, if present.
+///
+///
+/// You should use this if you want the default emoji font from a system installed
+/// downloadable fonts provider. This is the recommended behavior for all applications unless
+/// they install a custom emoji font.
+///
+///
+/// You may need to specialize the configuration beyond this default config in some
+/// situations:
+///
+/// <ul>
+/// <li>If you are trying to install a custom emoji font through downloadable fonts use
+/// FontRequestEmojiCompatConfig instead of this method.</li>
+/// <li>If you're trying to bundle an emoji font with your APK use {@code
+/// BundledEmojiCompatConfig} in the {@code emoji2-bundled} artifact.</li>
+/// <li>If you are building an APK that will be installed on devices that won't have a
+/// downloadable fonts provider, use {@code BundledEmojiCompatConfig}.</li>
+/// </ul>
+///
+/// The downloadable font provider used by {@code DefaultEmojiCompatConfig} always satisfies
+/// the following contract:
+///
+/// <ol>
+/// <li>It <i>MUST</i> provide an intent filter for {@code androidx.content.action.LOAD_EMOJI_FONT}.
+/// </li>
+/// <li>It <i>MUST</i> respond to the query {@code emojicompat-emoji-font} with a valid emoji compat
+/// font file including metadata.</li>
+/// <li>It <i>MUST</i> provide fonts via the same contract as downloadable fonts.</li>
+/// <li>It <i>MUST</i> be installed in the system image.</li>
+/// </ol>
+class DefaultEmojiCompatConfig extends jni.JObject {
+ @override
+ late final jni.JObjType<DefaultEmojiCompatConfig> $type = type;
+
+ DefaultEmojiCompatConfig.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $DefaultEmojiCompatConfigType();
+ static final _create = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "DefaultEmojiCompatConfig__create")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public androidx.emoji2.text.FontRequestEmojiCompatConfig create(android.content.Context context)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Get the default emoji compat config for this device.
+ ///
+ /// You may further configure the returned config before passing it to EmojiCompat\#init.
+ ///
+ /// Each call to this method will return a new EmojiCompat.Config, so changes to the returned
+ /// object will not modify future return values.
+ ///@param context context for lookup
+ ///@return A valid config for downloading the emoji compat font, or null if no font provider
+ /// could be found.
+ static jni.JObject create(
+ jni.JObject context,
+ ) {
+ return const jni.JObjectType().fromRef(_create(context.reference).object);
+ }
+}
+
+final class $DefaultEmojiCompatConfigType
+ extends jni.JObjType<DefaultEmojiCompatConfig> {
+ const $DefaultEmojiCompatConfigType();
+
+ @override
+ String get signature => r"Landroidx/emoji2/text/DefaultEmojiCompatConfig;";
+
+ @override
+ DefaultEmojiCompatConfig fromRef(jni.JObjectPtr ref) =>
+ DefaultEmojiCompatConfig.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($DefaultEmojiCompatConfigType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($DefaultEmojiCompatConfigType) &&
+ other is $DefaultEmojiCompatConfigType;
+ }
+}
+
+/// from: androidx.emoji2.text.DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API28
+///
+/// Helper to lookup signatures in package manager > API 28
+///@hide
+class DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28
+ extends DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19 {
+ @override
+ late final jni
+ .JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28>
+ $type = type;
+
+ DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type =
+ $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28Type();
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28() {
+ return DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28
+ .fromRef(_new0().object);
+ }
+
+ static final _getSigningSignatures1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__getSigningSignatures1")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public android.content.pm.Signature[] getSigningSignatures(android.content.pm.PackageManager packageManager, java.lang.String providerPackage)
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JArray<jni.JObject> getSigningSignatures1(
+ jni.JObject packageManager,
+ jni.JString providerPackage,
+ ) {
+ return const jni.JArrayType(jni.JObjectType()).fromRef(
+ _getSigningSignatures1(
+ reference, packageManager.reference, providerPackage.reference)
+ .object);
+ }
+}
+
+final class $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28Type
+ extends jni
+ .JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28> {
+ const $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28Type();
+
+ @override
+ String get signature =>
+ r"Landroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API28;";
+
+ @override
+ DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28 fromRef(
+ jni.JObjectPtr ref) =>
+ DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28.fromRef(
+ ref);
+
+ @override
+ jni.JObjType get superType =>
+ const $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19Type();
+
+ @override
+ final superCount = 3;
+
+ @override
+ int get hashCode =>
+ ($DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28Type)
+ .hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType ==
+ ($DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28Type) &&
+ other
+ is $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28Type;
+ }
+}
+
+/// from: androidx.emoji2.text.DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API19
+///
+/// Actually do lookups > API 19
+///@hide
+class DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19
+ extends DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper {
+ @override
+ late final jni
+ .JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19>
+ $type = type;
+
+ DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type =
+ $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19Type();
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19() {
+ return DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19
+ .fromRef(_new0().object);
+ }
+
+ static final _queryIntentContentProviders = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32)>>(
+ "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__queryIntentContentProviders")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(android.content.pm.PackageManager packageManager, android.content.Intent intent, int flags)
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JList<jni.JObject> queryIntentContentProviders(
+ jni.JObject packageManager,
+ jni.JObject intent,
+ int flags,
+ ) {
+ return const jni.JListType(jni.JObjectType()).fromRef(
+ _queryIntentContentProviders(
+ reference, packageManager.reference, intent.reference, flags)
+ .object);
+ }
+
+ static final _getProviderInfo = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__getProviderInfo")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public android.content.pm.ProviderInfo getProviderInfo(android.content.pm.ResolveInfo resolveInfo)
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject getProviderInfo(
+ jni.JObject resolveInfo,
+ ) {
+ return const jni.JObjectType()
+ .fromRef(_getProviderInfo(reference, resolveInfo.reference).object);
+ }
+}
+
+final class $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19Type
+ extends jni
+ .JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19> {
+ const $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19Type();
+
+ @override
+ String get signature =>
+ r"Landroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API19;";
+
+ @override
+ DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19 fromRef(
+ jni.JObjectPtr ref) =>
+ DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19.fromRef(
+ ref);
+
+ @override
+ jni.JObjType get superType =>
+ const $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelperType();
+
+ @override
+ final superCount = 2;
+
+ @override
+ int get hashCode =>
+ ($DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19Type)
+ .hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType ==
+ ($DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19Type) &&
+ other
+ is $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19Type;
+ }
+}
+
+/// from: androidx.emoji2.text.DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper
+///
+/// Helper to lookup signatures in package manager.
+///@hide
+class DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper
+ extends jni.JObject {
+ @override
+ late final jni
+ .JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper> $type =
+ type;
+
+ DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type =
+ $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelperType();
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper() {
+ return DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper.fromRef(
+ _new0().object);
+ }
+
+ static final _getSigningSignatures = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getSigningSignatures")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public android.content.pm.Signature[] getSigningSignatures(android.content.pm.PackageManager packageManager, java.lang.String providerPackage)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Get the signing signatures for a package in package manager.
+ jni.JArray<jni.JObject> getSigningSignatures(
+ jni.JObject packageManager,
+ jni.JString providerPackage,
+ ) {
+ return const jni.JArrayType(jni.JObjectType()).fromRef(
+ _getSigningSignatures(
+ reference, packageManager.reference, providerPackage.reference)
+ .object);
+ }
+
+ static final _queryIntentContentProviders = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32)>>(
+ "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__queryIntentContentProviders")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(android.content.pm.PackageManager packageManager, android.content.Intent intent, int flags)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Get the content provider by intent.
+ jni.JList<jni.JObject> queryIntentContentProviders(
+ jni.JObject packageManager,
+ jni.JObject intent,
+ int flags,
+ ) {
+ return const jni.JListType(jni.JObjectType()).fromRef(
+ _queryIntentContentProviders(
+ reference, packageManager.reference, intent.reference, flags)
+ .object);
+ }
+
+ static final _getProviderInfo = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getProviderInfo")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public android.content.pm.ProviderInfo getProviderInfo(android.content.pm.ResolveInfo resolveInfo)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Get a ProviderInfo, if present, from a ResolveInfo
+ ///@param resolveInfo the subject
+ ///@return resolveInfo.providerInfo above API 19
+ jni.JObject getProviderInfo(
+ jni.JObject resolveInfo,
+ ) {
+ return const jni.JObjectType()
+ .fromRef(_getProviderInfo(reference, resolveInfo.reference).object);
+ }
+}
+
+final class $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelperType
+ extends jni
+ .JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper> {
+ const $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelperType();
+
+ @override
+ String get signature =>
+ r"Landroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper;";
+
+ @override
+ DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper fromRef(
+ jni.JObjectPtr ref) =>
+ DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode =>
+ ($DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelperType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType ==
+ ($DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelperType) &&
+ other is $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelperType;
+ }
+}
+
+/// from: androidx.emoji2.text.DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory
+///
+/// Actual factory for generating default emoji configs, does service locator lookup internally.
+///@see DefaultEmojiCompatConfig\#create
+///@hide
+class DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory
+ extends jni.JObject {
+ @override
+ late final jni
+ .JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory>
+ $type = type;
+
+ DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type =
+ $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactoryType();
+ static final _new0 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__new0")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(androidx.emoji2.text.DefaultEmojiCompatConfig.DefaultEmojiCompatConfigHelper helper)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// @hide
+ factory DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory(
+ DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper helper,
+ ) {
+ return DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory.fromRef(
+ _new0(helper.reference).object);
+ }
+
+ static final _create = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__create")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public androidx.emoji2.text.EmojiCompat.Config create(android.content.Context context)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// @see DefaultEmojiCompatConfig\#create
+ ///@hide
+ EmojiCompat_Config create(
+ jni.JObject context,
+ ) {
+ return const $EmojiCompat_ConfigType()
+ .fromRef(_create(reference, context.reference).object);
+ }
+}
+
+final class $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactoryType
+ extends jni
+ .JObjType<DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory> {
+ const $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactoryType();
+
+ @override
+ String get signature =>
+ r"Landroidx/emoji2/text/DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory;";
+
+ @override
+ DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory fromRef(
+ jni.JObjectPtr ref) =>
+ DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode =>
+ ($DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactoryType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType ==
+ ($DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactoryType) &&
+ other is $DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactoryType;
+ }
+}
+
+/// from: android.os.Build$Partition
+class Build_Partition extends jni.JObject {
+ @override
+ late final jni.JObjType<Build_Partition> $type = type;
+
+ Build_Partition.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $Build_PartitionType();
+
+ /// from: static public final java.lang.String PARTITION_NAME_SYSTEM
+ static const PARTITION_NAME_SYSTEM = r"""system""";
+
+ static final _getName = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Build_Partition__getName")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getName()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JString getName() {
+ return const jni.JStringType().fromRef(_getName(reference).object);
+ }
+
+ static final _getFingerprint = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Build_Partition__getFingerprint")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getFingerprint()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JString getFingerprint() {
+ return const jni.JStringType().fromRef(_getFingerprint(reference).object);
+ }
+
+ static final _getBuildTimeMillis = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Build_Partition__getBuildTimeMillis")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public long getBuildTimeMillis()
+ int getBuildTimeMillis() {
+ return _getBuildTimeMillis(reference).long;
+ }
+
+ static final _equals1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("Build_Partition__equals1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean equals(java.lang.Object object)
+ bool equals1(
+ jni.JObject object,
+ ) {
+ return _equals1(reference, object.reference).boolean;
+ }
+
+ static final _hashCode1 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Build_Partition__hashCode1")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int hashCode()
+ int hashCode1() {
+ return _hashCode1(reference).integer;
+ }
+}
+
+final class $Build_PartitionType extends jni.JObjType<Build_Partition> {
+ const $Build_PartitionType();
+
+ @override
+ String get signature => r"Landroid/os/Build$Partition;";
+
+ @override
+ Build_Partition fromRef(jni.JObjectPtr ref) => Build_Partition.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($Build_PartitionType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($Build_PartitionType) &&
+ other is $Build_PartitionType;
+ }
+}
+
+/// from: android.os.Build$VERSION
+class Build_VERSION extends jni.JObject {
+ @override
+ late final jni.JObjType<Build_VERSION> $type = type;
+
+ Build_VERSION.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $Build_VERSIONType();
+ static final _get_BASE_OS =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build_VERSION__BASE_OS")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String BASE_OS
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get BASE_OS =>
+ const jni.JStringType().fromRef(_get_BASE_OS().object);
+
+ static final _get_CODENAME =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build_VERSION__CODENAME")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String CODENAME
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get CODENAME =>
+ const jni.JStringType().fromRef(_get_CODENAME().object);
+
+ static final _get_INCREMENTAL =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build_VERSION__INCREMENTAL")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String INCREMENTAL
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get INCREMENTAL =>
+ const jni.JStringType().fromRef(_get_INCREMENTAL().object);
+
+ static final _get_MEDIA_PERFORMANCE_CLASS =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build_VERSION__MEDIA_PERFORMANCE_CLASS")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final int MEDIA_PERFORMANCE_CLASS
+ static int get MEDIA_PERFORMANCE_CLASS =>
+ _get_MEDIA_PERFORMANCE_CLASS().integer;
+
+ static final _get_PREVIEW_SDK_INT =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build_VERSION__PREVIEW_SDK_INT")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final int PREVIEW_SDK_INT
+ static int get PREVIEW_SDK_INT => _get_PREVIEW_SDK_INT().integer;
+
+ static final _get_RELEASE =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build_VERSION__RELEASE")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String RELEASE
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get RELEASE =>
+ const jni.JStringType().fromRef(_get_RELEASE().object);
+
+ static final _get_RELEASE_OR_CODENAME =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build_VERSION__RELEASE_OR_CODENAME")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String RELEASE_OR_CODENAME
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get RELEASE_OR_CODENAME =>
+ const jni.JStringType().fromRef(_get_RELEASE_OR_CODENAME().object);
+
+ static final _get_RELEASE_OR_PREVIEW_DISPLAY =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build_VERSION__RELEASE_OR_PREVIEW_DISPLAY")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String RELEASE_OR_PREVIEW_DISPLAY
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get RELEASE_OR_PREVIEW_DISPLAY =>
+ const jni.JStringType().fromRef(_get_RELEASE_OR_PREVIEW_DISPLAY().object);
+
+ static final _get_SDK =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build_VERSION__SDK")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String SDK
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get SDK =>
+ const jni.JStringType().fromRef(_get_SDK().object);
+
+ static final _get_SDK_INT =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build_VERSION__SDK_INT")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final int SDK_INT
+ static int get SDK_INT => _get_SDK_INT().integer;
+
+ static final _get_SECURITY_PATCH =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build_VERSION__SECURITY_PATCH")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String SECURITY_PATCH
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get SECURITY_PATCH =>
+ const jni.JStringType().fromRef(_get_SECURITY_PATCH().object);
+
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Build_VERSION__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Build_VERSION() {
+ return Build_VERSION.fromRef(_new0().object);
+ }
+}
+
+final class $Build_VERSIONType extends jni.JObjType<Build_VERSION> {
+ const $Build_VERSIONType();
+
+ @override
+ String get signature => r"Landroid/os/Build$VERSION;";
+
+ @override
+ Build_VERSION fromRef(jni.JObjectPtr ref) => Build_VERSION.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($Build_VERSIONType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($Build_VERSIONType) &&
+ other is $Build_VERSIONType;
+ }
+}
+
+/// from: android.os.Build$VERSION_CODES
+class Build_VERSION_CODES extends jni.JObject {
+ @override
+ late final jni.JObjType<Build_VERSION_CODES> $type = type;
+
+ Build_VERSION_CODES.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $Build_VERSION_CODESType();
+
+ /// from: static public final int BASE
+ static const BASE = 1;
+
+ /// from: static public final int BASE_1_1
+ static const BASE_1_1 = 2;
+
+ /// from: static public final int CUPCAKE
+ static const CUPCAKE = 3;
+
+ /// from: static public final int CUR_DEVELOPMENT
+ static const CUR_DEVELOPMENT = 10000;
+
+ /// from: static public final int DONUT
+ static const DONUT = 4;
+
+ /// from: static public final int ECLAIR
+ static const ECLAIR = 5;
+
+ /// from: static public final int ECLAIR_0_1
+ static const ECLAIR_0_1 = 6;
+
+ /// from: static public final int ECLAIR_MR1
+ static const ECLAIR_MR1 = 7;
+
+ /// from: static public final int FROYO
+ static const FROYO = 8;
+
+ /// from: static public final int GINGERBREAD
+ static const GINGERBREAD = 9;
+
+ /// from: static public final int GINGERBREAD_MR1
+ static const GINGERBREAD_MR1 = 10;
+
+ /// from: static public final int HONEYCOMB
+ static const HONEYCOMB = 11;
+
+ /// from: static public final int HONEYCOMB_MR1
+ static const HONEYCOMB_MR1 = 12;
+
+ /// from: static public final int HONEYCOMB_MR2
+ static const HONEYCOMB_MR2 = 13;
+
+ /// from: static public final int ICE_CREAM_SANDWICH
+ static const ICE_CREAM_SANDWICH = 14;
+
+ /// from: static public final int ICE_CREAM_SANDWICH_MR1
+ static const ICE_CREAM_SANDWICH_MR1 = 15;
+
+ /// from: static public final int JELLY_BEAN
+ static const JELLY_BEAN = 16;
+
+ /// from: static public final int JELLY_BEAN_MR1
+ static const JELLY_BEAN_MR1 = 17;
+
+ /// from: static public final int JELLY_BEAN_MR2
+ static const JELLY_BEAN_MR2 = 18;
+
+ /// from: static public final int KITKAT
+ static const KITKAT = 19;
+
+ /// from: static public final int KITKAT_WATCH
+ static const KITKAT_WATCH = 20;
+
+ /// from: static public final int LOLLIPOP
+ static const LOLLIPOP = 21;
+
+ /// from: static public final int LOLLIPOP_MR1
+ static const LOLLIPOP_MR1 = 22;
+
+ /// from: static public final int M
+ static const M = 23;
+
+ /// from: static public final int N
+ static const N = 24;
+
+ /// from: static public final int N_MR1
+ static const N_MR1 = 25;
+
+ /// from: static public final int O
+ static const O = 26;
+
+ /// from: static public final int O_MR1
+ static const O_MR1 = 27;
+
+ /// from: static public final int P
+ static const P = 28;
+
+ /// from: static public final int Q
+ static const Q = 29;
+
+ /// from: static public final int R
+ static const R = 30;
+
+ /// from: static public final int S
+ static const S = 31;
+
+ /// from: static public final int S_V2
+ static const S_V2 = 32;
+
+ /// from: static public final int TIRAMISU
+ static const TIRAMISU = 33;
+
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Build_VERSION_CODES__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Build_VERSION_CODES() {
+ return Build_VERSION_CODES.fromRef(_new0().object);
+ }
+}
+
+final class $Build_VERSION_CODESType extends jni.JObjType<Build_VERSION_CODES> {
+ const $Build_VERSION_CODESType();
+
+ @override
+ String get signature => r"Landroid/os/Build$VERSION_CODES;";
+
+ @override
+ Build_VERSION_CODES fromRef(jni.JObjectPtr ref) =>
+ Build_VERSION_CODES.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($Build_VERSION_CODESType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($Build_VERSION_CODESType) &&
+ other is $Build_VERSION_CODESType;
+ }
+}
+
+/// from: android.os.Build
+class Build extends jni.JObject {
+ @override
+ late final jni.JObjType<Build> $type = type;
+
+ Build.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $BuildType();
+ static final _get_BOARD =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__BOARD")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String BOARD
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get BOARD =>
+ const jni.JStringType().fromRef(_get_BOARD().object);
+
+ static final _get_BOOTLOADER =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__BOOTLOADER")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String BOOTLOADER
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get BOOTLOADER =>
+ const jni.JStringType().fromRef(_get_BOOTLOADER().object);
+
+ static final _get_BRAND =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__BRAND")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String BRAND
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get BRAND =>
+ const jni.JStringType().fromRef(_get_BRAND().object);
+
+ static final _get_CPU_ABI =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__CPU_ABI")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String CPU_ABI
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get CPU_ABI =>
+ const jni.JStringType().fromRef(_get_CPU_ABI().object);
+
+ static final _get_CPU_ABI2 =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__CPU_ABI2")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String CPU_ABI2
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get CPU_ABI2 =>
+ const jni.JStringType().fromRef(_get_CPU_ABI2().object);
+
+ static final _get_DEVICE =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__DEVICE")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String DEVICE
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get DEVICE =>
+ const jni.JStringType().fromRef(_get_DEVICE().object);
+
+ static final _get_DISPLAY =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__DISPLAY")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String DISPLAY
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get DISPLAY =>
+ const jni.JStringType().fromRef(_get_DISPLAY().object);
+
+ static final _get_FINGERPRINT =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__FINGERPRINT")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String FINGERPRINT
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get FINGERPRINT =>
+ const jni.JStringType().fromRef(_get_FINGERPRINT().object);
+
+ static final _get_HARDWARE =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__HARDWARE")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String HARDWARE
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get HARDWARE =>
+ const jni.JStringType().fromRef(_get_HARDWARE().object);
+
+ static final _get_HOST =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("get_Build__HOST")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String HOST
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get HOST =>
+ const jni.JStringType().fromRef(_get_HOST().object);
+
+ static final _get_ID =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("get_Build__ID")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String ID
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get ID =>
+ const jni.JStringType().fromRef(_get_ID().object);
+
+ static final _get_MANUFACTURER =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__MANUFACTURER")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String MANUFACTURER
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get MANUFACTURER =>
+ const jni.JStringType().fromRef(_get_MANUFACTURER().object);
+
+ static final _get_MODEL =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__MODEL")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String MODEL
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get MODEL =>
+ const jni.JStringType().fromRef(_get_MODEL().object);
+
+ static final _get_ODM_SKU =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__ODM_SKU")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String ODM_SKU
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get ODM_SKU =>
+ const jni.JStringType().fromRef(_get_ODM_SKU().object);
+
+ static final _get_PRODUCT =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__PRODUCT")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String PRODUCT
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get PRODUCT =>
+ const jni.JStringType().fromRef(_get_PRODUCT().object);
+
+ static final _get_RADIO =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__RADIO")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String RADIO
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get RADIO =>
+ const jni.JStringType().fromRef(_get_RADIO().object);
+
+ static final _get_SERIAL =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__SERIAL")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String SERIAL
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get SERIAL =>
+ const jni.JStringType().fromRef(_get_SERIAL().object);
+
+ static final _get_SKU =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("get_Build__SKU")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String SKU
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get SKU =>
+ const jni.JStringType().fromRef(_get_SKU().object);
+
+ static final _get_SOC_MANUFACTURER =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__SOC_MANUFACTURER")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String SOC_MANUFACTURER
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get SOC_MANUFACTURER =>
+ const jni.JStringType().fromRef(_get_SOC_MANUFACTURER().object);
+
+ static final _get_SOC_MODEL =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__SOC_MODEL")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String SOC_MODEL
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get SOC_MODEL =>
+ const jni.JStringType().fromRef(_get_SOC_MODEL().object);
+
+ static final _get_SUPPORTED_32_BIT_ABIS =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__SUPPORTED_32_BIT_ABIS")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String[] SUPPORTED_32_BIT_ABIS
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<jni.JString> get SUPPORTED_32_BIT_ABIS =>
+ const jni.JArrayType(jni.JStringType())
+ .fromRef(_get_SUPPORTED_32_BIT_ABIS().object);
+
+ static final _get_SUPPORTED_64_BIT_ABIS =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__SUPPORTED_64_BIT_ABIS")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String[] SUPPORTED_64_BIT_ABIS
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<jni.JString> get SUPPORTED_64_BIT_ABIS =>
+ const jni.JArrayType(jni.JStringType())
+ .fromRef(_get_SUPPORTED_64_BIT_ABIS().object);
+
+ static final _get_SUPPORTED_ABIS =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Build__SUPPORTED_ABIS")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String[] SUPPORTED_ABIS
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<jni.JString> get SUPPORTED_ABIS =>
+ const jni.JArrayType(jni.JStringType())
+ .fromRef(_get_SUPPORTED_ABIS().object);
+
+ static final _get_TAGS =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("get_Build__TAGS")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String TAGS
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get TAGS =>
+ const jni.JStringType().fromRef(_get_TAGS().object);
+
+ static final _get_TIME =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("get_Build__TIME")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final long TIME
+ static int get TIME => _get_TIME().long;
+
+ static final _get_TYPE =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("get_Build__TYPE")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String TYPE
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get TYPE =>
+ const jni.JStringType().fromRef(_get_TYPE().object);
+
+ /// from: static public final java.lang.String UNKNOWN
+ static const UNKNOWN = r"""unknown""";
+
+ static final _get_USER =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("get_Build__USER")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.lang.String USER
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get USER =>
+ const jni.JStringType().fromRef(_get_USER().object);
+
+ static final _new0 =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("Build__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Build() {
+ return Build.fromRef(_new0().object);
+ }
+
+ static final _getSerial =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Build__getSerial")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public java.lang.String getSerial()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString getSerial() {
+ return const jni.JStringType().fromRef(_getSerial().object);
+ }
+
+ static final _getFingerprintedPartitions =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Build__getFingerprintedPartitions")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public java.util.List getFingerprintedPartitions()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JList<Build_Partition> getFingerprintedPartitions() {
+ return const jni.JListType($Build_PartitionType())
+ .fromRef(_getFingerprintedPartitions().object);
+ }
+
+ static final _getRadioVersion =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Build__getRadioVersion")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public java.lang.String getRadioVersion()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString getRadioVersion() {
+ return const jni.JStringType().fromRef(_getRadioVersion().object);
+ }
+}
+
+final class $BuildType extends jni.JObjType<Build> {
+ const $BuildType();
+
+ @override
+ String get signature => r"Landroid/os/Build;";
+
+ @override
+ Build fromRef(jni.JObjectPtr ref) => Build.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($BuildType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($BuildType) && other is $BuildType;
+ }
+}
+
+/// from: java.util.HashMap
+class HashMap<$K extends jni.JObject, $V extends jni.JObject>
+ extends jni.JObject {
+ @override
+ late final jni.JObjType<HashMap<$K, $V>> $type = type(K, V);
+
+ final jni.JObjType<$K> K;
+ final jni.JObjType<$V> V;
+
+ HashMap.fromRef(
+ this.K,
+ this.V,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static $HashMapType<$K, $V>
+ type<$K extends jni.JObject, $V extends jni.JObject>(
+ jni.JObjType<$K> K,
+ jni.JObjType<$V> V,
+ ) {
+ return $HashMapType(
+ K,
+ V,
+ );
+ }
+
+ static final _new0 = jniLookup<
+ ffi.NativeFunction<jni.JniResult Function(ffi.Int32, ffi.Float)>>(
+ "HashMap__new0")
+ .asFunction<jni.JniResult Function(int, double)>();
+
+ /// from: public void <init>(int i, float f)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory HashMap(
+ int i,
+ double f, {
+ required jni.JObjType<$K> K,
+ required jni.JObjType<$V> V,
+ }) {
+ return HashMap.fromRef(K, V, _new0(i, f).object);
+ }
+
+ static final _new1 =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Int32)>>(
+ "HashMap__new1")
+ .asFunction<jni.JniResult Function(int)>();
+
+ /// from: public void <init>(int i)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory HashMap.new1(
+ int i, {
+ required jni.JObjType<$K> K,
+ required jni.JObjType<$V> V,
+ }) {
+ return HashMap.fromRef(K, V, _new1(i).object);
+ }
+
+ static final _new2 =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("HashMap__new2")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory HashMap.new2({
+ required jni.JObjType<$K> K,
+ required jni.JObjType<$V> V,
+ }) {
+ return HashMap.fromRef(K, V, _new2().object);
+ }
+
+ static final _new3 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("HashMap__new3")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(java.util.Map map)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory HashMap.new3(
+ jni.JMap<$K, $V> map, {
+ jni.JObjType<$K>? K,
+ jni.JObjType<$V>? V,
+ }) {
+ K ??= jni.lowestCommonSuperType([
+ (map.$type as jni.JMapType).K,
+ ]) as jni.JObjType<$K>;
+ V ??= jni.lowestCommonSuperType([
+ (map.$type as jni.JMapType).V,
+ ]) as jni.JObjType<$V>;
+ return HashMap.fromRef(K, V, _new3(map.reference).object);
+ }
+
+ static final _size = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("HashMap__size")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int size()
+ int size() {
+ return _size(reference).integer;
+ }
+
+ static final _isEmpty = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "HashMap__isEmpty")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean isEmpty()
+ bool isEmpty() {
+ return _isEmpty(reference).boolean;
+ }
+
+ static final _get0 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("HashMap__get0")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public V get(java.lang.Object object)
+ /// The returned object must be released after use, by calling the [release] method.
+ $V get0(
+ jni.JObject object,
+ ) {
+ return V.fromRef(_get0(reference, object.reference).object);
+ }
+
+ static final _containsKey = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("HashMap__containsKey")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean containsKey(java.lang.Object object)
+ bool containsKey(
+ jni.JObject object,
+ ) {
+ return _containsKey(reference, object.reference).boolean;
+ }
+
+ static final _put = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("HashMap__put")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public V put(K object, V object1)
+ /// The returned object must be released after use, by calling the [release] method.
+ $V put(
+ $K object,
+ $V object1,
+ ) {
+ return V
+ .fromRef(_put(reference, object.reference, object1.reference).object);
+ }
+
+ static final _putAll = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("HashMap__putAll")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void putAll(java.util.Map map)
+ void putAll(
+ jni.JMap<$K, $V> map,
+ ) {
+ return _putAll(reference, map.reference).check();
+ }
+
+ static final _remove = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("HashMap__remove")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public V remove(java.lang.Object object)
+ /// The returned object must be released after use, by calling the [release] method.
+ $V remove(
+ jni.JObject object,
+ ) {
+ return V.fromRef(_remove(reference, object.reference).object);
+ }
+
+ static final _clear = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("HashMap__clear")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void clear()
+ void clear() {
+ return _clear(reference).check();
+ }
+
+ static final _containsValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("HashMap__containsValue")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean containsValue(java.lang.Object object)
+ bool containsValue(
+ jni.JObject object,
+ ) {
+ return _containsValue(reference, object.reference).boolean;
+ }
+
+ static final _keySet = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("HashMap__keySet")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.util.Set keySet()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JSet<$K> keySet() {
+ return jni.JSetType(K).fromRef(_keySet(reference).object);
+ }
+
+ static final _values = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("HashMap__values")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.util.Collection values()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject values() {
+ return const jni.JObjectType().fromRef(_values(reference).object);
+ }
+
+ static final _entrySet = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "HashMap__entrySet")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.util.Set entrySet()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JSet<jni.JObject> entrySet() {
+ return const jni.JSetType(jni.JObjectType())
+ .fromRef(_entrySet(reference).object);
+ }
+
+ static final _getOrDefault = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("HashMap__getOrDefault")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public V getOrDefault(java.lang.Object object, V object1)
+ /// The returned object must be released after use, by calling the [release] method.
+ $V getOrDefault(
+ jni.JObject object,
+ $V object1,
+ ) {
+ return V.fromRef(
+ _getOrDefault(reference, object.reference, object1.reference).object);
+ }
+
+ static final _putIfAbsent = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("HashMap__putIfAbsent")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public V putIfAbsent(K object, V object1)
+ /// The returned object must be released after use, by calling the [release] method.
+ $V putIfAbsent(
+ $K object,
+ $V object1,
+ ) {
+ return V.fromRef(
+ _putIfAbsent(reference, object.reference, object1.reference).object);
+ }
+
+ static final _remove1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("HashMap__remove1")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean remove(java.lang.Object object, java.lang.Object object1)
+ bool remove1(
+ jni.JObject object,
+ jni.JObject object1,
+ ) {
+ return _remove1(reference, object.reference, object1.reference).boolean;
+ }
+
+ static final _replace = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("HashMap__replace")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean replace(K object, V object1, V object2)
+ bool replace(
+ $K object,
+ $V object1,
+ $V object2,
+ ) {
+ return _replace(
+ reference, object.reference, object1.reference, object2.reference)
+ .boolean;
+ }
+
+ static final _replace1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("HashMap__replace1")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public V replace(K object, V object1)
+ /// The returned object must be released after use, by calling the [release] method.
+ $V replace1(
+ $K object,
+ $V object1,
+ ) {
+ return V.fromRef(
+ _replace1(reference, object.reference, object1.reference).object);
+ }
+
+ static final _computeIfAbsent = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("HashMap__computeIfAbsent")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public V computeIfAbsent(K object, java.util.function.Function function)
+ /// The returned object must be released after use, by calling the [release] method.
+ $V computeIfAbsent(
+ $K object,
+ jni.JObject function,
+ ) {
+ return V.fromRef(
+ _computeIfAbsent(reference, object.reference, function.reference)
+ .object);
+ }
+
+ static final _computeIfPresent = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("HashMap__computeIfPresent")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public V computeIfPresent(K object, java.util.function.BiFunction biFunction)
+ /// The returned object must be released after use, by calling the [release] method.
+ $V computeIfPresent(
+ $K object,
+ jni.JObject biFunction,
+ ) {
+ return V.fromRef(
+ _computeIfPresent(reference, object.reference, biFunction.reference)
+ .object);
+ }
+
+ static final _compute = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("HashMap__compute")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public V compute(K object, java.util.function.BiFunction biFunction)
+ /// The returned object must be released after use, by calling the [release] method.
+ $V compute(
+ $K object,
+ jni.JObject biFunction,
+ ) {
+ return V.fromRef(
+ _compute(reference, object.reference, biFunction.reference).object);
+ }
+
+ static final _merge = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("HashMap__merge")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public V merge(K object, V object1, java.util.function.BiFunction biFunction)
+ /// The returned object must be released after use, by calling the [release] method.
+ $V merge(
+ $K object,
+ $V object1,
+ jni.JObject biFunction,
+ ) {
+ return V.fromRef(_merge(reference, object.reference, object1.reference,
+ biFunction.reference)
+ .object);
+ }
+
+ static final _forEach = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("HashMap__forEach")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void forEach(java.util.function.BiConsumer biConsumer)
+ void forEach(
+ jni.JObject biConsumer,
+ ) {
+ return _forEach(reference, biConsumer.reference).check();
+ }
+
+ static final _replaceAll = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("HashMap__replaceAll")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void replaceAll(java.util.function.BiFunction biFunction)
+ void replaceAll(
+ jni.JObject biFunction,
+ ) {
+ return _replaceAll(reference, biFunction.reference).check();
+ }
+
+ static final _clone = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("HashMap__clone")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.Object clone()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject clone() {
+ return const jni.JObjectType().fromRef(_clone(reference).object);
+ }
+}
+
+final class $HashMapType<$K extends jni.JObject, $V extends jni.JObject>
+ extends jni.JObjType<HashMap<$K, $V>> {
+ final jni.JObjType<$K> K;
+ final jni.JObjType<$V> V;
+
+ const $HashMapType(
+ this.K,
+ this.V,
+ );
+
+ @override
+ String get signature => r"Ljava/util/HashMap;";
+
+ @override
+ HashMap<$K, $V> fromRef(jni.JObjectPtr ref) => HashMap.fromRef(K, V, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($HashMapType, K, V);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($HashMapType<$K, $V>) &&
+ other is $HashMapType<$K, $V> &&
+ K == other.K &&
+ V == other.V;
+ }
+}
diff --git a/pkgs/jnigen/example/in_app_java/lib/main.dart b/pkgs/jnigen/example/in_app_java/lib/main.dart
new file mode 100644
index 0000000..2257581
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/lib/main.dart
@@ -0,0 +1,86 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:flutter/material.dart';
+import 'package:jni/jni.dart';
+
+// The hierarchy created in generated code will mirror the java package
+// structure.
+import 'android_utils.dart';
+
+JObject activity = JObject.fromRef(Jni.getCurrentActivity());
+JObject context = JObject.fromRef(Jni.getCachedApplicationContext());
+
+final hashmap = HashMap.new2(K: JString.type, V: JString.type);
+
+final emojiCompat = EmojiCompat.get0();
+
+extension IntX on int {
+ JString toJString() {
+ return toString().toJString();
+ }
+}
+
+const sunglassEmoji = "😎";
+
+/// Display device model number and the number of times this was called
+/// as Toast.
+void showToast() {
+ final toastCount =
+ hashmap.getOrDefault("toastCount".toJString(), 0.toJString());
+ final newToastCount = (int.parse(toastCount.toDartString()) + 1).toJString();
+ hashmap.put("toastCount".toJString(), newToastCount);
+ final emoji = emojiCompat.hasEmojiGlyph(sunglassEmoji.toJString())
+ ? sunglassEmoji
+ : ':cool:';
+ final message =
+ '${newToastCount.toDartString()} - ${Build.MODEL.toDartString()} $emoji';
+ AndroidUtils.showToast(activity, message.toJString(), 0);
+}
+
+void main() {
+ EmojiCompat.init(context);
+ runApp(const MyApp());
+}
+
+class MyApp extends StatelessWidget {
+ const MyApp({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ title: 'Flutter Demo',
+ theme: ThemeData(
+ primarySwatch: Colors.teal,
+ ),
+ home: const MyHomePage(title: 'Flutter Demo Home Page'),
+ );
+ }
+}
+
+class MyHomePage extends StatelessWidget {
+ const MyHomePage({Key? key, required this.title}) : super(key: key);
+
+ final String title;
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text(title),
+ ),
+ body: Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ ElevatedButton(
+ child: const Text('Show Device Model'),
+ onPressed: () => showToast(),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/pkgs/jnigen/example/in_app_java/pubspec.yaml b/pkgs/jnigen/example/in_app_java/pubspec.yaml
new file mode 100644
index 0000000..321cc99
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/pubspec.yaml
@@ -0,0 +1,67 @@
+name: in_app_java
+description: |
+ Example on how to use jnigen to bridge between java and dart in a flutter
+ project.
+
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+version: 1.0.0+1
+
+environment:
+ sdk: '>=3.1.0 <4.0.0'
+
+dependencies:
+ flutter:
+ sdk: flutter
+ jni:
+ path: ../../../jni/
+
+ # The following adds the Cupertino Icons font to your application.
+ # Use with the CupertinoIcons class for iOS style icons.
+ cupertino_icons: ^1.0.2
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+ jnigen:
+ path: ../../
+
+ flutter_lints: ^2.0.0
+
+flutter:
+
+ # The following line ensures that the Material Icons font is
+ # included with your application, so that you can use the icons in
+ # the material Icons class.
+ uses-material-design: true
+
+ # To add assets to your application, add an assets section, like this:
+ # assets:
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
+
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/assets-and-images/#resolution-aware
+
+ # For details regarding adding assets from package dependencies, see
+ # https://flutter.dev/assets-and-images/#from-packages
+
+ # To add custom fonts to your application, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts from package dependencies,
+ # see https://flutter.dev/custom-fonts/#from-packages
diff --git a/pkgs/jnigen/example/in_app_java/src/android_utils/.clang-format b/pkgs/jnigen/example/in_app_java/src/android_utils/.clang-format
new file mode 100644
index 0000000..a256c2f
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/src/android_utils/.clang-format
@@ -0,0 +1,15 @@
+# From dart SDK: https://github.com/dart-lang/sdk/blob/main/.clang-format
+
+# Defines the Chromium style for automatic reformatting.
+# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
+BasedOnStyle: Chromium
+
+# clang-format doesn't seem to do a good job of this for longer comments.
+ReflowComments: 'false'
+
+# We have lots of these. Though we need to put them all in curly braces,
+# clang-format can't do that.
+AllowShortIfStatementsOnASingleLine: 'true'
+
+# Put escaped newlines into the rightmost column.
+AlignEscapedNewlinesLeft: false
diff --git a/pkgs/jnigen/example/in_app_java/src/android_utils/CMakeLists.txt b/pkgs/jnigen/example/in_app_java/src/android_utils/CMakeLists.txt
new file mode 100644
index 0000000..0c47c28
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/src/android_utils/CMakeLists.txt
@@ -0,0 +1,32 @@
+# jni_native_build (Build with jni:setup. Do not delete this line.)
+
+# 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)
+
+project(android_utils VERSION 0.0.1 LANGUAGES C)
+
+add_library(android_utils SHARED
+ "./android_utils.c"
+)
+
+set_target_properties(android_utils PROPERTIES
+ OUTPUT_NAME "android_utils"
+)
+
+target_compile_definitions(android_utils PUBLIC DART_SHARED_LIB)
+
+if(WIN32)
+ set_target_properties(${TARGET_NAME} PROPERTIES
+ LINK_FLAGS "/DELAYLOAD:jvm.dll")
+endif()
+
+if (ANDROID)
+ target_link_libraries(android_utils log)
+else()
+ find_package(Java REQUIRED)
+ find_package(JNI REQUIRED)
+ include_directories(${JNI_INCLUDE_DIRS})
+ target_link_libraries(android_utils ${JNI_LIBRARIES})
+endif()
diff --git a/pkgs/jnigen/example/in_app_java/src/android_utils/android_utils.c b/pkgs/jnigen/example/in_app_java/src/android_utils/android_utils.c
new file mode 100644
index 0000000..983838b
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/src/android_utils/android_utils.c
@@ -0,0 +1,2513 @@
+// Autogenerated by jnigen. DO NOT EDIT!
+
+#include <stdint.h>
+#include "dartjni.h"
+#include "jni.h"
+
+thread_local JNIEnv* jniEnv;
+JniContext* jni;
+
+JniContext* (*context_getter)(void);
+JNIEnv* (*env_getter)(void);
+
+void setJniGetters(JniContext* (*cg)(void), JNIEnv* (*eg)(void)) {
+ context_getter = cg;
+ env_getter = eg;
+}
+
+// com.example.in_app_java.AndroidUtils
+jclass _c_AndroidUtils = NULL;
+
+jmethodID _m_AndroidUtils__showToast = NULL;
+FFI_PLUGIN_EXPORT
+JniResult AndroidUtils__showToast(jobject mainActivity,
+ jobject text,
+ int32_t duration) {
+ load_env();
+ load_class_global_ref(&_c_AndroidUtils,
+ "com/example/in_app_java/AndroidUtils");
+ if (_c_AndroidUtils == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_AndroidUtils, &_m_AndroidUtils__showToast, "showToast",
+ "(Landroid/app/Activity;Ljava/lang/CharSequence;I)V");
+ if (_m_AndroidUtils__showToast == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallStaticVoidMethod(jniEnv, _c_AndroidUtils,
+ _m_AndroidUtils__showToast, mainActivity,
+ text, duration);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// androidx.emoji2.text.EmojiCompat
+jclass _c_EmojiCompat = NULL;
+
+jmethodID _m_EmojiCompat__init = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__init(jobject context) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_EmojiCompat, &_m_EmojiCompat__init, "init",
+ "(Landroid/content/Context;)Landroidx/emoji2/text/EmojiCompat;");
+ if (_m_EmojiCompat__init == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_EmojiCompat, _m_EmojiCompat__init, context);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat__init1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__init1(jobject context, jobject defaultFactory) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_EmojiCompat, &_m_EmojiCompat__init1, "init",
+ "(Landroid/content/Context;Landroidx/emoji2/text/"
+ "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory;"
+ ")Landroidx/emoji2/text/EmojiCompat;");
+ if (_m_EmojiCompat__init1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_EmojiCompat, _m_EmojiCompat__init1, context, defaultFactory);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat__init2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__init2(jobject config) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_EmojiCompat, &_m_EmojiCompat__init2, "init",
+ "(Landroidx/emoji2/text/EmojiCompat$Config;)Landroidx/"
+ "emoji2/text/EmojiCompat;");
+ if (_m_EmojiCompat__init2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_EmojiCompat, _m_EmojiCompat__init2, config);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat__isConfigured = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__isConfigured() {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_EmojiCompat, &_m_EmojiCompat__isConfigured,
+ "isConfigured", "()Z");
+ if (_m_EmojiCompat__isConfigured == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallStaticBooleanMethod(
+ jniEnv, _c_EmojiCompat, _m_EmojiCompat__isConfigured);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_EmojiCompat__reset = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__reset(jobject config) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_EmojiCompat, &_m_EmojiCompat__reset, "reset",
+ "(Landroidx/emoji2/text/EmojiCompat$Config;)Landroidx/"
+ "emoji2/text/EmojiCompat;");
+ if (_m_EmojiCompat__reset == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_EmojiCompat, _m_EmojiCompat__reset, config);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat__reset1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__reset1(jobject emojiCompat) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_EmojiCompat, &_m_EmojiCompat__reset1, "reset",
+ "(Landroidx/emoji2/text/EmojiCompat;)Landroidx/emoji2/text/EmojiCompat;");
+ if (_m_EmojiCompat__reset1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_EmojiCompat, _m_EmojiCompat__reset1, emojiCompat);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat__skipDefaultConfigurationLookup = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__skipDefaultConfigurationLookup(uint8_t shouldSkip) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_EmojiCompat,
+ &_m_EmojiCompat__skipDefaultConfigurationLookup,
+ "skipDefaultConfigurationLookup", "(Z)V");
+ if (_m_EmojiCompat__skipDefaultConfigurationLookup == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallStaticVoidMethod(
+ jniEnv, _c_EmojiCompat, _m_EmojiCompat__skipDefaultConfigurationLookup,
+ shouldSkip);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_EmojiCompat__get0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__get0() {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_EmojiCompat, &_m_EmojiCompat__get0, "get",
+ "()Landroidx/emoji2/text/EmojiCompat;");
+ if (_m_EmojiCompat__get0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_EmojiCompat,
+ _m_EmojiCompat__get0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat__load = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__load(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat, &_m_EmojiCompat__load, "load", "()V");
+ if (_m_EmojiCompat__load == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_EmojiCompat__load);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_EmojiCompat__registerInitCallback = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__registerInitCallback(jobject self_,
+ jobject initCallback) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat, &_m_EmojiCompat__registerInitCallback,
+ "registerInitCallback",
+ "(Landroidx/emoji2/text/EmojiCompat$InitCallback;)V");
+ if (_m_EmojiCompat__registerInitCallback == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_EmojiCompat__registerInitCallback,
+ initCallback);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_EmojiCompat__unregisterInitCallback = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__unregisterInitCallback(jobject self_,
+ jobject initCallback) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat, &_m_EmojiCompat__unregisterInitCallback,
+ "unregisterInitCallback",
+ "(Landroidx/emoji2/text/EmojiCompat$InitCallback;)V");
+ if (_m_EmojiCompat__unregisterInitCallback == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(
+ jniEnv, self_, _m_EmojiCompat__unregisterInitCallback, initCallback);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_EmojiCompat__getLoadState = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__getLoadState(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat, &_m_EmojiCompat__getLoadState, "getLoadState",
+ "()I");
+ if (_m_EmojiCompat__getLoadState == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_EmojiCompat__getLoadState);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_EmojiCompat__isEmojiSpanIndicatorEnabled = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__isEmojiSpanIndicatorEnabled(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat, &_m_EmojiCompat__isEmojiSpanIndicatorEnabled,
+ "isEmojiSpanIndicatorEnabled", "()Z");
+ if (_m_EmojiCompat__isEmojiSpanIndicatorEnabled == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_EmojiCompat__isEmojiSpanIndicatorEnabled);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_EmojiCompat__getEmojiSpanIndicatorColor = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__getEmojiSpanIndicatorColor(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat, &_m_EmojiCompat__getEmojiSpanIndicatorColor,
+ "getEmojiSpanIndicatorColor", "()I");
+ if (_m_EmojiCompat__getEmojiSpanIndicatorColor == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(
+ jniEnv, self_, _m_EmojiCompat__getEmojiSpanIndicatorColor);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_EmojiCompat__getEmojiStart = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__getEmojiStart(jobject self_,
+ jobject charSequence,
+ int32_t offset) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat, &_m_EmojiCompat__getEmojiStart, "getEmojiStart",
+ "(Ljava/lang/CharSequence;I)I");
+ if (_m_EmojiCompat__getEmojiStart == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(
+ jniEnv, self_, _m_EmojiCompat__getEmojiStart, charSequence, offset);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_EmojiCompat__getEmojiEnd = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__getEmojiEnd(jobject self_,
+ jobject charSequence,
+ int32_t offset) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat, &_m_EmojiCompat__getEmojiEnd, "getEmojiEnd",
+ "(Ljava/lang/CharSequence;I)I");
+ if (_m_EmojiCompat__getEmojiEnd == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(
+ jniEnv, self_, _m_EmojiCompat__getEmojiEnd, charSequence, offset);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_EmojiCompat__handleOnKeyDown = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__handleOnKeyDown(jobject editable,
+ int32_t keyCode,
+ jobject event) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_EmojiCompat, &_m_EmojiCompat__handleOnKeyDown,
+ "handleOnKeyDown",
+ "(Landroid/text/Editable;ILandroid/view/KeyEvent;)Z");
+ if (_m_EmojiCompat__handleOnKeyDown == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallStaticBooleanMethod(
+ jniEnv, _c_EmojiCompat, _m_EmojiCompat__handleOnKeyDown, editable,
+ keyCode, event);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_EmojiCompat__handleDeleteSurroundingText = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__handleDeleteSurroundingText(jobject inputConnection,
+ jobject editable,
+ int32_t beforeLength,
+ int32_t afterLength,
+ uint8_t inCodePoints) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_EmojiCompat,
+ &_m_EmojiCompat__handleDeleteSurroundingText,
+ "handleDeleteSurroundingText",
+ "(Landroid/view/inputmethod/InputConnection;Landroid/text/"
+ "Editable;IIZ)Z");
+ if (_m_EmojiCompat__handleDeleteSurroundingText == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallStaticBooleanMethod(
+ jniEnv, _c_EmojiCompat, _m_EmojiCompat__handleDeleteSurroundingText,
+ inputConnection, editable, beforeLength, afterLength, inCodePoints);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_EmojiCompat__hasEmojiGlyph = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__hasEmojiGlyph(jobject self_, jobject sequence) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat, &_m_EmojiCompat__hasEmojiGlyph, "hasEmojiGlyph",
+ "(Ljava/lang/CharSequence;)Z");
+ if (_m_EmojiCompat__hasEmojiGlyph == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_EmojiCompat__hasEmojiGlyph, sequence);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_EmojiCompat__hasEmojiGlyph1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__hasEmojiGlyph1(jobject self_,
+ jobject sequence,
+ int32_t metadataVersion) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat, &_m_EmojiCompat__hasEmojiGlyph1, "hasEmojiGlyph",
+ "(Ljava/lang/CharSequence;I)Z");
+ if (_m_EmojiCompat__hasEmojiGlyph1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_EmojiCompat__hasEmojiGlyph1, sequence, metadataVersion);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_EmojiCompat__getEmojiMatch = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__getEmojiMatch(jobject self_,
+ jobject sequence,
+ int32_t metadataVersion) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat, &_m_EmojiCompat__getEmojiMatch, "getEmojiMatch",
+ "(Ljava/lang/CharSequence;I)I");
+ if (_m_EmojiCompat__getEmojiMatch == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(
+ jniEnv, self_, _m_EmojiCompat__getEmojiMatch, sequence, metadataVersion);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_EmojiCompat__process = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__process(jobject self_, jobject charSequence) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat, &_m_EmojiCompat__process, "process",
+ "(Ljava/lang/CharSequence;)Ljava/lang/CharSequence;");
+ if (_m_EmojiCompat__process == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_EmojiCompat__process, charSequence);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat__process1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__process1(jobject self_,
+ jobject charSequence,
+ int32_t start,
+ int32_t end) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat, &_m_EmojiCompat__process1, "process",
+ "(Ljava/lang/CharSequence;II)Ljava/lang/CharSequence;");
+ if (_m_EmojiCompat__process1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_EmojiCompat__process1, charSequence, start, end);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat__process2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__process2(jobject self_,
+ jobject charSequence,
+ int32_t start,
+ int32_t end,
+ int32_t maxEmojiCount) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat, &_m_EmojiCompat__process2, "process",
+ "(Ljava/lang/CharSequence;III)Ljava/lang/CharSequence;");
+ if (_m_EmojiCompat__process2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_EmojiCompat__process2,
+ charSequence, start, end, maxEmojiCount);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat__process3 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__process3(jobject self_,
+ jobject charSequence,
+ int32_t start,
+ int32_t end,
+ int32_t maxEmojiCount,
+ int32_t replaceStrategy) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat, &_m_EmojiCompat__process3, "process",
+ "(Ljava/lang/CharSequence;IIII)Ljava/lang/CharSequence;");
+ if (_m_EmojiCompat__process3 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_EmojiCompat__process3, charSequence, start, end,
+ maxEmojiCount, replaceStrategy);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat__getAssetSignature = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__getAssetSignature(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat, &_m_EmojiCompat__getAssetSignature,
+ "getAssetSignature", "()Ljava/lang/String;");
+ if (_m_EmojiCompat__getAssetSignature == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_EmojiCompat__getAssetSignature);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat__updateEditorInfo = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat__updateEditorInfo(jobject self_, jobject outAttrs) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat, "androidx/emoji2/text/EmojiCompat");
+ if (_c_EmojiCompat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat, &_m_EmojiCompat__updateEditorInfo,
+ "updateEditorInfo", "(Landroid/view/inputmethod/EditorInfo;)V");
+ if (_m_EmojiCompat__updateEditorInfo == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_EmojiCompat__updateEditorInfo,
+ outAttrs);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// androidx.emoji2.text.EmojiCompat$Config
+jclass _c_EmojiCompat_Config = NULL;
+
+jmethodID _m_EmojiCompat_Config__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_Config__new0(jobject metadataLoader) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_Config,
+ "androidx/emoji2/text/EmojiCompat$Config");
+ if (_c_EmojiCompat_Config == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_Config, &_m_EmojiCompat_Config__new0, "<init>",
+ "(Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoader;)V");
+ if (_m_EmojiCompat_Config__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_EmojiCompat_Config,
+ _m_EmojiCompat_Config__new0, metadataLoader);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat_Config__registerInitCallback = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_Config__registerInitCallback(jobject self_,
+ jobject initCallback) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_Config,
+ "androidx/emoji2/text/EmojiCompat$Config");
+ if (_c_EmojiCompat_Config == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_Config,
+ &_m_EmojiCompat_Config__registerInitCallback,
+ "registerInitCallback",
+ "(Landroidx/emoji2/text/EmojiCompat$InitCallback;)Landroidx/"
+ "emoji2/text/EmojiCompat$Config;");
+ if (_m_EmojiCompat_Config__registerInitCallback == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_EmojiCompat_Config__registerInitCallback, initCallback);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat_Config__unregisterInitCallback = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_Config__unregisterInitCallback(jobject self_,
+ jobject initCallback) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_Config,
+ "androidx/emoji2/text/EmojiCompat$Config");
+ if (_c_EmojiCompat_Config == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_Config,
+ &_m_EmojiCompat_Config__unregisterInitCallback,
+ "unregisterInitCallback",
+ "(Landroidx/emoji2/text/EmojiCompat$InitCallback;)Landroidx/"
+ "emoji2/text/EmojiCompat$Config;");
+ if (_m_EmojiCompat_Config__unregisterInitCallback == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_EmojiCompat_Config__unregisterInitCallback,
+ initCallback);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat_Config__setReplaceAll = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_Config__setReplaceAll(jobject self_, uint8_t replaceAll) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_Config,
+ "androidx/emoji2/text/EmojiCompat$Config");
+ if (_c_EmojiCompat_Config == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_Config, &_m_EmojiCompat_Config__setReplaceAll,
+ "setReplaceAll", "(Z)Landroidx/emoji2/text/EmojiCompat$Config;");
+ if (_m_EmojiCompat_Config__setReplaceAll == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_EmojiCompat_Config__setReplaceAll, replaceAll);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat_Config__setUseEmojiAsDefaultStyle = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_Config__setUseEmojiAsDefaultStyle(
+ jobject self_,
+ uint8_t useEmojiAsDefaultStyle) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_Config,
+ "androidx/emoji2/text/EmojiCompat$Config");
+ if (_c_EmojiCompat_Config == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_Config,
+ &_m_EmojiCompat_Config__setUseEmojiAsDefaultStyle,
+ "setUseEmojiAsDefaultStyle",
+ "(Z)Landroidx/emoji2/text/EmojiCompat$Config;");
+ if (_m_EmojiCompat_Config__setUseEmojiAsDefaultStyle == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_EmojiCompat_Config__setUseEmojiAsDefaultStyle,
+ useEmojiAsDefaultStyle);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat_Config__setUseEmojiAsDefaultStyle1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_Config__setUseEmojiAsDefaultStyle1(
+ jobject self_,
+ uint8_t useEmojiAsDefaultStyle,
+ jobject emojiAsDefaultStyleExceptions) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_Config,
+ "androidx/emoji2/text/EmojiCompat$Config");
+ if (_c_EmojiCompat_Config == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_Config,
+ &_m_EmojiCompat_Config__setUseEmojiAsDefaultStyle1,
+ "setUseEmojiAsDefaultStyle",
+ "(ZLjava/util/List;)Landroidx/emoji2/text/EmojiCompat$Config;");
+ if (_m_EmojiCompat_Config__setUseEmojiAsDefaultStyle1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_EmojiCompat_Config__setUseEmojiAsDefaultStyle1,
+ useEmojiAsDefaultStyle, emojiAsDefaultStyleExceptions);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat_Config__setEmojiSpanIndicatorEnabled = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_Config__setEmojiSpanIndicatorEnabled(
+ jobject self_,
+ uint8_t emojiSpanIndicatorEnabled) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_Config,
+ "androidx/emoji2/text/EmojiCompat$Config");
+ if (_c_EmojiCompat_Config == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_Config,
+ &_m_EmojiCompat_Config__setEmojiSpanIndicatorEnabled,
+ "setEmojiSpanIndicatorEnabled",
+ "(Z)Landroidx/emoji2/text/EmojiCompat$Config;");
+ if (_m_EmojiCompat_Config__setEmojiSpanIndicatorEnabled == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_EmojiCompat_Config__setEmojiSpanIndicatorEnabled,
+ emojiSpanIndicatorEnabled);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat_Config__setEmojiSpanIndicatorColor = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_Config__setEmojiSpanIndicatorColor(jobject self_,
+ int32_t color) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_Config,
+ "androidx/emoji2/text/EmojiCompat$Config");
+ if (_c_EmojiCompat_Config == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_Config,
+ &_m_EmojiCompat_Config__setEmojiSpanIndicatorColor,
+ "setEmojiSpanIndicatorColor",
+ "(I)Landroidx/emoji2/text/EmojiCompat$Config;");
+ if (_m_EmojiCompat_Config__setEmojiSpanIndicatorColor == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_EmojiCompat_Config__setEmojiSpanIndicatorColor, color);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat_Config__setMetadataLoadStrategy = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_Config__setMetadataLoadStrategy(jobject self_,
+ int32_t strategy) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_Config,
+ "androidx/emoji2/text/EmojiCompat$Config");
+ if (_c_EmojiCompat_Config == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_Config,
+ &_m_EmojiCompat_Config__setMetadataLoadStrategy,
+ "setMetadataLoadStrategy",
+ "(I)Landroidx/emoji2/text/EmojiCompat$Config;");
+ if (_m_EmojiCompat_Config__setMetadataLoadStrategy == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_EmojiCompat_Config__setMetadataLoadStrategy, strategy);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat_Config__setSpanFactory = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_Config__setSpanFactory(jobject self_, jobject factory) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_Config,
+ "androidx/emoji2/text/EmojiCompat$Config");
+ if (_c_EmojiCompat_Config == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_Config, &_m_EmojiCompat_Config__setSpanFactory,
+ "setSpanFactory",
+ "(Landroidx/emoji2/text/EmojiCompat$SpanFactory;)Landroidx/"
+ "emoji2/text/EmojiCompat$Config;");
+ if (_m_EmojiCompat_Config__setSpanFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_EmojiCompat_Config__setSpanFactory, factory);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat_Config__setGlyphChecker = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_Config__setGlyphChecker(jobject self_,
+ jobject glyphChecker) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_Config,
+ "androidx/emoji2/text/EmojiCompat$Config");
+ if (_c_EmojiCompat_Config == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_Config, &_m_EmojiCompat_Config__setGlyphChecker,
+ "setGlyphChecker",
+ "(Landroidx/emoji2/text/EmojiCompat$GlyphChecker;)Landroidx/"
+ "emoji2/text/EmojiCompat$Config;");
+ if (_m_EmojiCompat_Config__setGlyphChecker == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_EmojiCompat_Config__setGlyphChecker, glyphChecker);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat_Config__getMetadataRepoLoader = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_Config__getMetadataRepoLoader(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_Config,
+ "androidx/emoji2/text/EmojiCompat$Config");
+ if (_c_EmojiCompat_Config == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_Config,
+ &_m_EmojiCompat_Config__getMetadataRepoLoader,
+ "getMetadataRepoLoader",
+ "()Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoader;");
+ if (_m_EmojiCompat_Config__getMetadataRepoLoader == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_EmojiCompat_Config__getMetadataRepoLoader);
+ return to_global_ref_result(_result);
+}
+
+// androidx.emoji2.text.EmojiCompat$MetadataRepoLoaderCallback
+jclass _c_EmojiCompat_MetadataRepoLoaderCallback = NULL;
+
+jmethodID _m_EmojiCompat_MetadataRepoLoaderCallback__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_MetadataRepoLoaderCallback__new0() {
+ load_env();
+ load_class_global_ref(
+ &_c_EmojiCompat_MetadataRepoLoaderCallback,
+ "androidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback");
+ if (_c_EmojiCompat_MetadataRepoLoaderCallback == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_MetadataRepoLoaderCallback,
+ &_m_EmojiCompat_MetadataRepoLoaderCallback__new0, "<init>",
+ "()V");
+ if (_m_EmojiCompat_MetadataRepoLoaderCallback__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_EmojiCompat_MetadataRepoLoaderCallback,
+ _m_EmojiCompat_MetadataRepoLoaderCallback__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat_MetadataRepoLoaderCallback__onLoaded = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_MetadataRepoLoaderCallback__onLoaded(
+ jobject self_,
+ jobject metadataRepo) {
+ load_env();
+ load_class_global_ref(
+ &_c_EmojiCompat_MetadataRepoLoaderCallback,
+ "androidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback");
+ if (_c_EmojiCompat_MetadataRepoLoaderCallback == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_MetadataRepoLoaderCallback,
+ &_m_EmojiCompat_MetadataRepoLoaderCallback__onLoaded, "onLoaded",
+ "(Landroidx/emoji2/text/MetadataRepo;)V");
+ if (_m_EmojiCompat_MetadataRepoLoaderCallback__onLoaded == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_EmojiCompat_MetadataRepoLoaderCallback__onLoaded,
+ metadataRepo);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_EmojiCompat_MetadataRepoLoaderCallback__onFailed = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_MetadataRepoLoaderCallback__onFailed(jobject self_,
+ jobject throwable) {
+ load_env();
+ load_class_global_ref(
+ &_c_EmojiCompat_MetadataRepoLoaderCallback,
+ "androidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback");
+ if (_c_EmojiCompat_MetadataRepoLoaderCallback == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_MetadataRepoLoaderCallback,
+ &_m_EmojiCompat_MetadataRepoLoaderCallback__onFailed, "onFailed",
+ "(Ljava/lang/Throwable;)V");
+ if (_m_EmojiCompat_MetadataRepoLoaderCallback__onFailed == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_EmojiCompat_MetadataRepoLoaderCallback__onFailed,
+ throwable);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// androidx.emoji2.text.EmojiCompat$GlyphChecker
+jclass _c_EmojiCompat_GlyphChecker = NULL;
+
+jmethodID _m_EmojiCompat_GlyphChecker__hasGlyph = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_GlyphChecker__hasGlyph(jobject self_,
+ jobject charSequence,
+ int32_t start,
+ int32_t end,
+ int32_t sdkAdded) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_GlyphChecker,
+ "androidx/emoji2/text/EmojiCompat$GlyphChecker");
+ if (_c_EmojiCompat_GlyphChecker == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_GlyphChecker,
+ &_m_EmojiCompat_GlyphChecker__hasGlyph, "hasGlyph",
+ "(Ljava/lang/CharSequence;III)Z");
+ if (_m_EmojiCompat_GlyphChecker__hasGlyph == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_EmojiCompat_GlyphChecker__hasGlyph, charSequence, start,
+ end, sdkAdded);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+// androidx.emoji2.text.EmojiCompat$MetadataRepoLoader
+jclass _c_EmojiCompat_MetadataRepoLoader = NULL;
+
+jmethodID _m_EmojiCompat_MetadataRepoLoader__load = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_MetadataRepoLoader__load(jobject self_,
+ jobject loaderCallback) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_MetadataRepoLoader,
+ "androidx/emoji2/text/EmojiCompat$MetadataRepoLoader");
+ if (_c_EmojiCompat_MetadataRepoLoader == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_EmojiCompat_MetadataRepoLoader,
+ &_m_EmojiCompat_MetadataRepoLoader__load, "load",
+ "(Landroidx/emoji2/text/EmojiCompat$MetadataRepoLoaderCallback;)V");
+ if (_m_EmojiCompat_MetadataRepoLoader__load == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(
+ jniEnv, self_, _m_EmojiCompat_MetadataRepoLoader__load, loaderCallback);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// androidx.emoji2.text.EmojiCompat$InitCallback
+jclass _c_EmojiCompat_InitCallback = NULL;
+
+jmethodID _m_EmojiCompat_InitCallback__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_InitCallback__new0() {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_InitCallback,
+ "androidx/emoji2/text/EmojiCompat$InitCallback");
+ if (_c_EmojiCompat_InitCallback == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_InitCallback, &_m_EmojiCompat_InitCallback__new0,
+ "<init>", "()V");
+ if (_m_EmojiCompat_InitCallback__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_EmojiCompat_InitCallback,
+ _m_EmojiCompat_InitCallback__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat_InitCallback__onInitialized = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_InitCallback__onInitialized(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_InitCallback,
+ "androidx/emoji2/text/EmojiCompat$InitCallback");
+ if (_c_EmojiCompat_InitCallback == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_InitCallback,
+ &_m_EmojiCompat_InitCallback__onInitialized, "onInitialized",
+ "()V");
+ if (_m_EmojiCompat_InitCallback__onInitialized == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_EmojiCompat_InitCallback__onInitialized);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_EmojiCompat_InitCallback__onFailed = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_InitCallback__onFailed(jobject self_, jobject throwable) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_InitCallback,
+ "androidx/emoji2/text/EmojiCompat$InitCallback");
+ if (_c_EmojiCompat_InitCallback == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_InitCallback,
+ &_m_EmojiCompat_InitCallback__onFailed, "onFailed",
+ "(Ljava/lang/Throwable;)V");
+ if (_m_EmojiCompat_InitCallback__onFailed == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_EmojiCompat_InitCallback__onFailed, throwable);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// androidx.emoji2.text.EmojiCompat$DefaultSpanFactory
+jclass _c_EmojiCompat_DefaultSpanFactory = NULL;
+
+jmethodID _m_EmojiCompat_DefaultSpanFactory__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_DefaultSpanFactory__new0() {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_DefaultSpanFactory,
+ "androidx/emoji2/text/EmojiCompat$DefaultSpanFactory");
+ if (_c_EmojiCompat_DefaultSpanFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_DefaultSpanFactory,
+ &_m_EmojiCompat_DefaultSpanFactory__new0, "<init>", "()V");
+ if (_m_EmojiCompat_DefaultSpanFactory__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_EmojiCompat_DefaultSpanFactory,
+ _m_EmojiCompat_DefaultSpanFactory__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_EmojiCompat_DefaultSpanFactory__createSpan = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_DefaultSpanFactory__createSpan(jobject self_,
+ jobject rasterizer) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_DefaultSpanFactory,
+ "androidx/emoji2/text/EmojiCompat$DefaultSpanFactory");
+ if (_c_EmojiCompat_DefaultSpanFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_DefaultSpanFactory,
+ &_m_EmojiCompat_DefaultSpanFactory__createSpan, "createSpan",
+ "(Landroidx/emoji2/text/TypefaceEmojiRasterizer;)Landroidx/"
+ "emoji2/text/EmojiSpan;");
+ if (_m_EmojiCompat_DefaultSpanFactory__createSpan == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_EmojiCompat_DefaultSpanFactory__createSpan, rasterizer);
+ return to_global_ref_result(_result);
+}
+
+// androidx.emoji2.text.EmojiCompat$SpanFactory
+jclass _c_EmojiCompat_SpanFactory = NULL;
+
+jmethodID _m_EmojiCompat_SpanFactory__createSpan = NULL;
+FFI_PLUGIN_EXPORT
+JniResult EmojiCompat_SpanFactory__createSpan(jobject self_,
+ jobject rasterizer) {
+ load_env();
+ load_class_global_ref(&_c_EmojiCompat_SpanFactory,
+ "androidx/emoji2/text/EmojiCompat$SpanFactory");
+ if (_c_EmojiCompat_SpanFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_EmojiCompat_SpanFactory,
+ &_m_EmojiCompat_SpanFactory__createSpan, "createSpan",
+ "(Landroidx/emoji2/text/TypefaceEmojiRasterizer;)Landroidx/"
+ "emoji2/text/EmojiSpan;");
+ if (_m_EmojiCompat_SpanFactory__createSpan == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_EmojiCompat_SpanFactory__createSpan, rasterizer);
+ return to_global_ref_result(_result);
+}
+
+// androidx.emoji2.text.DefaultEmojiCompatConfig
+jclass _c_DefaultEmojiCompatConfig = NULL;
+
+jmethodID _m_DefaultEmojiCompatConfig__create = NULL;
+FFI_PLUGIN_EXPORT
+JniResult DefaultEmojiCompatConfig__create(jobject context) {
+ load_env();
+ load_class_global_ref(&_c_DefaultEmojiCompatConfig,
+ "androidx/emoji2/text/DefaultEmojiCompatConfig");
+ if (_c_DefaultEmojiCompatConfig == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_DefaultEmojiCompatConfig,
+ &_m_DefaultEmojiCompatConfig__create, "create",
+ "(Landroid/content/Context;)Landroidx/emoji2/text/"
+ "FontRequestEmojiCompatConfig;");
+ if (_m_DefaultEmojiCompatConfig__create == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_DefaultEmojiCompatConfig, _m_DefaultEmojiCompatConfig__create,
+ context);
+ return to_global_ref_result(_result);
+}
+
+// androidx.emoji2.text.DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API28
+jclass _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28 = NULL;
+
+jmethodID
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__new0 =
+ NULL;
+FFI_PLUGIN_EXPORT
+JniResult
+DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__new0() {
+ load_env();
+ load_class_global_ref(
+ &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28,
+ "androidx/emoji2/text/"
+ "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API28");
+ if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28,
+ &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__new0,
+ "<init>", "()V");
+ if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__new0 ==
+ NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(
+ jniEnv, _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28,
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__getSigningSignatures1 =
+ NULL;
+FFI_PLUGIN_EXPORT
+JniResult
+DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__getSigningSignatures1(
+ jobject self_,
+ jobject packageManager,
+ jobject providerPackage) {
+ load_env();
+ load_class_global_ref(
+ &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28,
+ "androidx/emoji2/text/"
+ "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API28");
+ if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28,
+ &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__getSigningSignatures1,
+ "getSigningSignatures",
+ "(Landroid/content/pm/PackageManager;Ljava/lang/String;)[Landroid/"
+ "content/pm/Signature;");
+ if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__getSigningSignatures1 ==
+ NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_,
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API28__getSigningSignatures1,
+ packageManager, providerPackage);
+ return to_global_ref_result(_result);
+}
+
+// androidx.emoji2.text.DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API19
+jclass _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19 = NULL;
+
+jmethodID
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__new0 =
+ NULL;
+FFI_PLUGIN_EXPORT
+JniResult
+DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__new0() {
+ load_env();
+ load_class_global_ref(
+ &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19,
+ "androidx/emoji2/text/"
+ "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API19");
+ if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19,
+ &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__new0,
+ "<init>", "()V");
+ if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__new0 ==
+ NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(
+ jniEnv, _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19,
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__queryIntentContentProviders =
+ NULL;
+FFI_PLUGIN_EXPORT
+JniResult
+DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__queryIntentContentProviders(
+ jobject self_,
+ jobject packageManager,
+ jobject intent,
+ int32_t flags) {
+ load_env();
+ load_class_global_ref(
+ &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19,
+ "androidx/emoji2/text/"
+ "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API19");
+ if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19,
+ &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__queryIntentContentProviders,
+ "queryIntentContentProviders",
+ "(Landroid/content/pm/PackageManager;Landroid/content/Intent;I)Ljava/"
+ "util/List;");
+ if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__queryIntentContentProviders ==
+ NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_,
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__queryIntentContentProviders,
+ packageManager, intent, flags);
+ return to_global_ref_result(_result);
+}
+
+jmethodID
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__getProviderInfo =
+ NULL;
+FFI_PLUGIN_EXPORT
+JniResult
+DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__getProviderInfo(
+ jobject self_,
+ jobject resolveInfo) {
+ load_env();
+ load_class_global_ref(
+ &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19,
+ "androidx/emoji2/text/"
+ "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper_API19");
+ if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19,
+ &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__getProviderInfo,
+ "getProviderInfo",
+ "(Landroid/content/pm/ResolveInfo;)Landroid/content/pm/ProviderInfo;");
+ if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__getProviderInfo ==
+ NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_,
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper_API19__getProviderInfo,
+ resolveInfo);
+ return to_global_ref_result(_result);
+}
+
+// androidx.emoji2.text.DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper
+jclass _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper = NULL;
+
+jmethodID _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__new0 =
+ NULL;
+FFI_PLUGIN_EXPORT
+JniResult DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__new0() {
+ load_env();
+ load_class_global_ref(
+ &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
+ "androidx/emoji2/text/"
+ "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper");
+ if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
+ &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__new0,
+ "<init>", "()V");
+ if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(
+ jniEnv, _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getSigningSignatures =
+ NULL;
+FFI_PLUGIN_EXPORT
+JniResult
+DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getSigningSignatures(
+ jobject self_,
+ jobject packageManager,
+ jobject providerPackage) {
+ load_env();
+ load_class_global_ref(
+ &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
+ "androidx/emoji2/text/"
+ "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper");
+ if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
+ &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getSigningSignatures,
+ "getSigningSignatures",
+ "(Landroid/content/pm/PackageManager;Ljava/lang/String;)[Landroid/"
+ "content/pm/Signature;");
+ if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getSigningSignatures ==
+ NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_,
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getSigningSignatures,
+ packageManager, providerPackage);
+ return to_global_ref_result(_result);
+}
+
+jmethodID
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__queryIntentContentProviders =
+ NULL;
+FFI_PLUGIN_EXPORT
+JniResult
+DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__queryIntentContentProviders(
+ jobject self_,
+ jobject packageManager,
+ jobject intent,
+ int32_t flags) {
+ load_env();
+ load_class_global_ref(
+ &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
+ "androidx/emoji2/text/"
+ "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper");
+ if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
+ &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__queryIntentContentProviders,
+ "queryIntentContentProviders",
+ "(Landroid/content/pm/PackageManager;Landroid/content/Intent;I)Ljava/"
+ "util/List;");
+ if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__queryIntentContentProviders ==
+ NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_,
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__queryIntentContentProviders,
+ packageManager, intent, flags);
+ return to_global_ref_result(_result);
+}
+
+jmethodID
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getProviderInfo =
+ NULL;
+FFI_PLUGIN_EXPORT
+JniResult
+DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getProviderInfo(
+ jobject self_,
+ jobject resolveInfo) {
+ load_env();
+ load_class_global_ref(
+ &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
+ "androidx/emoji2/text/"
+ "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper");
+ if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper,
+ &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getProviderInfo,
+ "getProviderInfo",
+ "(Landroid/content/pm/ResolveInfo;)Landroid/content/pm/ProviderInfo;");
+ if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getProviderInfo ==
+ NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_,
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigHelper__getProviderInfo,
+ resolveInfo);
+ return to_global_ref_result(_result);
+}
+
+// androidx.emoji2.text.DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory
+jclass _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory = NULL;
+
+jmethodID _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__new0 =
+ NULL;
+FFI_PLUGIN_EXPORT
+JniResult DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__new0(
+ jobject helper) {
+ load_env();
+ load_class_global_ref(
+ &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory,
+ "androidx/emoji2/text/"
+ "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory");
+ if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory,
+ &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__new0,
+ "<init>",
+ "(Landroidx/emoji2/text/"
+ "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigHelper;)V");
+ if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(
+ jniEnv, _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory,
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__new0,
+ helper);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__create =
+ NULL;
+FFI_PLUGIN_EXPORT
+JniResult DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__create(
+ jobject self_,
+ jobject context) {
+ load_env();
+ load_class_global_ref(
+ &_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory,
+ "androidx/emoji2/text/"
+ "DefaultEmojiCompatConfig$DefaultEmojiCompatConfigFactory");
+ if (_c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory,
+ &_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__create,
+ "create",
+ "(Landroid/content/Context;)Landroidx/emoji2/text/EmojiCompat$Config;");
+ if (_m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__create ==
+ NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_,
+ _m_DefaultEmojiCompatConfig_DefaultEmojiCompatConfigFactory__create,
+ context);
+ return to_global_ref_result(_result);
+}
+
+// android.os.Build$Partition
+jclass _c_Build_Partition = NULL;
+
+jmethodID _m_Build_Partition__getName = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Build_Partition__getName(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Build_Partition, "android/os/Build$Partition");
+ if (_c_Build_Partition == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Build_Partition, &_m_Build_Partition__getName, "getName",
+ "()Ljava/lang/String;");
+ if (_m_Build_Partition__getName == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_Build_Partition__getName);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Build_Partition__getFingerprint = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Build_Partition__getFingerprint(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Build_Partition, "android/os/Build$Partition");
+ if (_c_Build_Partition == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Build_Partition, &_m_Build_Partition__getFingerprint,
+ "getFingerprint", "()Ljava/lang/String;");
+ if (_m_Build_Partition__getFingerprint == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_Build_Partition__getFingerprint);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Build_Partition__getBuildTimeMillis = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Build_Partition__getBuildTimeMillis(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Build_Partition, "android/os/Build$Partition");
+ if (_c_Build_Partition == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Build_Partition, &_m_Build_Partition__getBuildTimeMillis,
+ "getBuildTimeMillis", "()J");
+ if (_m_Build_Partition__getBuildTimeMillis == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int64_t _result = (*jniEnv)->CallLongMethod(
+ jniEnv, self_, _m_Build_Partition__getBuildTimeMillis);
+ return (JniResult){.value = {.j = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Build_Partition__equals1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Build_Partition__equals1(jobject self_, jobject object) {
+ load_env();
+ load_class_global_ref(&_c_Build_Partition, "android/os/Build$Partition");
+ if (_c_Build_Partition == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Build_Partition, &_m_Build_Partition__equals1, "equals",
+ "(Ljava/lang/Object;)Z");
+ if (_m_Build_Partition__equals1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_Build_Partition__equals1, object);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Build_Partition__hashCode1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Build_Partition__hashCode1(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Build_Partition, "android/os/Build$Partition");
+ if (_c_Build_Partition == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Build_Partition, &_m_Build_Partition__hashCode1, "hashCode",
+ "()I");
+ if (_m_Build_Partition__hashCode1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_Build_Partition__hashCode1);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+// android.os.Build$VERSION
+jclass _c_Build_VERSION = NULL;
+
+jmethodID _m_Build_VERSION__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Build_VERSION__new0() {
+ load_env();
+ load_class_global_ref(&_c_Build_VERSION, "android/os/Build$VERSION");
+ if (_c_Build_VERSION == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Build_VERSION, &_m_Build_VERSION__new0, "<init>", "()V");
+ if (_m_Build_VERSION__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_Build_VERSION, _m_Build_VERSION__new0);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build_VERSION__BASE_OS = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build_VERSION__BASE_OS() {
+ load_env();
+ load_class_global_ref(&_c_Build_VERSION, "android/os/Build$VERSION");
+ if (_c_Build_VERSION == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build_VERSION, &_f_Build_VERSION__BASE_OS, "BASE_OS",
+ "Ljava/lang/String;");
+ jobject _result = (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build_VERSION,
+ _f_Build_VERSION__BASE_OS);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build_VERSION__CODENAME = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build_VERSION__CODENAME() {
+ load_env();
+ load_class_global_ref(&_c_Build_VERSION, "android/os/Build$VERSION");
+ if (_c_Build_VERSION == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build_VERSION, &_f_Build_VERSION__CODENAME, "CODENAME",
+ "Ljava/lang/String;");
+ jobject _result = (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build_VERSION,
+ _f_Build_VERSION__CODENAME);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build_VERSION__INCREMENTAL = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build_VERSION__INCREMENTAL() {
+ load_env();
+ load_class_global_ref(&_c_Build_VERSION, "android/os/Build$VERSION");
+ if (_c_Build_VERSION == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build_VERSION, &_f_Build_VERSION__INCREMENTAL,
+ "INCREMENTAL", "Ljava/lang/String;");
+ jobject _result = (*jniEnv)->GetStaticObjectField(
+ jniEnv, _c_Build_VERSION, _f_Build_VERSION__INCREMENTAL);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build_VERSION__MEDIA_PERFORMANCE_CLASS = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build_VERSION__MEDIA_PERFORMANCE_CLASS() {
+ load_env();
+ load_class_global_ref(&_c_Build_VERSION, "android/os/Build$VERSION");
+ if (_c_Build_VERSION == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build_VERSION,
+ &_f_Build_VERSION__MEDIA_PERFORMANCE_CLASS,
+ "MEDIA_PERFORMANCE_CLASS", "I");
+ int32_t _result = (*jniEnv)->GetStaticIntField(
+ jniEnv, _c_Build_VERSION, _f_Build_VERSION__MEDIA_PERFORMANCE_CLASS);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jfieldID _f_Build_VERSION__PREVIEW_SDK_INT = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build_VERSION__PREVIEW_SDK_INT() {
+ load_env();
+ load_class_global_ref(&_c_Build_VERSION, "android/os/Build$VERSION");
+ if (_c_Build_VERSION == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build_VERSION, &_f_Build_VERSION__PREVIEW_SDK_INT,
+ "PREVIEW_SDK_INT", "I");
+ int32_t _result = (*jniEnv)->GetStaticIntField(
+ jniEnv, _c_Build_VERSION, _f_Build_VERSION__PREVIEW_SDK_INT);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jfieldID _f_Build_VERSION__RELEASE = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build_VERSION__RELEASE() {
+ load_env();
+ load_class_global_ref(&_c_Build_VERSION, "android/os/Build$VERSION");
+ if (_c_Build_VERSION == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build_VERSION, &_f_Build_VERSION__RELEASE, "RELEASE",
+ "Ljava/lang/String;");
+ jobject _result = (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build_VERSION,
+ _f_Build_VERSION__RELEASE);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build_VERSION__RELEASE_OR_CODENAME = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build_VERSION__RELEASE_OR_CODENAME() {
+ load_env();
+ load_class_global_ref(&_c_Build_VERSION, "android/os/Build$VERSION");
+ if (_c_Build_VERSION == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build_VERSION, &_f_Build_VERSION__RELEASE_OR_CODENAME,
+ "RELEASE_OR_CODENAME", "Ljava/lang/String;");
+ jobject _result = (*jniEnv)->GetStaticObjectField(
+ jniEnv, _c_Build_VERSION, _f_Build_VERSION__RELEASE_OR_CODENAME);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build_VERSION__RELEASE_OR_PREVIEW_DISPLAY = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build_VERSION__RELEASE_OR_PREVIEW_DISPLAY() {
+ load_env();
+ load_class_global_ref(&_c_Build_VERSION, "android/os/Build$VERSION");
+ if (_c_Build_VERSION == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build_VERSION,
+ &_f_Build_VERSION__RELEASE_OR_PREVIEW_DISPLAY,
+ "RELEASE_OR_PREVIEW_DISPLAY", "Ljava/lang/String;");
+ jobject _result = (*jniEnv)->GetStaticObjectField(
+ jniEnv, _c_Build_VERSION, _f_Build_VERSION__RELEASE_OR_PREVIEW_DISPLAY);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build_VERSION__SDK = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build_VERSION__SDK() {
+ load_env();
+ load_class_global_ref(&_c_Build_VERSION, "android/os/Build$VERSION");
+ if (_c_Build_VERSION == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build_VERSION, &_f_Build_VERSION__SDK, "SDK",
+ "Ljava/lang/String;");
+ jobject _result = (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build_VERSION,
+ _f_Build_VERSION__SDK);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build_VERSION__SDK_INT = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build_VERSION__SDK_INT() {
+ load_env();
+ load_class_global_ref(&_c_Build_VERSION, "android/os/Build$VERSION");
+ if (_c_Build_VERSION == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build_VERSION, &_f_Build_VERSION__SDK_INT, "SDK_INT",
+ "I");
+ int32_t _result = (*jniEnv)->GetStaticIntField(jniEnv, _c_Build_VERSION,
+ _f_Build_VERSION__SDK_INT);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jfieldID _f_Build_VERSION__SECURITY_PATCH = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build_VERSION__SECURITY_PATCH() {
+ load_env();
+ load_class_global_ref(&_c_Build_VERSION, "android/os/Build$VERSION");
+ if (_c_Build_VERSION == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build_VERSION, &_f_Build_VERSION__SECURITY_PATCH,
+ "SECURITY_PATCH", "Ljava/lang/String;");
+ jobject _result = (*jniEnv)->GetStaticObjectField(
+ jniEnv, _c_Build_VERSION, _f_Build_VERSION__SECURITY_PATCH);
+ return to_global_ref_result(_result);
+}
+
+// android.os.Build$VERSION_CODES
+jclass _c_Build_VERSION_CODES = NULL;
+
+jmethodID _m_Build_VERSION_CODES__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Build_VERSION_CODES__new0() {
+ load_env();
+ load_class_global_ref(&_c_Build_VERSION_CODES,
+ "android/os/Build$VERSION_CODES");
+ if (_c_Build_VERSION_CODES == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Build_VERSION_CODES, &_m_Build_VERSION_CODES__new0, "<init>",
+ "()V");
+ if (_m_Build_VERSION_CODES__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_Build_VERSION_CODES,
+ _m_Build_VERSION_CODES__new0);
+ return to_global_ref_result(_result);
+}
+
+// android.os.Build
+jclass _c_Build = NULL;
+
+jmethodID _m_Build__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Build__new0() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Build, &_m_Build__new0, "<init>", "()V");
+ if (_m_Build__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_Build, _m_Build__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Build__getSerial = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Build__getSerial() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Build, &_m_Build__getSerial, "getSerial",
+ "()Ljava/lang/String;");
+ if (_m_Build__getSerial == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_Build, _m_Build__getSerial);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Build__getFingerprintedPartitions = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Build__getFingerprintedPartitions() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Build, &_m_Build__getFingerprintedPartitions,
+ "getFingerprintedPartitions", "()Ljava/util/List;");
+ if (_m_Build__getFingerprintedPartitions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_Build, _m_Build__getFingerprintedPartitions);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Build__getRadioVersion = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Build__getRadioVersion() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Build, &_m_Build__getRadioVersion, "getRadioVersion",
+ "()Ljava/lang/String;");
+ if (_m_Build__getRadioVersion == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_Build, _m_Build__getRadioVersion);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__BOARD = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__BOARD() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__BOARD, "BOARD", "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__BOARD);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__BOOTLOADER = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__BOOTLOADER() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__BOOTLOADER, "BOOTLOADER",
+ "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__BOOTLOADER);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__BRAND = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__BRAND() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__BRAND, "BRAND", "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__BRAND);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__CPU_ABI = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__CPU_ABI() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__CPU_ABI, "CPU_ABI",
+ "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__CPU_ABI);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__CPU_ABI2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__CPU_ABI2() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__CPU_ABI2, "CPU_ABI2",
+ "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__CPU_ABI2);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__DEVICE = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__DEVICE() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__DEVICE, "DEVICE",
+ "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__DEVICE);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__DISPLAY = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__DISPLAY() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__DISPLAY, "DISPLAY",
+ "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__DISPLAY);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__FINGERPRINT = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__FINGERPRINT() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__FINGERPRINT, "FINGERPRINT",
+ "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__FINGERPRINT);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__HARDWARE = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__HARDWARE() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__HARDWARE, "HARDWARE",
+ "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__HARDWARE);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__HOST = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__HOST() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__HOST, "HOST", "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__HOST);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__ID = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__ID() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__ID, "ID", "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__ID);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__MANUFACTURER = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__MANUFACTURER() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__MANUFACTURER, "MANUFACTURER",
+ "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__MANUFACTURER);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__MODEL = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__MODEL() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__MODEL, "MODEL", "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__MODEL);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__ODM_SKU = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__ODM_SKU() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__ODM_SKU, "ODM_SKU",
+ "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__ODM_SKU);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__PRODUCT = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__PRODUCT() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__PRODUCT, "PRODUCT",
+ "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__PRODUCT);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__RADIO = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__RADIO() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__RADIO, "RADIO", "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__RADIO);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__SERIAL = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__SERIAL() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__SERIAL, "SERIAL",
+ "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__SERIAL);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__SKU = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__SKU() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__SKU, "SKU", "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__SKU);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__SOC_MANUFACTURER = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__SOC_MANUFACTURER() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__SOC_MANUFACTURER, "SOC_MANUFACTURER",
+ "Ljava/lang/String;");
+ jobject _result = (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build,
+ _f_Build__SOC_MANUFACTURER);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__SOC_MODEL = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__SOC_MODEL() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__SOC_MODEL, "SOC_MODEL",
+ "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__SOC_MODEL);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__SUPPORTED_32_BIT_ABIS = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__SUPPORTED_32_BIT_ABIS() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__SUPPORTED_32_BIT_ABIS,
+ "SUPPORTED_32_BIT_ABIS", "[Ljava/lang/String;");
+ jobject _result = (*jniEnv)->GetStaticObjectField(
+ jniEnv, _c_Build, _f_Build__SUPPORTED_32_BIT_ABIS);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__SUPPORTED_64_BIT_ABIS = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__SUPPORTED_64_BIT_ABIS() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__SUPPORTED_64_BIT_ABIS,
+ "SUPPORTED_64_BIT_ABIS", "[Ljava/lang/String;");
+ jobject _result = (*jniEnv)->GetStaticObjectField(
+ jniEnv, _c_Build, _f_Build__SUPPORTED_64_BIT_ABIS);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__SUPPORTED_ABIS = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__SUPPORTED_ABIS() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__SUPPORTED_ABIS, "SUPPORTED_ABIS",
+ "[Ljava/lang/String;");
+ jobject _result = (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build,
+ _f_Build__SUPPORTED_ABIS);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__TAGS = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__TAGS() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__TAGS, "TAGS", "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__TAGS);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__TIME = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__TIME() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__TIME, "TIME", "J");
+ int64_t _result =
+ (*jniEnv)->GetStaticLongField(jniEnv, _c_Build, _f_Build__TIME);
+ return (JniResult){.value = {.j = _result}, .exception = check_exception()};
+}
+
+jfieldID _f_Build__TYPE = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__TYPE() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__TYPE, "TYPE", "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__TYPE);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Build__USER = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Build__USER() {
+ load_env();
+ load_class_global_ref(&_c_Build, "android/os/Build");
+ if (_c_Build == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Build, &_f_Build__USER, "USER", "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Build, _f_Build__USER);
+ return to_global_ref_result(_result);
+}
+
+// java.util.HashMap
+jclass _c_HashMap = NULL;
+
+jmethodID _m_HashMap__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__new0(int32_t i, float f) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__new0, "<init>", "(IF)V");
+ if (_m_HashMap__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_HashMap, _m_HashMap__new0, i, f);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_HashMap__new1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__new1(int32_t i) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__new1, "<init>", "(I)V");
+ if (_m_HashMap__new1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_HashMap, _m_HashMap__new1, i);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_HashMap__new2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__new2() {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__new2, "<init>", "()V");
+ if (_m_HashMap__new2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_HashMap, _m_HashMap__new2);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_HashMap__new3 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__new3(jobject map) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__new3, "<init>", "(Ljava/util/Map;)V");
+ if (_m_HashMap__new3 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_HashMap, _m_HashMap__new3, map);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_HashMap__size = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__size(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__size, "size", "()I");
+ if (_m_HashMap__size == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_HashMap__size);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_HashMap__isEmpty = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__isEmpty(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__isEmpty, "isEmpty", "()Z");
+ if (_m_HashMap__isEmpty == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result =
+ (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_HashMap__isEmpty);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_HashMap__get0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__get0(jobject self_, jobject object) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__get0, "get",
+ "(Ljava/lang/Object;)Ljava/lang/Object;");
+ if (_m_HashMap__get0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__get0, object);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_HashMap__containsKey = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__containsKey(jobject self_, jobject object) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__containsKey, "containsKey",
+ "(Ljava/lang/Object;)Z");
+ if (_m_HashMap__containsKey == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_HashMap__containsKey, object);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_HashMap__put = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__put(jobject self_, jobject object, jobject object1) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__put, "put",
+ "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+ if (_m_HashMap__put == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__put,
+ object, object1);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_HashMap__putAll = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__putAll(jobject self_, jobject map) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__putAll, "putAll", "(Ljava/util/Map;)V");
+ if (_m_HashMap__putAll == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_HashMap__putAll, map);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_HashMap__remove = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__remove(jobject self_, jobject object) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__remove, "remove",
+ "(Ljava/lang/Object;)Ljava/lang/Object;");
+ if (_m_HashMap__remove == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__remove, object);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_HashMap__clear = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__clear(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__clear, "clear", "()V");
+ if (_m_HashMap__clear == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_HashMap__clear);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_HashMap__containsValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__containsValue(jobject self_, jobject object) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__containsValue, "containsValue",
+ "(Ljava/lang/Object;)Z");
+ if (_m_HashMap__containsValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_HashMap__containsValue, object);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_HashMap__keySet = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__keySet(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__keySet, "keySet", "()Ljava/util/Set;");
+ if (_m_HashMap__keySet == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__keySet);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_HashMap__values = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__values(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__values, "values",
+ "()Ljava/util/Collection;");
+ if (_m_HashMap__values == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__values);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_HashMap__entrySet = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__entrySet(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__entrySet, "entrySet",
+ "()Ljava/util/Set;");
+ if (_m_HashMap__entrySet == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__entrySet);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_HashMap__getOrDefault = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__getOrDefault(jobject self_,
+ jobject object,
+ jobject object1) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__getOrDefault, "getOrDefault",
+ "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+ if (_m_HashMap__getOrDefault == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_HashMap__getOrDefault, object, object1);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_HashMap__putIfAbsent = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__putIfAbsent(jobject self_, jobject object, jobject object1) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__putIfAbsent, "putIfAbsent",
+ "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+ if (_m_HashMap__putIfAbsent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_HashMap__putIfAbsent, object, object1);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_HashMap__remove1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__remove1(jobject self_, jobject object, jobject object1) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__remove1, "remove",
+ "(Ljava/lang/Object;Ljava/lang/Object;)Z");
+ if (_m_HashMap__remove1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_HashMap__remove1, object, object1);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_HashMap__replace = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__replace(jobject self_,
+ jobject object,
+ jobject object1,
+ jobject object2) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__replace, "replace",
+ "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Z");
+ if (_m_HashMap__replace == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_HashMap__replace, object, object1, object2);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_HashMap__replace1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__replace1(jobject self_, jobject object, jobject object1) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__replace1, "replace",
+ "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+ if (_m_HashMap__replace1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_HashMap__replace1, object, object1);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_HashMap__computeIfAbsent = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__computeIfAbsent(jobject self_,
+ jobject object,
+ jobject function) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_HashMap, &_m_HashMap__computeIfAbsent, "computeIfAbsent",
+ "(Ljava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object;");
+ if (_m_HashMap__computeIfAbsent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_HashMap__computeIfAbsent, object, function);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_HashMap__computeIfPresent = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__computeIfPresent(jobject self_,
+ jobject object,
+ jobject biFunction) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_HashMap, &_m_HashMap__computeIfPresent, "computeIfPresent",
+ "(Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object;");
+ if (_m_HashMap__computeIfPresent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_HashMap__computeIfPresent, object, biFunction);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_HashMap__compute = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__compute(jobject self_, jobject object, jobject biFunction) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_HashMap, &_m_HashMap__compute, "compute",
+ "(Ljava/lang/Object;Ljava/util/function/BiFunction;)Ljava/lang/Object;");
+ if (_m_HashMap__compute == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_HashMap__compute, object, biFunction);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_HashMap__merge = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__merge(jobject self_,
+ jobject object,
+ jobject object1,
+ jobject biFunction) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__merge, "merge",
+ "(Ljava/lang/Object;Ljava/lang/Object;Ljava/util/function/"
+ "BiFunction;)Ljava/lang/Object;");
+ if (_m_HashMap__merge == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_HashMap__merge, object, object1, biFunction);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_HashMap__forEach = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__forEach(jobject self_, jobject biConsumer) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__forEach, "forEach",
+ "(Ljava/util/function/BiConsumer;)V");
+ if (_m_HashMap__forEach == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_HashMap__forEach, biConsumer);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_HashMap__replaceAll = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__replaceAll(jobject self_, jobject biFunction) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__replaceAll, "replaceAll",
+ "(Ljava/util/function/BiFunction;)V");
+ if (_m_HashMap__replaceAll == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_HashMap__replaceAll, biFunction);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_HashMap__clone = NULL;
+FFI_PLUGIN_EXPORT
+JniResult HashMap__clone(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_HashMap, "java/util/HashMap");
+ if (_c_HashMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_HashMap, &_m_HashMap__clone, "clone", "()Ljava/lang/Object;");
+ if (_m_HashMap__clone == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_HashMap__clone);
+ return to_global_ref_result(_result);
+}
diff --git a/pkgs/jnigen/example/in_app_java/src/android_utils/dartjni.h b/pkgs/jnigen/example/in_app_java/src/android_utils/dartjni.h
new file mode 100644
index 0000000..8f1dc74
--- /dev/null
+++ b/pkgs/jnigen/example/in_app_java/src/android_utils/dartjni.h
@@ -0,0 +1,424 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#pragma once
+
+// Note: include appropriate system jni.h as found by CMake, not third_party/jni.h.
+#include <jni.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if _WIN32
+#include <windows.h>
+#else
+#include <pthread.h>
+#include <unistd.h>
+#endif
+
+#if _WIN32
+#define FFI_PLUGIN_EXPORT __declspec(dllexport)
+#else
+#define FFI_PLUGIN_EXPORT
+#endif
+
+#if defined _WIN32
+#define thread_local __declspec(thread)
+#else
+#define thread_local __thread
+#endif
+
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
+
+#ifdef __ANDROID__
+#define __ENVP_CAST (JNIEnv**)
+#else
+#define __ENVP_CAST (void**)
+#endif
+
+/// Locking functions for windows and pthread.
+
+#if defined _WIN32
+#include <windows.h>
+
+typedef CRITICAL_SECTION MutexLock;
+typedef CONDITION_VARIABLE ConditionVariable;
+
+static inline void init_lock(MutexLock* lock) {
+ InitializeCriticalSection(lock);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+ EnterCriticalSection(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+ LeaveCriticalSection(lock);
+}
+
+static inline void destroy_lock(MutexLock* lock) {
+ DeleteCriticalSection(lock);
+}
+
+static inline void init_cond(ConditionVariable* cond) {
+ InitializeConditionVariable(cond);
+}
+
+static inline void signal_cond(ConditionVariable* cond) {
+ WakeConditionVariable(cond);
+}
+
+static inline void wait_for(ConditionVariable* cond, MutexLock* lock) {
+ SleepConditionVariableCS(cond, lock, INFINITE);
+}
+
+static inline void destroy_cond(ConditionVariable* cond) {
+ // Not available.
+}
+
+#elif defined __APPLE__ || defined __LINUX__ || defined __ANDROID__ || \
+ defined __GNUC__
+#include <pthread.h>
+
+typedef pthread_mutex_t MutexLock;
+typedef pthread_cond_t ConditionVariable;
+
+static inline void init_lock(MutexLock* lock) {
+ pthread_mutex_init(lock, NULL);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+ pthread_mutex_lock(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+ pthread_mutex_unlock(lock);
+}
+
+static inline void destroy_lock(MutexLock* lock) {
+ pthread_mutex_destroy(lock);
+}
+
+static inline void init_cond(ConditionVariable* cond) {
+ pthread_cond_init(cond, NULL);
+}
+
+static inline void signal_cond(ConditionVariable* cond) {
+ pthread_cond_signal(cond);
+}
+
+static inline void wait_for(ConditionVariable* cond, MutexLock* lock) {
+ pthread_cond_wait(cond, lock);
+}
+
+static inline void destroy_cond(ConditionVariable* cond) {
+ pthread_cond_destroy(cond);
+}
+
+#else
+
+#error "No locking/condition variable support; Possibly unsupported platform"
+
+#endif
+
+typedef struct CallbackResult {
+ MutexLock lock;
+ ConditionVariable cond;
+ int ready;
+ jobject object;
+} CallbackResult;
+
+typedef struct JniLocks {
+ MutexLock classLoadingLock;
+ MutexLock methodLoadingLock;
+ MutexLock fieldLoadingLock;
+} JniLocks;
+
+/// Represents the error when dart-jni layer has already spawned singleton VM.
+#define DART_JNI_SINGLETON_EXISTS (-99);
+
+/// Stores the global state of the JNI.
+typedef struct JniContext {
+ JavaVM* jvm;
+ jobject classLoader;
+ jmethodID loadClassMethod;
+ jobject currentActivity;
+ jobject appContext;
+ JniLocks locks;
+} JniContext;
+
+// jniEnv for this thread, used by inline functions in this header,
+// therefore declared as extern.
+extern thread_local JNIEnv* jniEnv;
+
+extern JniContext* jni;
+
+/// Types used by JNI API to distinguish between primitive types.
+enum JniType {
+ booleanType = 0,
+ byteType = 1,
+ shortType = 2,
+ charType = 3,
+ intType = 4,
+ longType = 5,
+ floatType = 6,
+ doubleType = 7,
+ objectType = 8,
+ voidType = 9,
+};
+
+/// Result type for use by JNI.
+///
+/// If [exception] is null, it means the result is valid.
+/// It's assumed that the caller knows the expected type in [result].
+typedef struct JniResult {
+ jvalue value;
+ jthrowable exception;
+} JniResult;
+
+/// Similar to [JniResult] but for class lookups.
+typedef struct JniClassLookupResult {
+ jclass value;
+ jthrowable exception;
+} JniClassLookupResult;
+
+/// Similar to [JniResult] but for method/field ID lookups.
+typedef struct JniPointerResult {
+ const void* value;
+ jthrowable exception;
+} JniPointerResult;
+
+/// JniExceptionDetails holds 2 jstring objects, one is the result of
+/// calling `toString` on exception object, other is stack trace;
+typedef struct JniExceptionDetails {
+ jstring message;
+ jstring stacktrace;
+} JniExceptionDetails;
+
+/// This struct contains functions which wrap method call / field access conveniently along with
+/// exception checking.
+///
+/// Flutter embedding checks for pending JNI exceptions before an FFI transition, which requires us
+/// to check for and clear the exception before returning to dart code, which requires these functions
+/// to return result types.
+typedef struct JniAccessorsStruct {
+ JniClassLookupResult (*getClass)(char* internalName);
+ JniPointerResult (*getFieldID)(jclass cls, char* fieldName, char* signature);
+ JniPointerResult (*getStaticFieldID)(jclass cls,
+ char* fieldName,
+ char* signature);
+ JniPointerResult (*getMethodID)(jclass cls,
+ char* methodName,
+ char* signature);
+ JniPointerResult (*getStaticMethodID)(jclass cls,
+ char* methodName,
+ char* signature);
+ JniResult (*newObject)(jclass cls, jmethodID ctor, jvalue* args);
+ JniResult (*newPrimitiveArray)(jsize length, int type);
+ JniResult (*newObjectArray)(jsize length,
+ jclass elementClass,
+ jobject initialElement);
+ JniResult (*getArrayElement)(jarray array, int index, int type);
+ JniResult (*callMethod)(jobject obj,
+ jmethodID methodID,
+ int callType,
+ jvalue* args);
+ JniResult (*callStaticMethod)(jclass cls,
+ jmethodID methodID,
+ int callType,
+ jvalue* args);
+ JniResult (*getField)(jobject obj, jfieldID fieldID, int callType);
+ JniResult (*getStaticField)(jclass cls, jfieldID fieldID, int callType);
+ JniExceptionDetails (*getExceptionDetails)(jthrowable exception);
+} JniAccessorsStruct;
+
+FFI_PLUGIN_EXPORT JniAccessorsStruct* GetAccessors();
+
+FFI_PLUGIN_EXPORT JavaVM* GetJavaVM(void);
+
+FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv(void);
+
+/// Spawn a JVM with given arguments.
+///
+/// Returns JNI_OK on success, and one of the documented JNI error codes on
+/// failure. It returns DART_JNI_SINGLETON_EXISTS if an attempt to spawn multiple
+/// JVMs is made, even if the underlying API potentially supports multiple VMs.
+FFI_PLUGIN_EXPORT int SpawnJvm(JavaVMInitArgs* args);
+
+/// Load class through platform-specific mechanism.
+///
+/// Currently uses application classloader on android,
+/// and JNIEnv->FindClass on other platforms.
+FFI_PLUGIN_EXPORT jclass FindClass(const char* name);
+
+/// Returns Application classLoader (on Android),
+/// which can be used to load application and platform classes.
+///
+/// On other platforms, NULL is returned.
+FFI_PLUGIN_EXPORT jobject GetClassLoader(void);
+
+/// Returns application context on Android.
+///
+/// On other platforms, NULL is returned.
+FFI_PLUGIN_EXPORT jobject GetApplicationContext(void);
+
+/// Returns current activity of the app on Android.
+FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
+
+static inline void attach_thread() {
+ if (jniEnv == NULL) {
+ (*jni->jvm)->AttachCurrentThread(jni->jvm, __ENVP_CAST & jniEnv, NULL);
+ }
+}
+
+/// Load class into [cls] using platform specific mechanism
+static inline void load_class_platform(jclass* cls, const char* name) {
+#ifdef __ANDROID__
+ jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
+ *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni->classLoader,
+ jni->loadClassMethod, className);
+ (*jniEnv)->DeleteLocalRef(jniEnv, className);
+#else
+ *cls = (*jniEnv)->FindClass(jniEnv, name);
+#endif
+}
+
+static inline void load_class_local_ref(jclass* cls, const char* name) {
+ if (*cls == NULL) {
+ acquire_lock(&jni->locks.classLoadingLock);
+ if (*cls == NULL) {
+ load_class_platform(cls, name);
+ }
+ release_lock(&jni->locks.classLoadingLock);
+ }
+}
+
+static inline void load_class_global_ref(jclass* cls, const char* name) {
+ if (*cls == NULL) {
+ jclass tmp = NULL;
+ acquire_lock(&jni->locks.classLoadingLock);
+ if (*cls == NULL) {
+ load_class_platform(&tmp, name);
+ if (!(*jniEnv)->ExceptionCheck(jniEnv)) {
+ *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
+ (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
+ }
+ }
+ release_lock(&jni->locks.classLoadingLock);
+ }
+}
+
+static inline void load_method(jclass cls,
+ jmethodID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.methodLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.methodLoadingLock);
+ }
+}
+
+static inline void load_static_method(jclass cls,
+ jmethodID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.methodLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.methodLoadingLock);
+ }
+}
+
+static inline void load_field(jclass cls,
+ jfieldID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.fieldLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.fieldLoadingLock);
+ }
+}
+
+static inline void load_static_field(jclass cls,
+ jfieldID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.fieldLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.fieldLoadingLock);
+ }
+}
+
+static inline jobject to_global_ref(jobject ref) {
+ jobject g = (*jniEnv)->NewGlobalRef(jniEnv, ref);
+ (*jniEnv)->DeleteLocalRef(jniEnv, ref);
+ return g;
+}
+
+// These functions are useful for C+Dart bindings, and not required for pure dart bindings.
+
+FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr();
+
+/// For use by jni_gen's generated code
+/// don't use these.
+
+// these 2 fn ptr vars will be defined by generated code library
+extern JniContext* (*context_getter)(void);
+extern JNIEnv* (*env_getter)(void);
+
+// this function will be exported by generated code library
+// it will set above 2 variables.
+FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext* (*cg)(void),
+ JNIEnv* (*eg)(void));
+
+static inline void load_env() {
+ if (jniEnv == NULL) {
+ jni = context_getter();
+ jniEnv = env_getter();
+ }
+}
+
+static inline jthrowable check_exception() {
+ jthrowable exception = (*jniEnv)->ExceptionOccurred(jniEnv);
+ if (exception != NULL) (*jniEnv)->ExceptionClear(jniEnv);
+ if (exception == NULL) return NULL;
+ return to_global_ref(exception);
+}
+
+static inline JniResult to_global_ref_result(jobject ref) {
+ JniResult result;
+ result.exception = check_exception();
+ if (result.exception == NULL) {
+ result.value.l = to_global_ref(ref);
+ }
+ return result;
+}
+
+FFI_PLUGIN_EXPORT intptr_t InitDartApiDL(void* data);
+
+FFI_PLUGIN_EXPORT
+JniResult DartException__ctor(jstring message);
+
+FFI_PLUGIN_EXPORT
+JniResult PortContinuation__ctor(int64_t j);
+
+FFI_PLUGIN_EXPORT
+JniResult PortProxy__newInstance(jobject binaryName,
+ int64_t port,
+ int64_t functionPtr);
+
+FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
diff --git a/pkgs/jnigen/example/kotlin_plugin/.gitignore b/pkgs/jnigen/example/kotlin_plugin/.gitignore
new file mode 100644
index 0000000..96486fd
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/.gitignore
@@ -0,0 +1,30 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
+/pubspec.lock
+**/doc/api/
+.dart_tool/
+.packages
+build/
diff --git a/pkgs/jnigen/example/kotlin_plugin/.metadata b/pkgs/jnigen/example/kotlin_plugin/.metadata
new file mode 100644
index 0000000..2276419
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/.metadata
@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+ revision: 9b4416aaa79bf984d06aa40ab515a274a50a75a7
+ channel: beta
+
+project_type: package
diff --git a/pkgs/jnigen/example/kotlin_plugin/README.md b/pkgs/jnigen/example/kotlin_plugin/README.md
new file mode 100644
index 0000000..2a915c8
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/README.md
@@ -0,0 +1,38 @@
+# kotlin_plugin
+
+This example generates bindings for a Kotlin-based library. It showcases the conversion of `suspend fun` in Kotlin to `async` functions in Dart.
+
+The command to regenerate JNI bindings is:
+```
+flutter pub run jnigen --config jnigen.yaml # run from kotlin_plugin project root
+```
+
+The `example/` app must be built at least once in _release_ mode (eg `flutter build apk`) before running jnigen. This is the equivalent of Gradle Sync in Android Studio, and enables `jnigen` to run a Gradle stub and determine release build's classpath, which contains the paths to relevant dependencies. Therefore a build must have been run after cleaning build directories, or updating Java dependencies. This is a known complexity of the Gradle build system, and if you know a solution, please contribute to issue discussion at #33.
+
+Note that `jnigen.yaml` of this example contains the option `suspend_fun_to_async: true`. This will generate `async` method bindings from Kotlin's `suspend fun`s.
+
+For Kotlin coroutines to work, `Jni.initDLApi()` must be run first.
+
+## Creating a new Kotlin plugin
+
+Running `flutter create --template=plugin_ffi --platform=android kotlin_plugin` creates the skeleton of an Android plugin.
+
+In order to use Kotlin, `build.gradle` must be modified in the following way:
+
+```gradle
+apply plugin: 'com.android.library'
+// Add the line below:
+apply plugin: 'kotlin-android'
+```
+
+```gradle
+android {
+ // Add the following block
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+ // ...
+}
+```
+
+Now the Kotlin code in `src/main/kotlin` is included in the plugin.
diff --git a/pkgs/jnigen/example/kotlin_plugin/analysis_options.yaml b/pkgs/jnigen/example/kotlin_plugin/analysis_options.yaml
new file mode 100644
index 0000000..f9b3034
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/analysis_options.yaml
@@ -0,0 +1 @@
+include: package:flutter_lints/flutter.yaml
diff --git a/pkgs/jnigen/example/kotlin_plugin/android/.gitignore b/pkgs/jnigen/example/kotlin_plugin/android/.gitignore
new file mode 100644
index 0000000..161bdcd
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/android/.gitignore
@@ -0,0 +1,9 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+.cxx
diff --git a/pkgs/jnigen/example/kotlin_plugin/android/build.gradle b/pkgs/jnigen/example/kotlin_plugin/android/build.gradle
new file mode 100644
index 0000000..862afaf
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/android/build.gradle
@@ -0,0 +1,64 @@
+// The Android Gradle Plugin builds the native code with the Android NDK.
+
+group 'com.example.kotlin_plugin'
+version '1.0'
+
+buildscript {
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ // The Android Gradle Plugin knows how to build native code with the NDK.
+ classpath 'com.android.tools.build:gradle:7.1.2'
+ }
+}
+
+rootProject.allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+
+android {
+ // Bumping the plugin compileSdkVersion requires all clients of this plugin
+ // to bump the version in their app.
+ compileSdkVersion 31
+
+ // Bumping the plugin ndkVersion requires all clients of this plugin to bump
+ // the version in their app and to download a newer version of the NDK.
+ ndkVersion "21.1.6352462"
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+
+ // Invoke the shared CMake build with the Android Gradle Plugin.
+ externalNativeBuild {
+ cmake {
+ path "../src/CMakeLists.txt"
+
+ // The default CMake version for the Android Gradle Plugin is 3.10.2.
+ // https://developer.android.com/studio/projects/install-ndk#vanilla_cmake
+ //
+ // 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.
+ // version "3.10.2"
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ defaultConfig {
+ minSdkVersion 16
+ }
+}
diff --git a/pkgs/jnigen/example/kotlin_plugin/android/settings.gradle b/pkgs/jnigen/example/kotlin_plugin/android/settings.gradle
new file mode 100644
index 0000000..8e0a5b1
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/android/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'notification_plugin'
diff --git a/pkgs/jnigen/example/kotlin_plugin/android/src/main/AndroidManifest.xml b/pkgs/jnigen/example/kotlin_plugin/android/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..d7d511a
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/android/src/main/AndroidManifest.xml
@@ -0,0 +1,3 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.kotlin_plugin">
+</manifest>
diff --git a/pkgs/jnigen/example/kotlin_plugin/android/src/main/kotlin/Example.kt b/pkgs/jnigen/example/kotlin_plugin/android/src/main/kotlin/Example.kt
new file mode 100644
index 0000000..531f899
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/android/src/main/kotlin/Example.kt
@@ -0,0 +1,10 @@
+import androidx.annotation.Keep
+import kotlinx.coroutines.*
+
+@Keep
+class Example {
+ public suspend fun thinkBeforeAnswering(): String {
+ delay(1000L)
+ return "42"
+ }
+}
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/.gitignore b/pkgs/jnigen/example/kotlin_plugin/example/.gitignore
new file mode 100644
index 0000000..24476c5
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/.gitignore
@@ -0,0 +1,44 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/.metadata b/pkgs/jnigen/example/kotlin_plugin/example/.metadata
new file mode 100644
index 0000000..b510dd9
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/.metadata
@@ -0,0 +1,30 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled.
+
+version:
+ revision: 9b4416aaa79bf984d06aa40ab515a274a50a75a7
+ channel: beta
+
+project_type: app
+
+# Tracks metadata for the flutter migrate command
+migration:
+ platforms:
+ - platform: root
+ create_revision: 9b4416aaa79bf984d06aa40ab515a274a50a75a7
+ base_revision: 9b4416aaa79bf984d06aa40ab515a274a50a75a7
+ - platform: android
+ create_revision: 9b4416aaa79bf984d06aa40ab515a274a50a75a7
+ base_revision: 9b4416aaa79bf984d06aa40ab515a274a50a75a7
+
+ # User provided section
+
+ # List of Local paths (relative to this file) that should be
+ # ignored by the migrate tool.
+ #
+ # Files that are not part of the templates will be ignored by default.
+ unmanaged_files:
+ - 'lib/main.dart'
+ - 'ios/Runner.xcodeproj/project.pbxproj'
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/README.md b/pkgs/jnigen/example/kotlin_plugin/example/README.md
new file mode 100644
index 0000000..2b3fce4
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/README.md
@@ -0,0 +1,16 @@
+# example
+
+A new Flutter project.
+
+## Getting Started
+
+This project is a starting point for a Flutter application.
+
+A few resources to get you started if this is your first Flutter project:
+
+- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
+- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
+
+For help getting started with Flutter development, view the
+[online documentation](https://docs.flutter.dev/), which offers tutorials,
+samples, guidance on mobile development, and a full API reference.
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/analysis_options.yaml b/pkgs/jnigen/example/kotlin_plugin/example/analysis_options.yaml
new file mode 100644
index 0000000..61b6c4d
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/analysis_options.yaml
@@ -0,0 +1,29 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+ # The lint rules applied to this project can be customized in the
+ # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+ # included above or to enable additional rules. A list of all available lints
+ # and their documentation is published at
+ # https://dart-lang.github.io/linter/lints/index.html.
+ #
+ # Instead of disabling a lint rule for the entire project in the
+ # section below, it can also be suppressed for a single line of code
+ # or a specific dart file by using the `// ignore: name_of_lint` and
+ # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+ # producing the lint.
+ rules:
+ # avoid_print: false # Uncomment to disable the `avoid_print` rule
+ # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/.gitignore b/pkgs/jnigen/example/kotlin_plugin/example/android/.gitignore
new file mode 100644
index 0000000..6f56801
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/.gitignore
@@ -0,0 +1,13 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/app/build.gradle b/pkgs/jnigen/example/kotlin_plugin/example/android/app/build.gradle
new file mode 100644
index 0000000..7f1cb3e
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/app/build.gradle
@@ -0,0 +1,71 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+ localPropertiesFile.withReader('UTF-8') { reader ->
+ localProperties.load(reader)
+ }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+ throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+ flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+ flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+ compileSdkVersion flutter.compileSdkVersion
+ ndkVersion flutter.ndkVersion
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+
+ defaultConfig {
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId "com.example.kotlin_plugin.example"
+ // You can update the following values to match your application needs.
+ // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
+ minSdkVersion flutter.minSdkVersion
+ targetSdkVersion flutter.targetSdkVersion
+ versionCode flutterVersionCode.toInteger()
+ versionName flutterVersionName
+ }
+
+ buildTypes {
+ release {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig signingConfigs.debug
+ }
+ }
+}
+
+flutter {
+ source '../..'
+}
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/app/proguard-rules.pro b/pkgs/jnigen/example/kotlin_plugin/example/android/app/proguard-rules.pro
new file mode 100644
index 0000000..8c1218b
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/app/proguard-rules.pro
@@ -0,0 +1 @@
+-keep class kotlin.coroutines.** { *; }
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/debug/AndroidManifest.xml b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..0d1fc86
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.kotlin_plugin.example">
+ <!-- The INTERNET permission is required for development. Specifically,
+ the Flutter tool needs it to communicate with the running application
+ to allow setting breakpoints, to provide hot reload, etc.
+ -->
+ <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/AndroidManifest.xml b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..9059f10
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.kotlin_plugin.example">
+ <application
+ android:label="example"
+ android:name="${applicationName}"
+ android:icon="@mipmap/ic_launcher">
+ <activity
+ android:name=".MainActivity"
+ android:exported="true"
+ android:launchMode="singleTop"
+ android:theme="@style/LaunchTheme"
+ android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
+ android:hardwareAccelerated="true"
+ android:windowSoftInputMode="adjustResize">
+ <!-- Specifies an Android theme to apply to this Activity as soon as
+ the Android process has started. This theme is visible to the user
+ while the Flutter UI initializes. After that, this theme continues
+ to determine the Window background behind the Flutter UI. -->
+ <meta-data
+ android:name="io.flutter.embedding.android.NormalTheme"
+ android:resource="@style/NormalTheme"
+ />
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <!-- Don't delete the meta-data below.
+ This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
+ <meta-data
+ android:name="flutterEmbedding"
+ android:value="2" />
+ </application>
+</manifest>
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/kotlin/com/example/kotlin_plugin/example/MainActivity.kt b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/kotlin/com/example/kotlin_plugin/example/MainActivity.kt
new file mode 100644
index 0000000..4826f82
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/kotlin/com/example/kotlin_plugin/example/MainActivity.kt
@@ -0,0 +1,6 @@
+package com.example.kotlin_plugin.example
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="?android:colorBackground" />
+
+ <!-- You can insert your own image assets here -->
+ <!-- <item>
+ <bitmap
+ android:gravity="center"
+ android:src="@mipmap/launch_image" />
+ </item> -->
+</layer-list>
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/drawable/launch_background.xml b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..304732f
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@android:color/white" />
+
+ <!-- You can insert your own image assets here -->
+ <!-- <item>
+ <bitmap
+ android:gravity="center"
+ android:src="@mipmap/launch_image" />
+ </item> -->
+</layer-list>
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..db77bb4
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..17987b7
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..09d4391
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d5f1c8d
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d6372e
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/values-night/styles.xml b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..06952be
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
+ <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
+ <!-- Show a splash screen on the activity. Automatically removed when
+ the Flutter engine draws its first frame -->
+ <item name="android:windowBackground">@drawable/launch_background</item>
+ </style>
+ <!-- Theme applied to the Android Window as soon as the process has started.
+ This theme determines the color of the Android Window while your
+ Flutter UI initializes, as well as behind your Flutter UI while its
+ running.
+
+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
+ <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
+ <item name="android:windowBackground">?android:colorBackground</item>
+ </style>
+</resources>
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/values/styles.xml b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..cb1ef88
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
+ <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
+ <!-- Show a splash screen on the activity. Automatically removed when
+ the Flutter engine draws its first frame -->
+ <item name="android:windowBackground">@drawable/launch_background</item>
+ </style>
+ <!-- Theme applied to the Android Window as soon as the process has started.
+ This theme determines the color of the Android Window while your
+ Flutter UI initializes, as well as behind your Flutter UI while its
+ running.
+
+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
+ <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
+ <item name="android:windowBackground">?android:colorBackground</item>
+ </style>
+</resources>
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/profile/AndroidManifest.xml b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..2c06d9b
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.datastore.example">
+ <!-- The INTERNET permission is required for development. Specifically,
+ the Flutter tool needs it to communicate with the running application
+ to allow setting breakpoints, to provide hot reload, etc.
+ -->
+ <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/build.gradle b/pkgs/jnigen/example/kotlin_plugin/example/android/build.gradle
new file mode 100644
index 0000000..713d7f6
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/build.gradle
@@ -0,0 +1,31 @@
+buildscript {
+ ext.kotlin_version = '1.7.10'
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:7.2.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+ project.evaluationDependsOn(':app')
+}
+
+tasks.register("clean", Delete) {
+ delete rootProject.buildDir
+}
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/gradle.properties b/pkgs/jnigen/example/kotlin_plugin/example/android/gradle.properties
new file mode 100644
index 0000000..94adc3a
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/gradle/wrapper/gradle-wrapper.properties b/pkgs/jnigen/example/kotlin_plugin/example/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..3c472b9
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/android/settings.gradle b/pkgs/jnigen/example/kotlin_plugin/example/android/settings.gradle
new file mode 100644
index 0000000..44e62bc
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/android/settings.gradle
@@ -0,0 +1,11 @@
+include ':app'
+
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
+
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/lib/main.dart b/pkgs/jnigen/example/kotlin_plugin/example/lib/main.dart
new file mode 100644
index 0000000..50d1434
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/lib/main.dart
@@ -0,0 +1,98 @@
+import 'package:flutter/material.dart';
+import 'package:kotlin_plugin/kotlin_plugin.dart';
+import 'package:jni/jni.dart';
+
+void main() {
+ Jni.initDLApi();
+ runApp(const MyApp());
+}
+
+class MyApp extends StatelessWidget {
+ const MyApp({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ title: 'Kotlin Plugin Example',
+ theme: ThemeData(
+ primarySwatch: Colors.blue,
+ ),
+ home: const MyHomePage(title: 'Kotlin Plugin Example Home Page'),
+ );
+ }
+}
+
+class MyHomePage extends StatefulWidget {
+ const MyHomePage({super.key, required this.title});
+
+ final String title;
+
+ @override
+ State<MyHomePage> createState() => _MyHomePageState();
+}
+
+class _MyHomePageState extends State<MyHomePage> {
+ Future<String>? answer;
+
+ late Example example;
+
+ @override
+ void initState() {
+ super.initState();
+ example = Example();
+ }
+
+ @override
+ void dispose() {
+ example.release();
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text(widget.title),
+ ),
+ body: Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: <Widget>[
+ const Text(
+ 'What is the answer to life, the universe, and everything?',
+ ),
+ ElevatedButton(
+ onPressed: () {
+ setState(() {
+ answer = example.thinkBeforeAnswering().then(
+ (value) => value.toDartString(releaseOriginal: true));
+ });
+ },
+ child: const Text('Think...'),
+ ),
+ FutureBuilder<String>(
+ future: answer,
+ builder: (context, snapshot) {
+ switch (snapshot.connectionState) {
+ case ConnectionState.none:
+ return const SizedBox();
+ case ConnectionState.waiting:
+ case ConnectionState.active:
+ return Text(
+ 'Thinking...',
+ style: Theme.of(context).textTheme.headlineMedium,
+ );
+ case ConnectionState.done:
+ return Text(
+ snapshot.data ?? "I don't know!",
+ style: Theme.of(context).textTheme.headlineMedium,
+ );
+ }
+ },
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/pkgs/jnigen/example/kotlin_plugin/example/pubspec.yaml b/pkgs/jnigen/example/kotlin_plugin/example/pubspec.yaml
new file mode 100644
index 0000000..4c1c796
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/example/pubspec.yaml
@@ -0,0 +1,29 @@
+name: example
+description: A new Flutter project.
+
+publish_to: "none"
+
+version: 1.0.0+1
+
+environment:
+ sdk: '>=3.1.0 <4.0.0'
+
+dependencies:
+ flutter:
+ sdk: flutter
+
+ kotlin_plugin:
+ path: ../
+
+ jni:
+ path: ../../../../jni
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+
+ flutter_lints: ^2.0.0
+
+flutter:
+ uses-material-design: true
+
diff --git a/pkgs/jnigen/example/kotlin_plugin/jnigen.yaml b/pkgs/jnigen/example/kotlin_plugin/jnigen.yaml
new file mode 100644
index 0000000..60978f5
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/jnigen.yaml
@@ -0,0 +1,21 @@
+android_sdk_config:
+ add_gradle_deps: true
+ android_example: 'example/'
+
+summarizer:
+ backend: asm
+
+suspend_fun_to_async: true
+
+output:
+ c:
+ library_name: kotlin_plugin_bindings
+ path: src/
+ dart:
+ path: lib/kotlin_bindings.dart
+ structure: single_file
+
+log_level: all
+
+classes:
+ - 'Example'
diff --git a/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_bindings.dart b/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_bindings.dart
new file mode 100644
index 0000000..e1e7abb
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_bindings.dart
@@ -0,0 +1,97 @@
+// Autogenerated by jnigen. DO NOT EDIT!
+
+// ignore_for_file: annotate_overrides
+// ignore_for_file: camel_case_extensions
+// ignore_for_file: camel_case_types
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: doc_directive_unknown
+// ignore_for_file: file_names
+// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: overridden_fields
+// ignore_for_file: unnecessary_cast
+// ignore_for_file: unused_element
+// ignore_for_file: unused_field
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: unused_shown_name
+
+import "dart:isolate" show ReceivePort;
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+import "package:jni/jni.dart" as jni;
+
+// Auto-generated initialization code.
+
+final ffi.Pointer<T> Function<T extends ffi.NativeType>(String sym) jniLookup =
+ ProtectedJniExtensions.initGeneratedLibrary("kotlin_plugin_bindings");
+
+/// from: Example
+class Example extends jni.JObject {
+ @override
+ late final jni.JObjType<Example> $type = type;
+
+ Example.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $ExampleType();
+ static final _new0 =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("Example__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example() {
+ return Example.fromRef(_new0().object);
+ }
+
+ static final _thinkBeforeAnswering = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("Example__thinkBeforeAnswering")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final java.lang.Object thinkBeforeAnswering(kotlin.coroutines.Continuation continuation)
+ /// The returned object must be released after use, by calling the [release] method.
+ Future<jni.JString> thinkBeforeAnswering() async {
+ final $p = ReceivePort();
+ final $c =
+ jni.JObject.fromRef(ProtectedJniExtensions.newPortContinuation($p));
+ _thinkBeforeAnswering(reference, $c.reference).object;
+ final $o = jni.JObjectPtr.fromAddress(await $p.first);
+ final $k = const jni.JStringType().getClass().reference;
+ if (!jni.Jni.env.IsInstanceOf($o, $k)) {
+ throw "Failed";
+ }
+ return const jni.JStringType().fromRef($o);
+ }
+}
+
+final class $ExampleType extends jni.JObjType<Example> {
+ const $ExampleType();
+
+ @override
+ String get signature => r"LExample;";
+
+ @override
+ Example fromRef(jni.JObjectPtr ref) => Example.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($ExampleType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($ExampleType) && other is $ExampleType;
+ }
+}
diff --git a/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_plugin.dart b/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_plugin.dart
new file mode 100644
index 0000000..5919c22
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_plugin.dart
@@ -0,0 +1,3 @@
+library kotlin_plugin;
+
+export 'kotlin_bindings.dart';
diff --git a/pkgs/jnigen/example/kotlin_plugin/pubspec.yaml b/pkgs/jnigen/example/kotlin_plugin/pubspec.yaml
new file mode 100644
index 0000000..fd89ad6
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/pubspec.yaml
@@ -0,0 +1,31 @@
+# Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+name: kotlin_plugin
+description: Example of using jnigen to generate bindings for Kotlin.
+version: 0.0.1
+publish_to: none
+
+environment:
+ sdk: '>=3.1.0 <4.0.0'
+ flutter: ">=1.17.0"
+
+dependencies:
+ flutter:
+ sdk: flutter
+ jni:
+ path: ../../../jni
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+ flutter_lints: ^2.0.0
+ jnigen:
+ path: ../../
+
+flutter:
+ plugin:
+ platforms:
+ android:
+ ffiPlugin: true
diff --git a/pkgs/jnigen/example/kotlin_plugin/src/.clang-format b/pkgs/jnigen/example/kotlin_plugin/src/.clang-format
new file mode 100644
index 0000000..a256c2f
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/src/.clang-format
@@ -0,0 +1,15 @@
+# From dart SDK: https://github.com/dart-lang/sdk/blob/main/.clang-format
+
+# Defines the Chromium style for automatic reformatting.
+# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
+BasedOnStyle: Chromium
+
+# clang-format doesn't seem to do a good job of this for longer comments.
+ReflowComments: 'false'
+
+# We have lots of these. Though we need to put them all in curly braces,
+# clang-format can't do that.
+AllowShortIfStatementsOnASingleLine: 'true'
+
+# Put escaped newlines into the rightmost column.
+AlignEscapedNewlinesLeft: false
diff --git a/pkgs/jnigen/example/kotlin_plugin/src/CMakeLists.txt b/pkgs/jnigen/example/kotlin_plugin/src/CMakeLists.txt
new file mode 100644
index 0000000..78d9dca
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/src/CMakeLists.txt
@@ -0,0 +1,32 @@
+# jni_native_build (Build with jni:setup. Do not delete this line.)
+
+# 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)
+
+project(kotlin_plugin_bindings VERSION 0.0.1 LANGUAGES C)
+
+add_library(kotlin_plugin_bindings SHARED
+ "./kotlin_plugin_bindings.c"
+)
+
+set_target_properties(kotlin_plugin_bindings PROPERTIES
+ OUTPUT_NAME "kotlin_plugin_bindings"
+)
+
+target_compile_definitions(kotlin_plugin_bindings PUBLIC DART_SHARED_LIB)
+
+if(WIN32)
+ set_target_properties(${TARGET_NAME} PROPERTIES
+ LINK_FLAGS "/DELAYLOAD:jvm.dll")
+endif()
+
+if (ANDROID)
+ target_link_libraries(kotlin_plugin_bindings log)
+else()
+ find_package(Java REQUIRED)
+ find_package(JNI REQUIRED)
+ include_directories(${JNI_INCLUDE_DIRS})
+ target_link_libraries(kotlin_plugin_bindings ${JNI_LIBRARIES})
+endif()
diff --git a/pkgs/jnigen/example/kotlin_plugin/src/dartjni.h b/pkgs/jnigen/example/kotlin_plugin/src/dartjni.h
new file mode 100644
index 0000000..8f1dc74
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/src/dartjni.h
@@ -0,0 +1,424 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#pragma once
+
+// Note: include appropriate system jni.h as found by CMake, not third_party/jni.h.
+#include <jni.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if _WIN32
+#include <windows.h>
+#else
+#include <pthread.h>
+#include <unistd.h>
+#endif
+
+#if _WIN32
+#define FFI_PLUGIN_EXPORT __declspec(dllexport)
+#else
+#define FFI_PLUGIN_EXPORT
+#endif
+
+#if defined _WIN32
+#define thread_local __declspec(thread)
+#else
+#define thread_local __thread
+#endif
+
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
+
+#ifdef __ANDROID__
+#define __ENVP_CAST (JNIEnv**)
+#else
+#define __ENVP_CAST (void**)
+#endif
+
+/// Locking functions for windows and pthread.
+
+#if defined _WIN32
+#include <windows.h>
+
+typedef CRITICAL_SECTION MutexLock;
+typedef CONDITION_VARIABLE ConditionVariable;
+
+static inline void init_lock(MutexLock* lock) {
+ InitializeCriticalSection(lock);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+ EnterCriticalSection(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+ LeaveCriticalSection(lock);
+}
+
+static inline void destroy_lock(MutexLock* lock) {
+ DeleteCriticalSection(lock);
+}
+
+static inline void init_cond(ConditionVariable* cond) {
+ InitializeConditionVariable(cond);
+}
+
+static inline void signal_cond(ConditionVariable* cond) {
+ WakeConditionVariable(cond);
+}
+
+static inline void wait_for(ConditionVariable* cond, MutexLock* lock) {
+ SleepConditionVariableCS(cond, lock, INFINITE);
+}
+
+static inline void destroy_cond(ConditionVariable* cond) {
+ // Not available.
+}
+
+#elif defined __APPLE__ || defined __LINUX__ || defined __ANDROID__ || \
+ defined __GNUC__
+#include <pthread.h>
+
+typedef pthread_mutex_t MutexLock;
+typedef pthread_cond_t ConditionVariable;
+
+static inline void init_lock(MutexLock* lock) {
+ pthread_mutex_init(lock, NULL);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+ pthread_mutex_lock(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+ pthread_mutex_unlock(lock);
+}
+
+static inline void destroy_lock(MutexLock* lock) {
+ pthread_mutex_destroy(lock);
+}
+
+static inline void init_cond(ConditionVariable* cond) {
+ pthread_cond_init(cond, NULL);
+}
+
+static inline void signal_cond(ConditionVariable* cond) {
+ pthread_cond_signal(cond);
+}
+
+static inline void wait_for(ConditionVariable* cond, MutexLock* lock) {
+ pthread_cond_wait(cond, lock);
+}
+
+static inline void destroy_cond(ConditionVariable* cond) {
+ pthread_cond_destroy(cond);
+}
+
+#else
+
+#error "No locking/condition variable support; Possibly unsupported platform"
+
+#endif
+
+typedef struct CallbackResult {
+ MutexLock lock;
+ ConditionVariable cond;
+ int ready;
+ jobject object;
+} CallbackResult;
+
+typedef struct JniLocks {
+ MutexLock classLoadingLock;
+ MutexLock methodLoadingLock;
+ MutexLock fieldLoadingLock;
+} JniLocks;
+
+/// Represents the error when dart-jni layer has already spawned singleton VM.
+#define DART_JNI_SINGLETON_EXISTS (-99);
+
+/// Stores the global state of the JNI.
+typedef struct JniContext {
+ JavaVM* jvm;
+ jobject classLoader;
+ jmethodID loadClassMethod;
+ jobject currentActivity;
+ jobject appContext;
+ JniLocks locks;
+} JniContext;
+
+// jniEnv for this thread, used by inline functions in this header,
+// therefore declared as extern.
+extern thread_local JNIEnv* jniEnv;
+
+extern JniContext* jni;
+
+/// Types used by JNI API to distinguish between primitive types.
+enum JniType {
+ booleanType = 0,
+ byteType = 1,
+ shortType = 2,
+ charType = 3,
+ intType = 4,
+ longType = 5,
+ floatType = 6,
+ doubleType = 7,
+ objectType = 8,
+ voidType = 9,
+};
+
+/// Result type for use by JNI.
+///
+/// If [exception] is null, it means the result is valid.
+/// It's assumed that the caller knows the expected type in [result].
+typedef struct JniResult {
+ jvalue value;
+ jthrowable exception;
+} JniResult;
+
+/// Similar to [JniResult] but for class lookups.
+typedef struct JniClassLookupResult {
+ jclass value;
+ jthrowable exception;
+} JniClassLookupResult;
+
+/// Similar to [JniResult] but for method/field ID lookups.
+typedef struct JniPointerResult {
+ const void* value;
+ jthrowable exception;
+} JniPointerResult;
+
+/// JniExceptionDetails holds 2 jstring objects, one is the result of
+/// calling `toString` on exception object, other is stack trace;
+typedef struct JniExceptionDetails {
+ jstring message;
+ jstring stacktrace;
+} JniExceptionDetails;
+
+/// This struct contains functions which wrap method call / field access conveniently along with
+/// exception checking.
+///
+/// Flutter embedding checks for pending JNI exceptions before an FFI transition, which requires us
+/// to check for and clear the exception before returning to dart code, which requires these functions
+/// to return result types.
+typedef struct JniAccessorsStruct {
+ JniClassLookupResult (*getClass)(char* internalName);
+ JniPointerResult (*getFieldID)(jclass cls, char* fieldName, char* signature);
+ JniPointerResult (*getStaticFieldID)(jclass cls,
+ char* fieldName,
+ char* signature);
+ JniPointerResult (*getMethodID)(jclass cls,
+ char* methodName,
+ char* signature);
+ JniPointerResult (*getStaticMethodID)(jclass cls,
+ char* methodName,
+ char* signature);
+ JniResult (*newObject)(jclass cls, jmethodID ctor, jvalue* args);
+ JniResult (*newPrimitiveArray)(jsize length, int type);
+ JniResult (*newObjectArray)(jsize length,
+ jclass elementClass,
+ jobject initialElement);
+ JniResult (*getArrayElement)(jarray array, int index, int type);
+ JniResult (*callMethod)(jobject obj,
+ jmethodID methodID,
+ int callType,
+ jvalue* args);
+ JniResult (*callStaticMethod)(jclass cls,
+ jmethodID methodID,
+ int callType,
+ jvalue* args);
+ JniResult (*getField)(jobject obj, jfieldID fieldID, int callType);
+ JniResult (*getStaticField)(jclass cls, jfieldID fieldID, int callType);
+ JniExceptionDetails (*getExceptionDetails)(jthrowable exception);
+} JniAccessorsStruct;
+
+FFI_PLUGIN_EXPORT JniAccessorsStruct* GetAccessors();
+
+FFI_PLUGIN_EXPORT JavaVM* GetJavaVM(void);
+
+FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv(void);
+
+/// Spawn a JVM with given arguments.
+///
+/// Returns JNI_OK on success, and one of the documented JNI error codes on
+/// failure. It returns DART_JNI_SINGLETON_EXISTS if an attempt to spawn multiple
+/// JVMs is made, even if the underlying API potentially supports multiple VMs.
+FFI_PLUGIN_EXPORT int SpawnJvm(JavaVMInitArgs* args);
+
+/// Load class through platform-specific mechanism.
+///
+/// Currently uses application classloader on android,
+/// and JNIEnv->FindClass on other platforms.
+FFI_PLUGIN_EXPORT jclass FindClass(const char* name);
+
+/// Returns Application classLoader (on Android),
+/// which can be used to load application and platform classes.
+///
+/// On other platforms, NULL is returned.
+FFI_PLUGIN_EXPORT jobject GetClassLoader(void);
+
+/// Returns application context on Android.
+///
+/// On other platforms, NULL is returned.
+FFI_PLUGIN_EXPORT jobject GetApplicationContext(void);
+
+/// Returns current activity of the app on Android.
+FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
+
+static inline void attach_thread() {
+ if (jniEnv == NULL) {
+ (*jni->jvm)->AttachCurrentThread(jni->jvm, __ENVP_CAST & jniEnv, NULL);
+ }
+}
+
+/// Load class into [cls] using platform specific mechanism
+static inline void load_class_platform(jclass* cls, const char* name) {
+#ifdef __ANDROID__
+ jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
+ *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni->classLoader,
+ jni->loadClassMethod, className);
+ (*jniEnv)->DeleteLocalRef(jniEnv, className);
+#else
+ *cls = (*jniEnv)->FindClass(jniEnv, name);
+#endif
+}
+
+static inline void load_class_local_ref(jclass* cls, const char* name) {
+ if (*cls == NULL) {
+ acquire_lock(&jni->locks.classLoadingLock);
+ if (*cls == NULL) {
+ load_class_platform(cls, name);
+ }
+ release_lock(&jni->locks.classLoadingLock);
+ }
+}
+
+static inline void load_class_global_ref(jclass* cls, const char* name) {
+ if (*cls == NULL) {
+ jclass tmp = NULL;
+ acquire_lock(&jni->locks.classLoadingLock);
+ if (*cls == NULL) {
+ load_class_platform(&tmp, name);
+ if (!(*jniEnv)->ExceptionCheck(jniEnv)) {
+ *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
+ (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
+ }
+ }
+ release_lock(&jni->locks.classLoadingLock);
+ }
+}
+
+static inline void load_method(jclass cls,
+ jmethodID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.methodLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.methodLoadingLock);
+ }
+}
+
+static inline void load_static_method(jclass cls,
+ jmethodID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.methodLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.methodLoadingLock);
+ }
+}
+
+static inline void load_field(jclass cls,
+ jfieldID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.fieldLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.fieldLoadingLock);
+ }
+}
+
+static inline void load_static_field(jclass cls,
+ jfieldID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.fieldLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.fieldLoadingLock);
+ }
+}
+
+static inline jobject to_global_ref(jobject ref) {
+ jobject g = (*jniEnv)->NewGlobalRef(jniEnv, ref);
+ (*jniEnv)->DeleteLocalRef(jniEnv, ref);
+ return g;
+}
+
+// These functions are useful for C+Dart bindings, and not required for pure dart bindings.
+
+FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr();
+
+/// For use by jni_gen's generated code
+/// don't use these.
+
+// these 2 fn ptr vars will be defined by generated code library
+extern JniContext* (*context_getter)(void);
+extern JNIEnv* (*env_getter)(void);
+
+// this function will be exported by generated code library
+// it will set above 2 variables.
+FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext* (*cg)(void),
+ JNIEnv* (*eg)(void));
+
+static inline void load_env() {
+ if (jniEnv == NULL) {
+ jni = context_getter();
+ jniEnv = env_getter();
+ }
+}
+
+static inline jthrowable check_exception() {
+ jthrowable exception = (*jniEnv)->ExceptionOccurred(jniEnv);
+ if (exception != NULL) (*jniEnv)->ExceptionClear(jniEnv);
+ if (exception == NULL) return NULL;
+ return to_global_ref(exception);
+}
+
+static inline JniResult to_global_ref_result(jobject ref) {
+ JniResult result;
+ result.exception = check_exception();
+ if (result.exception == NULL) {
+ result.value.l = to_global_ref(ref);
+ }
+ return result;
+}
+
+FFI_PLUGIN_EXPORT intptr_t InitDartApiDL(void* data);
+
+FFI_PLUGIN_EXPORT
+JniResult DartException__ctor(jstring message);
+
+FFI_PLUGIN_EXPORT
+JniResult PortContinuation__ctor(int64_t j);
+
+FFI_PLUGIN_EXPORT
+JniResult PortProxy__newInstance(jobject binaryName,
+ int64_t port,
+ int64_t functionPtr);
+
+FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
diff --git a/pkgs/jnigen/example/kotlin_plugin/src/kotlin_plugin_bindings.c b/pkgs/jnigen/example/kotlin_plugin/src/kotlin_plugin_bindings.c
new file mode 100644
index 0000000..28a2af6
--- /dev/null
+++ b/pkgs/jnigen/example/kotlin_plugin/src/kotlin_plugin_bindings.c
@@ -0,0 +1,50 @@
+// Autogenerated by jnigen. DO NOT EDIT!
+
+#include <stdint.h>
+#include "dartjni.h"
+#include "jni.h"
+
+thread_local JNIEnv* jniEnv;
+JniContext* jni;
+
+JniContext* (*context_getter)(void);
+JNIEnv* (*env_getter)(void);
+
+void setJniGetters(JniContext* (*cg)(void), JNIEnv* (*eg)(void)) {
+ context_getter = cg;
+ env_getter = eg;
+}
+
+// Example
+jclass _c_Example = NULL;
+
+jmethodID _m_Example__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__new0() {
+ load_env();
+ load_class_global_ref(&_c_Example, "Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__new0, "<init>", "()V");
+ if (_m_Example__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_Example, _m_Example__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Example__thinkBeforeAnswering = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__thinkBeforeAnswering(jobject self_, jobject continuation) {
+ load_env();
+ load_class_global_ref(&_c_Example, "Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__thinkBeforeAnswering,
+ "thinkBeforeAnswering",
+ "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;");
+ if (_m_Example__thinkBeforeAnswering == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_Example__thinkBeforeAnswering, continuation);
+ return to_global_ref_result(_result);
+}
diff --git a/pkgs/jnigen/example/notification_plugin/.gitignore b/pkgs/jnigen/example/notification_plugin/.gitignore
new file mode 100644
index 0000000..96486fd
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/.gitignore
@@ -0,0 +1,30 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
+/pubspec.lock
+**/doc/api/
+.dart_tool/
+.packages
+build/
diff --git a/pkgs/jnigen/example/notification_plugin/.metadata b/pkgs/jnigen/example/notification_plugin/.metadata
new file mode 100644
index 0000000..d677252
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/.metadata
@@ -0,0 +1,30 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled.
+
+version:
+ revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
+ channel: stable
+
+project_type: plugin_ffi
+
+# Tracks metadata for the flutter migrate command
+migration:
+ platforms:
+ - platform: root
+ create_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
+ base_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
+ - platform: android
+ create_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
+ base_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
+
+ # User provided section
+
+ # List of Local paths (relative to this file) that should be
+ # ignored by the migrate tool.
+ #
+ # Files that are not part of the templates will be ignored by default.
+ unmanaged_files:
+ - 'lib/main.dart'
+ - 'ios/Runner.xcodeproj/project.pbxproj'
diff --git a/pkgs/jnigen/example/notification_plugin/README.md b/pkgs/jnigen/example/notification_plugin/README.md
new file mode 100644
index 0000000..e1b3af5
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/README.md
@@ -0,0 +1,13 @@
+# notification_plugin
+
+Example of Android plugin project with jnigen.
+
+This plugin project contains [custom code](android/src/main/java/com/example/notification_plugin) which uses the Android libraries. The bindings are generated using [jnigen config](jnigen.yaml) and then used in [flutter example](example/lib/main.dart), with help of `package:jni` APIs.
+
+The command to regenerate JNI bindings is:
+```
+flutter pub run jnigen --config jnigen.yaml # run from notification_plugin project root
+```
+
+The `example/` app must be built at least once in _release_ mode (eg `flutter build apk`) before running jnigen. This is the equivalent of Gradle Sync in Android Studio, and enables `jnigen` to run a Gradle stub and determine release build's classpath, which contains the paths to relevant dependencies. Therefore a build must have been run after cleaning build directories, or updating Java dependencies. This is a known complexity of the Gradle build system, and if you know a solution, please contribute to issue discussion at #33.
+
diff --git a/pkgs/jnigen/example/notification_plugin/analysis_options.yaml b/pkgs/jnigen/example/notification_plugin/analysis_options.yaml
new file mode 100644
index 0000000..a5744c1
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/analysis_options.yaml
@@ -0,0 +1,4 @@
+include: package:flutter_lints/flutter.yaml
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/pkgs/jnigen/example/notification_plugin/android/.gitignore b/pkgs/jnigen/example/notification_plugin/android/.gitignore
new file mode 100644
index 0000000..161bdcd
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/android/.gitignore
@@ -0,0 +1,9 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+.cxx
diff --git a/pkgs/jnigen/example/notification_plugin/android/build.gradle b/pkgs/jnigen/example/notification_plugin/android/build.gradle
new file mode 100644
index 0000000..7643ec5
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/android/build.gradle
@@ -0,0 +1,59 @@
+// The Android Gradle Plugin builds the native code with the Android NDK.
+
+group 'com.example.notification_plugin'
+version '1.0'
+
+buildscript {
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ // The Android Gradle Plugin knows how to build native code with the NDK.
+ classpath 'com.android.tools.build:gradle:7.1.2'
+ }
+}
+
+rootProject.allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+apply plugin: 'com.android.library'
+
+android {
+ // Bumping the plugin compileSdkVersion requires all clients of this plugin
+ // to bump the version in their app.
+ compileSdkVersion 31
+
+ // Bumping the plugin ndkVersion requires all clients of this plugin to bump
+ // the version in their app and to download a newer version of the NDK.
+ ndkVersion "21.1.6352462"
+
+ // Invoke the shared CMake build with the Android Gradle Plugin.
+ externalNativeBuild {
+ cmake {
+ path "../src/CMakeLists.txt"
+
+ // The default CMake version for the Android Gradle Plugin is 3.10.2.
+ // https://developer.android.com/studio/projects/install-ndk#vanilla_cmake
+ //
+ // 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.
+ // version "3.10.2"
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ defaultConfig {
+ minSdkVersion 16
+ }
+}
diff --git a/pkgs/jnigen/example/notification_plugin/android/settings.gradle b/pkgs/jnigen/example/notification_plugin/android/settings.gradle
new file mode 100644
index 0000000..8e0a5b1
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/android/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'notification_plugin'
diff --git a/pkgs/jnigen/example/notification_plugin/android/src/main/AndroidManifest.xml b/pkgs/jnigen/example/notification_plugin/android/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..01cb165
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/android/src/main/AndroidManifest.xml
@@ -0,0 +1,3 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.notification_plugin">
+</manifest>
diff --git a/pkgs/jnigen/example/notification_plugin/android/src/main/java/com/example/notification_plugin/Notifications.java b/pkgs/jnigen/example/notification_plugin/android/src/main/java/com/example/notification_plugin/Notifications.java
new file mode 100644
index 0000000..59f8b7a
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/android/src/main/java/com/example/notification_plugin/Notifications.java
@@ -0,0 +1,36 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.example.notification_plugin;
+
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.Build;
+import androidx.annotation.Keep;
+import androidx.core.app.NotificationCompat;
+
+@Keep
+public class Notifications {
+ public static void showNotification(
+ Context context, int notificationID, String title, String text) {
+ @SuppressWarnings("deprecation")
+ NotificationCompat.Builder builder =
+ new NotificationCompat.Builder(context)
+ .setSmallIcon(android.R.drawable.ic_dialog_info)
+ .setContentTitle(title)
+ .setContentText(text);
+ NotificationManager notificationManager =
+ (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
+ String channelId = "my_channel";
+ NotificationChannel channel =
+ new NotificationChannel(
+ channelId, "My App's notifications", NotificationManager.IMPORTANCE_HIGH);
+ notificationManager.createNotificationChannel(channel);
+ builder.setChannelId(channelId);
+ }
+ notificationManager.notify(notificationID, builder.build());
+ }
+}
diff --git a/pkgs/jnigen/example/notification_plugin/example/.gitignore b/pkgs/jnigen/example/notification_plugin/example/.gitignore
new file mode 100644
index 0000000..24476c5
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/.gitignore
@@ -0,0 +1,44 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
diff --git a/pkgs/jnigen/example/notification_plugin/example/README.md b/pkgs/jnigen/example/notification_plugin/example/README.md
new file mode 100644
index 0000000..0ec9e1d
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/README.md
@@ -0,0 +1,4 @@
+# notification_plugin_example
+
+This app demonstrates how to use the notification_plugin plugin.
+
diff --git a/pkgs/jnigen/example/notification_plugin/example/analysis_options.yaml b/pkgs/jnigen/example/notification_plugin/example/analysis_options.yaml
new file mode 100644
index 0000000..61b6c4d
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/analysis_options.yaml
@@ -0,0 +1,29 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+ # The lint rules applied to this project can be customized in the
+ # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+ # included above or to enable additional rules. A list of all available lints
+ # and their documentation is published at
+ # https://dart-lang.github.io/linter/lints/index.html.
+ #
+ # Instead of disabling a lint rule for the entire project in the
+ # section below, it can also be suppressed for a single line of code
+ # or a specific dart file by using the `// ignore: name_of_lint` and
+ # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+ # producing the lint.
+ rules:
+ # avoid_print: false # Uncomment to disable the `avoid_print` rule
+ # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/.gitignore b/pkgs/jnigen/example/notification_plugin/example/android/.gitignore
new file mode 100644
index 0000000..6f56801
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/.gitignore
@@ -0,0 +1,13 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/app/build.gradle b/pkgs/jnigen/example/notification_plugin/example/android/app/build.gradle
new file mode 100644
index 0000000..7f66900
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/app/build.gradle
@@ -0,0 +1,71 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+ localPropertiesFile.withReader('UTF-8') { reader ->
+ localProperties.load(reader)
+ }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+ throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+ flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+ flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+ compileSdkVersion flutter.compileSdkVersion
+ ndkVersion flutter.ndkVersion
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+
+ defaultConfig {
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId "com.example.notification_plugin_example"
+ // You can update the following values to match your application needs.
+ // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
+ minSdkVersion flutter.minSdkVersion
+ targetSdkVersion flutter.targetSdkVersion
+ versionCode flutterVersionCode.toInteger()
+ versionName flutterVersionName
+ }
+
+ buildTypes {
+ release {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig signingConfigs.debug
+ }
+ }
+}
+
+flutter {
+ source '../..'
+}
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/app/src/debug/AndroidManifest.xml b/pkgs/jnigen/example/notification_plugin/example/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..822a208
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.notification_plugin_example">
+ <!-- The INTERNET permission is required for development. Specifically,
+ the Flutter tool needs it to communicate with the running application
+ to allow setting breakpoints, to provide hot reload, etc.
+ -->
+ <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/AndroidManifest.xml b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..60e7eab
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.notification_plugin_example">
+ <application
+ android:label="notification_plugin_example"
+ android:name="${applicationName}"
+ android:icon="@mipmap/ic_launcher">
+ <activity
+ android:name=".MainActivity"
+ android:exported="true"
+ android:launchMode="singleTop"
+ android:theme="@style/LaunchTheme"
+ android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
+ android:hardwareAccelerated="true"
+ android:windowSoftInputMode="adjustResize">
+ <!-- Specifies an Android theme to apply to this Activity as soon as
+ the Android process has started. This theme is visible to the user
+ while the Flutter UI initializes. After that, this theme continues
+ to determine the Window background behind the Flutter UI. -->
+ <meta-data
+ android:name="io.flutter.embedding.android.NormalTheme"
+ android:resource="@style/NormalTheme"
+ />
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <!-- Don't delete the meta-data below.
+ This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
+ <meta-data
+ android:name="flutterEmbedding"
+ android:value="2" />
+ </application>
+</manifest>
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/kotlin/com/example/notification_plugin_example/MainActivity.kt b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/kotlin/com/example/notification_plugin_example/MainActivity.kt
new file mode 100644
index 0000000..af88e15
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/kotlin/com/example/notification_plugin_example/MainActivity.kt
@@ -0,0 +1,6 @@
+package com.example.notification_plugin_example
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="?android:colorBackground" />
+
+ <!-- You can insert your own image assets here -->
+ <!-- <item>
+ <bitmap
+ android:gravity="center"
+ android:src="@mipmap/launch_image" />
+ </item> -->
+</layer-list>
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/drawable/launch_background.xml b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..304732f
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@android:color/white" />
+
+ <!-- You can insert your own image assets here -->
+ <!-- <item>
+ <bitmap
+ android:gravity="center"
+ android:src="@mipmap/launch_image" />
+ </item> -->
+</layer-list>
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..db77bb4
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..17987b7
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..09d4391
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d5f1c8d
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d6372e
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/values-night/styles.xml b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..06952be
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
+ <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
+ <!-- Show a splash screen on the activity. Automatically removed when
+ the Flutter engine draws its first frame -->
+ <item name="android:windowBackground">@drawable/launch_background</item>
+ </style>
+ <!-- Theme applied to the Android Window as soon as the process has started.
+ This theme determines the color of the Android Window while your
+ Flutter UI initializes, as well as behind your Flutter UI while its
+ running.
+
+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
+ <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
+ <item name="android:windowBackground">?android:colorBackground</item>
+ </style>
+</resources>
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/values/styles.xml b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..cb1ef88
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
+ <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
+ <!-- Show a splash screen on the activity. Automatically removed when
+ the Flutter engine draws its first frame -->
+ <item name="android:windowBackground">@drawable/launch_background</item>
+ </style>
+ <!-- Theme applied to the Android Window as soon as the process has started.
+ This theme determines the color of the Android Window while your
+ Flutter UI initializes, as well as behind your Flutter UI while its
+ running.
+
+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
+ <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
+ <item name="android:windowBackground">?android:colorBackground</item>
+ </style>
+</resources>
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/app/src/profile/AndroidManifest.xml b/pkgs/jnigen/example/notification_plugin/example/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..822a208
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.notification_plugin_example">
+ <!-- The INTERNET permission is required for development. Specifically,
+ the Flutter tool needs it to communicate with the running application
+ to allow setting breakpoints, to provide hot reload, etc.
+ -->
+ <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/build.gradle b/pkgs/jnigen/example/notification_plugin/example/android/build.gradle
new file mode 100644
index 0000000..3cdaac9
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/build.gradle
@@ -0,0 +1,31 @@
+buildscript {
+ ext.kotlin_version = '1.6.10'
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:7.1.2'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+ project.evaluationDependsOn(':app')
+}
+
+tasks.register("clean", Delete) {
+ delete rootProject.buildDir
+}
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/gradle.properties b/pkgs/jnigen/example/notification_plugin/example/android/gradle.properties
new file mode 100644
index 0000000..94adc3a
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/gradle/wrapper/gradle-wrapper.properties b/pkgs/jnigen/example/notification_plugin/example/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..cb24abd
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
diff --git a/pkgs/jnigen/example/notification_plugin/example/android/settings.gradle b/pkgs/jnigen/example/notification_plugin/example/android/settings.gradle
new file mode 100644
index 0000000..44e62bc
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/android/settings.gradle
@@ -0,0 +1,11 @@
+include ':app'
+
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
+
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/pkgs/jnigen/example/notification_plugin/example/lib/main.dart b/pkgs/jnigen/example/notification_plugin/example/lib/main.dart
new file mode 100644
index 0000000..c834bcb
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/lib/main.dart
@@ -0,0 +1,89 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:flutter/material.dart';
+import 'package:jni/jni.dart';
+
+// The hierarchy created in generated code will mirror the java package
+// structure. This is an implementation convenience and we may allow
+// more customization in future.
+import 'package:notification_plugin/notifications.dart';
+
+JObject activity = JObject.fromRef(Jni.getCurrentActivity());
+
+int i = 0;
+
+void showNotification(String title, String text) {
+ i = i + 1;
+ var jTitle = JString.fromString(title);
+ var jText = JString.fromString(text);
+ Notifications.showNotification(activity, i, jTitle, jText);
+ jTitle.release();
+ jText.release();
+}
+
+void main() {
+ runApp(const MyApp());
+}
+
+class MyApp extends StatelessWidget {
+ const MyApp({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ title: 'Flutter Demo',
+ theme: ThemeData(
+ primarySwatch: Colors.teal,
+ ),
+ home: MyHomePage(title: 'Flutter Demo Home Page'),
+ );
+ }
+}
+
+class MyHomePage extends StatelessWidget {
+ MyHomePage({Key? key, required this.title}) : super(key: key);
+
+ final String title;
+
+ final _title = TextEditingController(text: 'Hello from JNI');
+ final _text = TextEditingController(text: '😀');
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text(title),
+ ),
+ body: Center(
+ child: Padding(
+ padding: const EdgeInsets.all(16),
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ TextFormField(
+ controller: _title,
+ textCapitalization: TextCapitalization.sentences,
+ decoration:
+ const InputDecoration(labelText: 'Notification title'),
+ ),
+ TextFormField(
+ controller: _text,
+ keyboardType: TextInputType.multiline,
+ minLines: 1,
+ maxLines: 4,
+ decoration:
+ const InputDecoration(labelText: 'Notification text'),
+ ),
+ ElevatedButton(
+ child: const Text('Show Notification'),
+ onPressed: () => showNotification(_title.text, _text.text),
+ ),
+ ],
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/pkgs/jnigen/example/notification_plugin/example/pubspec.yaml b/pkgs/jnigen/example/notification_plugin/example/pubspec.yaml
new file mode 100644
index 0000000..35f3357
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/example/pubspec.yaml
@@ -0,0 +1,89 @@
+name: notification_plugin_example
+description: Demonstrates how to use notification_plugin.
+
+# The following line prevents the package from being accidentally published to
+# pub.dev using `flutter pub publish`. This is preferred for private packages.
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+# The following defines the version and build number for your application.
+# A version number is three numbers separated by dots, like 1.2.43
+# followed by an optional build number separated by a +.
+# Both the version and the builder number may be overridden in flutter
+# build by specifying --build-name and --build-number, respectively.
+# In Android, build-name is used as versionName while build-number used as versionCode.
+# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
+# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
+# Read more about iOS versioning at
+# 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.0+1
+
+environment:
+ sdk: '>=3.1.0 <4.0.0'
+
+dependencies:
+ flutter:
+ sdk: flutter
+
+ notification_plugin:
+ path: ../
+
+ jni:
+ path: ../../../../jni/
+ # The following adds the Cupertino Icons font to your application.
+ # Use with the CupertinoIcons class for iOS style icons.
+ cupertino_icons: ^1.0.2
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+
+ # The "flutter_lints" package below contains a set of recommended lints to
+ # encourage good coding practices. The lint set provided by the package is
+ # activated in the `analysis_options.yaml` file located at the root of your
+ # package. See that file for information about deactivating specific lint
+ # rules and activating additional ones.
+ flutter_lints: ^2.0.0
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter packages.
+flutter:
+
+ # The following line ensures that the Material Icons font is
+ # included with your application, so that you can use the icons in
+ # the material Icons class.
+ uses-material-design: true
+
+ # To add assets to your application, add an assets section, like this:
+ # assets:
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
+
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/assets-and-images/#resolution-aware
+
+ # For details regarding adding assets from package dependencies, see
+ # https://flutter.dev/assets-and-images/#from-packages
+
+ # To add custom fonts to your application, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts from package dependencies,
+ # see https://flutter.dev/custom-fonts/#from-packages
diff --git a/pkgs/jnigen/example/notification_plugin/jnigen.yaml b/pkgs/jnigen/example/notification_plugin/jnigen.yaml
new file mode 100644
index 0000000..21f4106
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/jnigen.yaml
@@ -0,0 +1,24 @@
+android_sdk_config:
+ add_gradle_deps: true
+ android_example: 'example/'
+
+preamble: |
+ // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+ // for details. All rights reserved. Use of this source code is governed by a
+ // BSD-style license that can be found in the LICENSE file.
+
+source_path:
+ - 'android/src/main/java'
+classes:
+ - 'com.example.notification_plugin.Notifications'
+
+output:
+ c:
+ path: 'src/'
+ library_name: notification_plugin
+ dart:
+ path: 'lib/notifications.dart'
+ ## Output to single file instead of recreating source's file structure.
+ ## This will be useful to reduce clutter when binding a small number of
+ ## classes.
+ structure: 'single_file'
diff --git a/pkgs/jnigen/example/notification_plugin/lib/notifications.dart b/pkgs/jnigen/example/notification_plugin/lib/notifications.dart
new file mode 100644
index 0000000..d91a2f5
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/lib/notifications.dart
@@ -0,0 +1,102 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+// ignore_for_file: annotate_overrides
+// ignore_for_file: camel_case_extensions
+// ignore_for_file: camel_case_types
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: doc_directive_unknown
+// ignore_for_file: file_names
+// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: overridden_fields
+// ignore_for_file: unnecessary_cast
+// ignore_for_file: unused_element
+// ignore_for_file: unused_field
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: unused_shown_name
+
+import "dart:isolate" show ReceivePort;
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+import "package:jni/jni.dart" as jni;
+
+// Auto-generated initialization code.
+
+final ffi.Pointer<T> Function<T extends ffi.NativeType>(String sym) jniLookup =
+ ProtectedJniExtensions.initGeneratedLibrary("notification_plugin");
+
+/// from: com.example.notification_plugin.Notifications
+class Notifications extends jni.JObject {
+ @override
+ late final jni.JObjType<Notifications> $type = type;
+
+ Notifications.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $NotificationsType();
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Notifications__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Notifications() {
+ return Notifications.fromRef(_new0().object);
+ }
+
+ static final _showNotification = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("Notifications__showNotification")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, int,
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public void showNotification(android.content.Context context, int notificationID, java.lang.String title, java.lang.String text)
+ static void showNotification(
+ jni.JObject context,
+ int notificationID,
+ jni.JString title,
+ jni.JString text,
+ ) {
+ return _showNotification(
+ context.reference, notificationID, title.reference, text.reference)
+ .check();
+ }
+}
+
+final class $NotificationsType extends jni.JObjType<Notifications> {
+ const $NotificationsType();
+
+ @override
+ String get signature => r"Lcom/example/notification_plugin/Notifications;";
+
+ @override
+ Notifications fromRef(jni.JObjectPtr ref) => Notifications.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($NotificationsType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($NotificationsType) &&
+ other is $NotificationsType;
+ }
+}
diff --git a/pkgs/jnigen/example/notification_plugin/pubspec.yaml b/pkgs/jnigen/example/notification_plugin/pubspec.yaml
new file mode 100644
index 0000000..1f6cf49
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/pubspec.yaml
@@ -0,0 +1,76 @@
+name: notification_plugin
+description: Example for Android plugin with custom Java code using jnigen.
+version: 0.0.1
+publish_to: none
+homepage: https://github.com/dart-lang/jnigen
+
+environment:
+ sdk: '>=3.1.0 <4.0.0'
+ flutter: ">=2.11.0"
+
+dependencies:
+ jni:
+ path: ../../../jni/
+ flutter:
+ sdk: flutter
+ plugin_platform_interface: ^2.0.2
+
+dev_dependencies:
+ jnigen:
+ path: ../../
+ flutter_test:
+ sdk: flutter
+ flutter_lints: ^2.0.0
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter packages.
+flutter:
+ # This section identifies this Flutter project as a plugin project.
+ # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.)
+ # which should be registered in the plugin registry. This is required for
+ # using method channels.
+ # The Android 'package' specifies package in which the registered class is.
+ # This is required for using method channels on Android.
+ # The 'ffiPlugin' specifies that native code should be built and bundled.
+ # This is required for using `dart:ffi`.
+ # All these are used by the tooling to maintain consistency when
+ # adding or updating assets for this project.
+ #
+ # Please refer to README.md for a detailed explanation.
+ plugin:
+ platforms:
+ android:
+ ffiPlugin: true
+
+ # To add assets to your plugin package, add an assets section, like this:
+ # assets:
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
+ #
+ # For details regarding assets in packages, see
+ # https://flutter.dev/assets-and-images/#from-packages
+ #
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/assets-and-images/#resolution-aware
+
+ # To add custom fonts to your plugin package, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts in packages, see
+ # https://flutter.dev/custom-fonts/#from-packages
diff --git a/pkgs/jnigen/example/notification_plugin/src/.clang-format b/pkgs/jnigen/example/notification_plugin/src/.clang-format
new file mode 100644
index 0000000..a256c2f
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/src/.clang-format
@@ -0,0 +1,15 @@
+# From dart SDK: https://github.com/dart-lang/sdk/blob/main/.clang-format
+
+# Defines the Chromium style for automatic reformatting.
+# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
+BasedOnStyle: Chromium
+
+# clang-format doesn't seem to do a good job of this for longer comments.
+ReflowComments: 'false'
+
+# We have lots of these. Though we need to put them all in curly braces,
+# clang-format can't do that.
+AllowShortIfStatementsOnASingleLine: 'true'
+
+# Put escaped newlines into the rightmost column.
+AlignEscapedNewlinesLeft: false
diff --git a/pkgs/jnigen/example/notification_plugin/src/CMakeLists.txt b/pkgs/jnigen/example/notification_plugin/src/CMakeLists.txt
new file mode 100644
index 0000000..39c9850
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/src/CMakeLists.txt
@@ -0,0 +1,32 @@
+# jni_native_build (Build with jni:setup. Do not delete this line.)
+
+# 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)
+
+project(notification_plugin VERSION 0.0.1 LANGUAGES C)
+
+add_library(notification_plugin SHARED
+ "./notification_plugin.c"
+)
+
+set_target_properties(notification_plugin PROPERTIES
+ OUTPUT_NAME "notification_plugin"
+)
+
+target_compile_definitions(notification_plugin PUBLIC DART_SHARED_LIB)
+
+if(WIN32)
+ set_target_properties(${TARGET_NAME} PROPERTIES
+ LINK_FLAGS "/DELAYLOAD:jvm.dll")
+endif()
+
+if (ANDROID)
+ target_link_libraries(notification_plugin log)
+else()
+ find_package(Java REQUIRED)
+ find_package(JNI REQUIRED)
+ include_directories(${JNI_INCLUDE_DIRS})
+ target_link_libraries(notification_plugin ${JNI_LIBRARIES})
+endif()
diff --git a/pkgs/jnigen/example/notification_plugin/src/dartjni.h b/pkgs/jnigen/example/notification_plugin/src/dartjni.h
new file mode 100644
index 0000000..8f1dc74
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/src/dartjni.h
@@ -0,0 +1,424 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#pragma once
+
+// Note: include appropriate system jni.h as found by CMake, not third_party/jni.h.
+#include <jni.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if _WIN32
+#include <windows.h>
+#else
+#include <pthread.h>
+#include <unistd.h>
+#endif
+
+#if _WIN32
+#define FFI_PLUGIN_EXPORT __declspec(dllexport)
+#else
+#define FFI_PLUGIN_EXPORT
+#endif
+
+#if defined _WIN32
+#define thread_local __declspec(thread)
+#else
+#define thread_local __thread
+#endif
+
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
+
+#ifdef __ANDROID__
+#define __ENVP_CAST (JNIEnv**)
+#else
+#define __ENVP_CAST (void**)
+#endif
+
+/// Locking functions for windows and pthread.
+
+#if defined _WIN32
+#include <windows.h>
+
+typedef CRITICAL_SECTION MutexLock;
+typedef CONDITION_VARIABLE ConditionVariable;
+
+static inline void init_lock(MutexLock* lock) {
+ InitializeCriticalSection(lock);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+ EnterCriticalSection(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+ LeaveCriticalSection(lock);
+}
+
+static inline void destroy_lock(MutexLock* lock) {
+ DeleteCriticalSection(lock);
+}
+
+static inline void init_cond(ConditionVariable* cond) {
+ InitializeConditionVariable(cond);
+}
+
+static inline void signal_cond(ConditionVariable* cond) {
+ WakeConditionVariable(cond);
+}
+
+static inline void wait_for(ConditionVariable* cond, MutexLock* lock) {
+ SleepConditionVariableCS(cond, lock, INFINITE);
+}
+
+static inline void destroy_cond(ConditionVariable* cond) {
+ // Not available.
+}
+
+#elif defined __APPLE__ || defined __LINUX__ || defined __ANDROID__ || \
+ defined __GNUC__
+#include <pthread.h>
+
+typedef pthread_mutex_t MutexLock;
+typedef pthread_cond_t ConditionVariable;
+
+static inline void init_lock(MutexLock* lock) {
+ pthread_mutex_init(lock, NULL);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+ pthread_mutex_lock(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+ pthread_mutex_unlock(lock);
+}
+
+static inline void destroy_lock(MutexLock* lock) {
+ pthread_mutex_destroy(lock);
+}
+
+static inline void init_cond(ConditionVariable* cond) {
+ pthread_cond_init(cond, NULL);
+}
+
+static inline void signal_cond(ConditionVariable* cond) {
+ pthread_cond_signal(cond);
+}
+
+static inline void wait_for(ConditionVariable* cond, MutexLock* lock) {
+ pthread_cond_wait(cond, lock);
+}
+
+static inline void destroy_cond(ConditionVariable* cond) {
+ pthread_cond_destroy(cond);
+}
+
+#else
+
+#error "No locking/condition variable support; Possibly unsupported platform"
+
+#endif
+
+typedef struct CallbackResult {
+ MutexLock lock;
+ ConditionVariable cond;
+ int ready;
+ jobject object;
+} CallbackResult;
+
+typedef struct JniLocks {
+ MutexLock classLoadingLock;
+ MutexLock methodLoadingLock;
+ MutexLock fieldLoadingLock;
+} JniLocks;
+
+/// Represents the error when dart-jni layer has already spawned singleton VM.
+#define DART_JNI_SINGLETON_EXISTS (-99);
+
+/// Stores the global state of the JNI.
+typedef struct JniContext {
+ JavaVM* jvm;
+ jobject classLoader;
+ jmethodID loadClassMethod;
+ jobject currentActivity;
+ jobject appContext;
+ JniLocks locks;
+} JniContext;
+
+// jniEnv for this thread, used by inline functions in this header,
+// therefore declared as extern.
+extern thread_local JNIEnv* jniEnv;
+
+extern JniContext* jni;
+
+/// Types used by JNI API to distinguish between primitive types.
+enum JniType {
+ booleanType = 0,
+ byteType = 1,
+ shortType = 2,
+ charType = 3,
+ intType = 4,
+ longType = 5,
+ floatType = 6,
+ doubleType = 7,
+ objectType = 8,
+ voidType = 9,
+};
+
+/// Result type for use by JNI.
+///
+/// If [exception] is null, it means the result is valid.
+/// It's assumed that the caller knows the expected type in [result].
+typedef struct JniResult {
+ jvalue value;
+ jthrowable exception;
+} JniResult;
+
+/// Similar to [JniResult] but for class lookups.
+typedef struct JniClassLookupResult {
+ jclass value;
+ jthrowable exception;
+} JniClassLookupResult;
+
+/// Similar to [JniResult] but for method/field ID lookups.
+typedef struct JniPointerResult {
+ const void* value;
+ jthrowable exception;
+} JniPointerResult;
+
+/// JniExceptionDetails holds 2 jstring objects, one is the result of
+/// calling `toString` on exception object, other is stack trace;
+typedef struct JniExceptionDetails {
+ jstring message;
+ jstring stacktrace;
+} JniExceptionDetails;
+
+/// This struct contains functions which wrap method call / field access conveniently along with
+/// exception checking.
+///
+/// Flutter embedding checks for pending JNI exceptions before an FFI transition, which requires us
+/// to check for and clear the exception before returning to dart code, which requires these functions
+/// to return result types.
+typedef struct JniAccessorsStruct {
+ JniClassLookupResult (*getClass)(char* internalName);
+ JniPointerResult (*getFieldID)(jclass cls, char* fieldName, char* signature);
+ JniPointerResult (*getStaticFieldID)(jclass cls,
+ char* fieldName,
+ char* signature);
+ JniPointerResult (*getMethodID)(jclass cls,
+ char* methodName,
+ char* signature);
+ JniPointerResult (*getStaticMethodID)(jclass cls,
+ char* methodName,
+ char* signature);
+ JniResult (*newObject)(jclass cls, jmethodID ctor, jvalue* args);
+ JniResult (*newPrimitiveArray)(jsize length, int type);
+ JniResult (*newObjectArray)(jsize length,
+ jclass elementClass,
+ jobject initialElement);
+ JniResult (*getArrayElement)(jarray array, int index, int type);
+ JniResult (*callMethod)(jobject obj,
+ jmethodID methodID,
+ int callType,
+ jvalue* args);
+ JniResult (*callStaticMethod)(jclass cls,
+ jmethodID methodID,
+ int callType,
+ jvalue* args);
+ JniResult (*getField)(jobject obj, jfieldID fieldID, int callType);
+ JniResult (*getStaticField)(jclass cls, jfieldID fieldID, int callType);
+ JniExceptionDetails (*getExceptionDetails)(jthrowable exception);
+} JniAccessorsStruct;
+
+FFI_PLUGIN_EXPORT JniAccessorsStruct* GetAccessors();
+
+FFI_PLUGIN_EXPORT JavaVM* GetJavaVM(void);
+
+FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv(void);
+
+/// Spawn a JVM with given arguments.
+///
+/// Returns JNI_OK on success, and one of the documented JNI error codes on
+/// failure. It returns DART_JNI_SINGLETON_EXISTS if an attempt to spawn multiple
+/// JVMs is made, even if the underlying API potentially supports multiple VMs.
+FFI_PLUGIN_EXPORT int SpawnJvm(JavaVMInitArgs* args);
+
+/// Load class through platform-specific mechanism.
+///
+/// Currently uses application classloader on android,
+/// and JNIEnv->FindClass on other platforms.
+FFI_PLUGIN_EXPORT jclass FindClass(const char* name);
+
+/// Returns Application classLoader (on Android),
+/// which can be used to load application and platform classes.
+///
+/// On other platforms, NULL is returned.
+FFI_PLUGIN_EXPORT jobject GetClassLoader(void);
+
+/// Returns application context on Android.
+///
+/// On other platforms, NULL is returned.
+FFI_PLUGIN_EXPORT jobject GetApplicationContext(void);
+
+/// Returns current activity of the app on Android.
+FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
+
+static inline void attach_thread() {
+ if (jniEnv == NULL) {
+ (*jni->jvm)->AttachCurrentThread(jni->jvm, __ENVP_CAST & jniEnv, NULL);
+ }
+}
+
+/// Load class into [cls] using platform specific mechanism
+static inline void load_class_platform(jclass* cls, const char* name) {
+#ifdef __ANDROID__
+ jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
+ *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni->classLoader,
+ jni->loadClassMethod, className);
+ (*jniEnv)->DeleteLocalRef(jniEnv, className);
+#else
+ *cls = (*jniEnv)->FindClass(jniEnv, name);
+#endif
+}
+
+static inline void load_class_local_ref(jclass* cls, const char* name) {
+ if (*cls == NULL) {
+ acquire_lock(&jni->locks.classLoadingLock);
+ if (*cls == NULL) {
+ load_class_platform(cls, name);
+ }
+ release_lock(&jni->locks.classLoadingLock);
+ }
+}
+
+static inline void load_class_global_ref(jclass* cls, const char* name) {
+ if (*cls == NULL) {
+ jclass tmp = NULL;
+ acquire_lock(&jni->locks.classLoadingLock);
+ if (*cls == NULL) {
+ load_class_platform(&tmp, name);
+ if (!(*jniEnv)->ExceptionCheck(jniEnv)) {
+ *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
+ (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
+ }
+ }
+ release_lock(&jni->locks.classLoadingLock);
+ }
+}
+
+static inline void load_method(jclass cls,
+ jmethodID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.methodLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.methodLoadingLock);
+ }
+}
+
+static inline void load_static_method(jclass cls,
+ jmethodID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.methodLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.methodLoadingLock);
+ }
+}
+
+static inline void load_field(jclass cls,
+ jfieldID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.fieldLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.fieldLoadingLock);
+ }
+}
+
+static inline void load_static_field(jclass cls,
+ jfieldID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.fieldLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.fieldLoadingLock);
+ }
+}
+
+static inline jobject to_global_ref(jobject ref) {
+ jobject g = (*jniEnv)->NewGlobalRef(jniEnv, ref);
+ (*jniEnv)->DeleteLocalRef(jniEnv, ref);
+ return g;
+}
+
+// These functions are useful for C+Dart bindings, and not required for pure dart bindings.
+
+FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr();
+
+/// For use by jni_gen's generated code
+/// don't use these.
+
+// these 2 fn ptr vars will be defined by generated code library
+extern JniContext* (*context_getter)(void);
+extern JNIEnv* (*env_getter)(void);
+
+// this function will be exported by generated code library
+// it will set above 2 variables.
+FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext* (*cg)(void),
+ JNIEnv* (*eg)(void));
+
+static inline void load_env() {
+ if (jniEnv == NULL) {
+ jni = context_getter();
+ jniEnv = env_getter();
+ }
+}
+
+static inline jthrowable check_exception() {
+ jthrowable exception = (*jniEnv)->ExceptionOccurred(jniEnv);
+ if (exception != NULL) (*jniEnv)->ExceptionClear(jniEnv);
+ if (exception == NULL) return NULL;
+ return to_global_ref(exception);
+}
+
+static inline JniResult to_global_ref_result(jobject ref) {
+ JniResult result;
+ result.exception = check_exception();
+ if (result.exception == NULL) {
+ result.value.l = to_global_ref(ref);
+ }
+ return result;
+}
+
+FFI_PLUGIN_EXPORT intptr_t InitDartApiDL(void* data);
+
+FFI_PLUGIN_EXPORT
+JniResult DartException__ctor(jstring message);
+
+FFI_PLUGIN_EXPORT
+JniResult PortContinuation__ctor(int64_t j);
+
+FFI_PLUGIN_EXPORT
+JniResult PortProxy__newInstance(jobject binaryName,
+ int64_t port,
+ int64_t functionPtr);
+
+FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
diff --git a/pkgs/jnigen/example/notification_plugin/src/notification_plugin.c b/pkgs/jnigen/example/notification_plugin/src/notification_plugin.c
new file mode 100644
index 0000000..9f1e577
--- /dev/null
+++ b/pkgs/jnigen/example/notification_plugin/src/notification_plugin.c
@@ -0,0 +1,61 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+#include <stdint.h>
+#include "dartjni.h"
+#include "jni.h"
+
+thread_local JNIEnv* jniEnv;
+JniContext* jni;
+
+JniContext* (*context_getter)(void);
+JNIEnv* (*env_getter)(void);
+
+void setJniGetters(JniContext* (*cg)(void), JNIEnv* (*eg)(void)) {
+ context_getter = cg;
+ env_getter = eg;
+}
+
+// com.example.notification_plugin.Notifications
+jclass _c_Notifications = NULL;
+
+jmethodID _m_Notifications__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Notifications__new0() {
+ load_env();
+ load_class_global_ref(&_c_Notifications,
+ "com/example/notification_plugin/Notifications");
+ if (_c_Notifications == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Notifications, &_m_Notifications__new0, "<init>", "()V");
+ if (_m_Notifications__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_Notifications, _m_Notifications__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Notifications__showNotification = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Notifications__showNotification(jobject context,
+ int32_t notificationID,
+ jobject title,
+ jobject text) {
+ load_env();
+ load_class_global_ref(&_c_Notifications,
+ "com/example/notification_plugin/Notifications");
+ if (_c_Notifications == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_Notifications, &_m_Notifications__showNotification, "showNotification",
+ "(Landroid/content/Context;ILjava/lang/String;Ljava/lang/String;)V");
+ if (_m_Notifications__showNotification == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallStaticVoidMethod(jniEnv, _c_Notifications,
+ _m_Notifications__showNotification, context,
+ notificationID, title, text);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/.gitignore b/pkgs/jnigen/example/pdfbox_plugin/.gitignore
new file mode 100644
index 0000000..a117acd
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/.gitignore
@@ -0,0 +1,42 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
+/pubspec.lock
+**/doc/api/
+.dart_tool/
+.packages
+build/
+
+## Downloaded by jnigen
+/mvn_java/
+/mvn_jar/
+## Sometimes generated by maven.
+## TODO(#34) This is unwanted.
+/target/
+
+# Builds & downloads
+*.pdf
+*.jar
+*.exe
diff --git a/pkgs/jnigen/example/pdfbox_plugin/.metadata b/pkgs/jnigen/example/pdfbox_plugin/.metadata
new file mode 100644
index 0000000..9d23aa9
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/.metadata
@@ -0,0 +1,36 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled.
+
+version:
+ revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+ channel: stable
+
+project_type: plugin_ffi
+
+# Tracks metadata for the flutter migrate command
+migration:
+ platforms:
+ - platform: root
+ create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+ base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+ - platform: android
+ create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+ base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+ - platform: linux
+ create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+ base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+ - platform: windows
+ create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+ base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
+
+ # User provided section
+
+ # List of Local paths (relative to this file) that should be
+ # ignored by the migrate tool.
+ #
+ # Files that are not part of the templates will be ignored by default.
+ unmanaged_files:
+ - 'lib/main.dart'
+ - 'ios/Runner.xcodeproj/project.pbxproj'
diff --git a/pkgs/jnigen/example/pdfbox_plugin/README.md b/pkgs/jnigen/example/pdfbox_plugin/README.md
new file mode 100644
index 0000000..efa8caa
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/README.md
@@ -0,0 +1,8 @@
+# pdfbox_plugin
+
+Example of a JNI plugin using `jnigen` to auto-generate bindings for PDFBox java library.
+
+Bindings can be generated by running `dart run jnigen --config jnigen.yaml`. Required source code and JARs will be downloaded using maven (requires `mvn` command).
+
+`jnigen` is also available as an API which tooling scripts can use. See `tool/generate_bindings.dart` for the script equivalent of the YAML file.
+
diff --git a/pkgs/jnigen/example/pdfbox_plugin/analysis_options.yaml b/pkgs/jnigen/example/pdfbox_plugin/analysis_options.yaml
new file mode 100644
index 0000000..198e7e0
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/analysis_options.yaml
@@ -0,0 +1,4 @@
+#include: package:flutter_lints/flutter.yaml
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/pkgs/jnigen/example/pdfbox_plugin/android/.gitignore b/pkgs/jnigen/example/pdfbox_plugin/android/.gitignore
new file mode 100644
index 0000000..161bdcd
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/android/.gitignore
@@ -0,0 +1,9 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+.cxx
diff --git a/pkgs/jnigen/example/pdfbox_plugin/android/build.gradle b/pkgs/jnigen/example/pdfbox_plugin/android/build.gradle
new file mode 100644
index 0000000..9c3bca8
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/android/build.gradle
@@ -0,0 +1,59 @@
+// The Android Gradle Plugin builds the native code with the Android NDK.
+
+group 'com.example.pdfbox_plugin'
+version '1.0'
+
+buildscript {
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ // The Android Gradle Plugin knows how to build native code with the NDK.
+ classpath 'com.android.tools.build:gradle:7.1.2'
+ }
+}
+
+rootProject.allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+apply plugin: 'com.android.library'
+
+android {
+ // Bumping the plugin compileSdkVersion requires all clients of this plugin
+ // to bump the version in their app.
+ compileSdkVersion 31
+
+ // Bumping the plugin ndkVersion requires all clients of this plugin to bump
+ // the version in their app and to download a newer version of the NDK.
+ ndkVersion "21.1.6352462"
+
+ // Invoke the shared CMake build with the Android Gradle Plugin.
+ externalNativeBuild {
+ cmake {
+ path "../src/CMakeLists.txt"
+
+ // The default CMake version for the Android Gradle Plugin is 3.10.2.
+ // https://developer.android.com/studio/projects/install-ndk#vanilla_cmake
+ //
+ // 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.
+ // version "3.10.2"
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ defaultConfig {
+ minSdkVersion 16
+ }
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/android/settings.gradle b/pkgs/jnigen/example/pdfbox_plugin/android/settings.gradle
new file mode 100644
index 0000000..84ca2f9
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/android/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'pdfbox_plugin'
diff --git a/pkgs/jnigen/example/pdfbox_plugin/android/src/main/AndroidManifest.xml b/pkgs/jnigen/example/pdfbox_plugin/android/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ae0f6a3
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/android/src/main/AndroidManifest.xml
@@ -0,0 +1,3 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.pdfbox_plugin">
+</manifest>
diff --git a/pkgs/jnigen/example/pdfbox_plugin/dart_example/.gitignore b/pkgs/jnigen/example/pdfbox_plugin/dart_example/.gitignore
new file mode 100644
index 0000000..9644944
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/dart_example/.gitignore
@@ -0,0 +1,12 @@
+# Files and directories created by pub.
+.dart_tool/
+.packages
+
+# Conventional directory for build output.
+build/
+
+# PDF files
+*.pdf
+
+# AOT compiled
+*.exe
diff --git a/pkgs/jnigen/example/pdfbox_plugin/dart_example/CHANGELOG.md b/pkgs/jnigen/example/pdfbox_plugin/dart_example/CHANGELOG.md
new file mode 100644
index 0000000..effe43c
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/dart_example/CHANGELOG.md
@@ -0,0 +1,3 @@
+## 1.0.0
+
+- Initial version.
diff --git a/pkgs/jnigen/example/pdfbox_plugin/dart_example/README.md b/pkgs/jnigen/example/pdfbox_plugin/dart_example/README.md
new file mode 100644
index 0000000..6a6755e
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/dart_example/README.md
@@ -0,0 +1,10 @@
+## Running
+After generating `pdfbox_plugin` bindings in the parent directory
+
+* setup native libraries: `dart run jni:setup`
+
+* `dart run bin/pdf_info.dart <Path_to_PDF_File>`
+
+Alternatively, it's possible to compile `bin/pdf_info.dart` and then run it.
+
+To run it from other directories, the `helperDir` and `classpath` parameters in `Jni.spawn` call should be adjusted appropriately.
diff --git a/pkgs/jnigen/example/pdfbox_plugin/dart_example/analysis_options.yaml b/pkgs/jnigen/example/pdfbox_plugin/dart_example/analysis_options.yaml
new file mode 100644
index 0000000..dee8927
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/dart_example/analysis_options.yaml
@@ -0,0 +1,30 @@
+# This file configures the static analysis results for your project (errors,
+# warnings, and lints).
+#
+# This enables the 'recommended' set of lints from `package:lints`.
+# This set helps identify many issues that may lead to problems when running
+# or consuming Dart code, and enforces writing Dart using a single, idiomatic
+# style and format.
+#
+# If you want a smaller set of lints you can change this to specify
+# 'package:lints/core.yaml'. These are just the most critical lints
+# (the recommended set includes the core lints).
+# The core lints are also what is used by pub.dev for scoring packages.
+
+include: package:lints/recommended.yaml
+
+# Uncomment the following section to specify additional rules.
+
+# linter:
+# rules:
+# - camel_case_types
+
+# analyzer:
+# exclude:
+# - path/to/excluded/files/**
+
+# For more information about the core and recommended set of lints, see
+# https://dart.dev/go/core-lints
+
+# For additional information about configuring this file, see
+# https://dart.dev/guides/language/analysis-options
diff --git a/pkgs/jnigen/example/pdfbox_plugin/dart_example/bin/pdf_info.dart b/pkgs/jnigen/example/pdfbox_plugin/dart_example/bin/pdf_info.dart
new file mode 100644
index 0000000..5dfd585
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/dart_example/bin/pdf_info.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:path/path.dart';
+import 'package:jni/jni.dart';
+
+import 'package:pdfbox_plugin/pdfbox_plugin.dart';
+
+void writeInfo(String file) {
+ final inputFile = Jni.newInstance(
+ "java/io/FileInputStream", "(Ljava/lang/String;)V", [file]);
+ final pdDoc = PDDocument.load6(inputFile);
+ int pages = pdDoc.getNumberOfPages();
+ final info = pdDoc.getDocumentInformation();
+ final title = info.getTitle();
+ final subject = info.getSubject();
+ final author = info.getAuthor();
+ stderr.writeln('Number of pages: $pages');
+
+ if (!title.isNull) {
+ stderr.writeln('Title: ${title.toDartString()}');
+ }
+
+ if (!subject.isNull) {
+ stderr.writeln('Subject: ${subject.toDartString()}');
+ }
+
+ if (!author.isNull) {
+ stderr.writeln('Author: ${author.toDartString()}');
+ }
+
+ stderr.writeln('PDF Version: ${pdDoc.getVersion().toStringAsPrecision(2)}');
+}
+
+final jniLibsDir = join('build', 'jni_libs');
+
+const jarError = 'No JAR files were found.\n'
+ 'Run `dart run jnigen:download_maven_jars --config jnigen.yaml` '
+ 'in plugin directory.\n'
+ 'Alternatively, regenerate JNI bindings in plugin directory, which will '
+ 'automatically download the JAR files.';
+
+void main(List<String> arguments) {
+ final jarDir = join('..', 'mvn_jar');
+ List<String> jars;
+ try {
+ jars = Directory(jarDir)
+ .listSync()
+ .map((e) => e.path)
+ .where((path) => path.endsWith('.jar'))
+ .toList();
+ } on OSError catch (_) {
+ stderr.writeln(jarError);
+ return;
+ }
+ if (jars.isEmpty) {
+ stderr.writeln(jarError);
+ return;
+ }
+ Jni.spawn(dylibDir: jniLibsDir, classPath: jars);
+ if (arguments.length != 1) {
+ stderr.writeln('usage: dart run pdf_info:pdf_info <Path_to_PDF>');
+ exitCode = 1;
+ return;
+ }
+ writeInfo(arguments[0]);
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/dart_example/pubspec.yaml b/pkgs/jnigen/example/pdfbox_plugin/dart_example/pubspec.yaml
new file mode 100644
index 0000000..4af3cf1
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/dart_example/pubspec.yaml
@@ -0,0 +1,19 @@
+name: pdf_info
+description: Dart standalone example using jnigen PDFBox bindings.
+version: 1.0.0
+publish_to: none
+# homepage: https://www.example.com
+
+environment:
+ sdk: '>=3.1.0 <4.0.0'
+
+dependencies:
+ path: ^1.8.0
+ jni:
+ path: ../../../../jni/
+ pdfbox_plugin:
+ path: ../
+
+dev_dependencies:
+ lints: ^2.0.0
+ test: ^1.16.0
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/.gitignore b/pkgs/jnigen/example/pdfbox_plugin/example/.gitignore
new file mode 100644
index 0000000..a8e938c
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/.gitignore
@@ -0,0 +1,47 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Web related
+lib/generated_plugin_registrant.dart
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/README.md b/pkgs/jnigen/example/pdfbox_plugin/example/README.md
new file mode 100644
index 0000000..0f471be
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/README.md
@@ -0,0 +1,18 @@
+# pdfbox_plugin_example
+
+Demonstrates how to use the PDFBox bindings generated using `jnigen`. This is a Linux Flutter application. The sample application lists the PDF files in a directory with number of pages and title, also allowing to navigate between directories.
+
+First, it's required to have generated the dart and C bindings in the plugin directory, which also downloads the required JARs using maven. The bindings are not committed because generated code is several thousands of lines.
+
+On a Linux machine, following commands can be used to run the example application.
+
+```
+cd .. ## From this folder
+dart run jnigen --config jnigen.yaml ## Downloads PDFBox JARs and generates bindings.
+cd example/
+flutter run --release ## Opens the files list from home directory
+```
+
+It may take some time for PDFBox to process all PDFs in a directory. In the interest of simplicity, this example application displays the list after all PDFs are processed.
+
+Follow along the code in `lib/main.dart` to see how generated bindings are used.
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/analysis_options.yaml b/pkgs/jnigen/example/pdfbox_plugin/example/analysis_options.yaml
new file mode 100644
index 0000000..61b6c4d
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/analysis_options.yaml
@@ -0,0 +1,29 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+ # The lint rules applied to this project can be customized in the
+ # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+ # included above or to enable additional rules. A list of all available lints
+ # and their documentation is published at
+ # https://dart-lang.github.io/linter/lints/index.html.
+ #
+ # Instead of disabling a lint rule for the entire project in the
+ # section below, it can also be suppressed for a single line of code
+ # or a specific dart file by using the `// ignore: name_of_lint` and
+ # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+ # producing the lint.
+ rules:
+ # avoid_print: false # Uncomment to disable the `avoid_print` rule
+ # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/.gitignore b/pkgs/jnigen/example/pdfbox_plugin/example/android/.gitignore
new file mode 100644
index 0000000..6f56801
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/.gitignore
@@ -0,0 +1,13 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/app/build.gradle b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/build.gradle
new file mode 100644
index 0000000..c5791ba
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/build.gradle
@@ -0,0 +1,71 @@
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+ localPropertiesFile.withReader('UTF-8') { reader ->
+ localProperties.load(reader)
+ }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+ throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+ flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+ flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+ compileSdkVersion flutter.compileSdkVersion
+ ndkVersion flutter.ndkVersion
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+
+ defaultConfig {
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId "com.example.pdfbox_plugin_example"
+ // You can update the following values to match your application needs.
+ // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
+ minSdkVersion flutter.minSdkVersion
+ targetSdkVersion flutter.targetSdkVersion
+ versionCode flutterVersionCode.toInteger()
+ versionName flutterVersionName
+ }
+
+ buildTypes {
+ release {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig signingConfigs.debug
+ }
+ }
+}
+
+flutter {
+ source '../..'
+}
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/debug/AndroidManifest.xml b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..3789e50
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.pdfbox_plugin_example">
+ <!-- The INTERNET permission is required for development. Specifically,
+ the Flutter tool needs it to communicate with the running application
+ to allow setting breakpoints, to provide hot reload, etc.
+ -->
+ <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/AndroidManifest.xml b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..a46900a
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.pdfbox_plugin_example">
+ <application
+ android:label="pdfbox_plugin_example"
+ android:name="${applicationName}"
+ android:icon="@mipmap/ic_launcher">
+ <activity
+ android:name=".MainActivity"
+ android:exported="true"
+ android:launchMode="singleTop"
+ android:theme="@style/LaunchTheme"
+ android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
+ android:hardwareAccelerated="true"
+ android:windowSoftInputMode="adjustResize">
+ <!-- Specifies an Android theme to apply to this Activity as soon as
+ the Android process has started. This theme is visible to the user
+ while the Flutter UI initializes. After that, this theme continues
+ to determine the Window background behind the Flutter UI. -->
+ <meta-data
+ android:name="io.flutter.embedding.android.NormalTheme"
+ android:resource="@style/NormalTheme"
+ />
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <!-- Don't delete the meta-data below.
+ This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
+ <meta-data
+ android:name="flutterEmbedding"
+ android:value="2" />
+ </application>
+</manifest>
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/kotlin/com/example/pdfbox_plugin_example/MainActivity.kt b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/kotlin/com/example/pdfbox_plugin_example/MainActivity.kt
new file mode 100644
index 0000000..68d076c
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/kotlin/com/example/pdfbox_plugin_example/MainActivity.kt
@@ -0,0 +1,6 @@
+package com.example.pdfbox_plugin_example
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml
new file mode 100644
index 0000000..f74085f
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="?android:colorBackground" />
+
+ <!-- You can insert your own image assets here -->
+ <!-- <item>
+ <bitmap
+ android:gravity="center"
+ android:src="@mipmap/launch_image" />
+ </item> -->
+</layer-list>
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/drawable/launch_background.xml b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..304732f
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Modify this file to customize your launch splash screen -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@android:color/white" />
+
+ <!-- You can insert your own image assets here -->
+ <!-- <item>
+ <bitmap
+ android:gravity="center"
+ android:src="@mipmap/launch_image" />
+ </item> -->
+</layer-list>
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..db77bb4
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..17987b7
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..09d4391
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d5f1c8d
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d6372e
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/values-night/styles.xml b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/values-night/styles.xml
new file mode 100644
index 0000000..06952be
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/values-night/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
+ <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
+ <!-- Show a splash screen on the activity. Automatically removed when
+ the Flutter engine draws its first frame -->
+ <item name="android:windowBackground">@drawable/launch_background</item>
+ </style>
+ <!-- Theme applied to the Android Window as soon as the process has started.
+ This theme determines the color of the Android Window while your
+ Flutter UI initializes, as well as behind your Flutter UI while its
+ running.
+
+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
+ <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
+ <item name="android:windowBackground">?android:colorBackground</item>
+ </style>
+</resources>
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/values/styles.xml b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..cb1ef88
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
+ <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
+ <!-- Show a splash screen on the activity. Automatically removed when
+ the Flutter engine draws its first frame -->
+ <item name="android:windowBackground">@drawable/launch_background</item>
+ </style>
+ <!-- Theme applied to the Android Window as soon as the process has started.
+ This theme determines the color of the Android Window while your
+ Flutter UI initializes, as well as behind your Flutter UI while its
+ running.
+
+ This Theme is only used starting with V2 of Flutter's Android embedding. -->
+ <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
+ <item name="android:windowBackground">?android:colorBackground</item>
+ </style>
+</resources>
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/profile/AndroidManifest.xml b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..3789e50
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,8 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.pdfbox_plugin_example">
+ <!-- The INTERNET permission is required for development. Specifically,
+ the Flutter tool needs it to communicate with the running application
+ to allow setting breakpoints, to provide hot reload, etc.
+ -->
+ <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/build.gradle b/pkgs/jnigen/example/pdfbox_plugin/example/android/build.gradle
new file mode 100644
index 0000000..3cdaac9
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/build.gradle
@@ -0,0 +1,31 @@
+buildscript {
+ ext.kotlin_version = '1.6.10'
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:7.1.2'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+ project.evaluationDependsOn(':app')
+}
+
+tasks.register("clean", Delete) {
+ delete rootProject.buildDir
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/gradle.properties b/pkgs/jnigen/example/pdfbox_plugin/example/android/gradle.properties
new file mode 100644
index 0000000..94adc3a
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/gradle/wrapper/gradle-wrapper.properties b/pkgs/jnigen/example/pdfbox_plugin/example/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..cc5527d
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Jun 23 08:50:38 CEST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/android/settings.gradle b/pkgs/jnigen/example/pdfbox_plugin/example/android/settings.gradle
new file mode 100644
index 0000000..44e62bc
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/android/settings.gradle
@@ -0,0 +1,11 @@
+include ':app'
+
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
+
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/lib/main.dart b/pkgs/jnigen/example/pdfbox_plugin/example/lib/main.dart
new file mode 100644
index 0000000..ccc6563
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/lib/main.dart
@@ -0,0 +1,202 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:flutter/material.dart';
+import 'dart:io';
+import 'dart:async';
+
+import 'package:jni/jni.dart';
+import 'package:path/path.dart';
+
+import 'package:pdfbox_plugin/pdfbox_plugin.dart';
+
+Stream<String> files(String dir) => Directory(dir).list().map((e) => e.path);
+
+const jarError = 'No JAR files were found.\n'
+ 'Run `dart run jnigen:download_maven_jars --config jnigen.yaml` '
+ 'in plugin directory.\n'
+ 'Alternatively, regenerate JNI bindings in plugin directory, which will '
+ 'automatically download the JAR files.';
+
+void main() {
+ if (!Platform.isAndroid) {
+ // Assuming application is run from example/ folder
+ // It's required to manually provide the JAR files as classpath when
+ // spawning the JVM.
+ const jarDir = '../mvn_jar/';
+ List<String> jars;
+ try {
+ jars = Directory(jarDir)
+ .listSync()
+ .map((e) => e.path)
+ .where((path) => path.endsWith('.jar'))
+ .toList();
+ } on OSError catch (_) {
+ stderr.writeln(jarError);
+ return;
+ }
+ if (jars.isEmpty) {
+ stderr.writeln(jarError);
+ return;
+ }
+ Jni.spawn(classPath: jars);
+ }
+ runApp(const PDFInfoApp());
+}
+
+class PDFInfoApp extends StatefulWidget {
+ const PDFInfoApp({super.key});
+
+ @override
+ PDFInfoAppState createState() => PDFInfoAppState();
+}
+
+class PDFInfoAppState extends State<PDFInfoApp> {
+ bool _isLoading = true;
+ String _dir = '.';
+ List<String> _pdfs = [];
+ List<String> _dirs = [];
+
+ void setDir(String dir) async {
+ final pdfs = <String>[];
+ final dirs = <String>[];
+
+ setState(() => _isLoading = true);
+
+ await for (var item in Directory(dir).list()) {
+ final isDir = (await item.stat()).type == FileSystemEntityType.directory;
+ if (item.path.endsWith('.pdf') && !isDir) {
+ pdfs.add(item.path);
+ } else if (isDir) {
+ dirs.add(item.path);
+ }
+ }
+ setState(() {
+ _isLoading = false;
+ _dir = dir;
+ _pdfs = pdfs;
+ _dirs = dirs;
+ });
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ final dir = Platform.environment['HOME'] ?? '.';
+ setDir(dir);
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final dirBaseName = basename(_dir);
+ return MaterialApp(
+ home: Scaffold(
+ appBar: AppBar(
+ title: Text('PDF Info: $dirBaseName'),
+ ),
+ body: SingleChildScrollView(
+ child: Container(
+ padding: const EdgeInsets.all(10),
+ child: _isLoading
+ ? const Text('loading...')
+ : Table(border: TableBorder.all(), children: [
+ TableRow(children: [
+ for (var heading in ['File', 'Title', 'Pages'])
+ TableCell(
+ child: _pad(Text(heading,
+ style: const TextStyle(
+ fontSize: 16,
+ decoration: TextDecoration.underline)))),
+ ]),
+ TableRow(children: [
+ TableCell(
+ child: _pad(
+ InkWell(
+ child: const Text('..'),
+ onTap: () => setDir(dirname(_dir)),
+ ),
+ ),
+ ),
+ const TableCell(child: Text('')),
+ const TableCell(child: Text('')),
+ ]),
+ for (var dir in _dirs) _dirTile(basename(dir)),
+ for (var pdfname in _pdfs)
+ _pdfInfo(PDFFileInfo.usingPDFBox(pdfname)),
+ ])),
+ ),
+ ),
+ );
+ }
+
+ TableRow _dirTile(String target) {
+ return TableRow(children: [
+ TableCell(
+ child: _pad(
+ InkWell(
+ onTap: () => setDir(join(_dir, target)),
+ child: Text(
+ target,
+ style: const TextStyle(fontWeight: FontWeight.bold),
+ ),
+ ),
+ ),
+ ),
+ const TableCell(child: Text('-')),
+ const TableCell(child: Text('-')),
+ ]);
+ }
+}
+
+// It's generally a good practice to separate JNI calls from UI / model code.
+class PDFFileInfo {
+ String filename;
+ late String author, subject, title;
+ late int numPages;
+
+ /// Converts JString to dart string and deletes the original.
+ /// Also handles the case where the underlying string is Null.
+ String _fromJavaStr(JString jstr) {
+ if (jstr.reference == nullptr) {
+ return '(null)';
+ }
+ return jstr.toDartString(releaseOriginal: true);
+ }
+
+ PDFFileInfo.usingPDFBox(this.filename) {
+ // Since java.io is not directly available, use package:jni API to
+ // create a java.io.File object.
+ final inputFile =
+ Jni.newInstance("java/io/File", "(Ljava/lang/String;)V", [filename]);
+ // Static method call PDDocument.load -> PDDocument
+ final pdf = PDDocument.load(inputFile);
+ // Instance method call getNumberOfPages() -> int
+ numPages = pdf.getNumberOfPages();
+ // Instance method that returns an object
+ final info = pdf.getDocumentInformation();
+
+ /// java.lang.String is a special case and is mapped to JlString which is
+ /// a subclass of JlObject.
+ author = _fromJavaStr(info.getAuthor());
+ title = _fromJavaStr(info.getTitle());
+ subject = _fromJavaStr(info.getSubject());
+
+ pdf.close();
+ }
+}
+
+Padding _pad(Widget w) => Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: w);
+
+TableRow _pdfInfo(PDFFileInfo info) {
+ return TableRow(children: [
+ TableCell(
+ child: _pad(Text(basename(info.filename),
+ style: const TextStyle(fontWeight: FontWeight.bold)))),
+ TableCell(child: _pad(Text(info.title))),
+ TableCell(
+ child: _pad(Text(info.numPages.toString(),
+ style: const TextStyle(color: Colors.grey)))),
+ ]);
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/linux/.gitignore b/pkgs/jnigen/example/pdfbox_plugin/example/linux/.gitignore
new file mode 100644
index 0000000..d3896c9
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/linux/.gitignore
@@ -0,0 +1 @@
+flutter/ephemeral
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/linux/CMakeLists.txt b/pkgs/jnigen/example/pdfbox_plugin/example/linux/CMakeLists.txt
new file mode 100644
index 0000000..f36768d
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/linux/CMakeLists.txt
@@ -0,0 +1,138 @@
+# Project-level configuration.
+cmake_minimum_required(VERSION 3.10)
+project(runner LANGUAGES CXX)
+
+# The name of the executable created for the application. Change this to change
+# the on-disk name of your application.
+set(BINARY_NAME "pdfbox_plugin_example")
+# The unique GTK application identifier for this application. See:
+# https://wiki.gnome.org/HowDoI/ChooseApplicationID
+set(APPLICATION_ID "com.example.pdfbox_plugin")
+
+# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
+# versions of CMake.
+cmake_policy(SET CMP0063 NEW)
+
+# Load bundled libraries from the lib/ directory relative to the binary.
+set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
+
+# Root filesystem for cross-building.
+if(FLUTTER_TARGET_PLATFORM_SYSROOT)
+ set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT})
+ set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})
+ set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
+ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
+ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+endif()
+
+# Define build configuration options.
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+ set(CMAKE_BUILD_TYPE "Debug" CACHE
+ STRING "Flutter build mode" FORCE)
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+ "Debug" "Profile" "Release")
+endif()
+
+# Compilation settings that should be applied to most targets.
+#
+# Be cautious about adding new options here, as plugins use this function by
+# default. In most cases, you should add new options to specific targets instead
+# of modifying this function.
+function(APPLY_STANDARD_SETTINGS TARGET)
+ target_compile_features(${TARGET} PUBLIC cxx_std_14)
+ target_compile_options(${TARGET} PRIVATE -Wall -Werror)
+ target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
+ target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
+endfunction()
+
+# Flutter library and tool build rules.
+set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
+add_subdirectory(${FLUTTER_MANAGED_DIR})
+
+# System-level dependencies.
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
+
+add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
+
+# Define the application target. To change its name, change BINARY_NAME above,
+# not the value here, or `flutter run` will no longer work.
+#
+# Any new source files that you add to the application should be added here.
+add_executable(${BINARY_NAME}
+ "main.cc"
+ "my_application.cc"
+ "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
+)
+
+# Apply the standard set of build settings. This can be removed for applications
+# that need different build settings.
+apply_standard_settings(${BINARY_NAME})
+
+# Add dependency libraries. Add any application-specific dependencies here.
+target_link_libraries(${BINARY_NAME} PRIVATE flutter)
+target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
+
+# Run the Flutter tool portions of the build. This must not be removed.
+add_dependencies(${BINARY_NAME} flutter_assemble)
+
+# Only the install-generated bundle's copy of the executable will launch
+# correctly, since the resources must in the right relative locations. To avoid
+# people trying to run the unbundled copy, put it in a subdirectory instead of
+# the default top-level location.
+set_target_properties(${BINARY_NAME}
+ PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
+)
+
+# Generated plugin build rules, which manage building the plugins and adding
+# them to the application.
+include(flutter/generated_plugins.cmake)
+
+
+# === Installation ===
+# By default, "installing" just makes a relocatable bundle in the build
+# directory.
+set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
+endif()
+
+# Start with a clean build bundle directory every time.
+install(CODE "
+ file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
+ " COMPONENT Runtime)
+
+set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
+set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
+
+install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
+ COMPONENT Runtime)
+
+install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
+ COMPONENT Runtime)
+
+install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+
+foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
+ install(FILES "${bundled_library}"
+ DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+endforeach(bundled_library)
+
+# Fully re-copy the assets directory on each build to avoid having stale files
+# from a previous install.
+set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
+install(CODE "
+ file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
+ " COMPONENT Runtime)
+install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
+ DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
+
+# Install the AOT library on non-Debug builds only.
+if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
+ install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+endif()
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/CMakeLists.txt b/pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/CMakeLists.txt
new file mode 100644
index 0000000..d5bd016
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/CMakeLists.txt
@@ -0,0 +1,88 @@
+# This file controls Flutter-level build steps. It should not be edited.
+cmake_minimum_required(VERSION 3.10)
+
+set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
+
+# Configuration provided via flutter tool.
+include(${EPHEMERAL_DIR}/generated_config.cmake)
+
+# TODO: Move the rest of this into files in ephemeral. See
+# https://github.com/flutter/flutter/issues/57146.
+
+# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
+# which isn't available in 3.10.
+function(list_prepend LIST_NAME PREFIX)
+ set(NEW_LIST "")
+ foreach(element ${${LIST_NAME}})
+ list(APPEND NEW_LIST "${PREFIX}${element}")
+ endforeach(element)
+ set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
+endfunction()
+
+# === Flutter Library ===
+# System-level dependencies.
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
+pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
+pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
+
+set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
+
+# Published to parent scope for install step.
+set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
+set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
+set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
+set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
+
+list(APPEND FLUTTER_LIBRARY_HEADERS
+ "fl_basic_message_channel.h"
+ "fl_binary_codec.h"
+ "fl_binary_messenger.h"
+ "fl_dart_project.h"
+ "fl_engine.h"
+ "fl_json_message_codec.h"
+ "fl_json_method_codec.h"
+ "fl_message_codec.h"
+ "fl_method_call.h"
+ "fl_method_channel.h"
+ "fl_method_codec.h"
+ "fl_method_response.h"
+ "fl_plugin_registrar.h"
+ "fl_plugin_registry.h"
+ "fl_standard_message_codec.h"
+ "fl_standard_method_codec.h"
+ "fl_string_codec.h"
+ "fl_value.h"
+ "fl_view.h"
+ "flutter_linux.h"
+)
+list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
+add_library(flutter INTERFACE)
+target_include_directories(flutter INTERFACE
+ "${EPHEMERAL_DIR}"
+)
+target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
+target_link_libraries(flutter INTERFACE
+ PkgConfig::GTK
+ PkgConfig::GLIB
+ PkgConfig::GIO
+)
+add_dependencies(flutter flutter_assemble)
+
+# === Flutter tool backend ===
+# _phony_ is a non-existent file to force this command to run every time,
+# since currently there's no way to get a full input/output list from the
+# flutter tool.
+add_custom_command(
+ OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
+ ${CMAKE_CURRENT_BINARY_DIR}/_phony_
+ COMMAND ${CMAKE_COMMAND} -E env
+ ${FLUTTER_TOOL_ENVIRONMENT}
+ "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
+ ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
+ VERBATIM
+)
+add_custom_target(flutter_assemble DEPENDS
+ "${FLUTTER_LIBRARY}"
+ ${FLUTTER_LIBRARY_HEADERS}
+)
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.cc b/pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.cc
new file mode 100644
index 0000000..e71a16d
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.cc
@@ -0,0 +1,11 @@
+//
+// Generated file. Do not edit.
+//
+
+// clang-format off
+
+#include "generated_plugin_registrant.h"
+
+
+void fl_register_plugins(FlPluginRegistry* registry) {
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.h b/pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.h
new file mode 100644
index 0000000..e0f0a47
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/generated_plugin_registrant.h
@@ -0,0 +1,15 @@
+//
+// Generated file. Do not edit.
+//
+
+// clang-format off
+
+#ifndef GENERATED_PLUGIN_REGISTRANT_
+#define GENERATED_PLUGIN_REGISTRANT_
+
+#include <flutter_linux/flutter_linux.h>
+
+// Registers Flutter plugins.
+void fl_register_plugins(FlPluginRegistry* registry);
+
+#endif // GENERATED_PLUGIN_REGISTRANT_
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/generated_plugins.cmake b/pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/generated_plugins.cmake
new file mode 100644
index 0000000..d2cbe73
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/linux/flutter/generated_plugins.cmake
@@ -0,0 +1,25 @@
+#
+# Generated file, do not edit.
+#
+
+list(APPEND FLUTTER_PLUGIN_LIST
+)
+
+list(APPEND FLUTTER_FFI_PLUGIN_LIST
+ jni
+ pdfbox_plugin
+)
+
+set(PLUGIN_BUNDLED_LIBRARIES)
+
+foreach(plugin ${FLUTTER_PLUGIN_LIST})
+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
+ target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
+endforeach(plugin)
+
+foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin})
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
+endforeach(ffi_plugin)
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/linux/main.cc b/pkgs/jnigen/example/pdfbox_plugin/example/linux/main.cc
new file mode 100644
index 0000000..e7c5c54
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/linux/main.cc
@@ -0,0 +1,6 @@
+#include "my_application.h"
+
+int main(int argc, char** argv) {
+ g_autoptr(MyApplication) app = my_application_new();
+ return g_application_run(G_APPLICATION(app), argc, argv);
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/linux/my_application.cc b/pkgs/jnigen/example/pdfbox_plugin/example/linux/my_application.cc
new file mode 100644
index 0000000..b13351b
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/linux/my_application.cc
@@ -0,0 +1,104 @@
+#include "my_application.h"
+
+#include <flutter_linux/flutter_linux.h>
+#ifdef GDK_WINDOWING_X11
+#include <gdk/gdkx.h>
+#endif
+
+#include "flutter/generated_plugin_registrant.h"
+
+struct _MyApplication {
+ GtkApplication parent_instance;
+ char** dart_entrypoint_arguments;
+};
+
+G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
+
+// Implements GApplication::activate.
+static void my_application_activate(GApplication* application) {
+ MyApplication* self = MY_APPLICATION(application);
+ GtkWindow* window =
+ GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
+
+ // Use a header bar when running in GNOME as this is the common style used
+ // by applications and is the setup most users will be using (e.g. Ubuntu
+ // desktop).
+ // If running on X and not using GNOME then just use a traditional title bar
+ // in case the window manager does more exotic layout, e.g. tiling.
+ // If running on Wayland assume the header bar will work (may need changing
+ // if future cases occur).
+ gboolean use_header_bar = TRUE;
+#ifdef GDK_WINDOWING_X11
+ GdkScreen* screen = gtk_window_get_screen(window);
+ if (GDK_IS_X11_SCREEN(screen)) {
+ const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen);
+ if (g_strcmp0(wm_name, "GNOME Shell") != 0) {
+ use_header_bar = FALSE;
+ }
+ }
+#endif
+ if (use_header_bar) {
+ GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
+ gtk_widget_show(GTK_WIDGET(header_bar));
+ gtk_header_bar_set_title(header_bar, "pdfbox_plugin_example");
+ gtk_header_bar_set_show_close_button(header_bar, TRUE);
+ gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
+ } else {
+ gtk_window_set_title(window, "pdfbox_plugin_example");
+ }
+
+ gtk_window_set_default_size(window, 1280, 720);
+ gtk_widget_show(GTK_WIDGET(window));
+
+ g_autoptr(FlDartProject) project = fl_dart_project_new();
+ fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments);
+
+ FlView* view = fl_view_new(project);
+ gtk_widget_show(GTK_WIDGET(view));
+ gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
+
+ fl_register_plugins(FL_PLUGIN_REGISTRY(view));
+
+ gtk_widget_grab_focus(GTK_WIDGET(view));
+}
+
+// Implements GApplication::local_command_line.
+static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
+ MyApplication* self = MY_APPLICATION(application);
+ // Strip out the first argument as it is the binary name.
+ self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
+
+ g_autoptr(GError) error = nullptr;
+ if (!g_application_register(application, nullptr, &error)) {
+ g_warning("Failed to register: %s", error->message);
+ *exit_status = 1;
+ return TRUE;
+ }
+
+ g_application_activate(application);
+ *exit_status = 0;
+
+ return TRUE;
+}
+
+// Implements GObject::dispose.
+static void my_application_dispose(GObject* object) {
+ MyApplication* self = MY_APPLICATION(object);
+ g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
+ G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
+}
+
+static void my_application_class_init(MyApplicationClass* klass) {
+ G_APPLICATION_CLASS(klass)->activate = my_application_activate;
+ G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
+ G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
+}
+
+static void my_application_init(MyApplication* self) {}
+
+MyApplication* my_application_new() {
+ return MY_APPLICATION(g_object_new(my_application_get_type(),
+ "application-id", APPLICATION_ID,
+ "flags", G_APPLICATION_NON_UNIQUE,
+ nullptr));
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/linux/my_application.h b/pkgs/jnigen/example/pdfbox_plugin/example/linux/my_application.h
new file mode 100644
index 0000000..72271d5
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/linux/my_application.h
@@ -0,0 +1,18 @@
+#ifndef FLUTTER_MY_APPLICATION_H_
+#define FLUTTER_MY_APPLICATION_H_
+
+#include <gtk/gtk.h>
+
+G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
+ GtkApplication)
+
+/**
+ * my_application_new:
+ *
+ * Creates a new Flutter-based application.
+ *
+ * Returns: a new #MyApplication.
+ */
+MyApplication* my_application_new();
+
+#endif // FLUTTER_MY_APPLICATION_H_
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/pubspec.yaml b/pkgs/jnigen/example/pdfbox_plugin/example/pubspec.yaml
new file mode 100644
index 0000000..13d0df0
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/pubspec.yaml
@@ -0,0 +1,99 @@
+name: pdfbox_example
+description: Demonstrates how to use pdfbox_plugin.
+
+# The following line prevents the package from being accidentally published to
+# pub.dev using `flutter pub publish`. This is preferred for private packages.
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+# The following defines the version and build number for your application.
+# A version number is three numbers separated by dots, like 1.2.43
+# followed by an optional build number separated by a +.
+# Both the version and the builder number may be overridden in flutter
+# build by specifying --build-name and --build-number, respectively.
+# In Android, build-name is used as versionName while build-number used as versionCode.
+# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
+# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
+# Read more about iOS versioning at
+# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
+version: 1.0.0+1
+
+environment:
+ sdk: '>=3.1.0 <4.0.0'
+
+# Dependencies specify other packages that your package needs in order to work.
+# To automatically upgrade your package dependencies to the latest versions
+# consider running `flutter pub upgrade --major-versions`. Alternatively,
+# dependencies can be manually updated by changing the version numbers below to
+# the latest version available on pub.dev. To see which dependencies have newer
+# versions available, run `flutter pub outdated`.
+dependencies:
+ flutter:
+ sdk: flutter
+
+ jni:
+ path: ../../../../jni/
+ path: ^1.8.0
+ pdfbox_plugin:
+ # When depending on this package from a real application you should use:
+ # pdfbox_plugin: ^x.y.z
+ # See https://dart.dev/tools/pub/dependencies#version-constraints
+ # The example app is bundled with the plugin so we use a path dependency on
+ # the parent directory to use the current plugin's version.
+ path: ../
+
+ # The following adds the Cupertino Icons font to your application.
+ # Use with the CupertinoIcons class for iOS style icons.
+ cupertino_icons: ^1.0.2
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+
+ # The "flutter_lints" package below contains a set of recommended lints to
+ # encourage good coding practices. The lint set provided by the package is
+ # activated in the `analysis_options.yaml` file located at the root of your
+ # package. See that file for information about deactivating specific lint
+ # rules and activating additional ones.
+ flutter_lints: ^2.0.0
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter packages.
+flutter:
+
+ # The following line ensures that the Material Icons font is
+ # included with your application, so that you can use the icons in
+ # the material Icons class.
+ uses-material-design: true
+
+ # To add assets to your application, add an assets section, like this:
+ # assets:
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
+
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/assets-and-images/#resolution-aware
+
+ # For details regarding adding assets from package dependencies, see
+ # https://flutter.dev/assets-and-images/#from-packages
+
+ # To add custom fonts to your application, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts from package dependencies,
+ # see https://flutter.dev/custom-fonts/#from-packages
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/.gitignore b/pkgs/jnigen/example/pdfbox_plugin/example/windows/.gitignore
new file mode 100644
index 0000000..d492d0d
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/.gitignore
@@ -0,0 +1,17 @@
+flutter/ephemeral/
+
+# Visual Studio user-specific files.
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# Visual Studio build-related files.
+x64/
+x86/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/CMakeLists.txt b/pkgs/jnigen/example/pdfbox_plugin/example/windows/CMakeLists.txt
new file mode 100644
index 0000000..c233397
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/CMakeLists.txt
@@ -0,0 +1,101 @@
+# Project-level configuration.
+cmake_minimum_required(VERSION 3.14)
+project(pdfbox_plugin_example LANGUAGES CXX)
+
+# The name of the executable created for the application. Change this to change
+# the on-disk name of your application.
+set(BINARY_NAME "pdfbox_plugin_example")
+
+# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
+# versions of CMake.
+cmake_policy(SET CMP0063 NEW)
+
+# Define build configuration option.
+get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+if(IS_MULTICONFIG)
+ set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
+ CACHE STRING "" FORCE)
+else()
+ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+ set(CMAKE_BUILD_TYPE "Debug" CACHE
+ STRING "Flutter build mode" FORCE)
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+ "Debug" "Profile" "Release")
+ endif()
+endif()
+# Define settings for the Profile build mode.
+set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
+set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
+set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
+set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
+
+# Use Unicode for all projects.
+add_definitions(-DUNICODE -D_UNICODE)
+
+# Compilation settings that should be applied to most targets.
+#
+# Be cautious about adding new options here, as plugins use this function by
+# default. In most cases, you should add new options to specific targets instead
+# of modifying this function.
+function(APPLY_STANDARD_SETTINGS TARGET)
+ target_compile_features(${TARGET} PUBLIC cxx_std_17)
+ target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
+ target_compile_options(${TARGET} PRIVATE /EHsc)
+ target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0")
+ target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>")
+endfunction()
+
+# Flutter library and tool build rules.
+set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
+add_subdirectory(${FLUTTER_MANAGED_DIR})
+
+# Application build; see runner/CMakeLists.txt.
+add_subdirectory("runner")
+
+# Generated plugin build rules, which manage building the plugins and adding
+# them to the application.
+include(flutter/generated_plugins.cmake)
+
+
+# === Installation ===
+# Support files are copied into place next to the executable, so that it can
+# run in place. This is done instead of making a separate bundle (as on Linux)
+# so that building and running from within Visual Studio will work.
+set(BUILD_BUNDLE_DIR "$<TARGET_FILE_DIR:${BINARY_NAME}>")
+# Make the "install" step default, as it's required to run.
+set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+ set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
+endif()
+
+set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
+set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
+
+install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
+ COMPONENT Runtime)
+
+install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
+ COMPONENT Runtime)
+
+install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+
+if(PLUGIN_BUNDLED_LIBRARIES)
+ install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
+ DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
+ COMPONENT Runtime)
+endif()
+
+# Fully re-copy the assets directory on each build to avoid having stale files
+# from a previous install.
+set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
+install(CODE "
+ file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
+ " COMPONENT Runtime)
+install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
+ DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
+
+# Install the AOT library on non-Debug builds only.
+install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
+ CONFIGURATIONS Profile;Release
+ COMPONENT Runtime)
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/CMakeLists.txt b/pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/CMakeLists.txt
new file mode 100644
index 0000000..930d207
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/CMakeLists.txt
@@ -0,0 +1,104 @@
+# This file controls Flutter-level build steps. It should not be edited.
+cmake_minimum_required(VERSION 3.14)
+
+set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
+
+# Configuration provided via flutter tool.
+include(${EPHEMERAL_DIR}/generated_config.cmake)
+
+# TODO: Move the rest of this into files in ephemeral. See
+# https://github.com/flutter/flutter/issues/57146.
+set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper")
+
+# === Flutter Library ===
+set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll")
+
+# Published to parent scope for install step.
+set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
+set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
+set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
+set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE)
+
+list(APPEND FLUTTER_LIBRARY_HEADERS
+ "flutter_export.h"
+ "flutter_windows.h"
+ "flutter_messenger.h"
+ "flutter_plugin_registrar.h"
+ "flutter_texture_registrar.h"
+)
+list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
+add_library(flutter INTERFACE)
+target_include_directories(flutter INTERFACE
+ "${EPHEMERAL_DIR}"
+)
+target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib")
+add_dependencies(flutter flutter_assemble)
+
+# === Wrapper ===
+list(APPEND CPP_WRAPPER_SOURCES_CORE
+ "core_implementations.cc"
+ "standard_codec.cc"
+)
+list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/")
+list(APPEND CPP_WRAPPER_SOURCES_PLUGIN
+ "plugin_registrar.cc"
+)
+list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/")
+list(APPEND CPP_WRAPPER_SOURCES_APP
+ "flutter_engine.cc"
+ "flutter_view_controller.cc"
+)
+list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/")
+
+# Wrapper sources needed for a plugin.
+add_library(flutter_wrapper_plugin STATIC
+ ${CPP_WRAPPER_SOURCES_CORE}
+ ${CPP_WRAPPER_SOURCES_PLUGIN}
+)
+apply_standard_settings(flutter_wrapper_plugin)
+set_target_properties(flutter_wrapper_plugin PROPERTIES
+ POSITION_INDEPENDENT_CODE ON)
+set_target_properties(flutter_wrapper_plugin PROPERTIES
+ CXX_VISIBILITY_PRESET hidden)
+target_link_libraries(flutter_wrapper_plugin PUBLIC flutter)
+target_include_directories(flutter_wrapper_plugin PUBLIC
+ "${WRAPPER_ROOT}/include"
+)
+add_dependencies(flutter_wrapper_plugin flutter_assemble)
+
+# Wrapper sources needed for the runner.
+add_library(flutter_wrapper_app STATIC
+ ${CPP_WRAPPER_SOURCES_CORE}
+ ${CPP_WRAPPER_SOURCES_APP}
+)
+apply_standard_settings(flutter_wrapper_app)
+target_link_libraries(flutter_wrapper_app PUBLIC flutter)
+target_include_directories(flutter_wrapper_app PUBLIC
+ "${WRAPPER_ROOT}/include"
+)
+add_dependencies(flutter_wrapper_app flutter_assemble)
+
+# === Flutter tool backend ===
+# _phony_ is a non-existent file to force this command to run every time,
+# since currently there's no way to get a full input/output list from the
+# flutter tool.
+set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
+set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
+add_custom_command(
+ OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
+ ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
+ ${CPP_WRAPPER_SOURCES_APP}
+ ${PHONY_OUTPUT}
+ COMMAND ${CMAKE_COMMAND} -E env
+ ${FLUTTER_TOOL_ENVIRONMENT}
+ "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
+ windows-x64 $<CONFIG>
+ VERBATIM
+)
+add_custom_target(flutter_assemble DEPENDS
+ "${FLUTTER_LIBRARY}"
+ ${FLUTTER_LIBRARY_HEADERS}
+ ${CPP_WRAPPER_SOURCES_CORE}
+ ${CPP_WRAPPER_SOURCES_PLUGIN}
+ ${CPP_WRAPPER_SOURCES_APP}
+)
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.cc b/pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.cc
new file mode 100644
index 0000000..8b6d468
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.cc
@@ -0,0 +1,11 @@
+//
+// Generated file. Do not edit.
+//
+
+// clang-format off
+
+#include "generated_plugin_registrant.h"
+
+
+void RegisterPlugins(flutter::PluginRegistry* registry) {
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.h b/pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.h
new file mode 100644
index 0000000..dc139d8
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/generated_plugin_registrant.h
@@ -0,0 +1,15 @@
+//
+// Generated file. Do not edit.
+//
+
+// clang-format off
+
+#ifndef GENERATED_PLUGIN_REGISTRANT_
+#define GENERATED_PLUGIN_REGISTRANT_
+
+#include <flutter/plugin_registry.h>
+
+// Registers Flutter plugins.
+void RegisterPlugins(flutter::PluginRegistry* registry);
+
+#endif // GENERATED_PLUGIN_REGISTRANT_
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/generated_plugins.cmake b/pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/generated_plugins.cmake
new file mode 100644
index 0000000..facaded
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/flutter/generated_plugins.cmake
@@ -0,0 +1,25 @@
+#
+# Generated file, do not edit.
+#
+
+list(APPEND FLUTTER_PLUGIN_LIST
+)
+
+list(APPEND FLUTTER_FFI_PLUGIN_LIST
+ jni
+ pdfbox_plugin
+)
+
+set(PLUGIN_BUNDLED_LIBRARIES)
+
+foreach(plugin ${FLUTTER_PLUGIN_LIST})
+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
+ target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
+endforeach(plugin)
+
+foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
+ add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
+ list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
+endforeach(ffi_plugin)
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/CMakeLists.txt b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/CMakeLists.txt
new file mode 100644
index 0000000..b9e550f
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.14)
+project(runner LANGUAGES CXX)
+
+# Define the application target. To change its name, change BINARY_NAME in the
+# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
+# work.
+#
+# Any new source files that you add to the application should be added here.
+add_executable(${BINARY_NAME} WIN32
+ "flutter_window.cpp"
+ "main.cpp"
+ "utils.cpp"
+ "win32_window.cpp"
+ "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
+ "Runner.rc"
+ "runner.exe.manifest"
+)
+
+# Apply the standard set of build settings. This can be removed for applications
+# that need different build settings.
+apply_standard_settings(${BINARY_NAME})
+
+# Disable Windows macros that collide with C++ standard library functions.
+target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
+
+# Add dependency libraries and include directories. Add any application-specific
+# dependencies here.
+target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
+target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
+
+# Run the Flutter tool portions of the build. This must not be removed.
+add_dependencies(${BINARY_NAME} flutter_assemble)
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/Runner.rc b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/Runner.rc
new file mode 100644
index 0000000..05d079f
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/Runner.rc
@@ -0,0 +1,121 @@
+// Microsoft Visual C++ generated resource script.
+//
+#pragma code_page(65001)
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_APP_ICON ICON "resources\\app_icon.ico"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+#ifdef FLUTTER_BUILD_NUMBER
+#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER
+#else
+#define VERSION_AS_NUMBER 1,0,0
+#endif
+
+#ifdef FLUTTER_BUILD_NAME
+#define VERSION_AS_STRING #FLUTTER_BUILD_NAME
+#else
+#define VERSION_AS_STRING "1.0.0"
+#endif
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION VERSION_AS_NUMBER
+ PRODUCTVERSION VERSION_AS_NUMBER
+ FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#ifdef _DEBUG
+ FILEFLAGS VS_FF_DEBUG
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_APP
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e4"
+ BEGIN
+ VALUE "CompanyName", "com.example" "\0"
+ VALUE "FileDescription", "pdfbox_plugin_example" "\0"
+ VALUE "FileVersion", VERSION_AS_STRING "\0"
+ VALUE "InternalName", "pdfbox_plugin_example" "\0"
+ VALUE "LegalCopyright", "Copyright (C) 2022 com.example. All rights reserved." "\0"
+ VALUE "OriginalFilename", "pdfbox_plugin_example.exe" "\0"
+ VALUE "ProductName", "pdfbox_plugin_example" "\0"
+ VALUE "ProductVersion", VERSION_AS_STRING "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1252
+ END
+END
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/flutter_window.cpp b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/flutter_window.cpp
new file mode 100644
index 0000000..b43b909
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/flutter_window.cpp
@@ -0,0 +1,61 @@
+#include "flutter_window.h"
+
+#include <optional>
+
+#include "flutter/generated_plugin_registrant.h"
+
+FlutterWindow::FlutterWindow(const flutter::DartProject& project)
+ : project_(project) {}
+
+FlutterWindow::~FlutterWindow() {}
+
+bool FlutterWindow::OnCreate() {
+ if (!Win32Window::OnCreate()) {
+ return false;
+ }
+
+ RECT frame = GetClientArea();
+
+ // The size here must match the window dimensions to avoid unnecessary surface
+ // creation / destruction in the startup path.
+ flutter_controller_ = std::make_unique<flutter::FlutterViewController>(
+ frame.right - frame.left, frame.bottom - frame.top, project_);
+ // Ensure that basic setup of the controller was successful.
+ if (!flutter_controller_->engine() || !flutter_controller_->view()) {
+ return false;
+ }
+ RegisterPlugins(flutter_controller_->engine());
+ SetChildContent(flutter_controller_->view()->GetNativeWindow());
+ return true;
+}
+
+void FlutterWindow::OnDestroy() {
+ if (flutter_controller_) {
+ flutter_controller_ = nullptr;
+ }
+
+ Win32Window::OnDestroy();
+}
+
+LRESULT
+FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept {
+ // Give Flutter, including plugins, an opportunity to handle window messages.
+ if (flutter_controller_) {
+ std::optional<LRESULT> result =
+ flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
+ lparam);
+ if (result) {
+ return *result;
+ }
+ }
+
+ switch (message) {
+ case WM_FONTCHANGE:
+ flutter_controller_->engine()->ReloadSystemFonts();
+ break;
+ }
+
+ return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/flutter_window.h b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/flutter_window.h
new file mode 100644
index 0000000..6da0652
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/flutter_window.h
@@ -0,0 +1,33 @@
+#ifndef RUNNER_FLUTTER_WINDOW_H_
+#define RUNNER_FLUTTER_WINDOW_H_
+
+#include <flutter/dart_project.h>
+#include <flutter/flutter_view_controller.h>
+
+#include <memory>
+
+#include "win32_window.h"
+
+// A window that does nothing but host a Flutter view.
+class FlutterWindow : public Win32Window {
+ public:
+ // Creates a new FlutterWindow hosting a Flutter view running |project|.
+ explicit FlutterWindow(const flutter::DartProject& project);
+ virtual ~FlutterWindow();
+
+ protected:
+ // Win32Window:
+ bool OnCreate() override;
+ void OnDestroy() override;
+ LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
+ LPARAM const lparam) noexcept override;
+
+ private:
+ // The project to run.
+ flutter::DartProject project_;
+
+ // The Flutter instance hosted by this window.
+ std::unique_ptr<flutter::FlutterViewController> flutter_controller_;
+};
+
+#endif // RUNNER_FLUTTER_WINDOW_H_
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/main.cpp b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/main.cpp
new file mode 100644
index 0000000..44bdbc6
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/main.cpp
@@ -0,0 +1,43 @@
+#include <flutter/dart_project.h>
+#include <flutter/flutter_view_controller.h>
+#include <windows.h>
+
+#include "flutter_window.h"
+#include "utils.h"
+
+int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
+ _In_ wchar_t *command_line, _In_ int show_command) {
+ // Attach to console when present (e.g., 'flutter run') or create a
+ // new console when running with a debugger.
+ if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
+ CreateAndAttachConsole();
+ }
+
+ // Initialize COM, so that it is available for use in the library and/or
+ // plugins.
+ ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
+
+ flutter::DartProject project(L"data");
+
+ std::vector<std::string> command_line_arguments =
+ GetCommandLineArguments();
+
+ project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
+
+ FlutterWindow window(project);
+ Win32Window::Point origin(10, 10);
+ Win32Window::Size size(1280, 720);
+ if (!window.CreateAndShow(L"pdfbox_plugin_example", origin, size)) {
+ return EXIT_FAILURE;
+ }
+ window.SetQuitOnClose(true);
+
+ ::MSG msg;
+ while (::GetMessage(&msg, nullptr, 0, 0)) {
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ }
+
+ ::CoUninitialize();
+ return EXIT_SUCCESS;
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/resource.h b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/resource.h
new file mode 100644
index 0000000..66a65d1
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/resource.h
@@ -0,0 +1,16 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by Runner.rc
+//
+#define IDI_APP_ICON 101
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/resources/app_icon.ico b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/resources/app_icon.ico
new file mode 100644
index 0000000..c04e20c
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/resources/app_icon.ico
Binary files differ
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/runner.exe.manifest b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/runner.exe.manifest
new file mode 100644
index 0000000..c977c4a
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/runner.exe.manifest
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <application xmlns="urn:schemas-microsoft-com:asm.v3">
+ <windowsSettings>
+ <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
+ </windowsSettings>
+ </application>
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <!-- Windows 10 -->
+ <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+ <!-- Windows 8.1 -->
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+ <!-- Windows 8 -->
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+ <!-- Windows 7 -->
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+ </application>
+ </compatibility>
+</assembly>
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/utils.cpp b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/utils.cpp
new file mode 100644
index 0000000..f5bf9fa
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/utils.cpp
@@ -0,0 +1,64 @@
+#include "utils.h"
+
+#include <flutter_windows.h>
+#include <io.h>
+#include <stdio.h>
+#include <windows.h>
+
+#include <iostream>
+
+void CreateAndAttachConsole() {
+ if (::AllocConsole()) {
+ FILE *unused;
+ if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
+ _dup2(_fileno(stdout), 1);
+ }
+ if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
+ _dup2(_fileno(stdout), 2);
+ }
+ std::ios::sync_with_stdio();
+ FlutterDesktopResyncOutputStreams();
+ }
+}
+
+std::vector<std::string> GetCommandLineArguments() {
+ // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
+ int argc;
+ wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
+ if (argv == nullptr) {
+ return std::vector<std::string>();
+ }
+
+ std::vector<std::string> command_line_arguments;
+
+ // Skip the first argument as it's the binary name.
+ for (int i = 1; i < argc; i++) {
+ command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
+ }
+
+ ::LocalFree(argv);
+
+ return command_line_arguments;
+}
+
+std::string Utf8FromUtf16(const wchar_t* utf16_string) {
+ if (utf16_string == nullptr) {
+ return std::string();
+ }
+ int target_length = ::WideCharToMultiByte(
+ CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
+ -1, nullptr, 0, nullptr, nullptr);
+ std::string utf8_string;
+ if (target_length == 0 || target_length > utf8_string.max_size()) {
+ return utf8_string;
+ }
+ utf8_string.resize(target_length);
+ int converted_length = ::WideCharToMultiByte(
+ CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
+ -1, utf8_string.data(),
+ target_length, nullptr, nullptr);
+ if (converted_length == 0) {
+ return std::string();
+ }
+ return utf8_string;
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/utils.h b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/utils.h
new file mode 100644
index 0000000..3879d54
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/utils.h
@@ -0,0 +1,19 @@
+#ifndef RUNNER_UTILS_H_
+#define RUNNER_UTILS_H_
+
+#include <string>
+#include <vector>
+
+// Creates a console for the process, and redirects stdout and stderr to
+// it for both the runner and the Flutter library.
+void CreateAndAttachConsole();
+
+// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
+// encoded in UTF-8. Returns an empty std::string on failure.
+std::string Utf8FromUtf16(const wchar_t* utf16_string);
+
+// Gets the command line arguments passed in as a std::vector<std::string>,
+// encoded in UTF-8. Returns an empty std::vector<std::string> on failure.
+std::vector<std::string> GetCommandLineArguments();
+
+#endif // RUNNER_UTILS_H_
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/win32_window.cpp b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/win32_window.cpp
new file mode 100644
index 0000000..c10f08d
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/win32_window.cpp
@@ -0,0 +1,245 @@
+#include "win32_window.h"
+
+#include <flutter_windows.h>
+
+#include "resource.h"
+
+namespace {
+
+constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW";
+
+// The number of Win32Window objects that currently exist.
+static int g_active_window_count = 0;
+
+using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd);
+
+// Scale helper to convert logical scaler values to physical using passed in
+// scale factor
+int Scale(int source, double scale_factor) {
+ return static_cast<int>(source * scale_factor);
+}
+
+// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module.
+// This API is only needed for PerMonitor V1 awareness mode.
+void EnableFullDpiSupportIfAvailable(HWND hwnd) {
+ HMODULE user32_module = LoadLibraryA("User32.dll");
+ if (!user32_module) {
+ return;
+ }
+ auto enable_non_client_dpi_scaling =
+ reinterpret_cast<EnableNonClientDpiScaling*>(
+ GetProcAddress(user32_module, "EnableNonClientDpiScaling"));
+ if (enable_non_client_dpi_scaling != nullptr) {
+ enable_non_client_dpi_scaling(hwnd);
+ FreeLibrary(user32_module);
+ }
+}
+
+} // namespace
+
+// Manages the Win32Window's window class registration.
+class WindowClassRegistrar {
+ public:
+ ~WindowClassRegistrar() = default;
+
+ // Returns the singleton registar instance.
+ static WindowClassRegistrar* GetInstance() {
+ if (!instance_) {
+ instance_ = new WindowClassRegistrar();
+ }
+ return instance_;
+ }
+
+ // Returns the name of the window class, registering the class if it hasn't
+ // previously been registered.
+ const wchar_t* GetWindowClass();
+
+ // Unregisters the window class. Should only be called if there are no
+ // instances of the window.
+ void UnregisterWindowClass();
+
+ private:
+ WindowClassRegistrar() = default;
+
+ static WindowClassRegistrar* instance_;
+
+ bool class_registered_ = false;
+};
+
+WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr;
+
+const wchar_t* WindowClassRegistrar::GetWindowClass() {
+ if (!class_registered_) {
+ WNDCLASS window_class{};
+ window_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
+ window_class.lpszClassName = kWindowClassName;
+ window_class.style = CS_HREDRAW | CS_VREDRAW;
+ window_class.cbClsExtra = 0;
+ window_class.cbWndExtra = 0;
+ window_class.hInstance = GetModuleHandle(nullptr);
+ window_class.hIcon =
+ LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
+ window_class.hbrBackground = 0;
+ window_class.lpszMenuName = nullptr;
+ window_class.lpfnWndProc = Win32Window::WndProc;
+ RegisterClass(&window_class);
+ class_registered_ = true;
+ }
+ return kWindowClassName;
+}
+
+void WindowClassRegistrar::UnregisterWindowClass() {
+ UnregisterClass(kWindowClassName, nullptr);
+ class_registered_ = false;
+}
+
+Win32Window::Win32Window() {
+ ++g_active_window_count;
+}
+
+Win32Window::~Win32Window() {
+ --g_active_window_count;
+ Destroy();
+}
+
+bool Win32Window::CreateAndShow(const std::wstring& title,
+ const Point& origin,
+ const Size& size) {
+ Destroy();
+
+ const wchar_t* window_class =
+ WindowClassRegistrar::GetInstance()->GetWindowClass();
+
+ const POINT target_point = {static_cast<LONG>(origin.x),
+ static_cast<LONG>(origin.y)};
+ HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST);
+ UINT dpi = FlutterDesktopGetDpiForMonitor(monitor);
+ double scale_factor = dpi / 96.0;
+
+ HWND window = CreateWindow(
+ window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+ Scale(origin.x, scale_factor), Scale(origin.y, scale_factor),
+ Scale(size.width, scale_factor), Scale(size.height, scale_factor),
+ nullptr, nullptr, GetModuleHandle(nullptr), this);
+
+ if (!window) {
+ return false;
+ }
+
+ return OnCreate();
+}
+
+// static
+LRESULT CALLBACK Win32Window::WndProc(HWND const window,
+ UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept {
+ if (message == WM_NCCREATE) {
+ auto window_struct = reinterpret_cast<CREATESTRUCT*>(lparam);
+ SetWindowLongPtr(window, GWLP_USERDATA,
+ reinterpret_cast<LONG_PTR>(window_struct->lpCreateParams));
+
+ auto that = static_cast<Win32Window*>(window_struct->lpCreateParams);
+ EnableFullDpiSupportIfAvailable(window);
+ that->window_handle_ = window;
+ } else if (Win32Window* that = GetThisFromHandle(window)) {
+ return that->MessageHandler(window, message, wparam, lparam);
+ }
+
+ return DefWindowProc(window, message, wparam, lparam);
+}
+
+LRESULT
+Win32Window::MessageHandler(HWND hwnd,
+ UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept {
+ switch (message) {
+ case WM_DESTROY:
+ window_handle_ = nullptr;
+ Destroy();
+ if (quit_on_close_) {
+ PostQuitMessage(0);
+ }
+ return 0;
+
+ case WM_DPICHANGED: {
+ auto newRectSize = reinterpret_cast<RECT*>(lparam);
+ LONG newWidth = newRectSize->right - newRectSize->left;
+ LONG newHeight = newRectSize->bottom - newRectSize->top;
+
+ SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth,
+ newHeight, SWP_NOZORDER | SWP_NOACTIVATE);
+
+ return 0;
+ }
+ case WM_SIZE: {
+ RECT rect = GetClientArea();
+ if (child_content_ != nullptr) {
+ // Size and position the child window.
+ MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
+ rect.bottom - rect.top, TRUE);
+ }
+ return 0;
+ }
+
+ case WM_ACTIVATE:
+ if (child_content_ != nullptr) {
+ SetFocus(child_content_);
+ }
+ return 0;
+ }
+
+ return DefWindowProc(window_handle_, message, wparam, lparam);
+}
+
+void Win32Window::Destroy() {
+ OnDestroy();
+
+ if (window_handle_) {
+ DestroyWindow(window_handle_);
+ window_handle_ = nullptr;
+ }
+ if (g_active_window_count == 0) {
+ WindowClassRegistrar::GetInstance()->UnregisterWindowClass();
+ }
+}
+
+Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
+ return reinterpret_cast<Win32Window*>(
+ GetWindowLongPtr(window, GWLP_USERDATA));
+}
+
+void Win32Window::SetChildContent(HWND content) {
+ child_content_ = content;
+ SetParent(content, window_handle_);
+ RECT frame = GetClientArea();
+
+ MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
+ frame.bottom - frame.top, true);
+
+ SetFocus(child_content_);
+}
+
+RECT Win32Window::GetClientArea() {
+ RECT frame;
+ GetClientRect(window_handle_, &frame);
+ return frame;
+}
+
+HWND Win32Window::GetHandle() {
+ return window_handle_;
+}
+
+void Win32Window::SetQuitOnClose(bool quit_on_close) {
+ quit_on_close_ = quit_on_close;
+}
+
+bool Win32Window::OnCreate() {
+ // No-op; provided for subclasses.
+ return true;
+}
+
+void Win32Window::OnDestroy() {
+ // No-op; provided for subclasses.
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/win32_window.h b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/win32_window.h
new file mode 100644
index 0000000..17ba431
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/example/windows/runner/win32_window.h
@@ -0,0 +1,98 @@
+#ifndef RUNNER_WIN32_WINDOW_H_
+#define RUNNER_WIN32_WINDOW_H_
+
+#include <windows.h>
+
+#include <functional>
+#include <memory>
+#include <string>
+
+// A class abstraction for a high DPI-aware Win32 Window. Intended to be
+// inherited from by classes that wish to specialize with custom
+// rendering and input handling
+class Win32Window {
+ public:
+ struct Point {
+ unsigned int x;
+ unsigned int y;
+ Point(unsigned int x, unsigned int y) : x(x), y(y) {}
+ };
+
+ struct Size {
+ unsigned int width;
+ unsigned int height;
+ Size(unsigned int width, unsigned int height)
+ : width(width), height(height) {}
+ };
+
+ Win32Window();
+ virtual ~Win32Window();
+
+ // Creates and shows a win32 window with |title| and position and size using
+ // |origin| and |size|. New windows are created on the default monitor. Window
+ // sizes are specified to the OS in physical pixels, hence to ensure a
+ // consistent size to will treat the width height passed in to this function
+ // as logical pixels and scale to appropriate for the default monitor. Returns
+ // true if the window was created successfully.
+ bool CreateAndShow(const std::wstring& title,
+ const Point& origin,
+ const Size& size);
+
+ // Release OS resources associated with window.
+ void Destroy();
+
+ // Inserts |content| into the window tree.
+ void SetChildContent(HWND content);
+
+ // Returns the backing Window handle to enable clients to set icon and other
+ // window properties. Returns nullptr if the window has been destroyed.
+ HWND GetHandle();
+
+ // If true, closing this window will quit the application.
+ void SetQuitOnClose(bool quit_on_close);
+
+ // Return a RECT representing the bounds of the current client area.
+ RECT GetClientArea();
+
+ protected:
+ // Processes and route salient window messages for mouse handling,
+ // size change and DPI. Delegates handling of these to member overloads that
+ // inheriting classes can handle.
+ virtual LRESULT MessageHandler(HWND window,
+ UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept;
+
+ // Called when CreateAndShow is called, allowing subclass window-related
+ // setup. Subclasses should return false if setup fails.
+ virtual bool OnCreate();
+
+ // Called when Destroy is called.
+ virtual void OnDestroy();
+
+ private:
+ friend class WindowClassRegistrar;
+
+ // OS callback called by message pump. Handles the WM_NCCREATE message which
+ // is passed when the non-client area is being created and enables automatic
+ // non-client DPI scaling so that the non-client area automatically
+ // responsponds to changes in DPI. All other messages are handled by
+ // MessageHandler.
+ static LRESULT CALLBACK WndProc(HWND const window,
+ UINT const message,
+ WPARAM const wparam,
+ LPARAM const lparam) noexcept;
+
+ // Retrieves a class instance pointer for |window|
+ static Win32Window* GetThisFromHandle(HWND const window) noexcept;
+
+ bool quit_on_close_ = false;
+
+ // window handle for top level window.
+ HWND window_handle_ = nullptr;
+
+ // window handle for hosted content.
+ HWND child_content_ = nullptr;
+};
+
+#endif // RUNNER_WIN32_WINDOW_H_
diff --git a/pkgs/jnigen/example/pdfbox_plugin/jnigen.yaml b/pkgs/jnigen/example/pdfbox_plugin/jnigen.yaml
new file mode 100644
index 0000000..584a3bf
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/jnigen.yaml
@@ -0,0 +1,80 @@
+## String to be pasted verbatim into generated bindings
+preamble: |
+ // Generated from Apache PDFBox library which is licensed under the Apache License 2.0.
+ // The following copyright from the original authors applies.
+ //
+ // Licensed to the Apache Software Foundation (ASF) under one or more
+ // contributor license agreements. See the NOTICE file distributed with
+ // this work for additional information regarding copyright ownership.
+ // The ASF licenses this file to You under the Apache License, Version 2.0
+ // (the "License"); you may not use this file except in compliance with
+ // the License. You may obtain a copy of the License at
+ //
+ // http://www.apache.org/licenses/LICENSE-2.0
+ //
+ // Unless required by applicable law or agreed to in writing, software
+ // distributed under the License is distributed on an "AS IS" BASIS,
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ // See the License for the specific language governing permissions and
+ // limitations under the License.
+
+## Output configuration
+output:
+ c:
+ ## Path to write generated C bindings
+ path: 'src/'
+ ## C files can be stored in a different sub-directory inside root.
+ ##
+ ## We have a guideline to keep all generated code in third_party/ since the
+ ## original project's license applies to generated code. So we specify
+ ## third_party/ as c_subdir while keeping generated CMakeLists.txt in src/.
+ subdir: 'third_party/'
+ ## Name of the generated library. This is a required parameter, and used
+ ## for the name of the shared library and CMake configuration.
+ library_name: 'pdfbox_plugin'
+ dart:
+ ## Generated dart bindings will be written to this path. They will follow
+ ## the same folder hierarchy as the original Java code.
+ path: 'lib/src/third_party/'
+
+## Classes / packages for which bindings need to be generated.
+classes:
+ - 'org.apache.pdfbox.pdmodel.PDDocument'
+ - 'org.apache.pdfbox.pdmodel.PDDocumentInformation'
+ - 'org.apache.pdfbox.text.PDFTextStripper'
+
+## Exclude a problematic static field. Static fields are usually converted
+## directly to dart static fields. In the current implementation some string
+## escaping problems may occur.
+##
+## See issue #31 (https://github.com/dart-lang/jnigen/issues/31) for details.
+## (This field does not appear in bindings unless full package bindings are
+## generated using a `-Dclasses` override.)
+##
+## TODO(#31): For string fields, it may be better to generate a field getter
+## than a direct literal.
+exclude:
+ fields:
+ - 'org.apache.pdfbox.contentstream.operator.OperatorName#SHOW_TEXT_LINE_AND_SPACE'
+
+## Dependencies to be downloaded using Maven (Invokes `mvn` command). These
+## dependencies are always downloaded along with their transitive dependencies.
+##
+## Dependencies should be specified using groupID:artifactID:version format
+## The downloaded dependencies are automatically added to classpath of the
+## Java API scanning process. There's no need to specify these again in
+## sourcepath and classpath.
+##
+## Note that when maven based tooling is used, the first run often has to fetch
+## all the dependencies and might take some time. However, maven caches the
+## artifacts in local repository, thus subsequent runs will be faster.
+maven_downloads:
+ ## For these dependencies, both source and JARs are downloaded.
+ source_deps:
+ - 'org.apache.pdfbox:pdfbox:2.0.26'
+ ## Runtime dependencies for which bindings aren't generated directly.
+ ## Only JARs are downloaded.
+ jar_only_deps:
+ - 'org.bouncycastle:bcmail-jdk15on:1.70'
+ - 'org.bouncycastle:bcprov-jdk15on:1.70'
+
diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/pdfbox_plugin.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/pdfbox_plugin.dart
new file mode 100644
index 0000000..3cdeeff
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/lib/pdfbox_plugin.dart
@@ -0,0 +1,6 @@
+/// File merely exporting the generated bindings from lib/src/third_party
+library pdfbox_plugin;
+
+export 'src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart';
+export 'src/third_party/org/apache/pdfbox/pdmodel/PDDocumentInformation.dart';
+export 'src/third_party/org/apache/pdfbox/text/PDFTextStripper.dart';
diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/_init.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/_init.dart
new file mode 100644
index 0000000..57aea60
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/_init.dart
@@ -0,0 +1,25 @@
+// Generated from Apache PDFBox library which is licensed under the Apache License 2.0.
+// The following copyright from the original authors applies.
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+
+// Auto-generated initialization code.
+
+final ffi.Pointer<T> Function<T extends ffi.NativeType>(String sym) jniLookup =
+ ProtectedJniExtensions.initGeneratedLibrary("pdfbox_plugin");
diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart
new file mode 100644
index 0000000..e8777cb
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart
@@ -0,0 +1,1536 @@
+// Generated from Apache PDFBox library which is licensed under the Apache License 2.0.
+// The following copyright from the original authors applies.
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+// ignore_for_file: annotate_overrides
+// ignore_for_file: camel_case_extensions
+// ignore_for_file: camel_case_types
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: doc_directive_unknown
+// ignore_for_file: file_names
+// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: overridden_fields
+// ignore_for_file: unnecessary_cast
+// ignore_for_file: unused_element
+// ignore_for_file: unused_field
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: unused_shown_name
+
+import "dart:isolate" show ReceivePort;
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+import "package:jni/jni.dart" as jni;
+
+import "PDDocumentInformation.dart" as pddocumentinformation_;
+import "../../../../_init.dart";
+
+/// from: org.apache.pdfbox.pdmodel.PDDocument
+///
+/// This is the in-memory representation of the PDF document.
+/// The \#close() method must be called once the document is no longer needed.
+///@author Ben Litchfield
+class PDDocument extends jni.JObject {
+ @override
+ late final jni.JObjType<PDDocument> $type = type;
+
+ PDDocument.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $PDDocumentType();
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "PDDocument__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Creates an empty PDF document.
+ /// You need to add at least one page for the document to be valid.
+ factory PDDocument() {
+ return PDDocument.fromRef(_new0().object);
+ }
+
+ static final _new1 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__new1")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Creates an empty PDF document.
+ /// You need to add at least one page for the document to be valid.
+ ///@param memUsageSetting defines how memory is used for buffering PDF streams
+ factory PDDocument.new1(
+ jni.JObject memUsageSetting,
+ ) {
+ return PDDocument.fromRef(_new1(memUsageSetting.reference).object);
+ }
+
+ static final _new2 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__new2")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(org.apache.pdfbox.cos.COSDocument doc)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Constructor that uses an existing document. The COSDocument that is passed in must be valid.
+ ///@param doc The COSDocument that this document wraps.
+ factory PDDocument.new2(
+ jni.JObject doc,
+ ) {
+ return PDDocument.fromRef(_new2(doc.reference).object);
+ }
+
+ static final _new3 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__new3")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(org.apache.pdfbox.cos.COSDocument doc, org.apache.pdfbox.io.RandomAccessRead source)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Constructor that uses an existing document. The COSDocument that is passed in must be valid.
+ ///@param doc The COSDocument that this document wraps.
+ ///@param source the parser which is used to read the pdf
+ factory PDDocument.new3(
+ jni.JObject doc,
+ jni.JObject source,
+ ) {
+ return PDDocument.fromRef(_new3(doc.reference, source.reference).object);
+ }
+
+ static final _new4 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__new4")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(org.apache.pdfbox.cos.COSDocument doc, org.apache.pdfbox.io.RandomAccessRead source, org.apache.pdfbox.pdmodel.encryption.AccessPermission permission)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Constructor that uses an existing document. The COSDocument that is passed in must be valid.
+ ///@param doc The COSDocument that this document wraps.
+ ///@param source the parser which is used to read the pdf
+ ///@param permission he access permissions of the pdf
+ factory PDDocument.new4(
+ jni.JObject doc,
+ jni.JObject source,
+ jni.JObject permission,
+ ) {
+ return PDDocument.fromRef(
+ _new4(doc.reference, source.reference, permission.reference).object);
+ }
+
+ static final _addPage = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__addPage")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void addPage(org.apache.pdfbox.pdmodel.PDPage page)
+ ///
+ /// This will add a page to the document. This is a convenience method, that will add the page to the root of the
+ /// hierarchy and set the parent of the page to the root.
+ ///@param page The page to add to the document.
+ void addPage(
+ jni.JObject page,
+ ) {
+ return _addPage(reference, page.reference).check();
+ }
+
+ static final _addSignature = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__addSignature")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void addSignature(org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature sigObject)
+ ///
+ /// Add parameters of signature to be created externally using default signature options. See
+ /// \#saveIncrementalForExternalSigning(OutputStream) method description on external
+ /// signature creation scenario details.
+ ///
+ /// Only one signature may be added in a document. To sign several times,
+ /// load document, add signature, save incremental and close again.
+ ///@param sigObject is the PDSignatureField model
+ ///@throws IOException if there is an error creating required fields
+ ///@throws IllegalStateException if one attempts to add several signature
+ /// fields.
+ void addSignature(
+ jni.JObject sigObject,
+ ) {
+ return _addSignature(reference, sigObject.reference).check();
+ }
+
+ static final _addSignature1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__addSignature1")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void addSignature(org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature sigObject, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions options)
+ ///
+ /// Add parameters of signature to be created externally. See
+ /// \#saveIncrementalForExternalSigning(OutputStream) method description on external
+ /// signature creation scenario details.
+ ///
+ /// Only one signature may be added in a document. To sign several times,
+ /// load document, add signature, save incremental and close again.
+ ///@param sigObject is the PDSignatureField model
+ ///@param options signature options
+ ///@throws IOException if there is an error creating required fields
+ ///@throws IllegalStateException if one attempts to add several signature
+ /// fields.
+ void addSignature1(
+ jni.JObject sigObject,
+ jni.JObject options,
+ ) {
+ return _addSignature1(reference, sigObject.reference, options.reference)
+ .check();
+ }
+
+ static final _addSignature2 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__addSignature2")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void addSignature(org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature sigObject, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface signatureInterface)
+ ///
+ /// Add a signature to be created using the instance of given interface.
+ ///
+ /// Only one signature may be added in a document. To sign several times,
+ /// load document, add signature, save incremental and close again.
+ ///@param sigObject is the PDSignatureField model
+ ///@param signatureInterface is an interface whose implementation provides
+ /// signing capabilities. Can be null if external signing if used.
+ ///@throws IOException if there is an error creating required fields
+ ///@throws IllegalStateException if one attempts to add several signature
+ /// fields.
+ void addSignature2(
+ jni.JObject sigObject,
+ jni.JObject signatureInterface,
+ ) {
+ return _addSignature2(
+ reference, sigObject.reference, signatureInterface.reference)
+ .check();
+ }
+
+ static final _addSignature3 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__addSignature3")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void addSignature(org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature sigObject, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface signatureInterface, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions options)
+ ///
+ /// This will add a signature to the document. If the 0-based page number in the options
+ /// parameter is smaller than 0 or larger than max, the nearest valid page number will be used
+ /// (i.e. 0 or max) and no exception will be thrown.
+ ///
+ /// Only one signature may be added in a document. To sign several times,
+ /// load document, add signature, save incremental and close again.
+ ///@param sigObject is the PDSignatureField model
+ ///@param signatureInterface is an interface whose implementation provides
+ /// signing capabilities. Can be null if external signing if used.
+ ///@param options signature options
+ ///@throws IOException if there is an error creating required fields
+ ///@throws IllegalStateException if one attempts to add several signature
+ /// fields.
+ void addSignature3(
+ jni.JObject sigObject,
+ jni.JObject signatureInterface,
+ jni.JObject options,
+ ) {
+ return _addSignature3(reference, sigObject.reference,
+ signatureInterface.reference, options.reference)
+ .check();
+ }
+
+ static final _addSignatureField = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__addSignatureField")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void addSignatureField(java.util.List<org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField> sigFields, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface signatureInterface, org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions options)
+ ///
+ /// This will add a list of signature fields to the document.
+ ///@param sigFields are the PDSignatureFields that should be added to the document
+ ///@param signatureInterface is an interface whose implementation provides
+ /// signing capabilities. Can be null if external signing if used.
+ ///@param options signature options
+ ///@throws IOException if there is an error creating required fields
+ ///@deprecated The method is misleading, because only one signature may be
+ /// added in a document. The method will be removed in the future.
+ void addSignatureField(
+ jni.JList<jni.JObject> sigFields,
+ jni.JObject signatureInterface,
+ jni.JObject options,
+ ) {
+ return _addSignatureField(reference, sigFields.reference,
+ signatureInterface.reference, options.reference)
+ .check();
+ }
+
+ static final _removePage = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__removePage")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void removePage(org.apache.pdfbox.pdmodel.PDPage page)
+ ///
+ /// Remove the page from the document.
+ ///@param page The page to remove from the document.
+ void removePage(
+ jni.JObject page,
+ ) {
+ return _removePage(reference, page.reference).check();
+ }
+
+ static final _removePage1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Int32)>>("PDDocument__removePage1")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public void removePage(int pageNumber)
+ ///
+ /// Remove the page from the document.
+ ///@param pageNumber 0 based index to page number.
+ void removePage1(
+ int pageNumber,
+ ) {
+ return _removePage1(reference, pageNumber).check();
+ }
+
+ static final _importPage = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__importPage")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public org.apache.pdfbox.pdmodel.PDPage importPage(org.apache.pdfbox.pdmodel.PDPage page)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will import and copy the contents from another location. Currently the content stream is
+ /// stored in a scratch file. The scratch file is associated with the document. If you are adding
+ /// a page to this document from another document and want to copy the contents to this
+ /// document's scratch file then use this method otherwise just use the \#addPage addPage()
+ /// method.
+ ///
+ /// Unlike \#addPage addPage(), this method creates a new PDPage object. If your page has
+ /// annotations, and if these link to pages not in the target document, then the target document
+ /// might become huge. What you need to do is to delete page references of such annotations. See
+ /// <a href="http://stackoverflow.com/a/35477351/535646">here</a> for how to do this.
+ ///
+ /// Inherited (global) resources are ignored because these can contain resources not needed for
+ /// this page which could bloat your document, see
+ /// <a href="https://issues.apache.org/jira/browse/PDFBOX-28">PDFBOX-28</a> and related issues.
+ /// If you need them, call <code>importedPage.setResources(page.getResources());</code>
+ ///
+ /// This method should only be used to import a page from a loaded document, not from a generated
+ /// document because these can contain unfinished parts, e.g. font subsetting information.
+ ///@param page The page to import.
+ ///@return The page that was imported.
+ ///@throws IOException If there is an error copying the page.
+ jni.JObject importPage(
+ jni.JObject page,
+ ) {
+ return const jni.JObjectType()
+ .fromRef(_importPage(reference, page.reference).object);
+ }
+
+ static final _getDocument = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__getDocument")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public org.apache.pdfbox.cos.COSDocument getDocument()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the low level document.
+ ///@return The document that this layer sits on top of.
+ jni.JObject getDocument() {
+ return const jni.JObjectType().fromRef(_getDocument(reference).object);
+ }
+
+ static final _getDocumentInformation = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__getDocumentInformation")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public org.apache.pdfbox.pdmodel.PDDocumentInformation getDocumentInformation()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the document info dictionary. If it doesn't exist, an empty document info
+ /// dictionary is created in the document trailer.
+ ///
+ /// In PDF 2.0 this is deprecated except for two entries, /CreationDate and /ModDate. For any other
+ /// document level metadata, a metadata stream should be used instead, see
+ /// PDDocumentCatalog\#getMetadata().
+ ///@return The documents /Info dictionary, never null.
+ pddocumentinformation_.PDDocumentInformation getDocumentInformation() {
+ return const pddocumentinformation_.$PDDocumentInformationType()
+ .fromRef(_getDocumentInformation(reference).object);
+ }
+
+ static final _setDocumentInformation = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__setDocumentInformation")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setDocumentInformation(org.apache.pdfbox.pdmodel.PDDocumentInformation info)
+ ///
+ /// This will set the document information for this document.
+ ///
+ /// In PDF 2.0 this is deprecated except for two entries, /CreationDate and /ModDate. For any other
+ /// document level metadata, a metadata stream should be used instead, see
+ /// PDDocumentCatalog\#setMetadata(org.apache.pdfbox.pdmodel.common.PDMetadata) PDDocumentCatalog\#setMetadata(PDMetadata).
+ ///@param info The updated document information.
+ void setDocumentInformation(
+ pddocumentinformation_.PDDocumentInformation info,
+ ) {
+ return _setDocumentInformation(reference, info.reference).check();
+ }
+
+ static final _getDocumentCatalog = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__getDocumentCatalog")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public org.apache.pdfbox.pdmodel.PDDocumentCatalog getDocumentCatalog()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the document CATALOG. This is guaranteed to not return null.
+ ///@return The documents /Root dictionary
+ jni.JObject getDocumentCatalog() {
+ return const jni.JObjectType()
+ .fromRef(_getDocumentCatalog(reference).object);
+ }
+
+ static final _isEncrypted = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__isEncrypted")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean isEncrypted()
+ ///
+ /// This will tell if this document is encrypted or not.
+ ///@return true If this document is encrypted.
+ bool isEncrypted() {
+ return _isEncrypted(reference).boolean;
+ }
+
+ static final _getEncryption = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__getEncryption")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public org.apache.pdfbox.pdmodel.encryption.PDEncryption getEncryption()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the encryption dictionary for this document. This will still return the parameters if the document
+ /// was decrypted. As the encryption architecture in PDF documents is pluggable this returns an abstract class,
+ /// but the only supported subclass at this time is a
+ /// PDStandardEncryption object.
+ ///@return The encryption dictionary(most likely a PDStandardEncryption object)
+ jni.JObject getEncryption() {
+ return const jni.JObjectType().fromRef(_getEncryption(reference).object);
+ }
+
+ static final _setEncryptionDictionary = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__setEncryptionDictionary")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setEncryptionDictionary(org.apache.pdfbox.pdmodel.encryption.PDEncryption encryption)
+ ///
+ /// This will set the encryption dictionary for this document.
+ ///@param encryption The encryption dictionary(most likely a PDStandardEncryption object)
+ ///@throws IOException If there is an error determining which security handler to use.
+ void setEncryptionDictionary(
+ jni.JObject encryption,
+ ) {
+ return _setEncryptionDictionary(reference, encryption.reference).check();
+ }
+
+ static final _getLastSignatureDictionary = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__getLastSignatureDictionary")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature getLastSignatureDictionary()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will return the last signature from the field tree. Note that this may not be the
+ /// last in time when empty signature fields are created first but signed after other fields.
+ ///@return the last signature as <code>PDSignatureField</code>.
+ ///@throws IOException if no document catalog can be found.
+ jni.JObject getLastSignatureDictionary() {
+ return const jni.JObjectType()
+ .fromRef(_getLastSignatureDictionary(reference).object);
+ }
+
+ static final _getSignatureFields = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__getSignatureFields")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.util.List<org.apache.pdfbox.pdmodel.interactive.form.PDSignatureField> getSignatureFields()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Retrieve all signature fields from the document.
+ ///@return a <code>List</code> of <code>PDSignatureField</code>s
+ ///@throws IOException if no document catalog can be found.
+ jni.JList<jni.JObject> getSignatureFields() {
+ return const jni.JListType(jni.JObjectType())
+ .fromRef(_getSignatureFields(reference).object);
+ }
+
+ static final _getSignatureDictionaries = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__getSignatureDictionaries")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.util.List<org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature> getSignatureDictionaries()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Retrieve all signature dictionaries from the document.
+ ///@return a <code>List</code> of <code>PDSignatureField</code>s
+ ///@throws IOException if no document catalog can be found.
+ jni.JList<jni.JObject> getSignatureDictionaries() {
+ return const jni.JListType(jni.JObjectType())
+ .fromRef(_getSignatureDictionaries(reference).object);
+ }
+
+ static final _registerTrueTypeFontForClosing = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__registerTrueTypeFontForClosing")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void registerTrueTypeFontForClosing(org.apache.fontbox.ttf.TrueTypeFont ttf)
+ ///
+ /// For internal PDFBox use when creating PDF documents: register a TrueTypeFont to make sure it
+ /// is closed when the PDDocument is closed to avoid memory leaks. Users don't have to call this
+ /// method, it is done by the appropriate PDFont classes.
+ ///@param ttf
+ void registerTrueTypeFontForClosing(
+ jni.JObject ttf,
+ ) {
+ return _registerTrueTypeFontForClosing(reference, ttf.reference).check();
+ }
+
+ static final _load = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__load")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
+ ///@param file file to be loaded
+ ///@return loaded document
+ ///@throws InvalidPasswordException If the file required a non-empty password.
+ ///@throws IOException in case of a file reading or parsing error
+ static PDDocument load(
+ jni.JObject file,
+ ) {
+ return const $PDDocumentType().fromRef(_load(file.reference).object);
+ }
+
+ static final _load1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__load1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Parses a PDF.
+ ///@param file file to be loaded
+ ///@param memUsageSetting defines how memory is used for buffering PDF streams
+ ///@return loaded document
+ ///@throws InvalidPasswordException If the file required a non-empty password.
+ ///@throws IOException in case of a file reading or parsing error
+ static PDDocument load1(
+ jni.JObject file,
+ jni.JObject memUsageSetting,
+ ) {
+ return const $PDDocumentType()
+ .fromRef(_load1(file.reference, memUsageSetting.reference).object);
+ }
+
+ static final _load2 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__load2")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file, java.lang.String password)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
+ ///@param file file to be loaded
+ ///@param password password to be used for decryption
+ ///@return loaded document
+ ///@throws InvalidPasswordException If the password is incorrect.
+ ///@throws IOException in case of a file reading or parsing error
+ static PDDocument load2(
+ jni.JObject file,
+ jni.JString password,
+ ) {
+ return const $PDDocumentType()
+ .fromRef(_load2(file.reference, password.reference).object);
+ }
+
+ static final _load3 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__load3")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file, java.lang.String password, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Parses a PDF.
+ ///@param file file to be loaded
+ ///@param password password to be used for decryption
+ ///@param memUsageSetting defines how memory is used for buffering PDF streams
+ ///@return loaded document
+ ///@throws InvalidPasswordException If the password is incorrect.
+ ///@throws IOException in case of a file reading or parsing error
+ static PDDocument load3(
+ jni.JObject file,
+ jni.JString password,
+ jni.JObject memUsageSetting,
+ ) {
+ return const $PDDocumentType().fromRef(
+ _load3(file.reference, password.reference, memUsageSetting.reference)
+ .object);
+ }
+
+ static final _load4 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__load4")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file, java.lang.String password, java.io.InputStream keyStore, java.lang.String alias)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
+ ///@param file file to be loaded
+ ///@param password password to be used for decryption
+ ///@param keyStore key store to be used for decryption when using public key security
+ ///@param alias alias to be used for decryption when using public key security
+ ///@return loaded document
+ ///@throws IOException in case of a file reading or parsing error
+ static PDDocument load4(
+ jni.JObject file,
+ jni.JString password,
+ jni.JObject keyStore,
+ jni.JString alias,
+ ) {
+ return const $PDDocumentType().fromRef(_load4(file.reference,
+ password.reference, keyStore.reference, alias.reference)
+ .object);
+ }
+
+ static final _load5 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__load5")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.File file, java.lang.String password, java.io.InputStream keyStore, java.lang.String alias, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Parses a PDF.
+ ///@param file file to be loaded
+ ///@param password password to be used for decryption
+ ///@param keyStore key store to be used for decryption when using public key security
+ ///@param alias alias to be used for decryption when using public key security
+ ///@param memUsageSetting defines how memory is used for buffering PDF streams
+ ///@return loaded document
+ ///@throws IOException in case of a file reading or parsing error
+ static PDDocument load5(
+ jni.JObject file,
+ jni.JString password,
+ jni.JObject keyStore,
+ jni.JString alias,
+ jni.JObject memUsageSetting,
+ ) {
+ return const $PDDocumentType().fromRef(_load5(
+ file.reference,
+ password.reference,
+ keyStore.reference,
+ alias.reference,
+ memUsageSetting.reference)
+ .object);
+ }
+
+ static final _load6 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__load6")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Parses a PDF. The given input stream is copied to the memory to enable random access to the
+ /// pdf. Unrestricted main memory will be used for buffering PDF streams.
+ ///@param input stream that contains the document. Don't forget to close it after loading.
+ ///@return loaded document
+ ///@throws InvalidPasswordException If the PDF required a non-empty password.
+ ///@throws IOException In case of a reading or parsing error.
+ static PDDocument load6(
+ jni.JObject input,
+ ) {
+ return const $PDDocumentType().fromRef(_load6(input.reference).object);
+ }
+
+ static final _load7 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__load7")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Parses a PDF. Depending on the memory settings parameter the given input stream is either
+ /// copied to main memory or to a temporary file to enable random access to the pdf.
+ ///@param input stream that contains the document. Don't forget to close it after loading.
+ ///@param memUsageSetting defines how memory is used for buffering input stream and PDF streams
+ ///@return loaded document
+ ///@throws InvalidPasswordException If the PDF required a non-empty password.
+ ///@throws IOException In case of a reading or parsing error.
+ static PDDocument load7(
+ jni.JObject input,
+ jni.JObject memUsageSetting,
+ ) {
+ return const $PDDocumentType()
+ .fromRef(_load7(input.reference, memUsageSetting.reference).object);
+ }
+
+ static final _load8 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__load8")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input, java.lang.String password)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Parses a PDF. The given input stream is copied to the memory to enable random access to the
+ /// pdf. Unrestricted main memory will be used for buffering PDF streams.
+ ///@param input stream that contains the document. Don't forget to close it after loading.
+ ///@param password password to be used for decryption
+ ///@return loaded document
+ ///@throws InvalidPasswordException If the password is incorrect.
+ ///@throws IOException In case of a reading or parsing error.
+ static PDDocument load8(
+ jni.JObject input,
+ jni.JString password,
+ ) {
+ return const $PDDocumentType()
+ .fromRef(_load8(input.reference, password.reference).object);
+ }
+
+ static final _load9 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__load9")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input, java.lang.String password, java.io.InputStream keyStore, java.lang.String alias)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Parses a PDF. The given input stream is copied to the memory to enable random access to the
+ /// pdf. Unrestricted main memory will be used for buffering PDF streams.
+ ///@param input stream that contains the document. Don't forget to close it after loading.
+ ///@param password password to be used for decryption
+ ///@param keyStore key store to be used for decryption when using public key security
+ ///@param alias alias to be used for decryption when using public key security
+ ///@return loaded document
+ ///@throws IOException In case of a reading or parsing error.
+ static PDDocument load9(
+ jni.JObject input,
+ jni.JString password,
+ jni.JObject keyStore,
+ jni.JString alias,
+ ) {
+ return const $PDDocumentType().fromRef(_load9(input.reference,
+ password.reference, keyStore.reference, alias.reference)
+ .object);
+ }
+
+ static final _load10 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__load10")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input, java.lang.String password, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Parses a PDF. Depending on the memory settings parameter the given input stream is either
+ /// copied to main memory or to a temporary file to enable random access to the pdf.
+ ///@param input stream that contains the document. Don't forget to close it after loading.
+ ///@param password password to be used for decryption
+ ///@param memUsageSetting defines how memory is used for buffering input stream and PDF streams
+ ///@return loaded document
+ ///@throws InvalidPasswordException If the password is incorrect.
+ ///@throws IOException In case of a reading or parsing error.
+ static PDDocument load10(
+ jni.JObject input,
+ jni.JString password,
+ jni.JObject memUsageSetting,
+ ) {
+ return const $PDDocumentType().fromRef(
+ _load10(input.reference, password.reference, memUsageSetting.reference)
+ .object);
+ }
+
+ static final _load11 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__load11")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(java.io.InputStream input, java.lang.String password, java.io.InputStream keyStore, java.lang.String alias, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Parses a PDF. Depending on the memory settings parameter the given input stream is either
+ /// copied to memory or to a temporary file to enable random access to the pdf.
+ ///@param input stream that contains the document. Don't forget to close it after loading.
+ ///@param password password to be used for decryption
+ ///@param keyStore key store to be used for decryption when using public key security
+ ///@param alias alias to be used for decryption when using public key security
+ ///@param memUsageSetting defines how memory is used for buffering input stream and PDF streams
+ ///@return loaded document
+ ///@throws InvalidPasswordException If the password is incorrect.
+ ///@throws IOException In case of a reading or parsing error.
+ static PDDocument load11(
+ jni.JObject input,
+ jni.JString password,
+ jni.JObject keyStore,
+ jni.JString alias,
+ jni.JObject memUsageSetting,
+ ) {
+ return const $PDDocumentType().fromRef(_load11(
+ input.reference,
+ password.reference,
+ keyStore.reference,
+ alias.reference,
+ memUsageSetting.reference)
+ .object);
+ }
+
+ static final _load12 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__load12")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(byte[] input)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
+ ///@param input byte array that contains the document.
+ ///@return loaded document
+ ///@throws InvalidPasswordException If the PDF required a non-empty password.
+ ///@throws IOException In case of a reading or parsing error.
+ static PDDocument load12(
+ jni.JArray<jni.jbyte> input,
+ ) {
+ return const $PDDocumentType().fromRef(_load12(input.reference).object);
+ }
+
+ static final _load13 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__load13")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(byte[] input, java.lang.String password)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
+ ///@param input byte array that contains the document.
+ ///@param password password to be used for decryption
+ ///@return loaded document
+ ///@throws InvalidPasswordException If the password is incorrect.
+ ///@throws IOException In case of a reading or parsing error.
+ static PDDocument load13(
+ jni.JArray<jni.jbyte> input,
+ jni.JString password,
+ ) {
+ return const $PDDocumentType()
+ .fromRef(_load13(input.reference, password.reference).object);
+ }
+
+ static final _load14 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__load14")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(byte[] input, java.lang.String password, java.io.InputStream keyStore, java.lang.String alias)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Parses a PDF. Unrestricted main memory will be used for buffering PDF streams.
+ ///@param input byte array that contains the document.
+ ///@param password password to be used for decryption
+ ///@param keyStore key store to be used for decryption when using public key security
+ ///@param alias alias to be used for decryption when using public key security
+ ///@return loaded document
+ ///@throws InvalidPasswordException If the password is incorrect.
+ ///@throws IOException In case of a reading or parsing error.
+ static PDDocument load14(
+ jni.JArray<jni.jbyte> input,
+ jni.JString password,
+ jni.JObject keyStore,
+ jni.JString alias,
+ ) {
+ return const $PDDocumentType().fromRef(_load14(input.reference,
+ password.reference, keyStore.reference, alias.reference)
+ .object);
+ }
+
+ static final _load15 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__load15")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public org.apache.pdfbox.pdmodel.PDDocument load(byte[] input, java.lang.String password, java.io.InputStream keyStore, java.lang.String alias, org.apache.pdfbox.io.MemoryUsageSetting memUsageSetting)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Parses a PDF.
+ ///@param input byte array that contains the document.
+ ///@param password password to be used for decryption
+ ///@param keyStore key store to be used for decryption when using public key security
+ ///@param alias alias to be used for decryption when using public key security
+ ///@param memUsageSetting defines how memory is used for buffering input stream and PDF streams
+ ///@return loaded document
+ ///@throws InvalidPasswordException If the password is incorrect.
+ ///@throws IOException In case of a reading or parsing error.
+ static PDDocument load15(
+ jni.JArray<jni.jbyte> input,
+ jni.JString password,
+ jni.JObject keyStore,
+ jni.JString alias,
+ jni.JObject memUsageSetting,
+ ) {
+ return const $PDDocumentType().fromRef(_load15(
+ input.reference,
+ password.reference,
+ keyStore.reference,
+ alias.reference,
+ memUsageSetting.reference)
+ .object);
+ }
+
+ static final _save = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__save")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void save(java.lang.String fileName)
+ ///
+ /// Save the document to a file.
+ ///
+ /// If encryption has been activated (with
+ /// \#protect(org.apache.pdfbox.pdmodel.encryption.ProtectionPolicy) protect(ProtectionPolicy)),
+ /// do not use the document after saving because the contents are now encrypted.
+ ///@param fileName The file to save as.
+ ///@throws IOException if the output could not be written
+ void save(
+ jni.JString fileName,
+ ) {
+ return _save(reference, fileName.reference).check();
+ }
+
+ static final _save1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__save1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void save(java.io.File file)
+ ///
+ /// Save the document to a file.
+ ///
+ /// If encryption has been activated (with
+ /// \#protect(org.apache.pdfbox.pdmodel.encryption.ProtectionPolicy) protect(ProtectionPolicy)),
+ /// do not use the document after saving because the contents are now encrypted.
+ ///@param file The file to save as.
+ ///@throws IOException if the output could not be written
+ void save1(
+ jni.JObject file,
+ ) {
+ return _save1(reference, file.reference).check();
+ }
+
+ static final _save2 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__save2")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void save(java.io.OutputStream output)
+ ///
+ /// This will save the document to an output stream.
+ ///
+ /// If encryption has been activated (with
+ /// \#protect(org.apache.pdfbox.pdmodel.encryption.ProtectionPolicy) protect(ProtectionPolicy)),
+ /// do not use the document after saving because the contents are now encrypted.
+ ///@param output The stream to write to. It will be closed when done. It is recommended to wrap
+ /// it in a java.io.BufferedOutputStream, unless it is already buffered.
+ ///@throws IOException if the output could not be written
+ void save2(
+ jni.JObject output,
+ ) {
+ return _save2(reference, output.reference).check();
+ }
+
+ static final _saveIncremental = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__saveIncremental")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void saveIncremental(java.io.OutputStream output)
+ ///
+ /// Save the PDF as an incremental update. This is only possible if the PDF was loaded from a
+ /// file or a stream, not if the document was created in PDFBox itself. There must be a path of
+ /// objects that have COSUpdateInfo\#isNeedToBeUpdated() set, starting from the document
+ /// catalog. For signatures this is taken care by PDFBox itself.
+ ///
+ /// Other usages of this method are for experienced users only. You will usually never need it.
+ /// It is useful only if you are required to keep the current revision and append the changes. A
+ /// typical use case is changing a signed file without invalidating the signature.
+ ///@param output stream to write to. It will be closed when done. It
+ /// <i>__must never__</i> point to the source file or that one will be
+ /// harmed!
+ ///@throws IOException if the output could not be written
+ ///@throws IllegalStateException if the document was not loaded from a file or a stream.
+ void saveIncremental(
+ jni.JObject output,
+ ) {
+ return _saveIncremental(reference, output.reference).check();
+ }
+
+ static final _saveIncremental1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__saveIncremental1")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void saveIncremental(java.io.OutputStream output, java.util.Set<org.apache.pdfbox.cos.COSDictionary> objectsToWrite)
+ ///
+ /// Save the PDF as an incremental update. This is only possible if the PDF was loaded from a
+ /// file or a stream, not if the document was created in PDFBox itself. This allows to include
+ /// objects even if there is no path of objects that have
+ /// COSUpdateInfo\#isNeedToBeUpdated() set so the incremental update gets smaller. Only
+ /// dictionaries are supported; if you need to update other objects classes, then add their
+ /// parent dictionary.
+ ///
+ /// This method is for experienced users only. You will usually never need it. It is useful only
+ /// if you are required to keep the current revision and append the changes. A typical use case
+ /// is changing a signed file without invalidating the signature. To know which objects are
+ /// getting changed, you need to have some understanding of the PDF specification, and look at
+ /// the saved file with an editor to verify that you are updating the correct objects. You should
+ /// also inspect the page and document structures of the file with PDFDebugger.
+ ///@param output stream to write to. It will be closed when done. It
+ /// <i>__must never__</i> point to the source file or that one will be harmed!
+ ///@param objectsToWrite objects that __must__ be part of the incremental saving.
+ ///@throws IOException if the output could not be written
+ ///@throws IllegalStateException if the document was not loaded from a file or a stream.
+ void saveIncremental1(
+ jni.JObject output,
+ jni.JSet<jni.JObject> objectsToWrite,
+ ) {
+ return _saveIncremental1(
+ reference, output.reference, objectsToWrite.reference)
+ .check();
+ }
+
+ static final _saveIncrementalForExternalSigning = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__saveIncrementalForExternalSigning")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public org.apache.pdfbox.pdmodel.interactive.digitalsignature.ExternalSigningSupport saveIncrementalForExternalSigning(java.io.OutputStream output)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ ///
+ /// __(This is a new feature for 2.0.3. The API for external signing might change based on feedback after release!)__
+ ///
+ /// Save PDF incrementally without closing for external signature creation scenario. The general
+ /// sequence is:
+ /// <pre>
+ /// PDDocument pdDocument = ...;
+ /// OutputStream outputStream = ...;
+ /// SignatureOptions signatureOptions = ...; // options to specify fine tuned signature options or null for defaults
+ /// PDSignature pdSignature = ...;
+ ///
+ /// // add signature parameters to be used when creating signature dictionary
+ /// pdDocument.addSignature(pdSignature, signatureOptions);
+ /// // prepare PDF for signing and obtain helper class to be used
+ /// ExternalSigningSupport externalSigningSupport = pdDocument.saveIncrementalForExternalSigning(outputStream);
+ /// // get data to be signed
+ /// InputStream dataToBeSigned = externalSigningSupport.getContent();
+ /// // invoke signature service
+ /// byte[] signature = sign(dataToBeSigned);
+ /// // set resulted CMS signature
+ /// externalSigningSupport.setSignature(signature);
+ ///
+ /// // last step is to close the document
+ /// pdDocument.close();
+ /// </pre>
+ ///
+ /// Note that after calling this method, only {@code close()} method may invoked for
+ /// {@code PDDocument} instance and only AFTER ExternalSigningSupport instance is used.
+ ///
+ ///
+ ///@param output stream to write the final PDF. It will be closed when the
+ /// document is closed. It <i>__must never__</i> point to the source file
+ /// or that one will be harmed!
+ ///@return instance to be used for external signing and setting CMS signature
+ ///@throws IOException if the output could not be written
+ ///@throws IllegalStateException if the document was not loaded from a file or a stream or
+ /// signature options were not set.
+ jni.JObject saveIncrementalForExternalSigning(
+ jni.JObject output,
+ ) {
+ return const jni.JObjectType().fromRef(
+ _saveIncrementalForExternalSigning(reference, output.reference).object);
+ }
+
+ static final _getPage = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Int32)>>("PDDocument__getPage")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public org.apache.pdfbox.pdmodel.PDPage getPage(int pageIndex)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Returns the page at the given 0-based index.
+ ///
+ /// This method is too slow to get all the pages from a large PDF document
+ /// (1000 pages or more). For such documents, use the iterator of
+ /// PDDocument\#getPages() instead.
+ ///@param pageIndex the 0-based page index
+ ///@return the page at the given index.
+ jni.JObject getPage(
+ int pageIndex,
+ ) {
+ return const jni.JObjectType()
+ .fromRef(_getPage(reference, pageIndex).object);
+ }
+
+ static final _getPages = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__getPages")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public org.apache.pdfbox.pdmodel.PDPageTree getPages()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Returns the page tree.
+ ///@return the page tree
+ jni.JObject getPages() {
+ return const jni.JObjectType().fromRef(_getPages(reference).object);
+ }
+
+ static final _getNumberOfPages = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__getNumberOfPages")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int getNumberOfPages()
+ ///
+ /// This will return the total page count of the PDF document.
+ ///@return The total number of pages in the PDF document.
+ int getNumberOfPages() {
+ return _getNumberOfPages(reference).integer;
+ }
+
+ static final _close = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__close")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void close()
+ ///
+ /// This will close the underlying COSDocument object.
+ ///@throws IOException If there is an error releasing resources.
+ void close() {
+ return _close(reference).check();
+ }
+
+ static final _protect = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__protect")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void protect(org.apache.pdfbox.pdmodel.encryption.ProtectionPolicy policy)
+ ///
+ /// Protects the document with a protection policy. The document content will be really
+ /// encrypted when it will be saved. This method only marks the document for encryption. It also
+ /// calls \#setAllSecurityToBeRemoved(boolean) with a false argument if it was set to true
+ /// previously and logs a warning.
+ ///
+ /// Do not use the document after saving, because the structures are encrypted.
+ ///@see org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy
+ ///@see org.apache.pdfbox.pdmodel.encryption.PublicKeyProtectionPolicy
+ ///@param policy The protection policy.
+ ///@throws IOException if there isn't any suitable security handler.
+ void protect(
+ jni.JObject policy,
+ ) {
+ return _protect(reference, policy.reference).check();
+ }
+
+ static final _getCurrentAccessPermission = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__getCurrentAccessPermission")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public org.apache.pdfbox.pdmodel.encryption.AccessPermission getCurrentAccessPermission()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Returns the access permissions granted when the document was decrypted. If the document was not decrypted this
+ /// method returns the access permission for a document owner (ie can do everything). The returned object is in read
+ /// only mode so that permissions cannot be changed. Methods providing access to content should rely on this object
+ /// to verify if the current user is allowed to proceed.
+ ///@return the access permissions for the current user on the document.
+ jni.JObject getCurrentAccessPermission() {
+ return const jni.JObjectType()
+ .fromRef(_getCurrentAccessPermission(reference).object);
+ }
+
+ static final _isAllSecurityToBeRemoved = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__isAllSecurityToBeRemoved")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean isAllSecurityToBeRemoved()
+ ///
+ /// Indicates if all security is removed or not when writing the pdf.
+ ///@return returns true if all security shall be removed otherwise false
+ bool isAllSecurityToBeRemoved() {
+ return _isAllSecurityToBeRemoved(reference).boolean;
+ }
+
+ static final _setAllSecurityToBeRemoved = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Uint8)>>("PDDocument__setAllSecurityToBeRemoved")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public void setAllSecurityToBeRemoved(boolean removeAllSecurity)
+ ///
+ /// Activates/Deactivates the removal of all security when writing the pdf.
+ ///@param removeAllSecurity remove all security if set to true
+ void setAllSecurityToBeRemoved(
+ bool removeAllSecurity,
+ ) {
+ return _setAllSecurityToBeRemoved(reference, removeAllSecurity ? 1 : 0)
+ .check();
+ }
+
+ static final _getDocumentId = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__getDocumentId")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.Long getDocumentId()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Provides the document ID.
+ ///@return the document ID
+ jni.JLong getDocumentId() {
+ return const jni.JLongType().fromRef(_getDocumentId(reference).object);
+ }
+
+ static final _setDocumentId = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__setDocumentId")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setDocumentId(java.lang.Long docId)
+ ///
+ /// Sets the document ID to the given value.
+ ///@param docId the new document ID
+ void setDocumentId(
+ jni.JLong docId,
+ ) {
+ return _setDocumentId(reference, docId.reference).check();
+ }
+
+ static final _getVersion = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__getVersion")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public float getVersion()
+ ///
+ /// Returns the PDF specification version this document conforms to.
+ ///@return the PDF version (e.g. 1.4f)
+ double getVersion() {
+ return _getVersion(reference).float;
+ }
+
+ static final _setVersion = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Float)>>("PDDocument__setVersion")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, double)>();
+
+ /// from: public void setVersion(float newVersion)
+ ///
+ /// Sets the PDF specification version for this document.
+ ///@param newVersion the new PDF version (e.g. 1.4f)
+ void setVersion(
+ double newVersion,
+ ) {
+ return _setVersion(reference, newVersion).check();
+ }
+
+ static final _getResourceCache = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocument__getResourceCache")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public org.apache.pdfbox.pdmodel.ResourceCache getResourceCache()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Returns the resource cache associated with this document, or null if there is none.
+ ///@return the resource cache or null.
+ jni.JObject getResourceCache() {
+ return const jni.JObjectType().fromRef(_getResourceCache(reference).object);
+ }
+
+ static final _setResourceCache = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocument__setResourceCache")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setResourceCache(org.apache.pdfbox.pdmodel.ResourceCache resourceCache)
+ ///
+ /// Sets the resource cache associated with this document.
+ ///@param resourceCache A resource cache, or null.
+ void setResourceCache(
+ jni.JObject resourceCache,
+ ) {
+ return _setResourceCache(reference, resourceCache.reference).check();
+ }
+}
+
+final class $PDDocumentType extends jni.JObjType<PDDocument> {
+ const $PDDocumentType();
+
+ @override
+ String get signature => r"Lorg/apache/pdfbox/pdmodel/PDDocument;";
+
+ @override
+ PDDocument fromRef(jni.JObjectPtr ref) => PDDocument.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($PDDocumentType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($PDDocumentType) && other is $PDDocumentType;
+ }
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocumentInformation.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocumentInformation.dart
new file mode 100644
index 0000000..b05c031
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocumentInformation.dart
@@ -0,0 +1,525 @@
+// Generated from Apache PDFBox library which is licensed under the Apache License 2.0.
+// The following copyright from the original authors applies.
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+// ignore_for_file: annotate_overrides
+// ignore_for_file: camel_case_extensions
+// ignore_for_file: camel_case_types
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: doc_directive_unknown
+// ignore_for_file: file_names
+// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: overridden_fields
+// ignore_for_file: unnecessary_cast
+// ignore_for_file: unused_element
+// ignore_for_file: unused_field
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: unused_shown_name
+
+import "dart:isolate" show ReceivePort;
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+import "package:jni/jni.dart" as jni;
+
+import "../../../../_init.dart";
+
+/// from: org.apache.pdfbox.pdmodel.PDDocumentInformation
+///
+/// This is the document metadata. Each getXXX method will return the entry if
+/// it exists or null if it does not exist. If you pass in null for the setXXX
+/// method then it will clear the value.
+///@author Ben Litchfield
+///@author Gerardo Ortiz
+class PDDocumentInformation extends jni.JObject {
+ @override
+ late final jni.JObjType<PDDocumentInformation> $type = type;
+
+ PDDocumentInformation.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $PDDocumentInformationType();
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "PDDocumentInformation__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Default Constructor.
+ factory PDDocumentInformation() {
+ return PDDocumentInformation.fromRef(_new0().object);
+ }
+
+ static final _new1 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocumentInformation__new1")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(org.apache.pdfbox.cos.COSDictionary dic)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Constructor that is used for a preexisting dictionary.
+ ///@param dic The underlying dictionary.
+ factory PDDocumentInformation.new1(
+ jni.JObject dic,
+ ) {
+ return PDDocumentInformation.fromRef(_new1(dic.reference).object);
+ }
+
+ static final _getCOSObject = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocumentInformation__getCOSObject")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public org.apache.pdfbox.cos.COSDictionary getCOSObject()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the underlying dictionary that this object wraps.
+ ///@return The underlying info dictionary.
+ jni.JObject getCOSObject() {
+ return const jni.JObjectType().fromRef(_getCOSObject(reference).object);
+ }
+
+ static final _getPropertyStringValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "PDDocumentInformation__getPropertyStringValue")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.Object getPropertyStringValue(java.lang.String propertyKey)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Return the properties String value.
+ ///
+ /// Allows to retrieve the
+ /// low level date for validation purposes.
+ ///
+ ///
+ ///@param propertyKey the dictionaries key
+ ///@return the properties value
+ jni.JObject getPropertyStringValue(
+ jni.JString propertyKey,
+ ) {
+ return const jni.JObjectType().fromRef(
+ _getPropertyStringValue(reference, propertyKey.reference).object);
+ }
+
+ static final _getTitle = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocumentInformation__getTitle")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getTitle()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the title of the document. This will return null if no title exists.
+ ///@return The title of the document.
+ jni.JString getTitle() {
+ return const jni.JStringType().fromRef(_getTitle(reference).object);
+ }
+
+ static final _setTitle = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocumentInformation__setTitle")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setTitle(java.lang.String title)
+ ///
+ /// This will set the title of the document.
+ ///@param title The new title for the document.
+ void setTitle(
+ jni.JString title,
+ ) {
+ return _setTitle(reference, title.reference).check();
+ }
+
+ static final _getAuthor = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocumentInformation__getAuthor")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getAuthor()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the author of the document. This will return null if no author exists.
+ ///@return The author of the document.
+ jni.JString getAuthor() {
+ return const jni.JStringType().fromRef(_getAuthor(reference).object);
+ }
+
+ static final _setAuthor = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocumentInformation__setAuthor")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setAuthor(java.lang.String author)
+ ///
+ /// This will set the author of the document.
+ ///@param author The new author for the document.
+ void setAuthor(
+ jni.JString author,
+ ) {
+ return _setAuthor(reference, author.reference).check();
+ }
+
+ static final _getSubject = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocumentInformation__getSubject")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getSubject()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the subject of the document. This will return null if no subject exists.
+ ///@return The subject of the document.
+ jni.JString getSubject() {
+ return const jni.JStringType().fromRef(_getSubject(reference).object);
+ }
+
+ static final _setSubject = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocumentInformation__setSubject")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setSubject(java.lang.String subject)
+ ///
+ /// This will set the subject of the document.
+ ///@param subject The new subject for the document.
+ void setSubject(
+ jni.JString subject,
+ ) {
+ return _setSubject(reference, subject.reference).check();
+ }
+
+ static final _getKeywords = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocumentInformation__getKeywords")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getKeywords()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the keywords of the document. This will return null if no keywords exists.
+ ///@return The keywords of the document.
+ jni.JString getKeywords() {
+ return const jni.JStringType().fromRef(_getKeywords(reference).object);
+ }
+
+ static final _setKeywords = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocumentInformation__setKeywords")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setKeywords(java.lang.String keywords)
+ ///
+ /// This will set the keywords of the document.
+ ///@param keywords The new keywords for the document.
+ void setKeywords(
+ jni.JString keywords,
+ ) {
+ return _setKeywords(reference, keywords.reference).check();
+ }
+
+ static final _getCreator = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocumentInformation__getCreator")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getCreator()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the creator of the document. This will return null if no creator exists.
+ ///@return The creator of the document.
+ jni.JString getCreator() {
+ return const jni.JStringType().fromRef(_getCreator(reference).object);
+ }
+
+ static final _setCreator = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocumentInformation__setCreator")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setCreator(java.lang.String creator)
+ ///
+ /// This will set the creator of the document.
+ ///@param creator The new creator for the document.
+ void setCreator(
+ jni.JString creator,
+ ) {
+ return _setCreator(reference, creator.reference).check();
+ }
+
+ static final _getProducer = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocumentInformation__getProducer")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getProducer()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the producer of the document. This will return null if no producer exists.
+ ///@return The producer of the document.
+ jni.JString getProducer() {
+ return const jni.JStringType().fromRef(_getProducer(reference).object);
+ }
+
+ static final _setProducer = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocumentInformation__setProducer")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setProducer(java.lang.String producer)
+ ///
+ /// This will set the producer of the document.
+ ///@param producer The new producer for the document.
+ void setProducer(
+ jni.JString producer,
+ ) {
+ return _setProducer(reference, producer.reference).check();
+ }
+
+ static final _getCreationDate = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocumentInformation__getCreationDate")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.util.Calendar getCreationDate()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the creation date of the document. This will return null if no creation date exists.
+ ///@return The creation date of the document.
+ jni.JObject getCreationDate() {
+ return const jni.JObjectType().fromRef(_getCreationDate(reference).object);
+ }
+
+ static final _setCreationDate = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "PDDocumentInformation__setCreationDate")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setCreationDate(java.util.Calendar date)
+ ///
+ /// This will set the creation date of the document.
+ ///@param date The new creation date for the document.
+ void setCreationDate(
+ jni.JObject date,
+ ) {
+ return _setCreationDate(reference, date.reference).check();
+ }
+
+ static final _getModificationDate = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocumentInformation__getModificationDate")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.util.Calendar getModificationDate()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the modification date of the document. This will return null if no modification date exists.
+ ///@return The modification date of the document.
+ jni.JObject getModificationDate() {
+ return const jni.JObjectType()
+ .fromRef(_getModificationDate(reference).object);
+ }
+
+ static final _setModificationDate = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "PDDocumentInformation__setModificationDate")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setModificationDate(java.util.Calendar date)
+ ///
+ /// This will set the modification date of the document.
+ ///@param date The new modification date for the document.
+ void setModificationDate(
+ jni.JObject date,
+ ) {
+ return _setModificationDate(reference, date.reference).check();
+ }
+
+ static final _getTrapped = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocumentInformation__getTrapped")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getTrapped()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the trapped value for the document.
+ /// This will return null if one is not found.
+ ///@return The trapped value for the document.
+ jni.JString getTrapped() {
+ return const jni.JStringType().fromRef(_getTrapped(reference).object);
+ }
+
+ static final _getMetadataKeys = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDDocumentInformation__getMetadataKeys")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.util.Set<java.lang.String> getMetadataKeys()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the keys of all metadata information fields for the document.
+ ///@return all metadata key strings.
+ ///@since Apache PDFBox 1.3.0
+ jni.JSet<jni.JString> getMetadataKeys() {
+ return const jni.JSetType(jni.JStringType())
+ .fromRef(_getMetadataKeys(reference).object);
+ }
+
+ static final _getCustomMetadataValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "PDDocumentInformation__getCustomMetadataValue")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getCustomMetadataValue(java.lang.String fieldName)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the value of a custom metadata information field for the document.
+ /// This will return null if one is not found.
+ ///@param fieldName Name of custom metadata field from pdf document.
+ ///@return String Value of metadata field
+ jni.JString getCustomMetadataValue(
+ jni.JString fieldName,
+ ) {
+ return const jni.JStringType().fromRef(
+ _getCustomMetadataValue(reference, fieldName.reference).object);
+ }
+
+ static final _setCustomMetadataValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "PDDocumentInformation__setCustomMetadataValue")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setCustomMetadataValue(java.lang.String fieldName, java.lang.String fieldValue)
+ ///
+ /// Set the custom metadata value.
+ ///@param fieldName The name of the custom metadata field.
+ ///@param fieldValue The value to the custom metadata field.
+ void setCustomMetadataValue(
+ jni.JString fieldName,
+ jni.JString fieldValue,
+ ) {
+ return _setCustomMetadataValue(
+ reference, fieldName.reference, fieldValue.reference)
+ .check();
+ }
+
+ static final _setTrapped = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDDocumentInformation__setTrapped")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setTrapped(java.lang.String value)
+ ///
+ /// This will set the trapped of the document. This will be
+ /// 'True', 'False', or 'Unknown'.
+ ///@param value The new trapped value for the document.
+ ///@throws IllegalArgumentException if the parameter is invalid.
+ void setTrapped(
+ jni.JString value,
+ ) {
+ return _setTrapped(reference, value.reference).check();
+ }
+}
+
+final class $PDDocumentInformationType
+ extends jni.JObjType<PDDocumentInformation> {
+ const $PDDocumentInformationType();
+
+ @override
+ String get signature => r"Lorg/apache/pdfbox/pdmodel/PDDocumentInformation;";
+
+ @override
+ PDDocumentInformation fromRef(jni.JObjectPtr ref) =>
+ PDDocumentInformation.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($PDDocumentInformationType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($PDDocumentInformationType) &&
+ other is $PDDocumentInformationType;
+ }
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/_package.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/_package.dart
new file mode 100644
index 0000000..d2b3929
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/_package.dart
@@ -0,0 +1,2 @@
+export "PDDocument.dart";
+export "PDDocumentInformation.dart";
diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/PDFTextStripper.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/PDFTextStripper.dart
new file mode 100644
index 0000000..fcdfda2
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/PDFTextStripper.dart
@@ -0,0 +1,1425 @@
+// Generated from Apache PDFBox library which is licensed under the Apache License 2.0.
+// The following copyright from the original authors applies.
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+// ignore_for_file: annotate_overrides
+// ignore_for_file: camel_case_extensions
+// ignore_for_file: camel_case_types
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: doc_directive_unknown
+// ignore_for_file: file_names
+// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: overridden_fields
+// ignore_for_file: unnecessary_cast
+// ignore_for_file: unused_element
+// ignore_for_file: unused_field
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: unused_shown_name
+
+import "dart:isolate" show ReceivePort;
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+import "package:jni/jni.dart" as jni;
+
+import "../pdmodel/PDDocument.dart" as pddocument_;
+import "../../../../_init.dart";
+
+/// from: org.apache.pdfbox.text.PDFTextStripper
+///
+/// This class will take a pdf document and strip out all of the text and ignore the formatting and such. Please note; it
+/// is up to clients of this class to verify that a specific user has the correct permissions to extract text from the
+/// PDF document.
+///
+/// The basic flow of this process is that we get a document and use a series of processXXX() functions that work on
+/// smaller and smaller chunks of the page. Eventually, we fully process each page and then print it.
+///@author Ben Litchfield
+class PDFTextStripper extends jni.JObject {
+ @override
+ late final jni.JObjType<PDFTextStripper> $type = type;
+
+ PDFTextStripper.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $PDFTextStripperType();
+ static final _get_LINE_SEPARATOR = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_PDFTextStripper__LINE_SEPARATOR")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ /// from: protected final java.lang.String LINE_SEPARATOR
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// The platform's line separator.
+ jni.JString get LINE_SEPARATOR =>
+ const jni.JStringType().fromRef(_get_LINE_SEPARATOR(reference).object);
+
+ static final _get_charactersByArticle = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_PDFTextStripper__charactersByArticle")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_charactersByArticle = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>(
+ "set_PDFTextStripper__charactersByArticle")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected java.util.ArrayList<java.util.List<org.apache.pdfbox.text.TextPosition>> charactersByArticle
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// The charactersByArticle is used to extract text by article divisions. For example a PDF that has two columns like
+ /// a newspaper, we want to extract the first column and then the second column. In this example the PDF would have 2
+ /// beads(or articles), one for each column. The size of the charactersByArticle would be 5, because not all text on
+ /// the screen will fall into one of the articles. The five divisions are shown below
+ ///
+ /// Text before first article
+ /// first article text
+ /// text between first article and second article
+ /// second article text
+ /// text after second article
+ ///
+ /// Most PDFs won't have any beads, so charactersByArticle will contain a single entry.
+ jni.JObject get charactersByArticle => const jni.JObjectType()
+ .fromRef(_get_charactersByArticle(reference).object);
+
+ /// from: protected java.util.ArrayList<java.util.List<org.apache.pdfbox.text.TextPosition>> charactersByArticle
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// The charactersByArticle is used to extract text by article divisions. For example a PDF that has two columns like
+ /// a newspaper, we want to extract the first column and then the second column. In this example the PDF would have 2
+ /// beads(or articles), one for each column. The size of the charactersByArticle would be 5, because not all text on
+ /// the screen will fall into one of the articles. The five divisions are shown below
+ ///
+ /// Text before first article
+ /// first article text
+ /// text between first article and second article
+ /// second article text
+ /// text after second article
+ ///
+ /// Most PDFs won't have any beads, so charactersByArticle will contain a single entry.
+ set charactersByArticle(jni.JObject value) =>
+ _set_charactersByArticle(reference, value.reference).check();
+
+ static final _get_document = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_PDFTextStripper__document")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_document = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(jni.JObjectPtr,
+ ffi.Pointer<ffi.Void>)>>("set_PDFTextStripper__document")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected org.apache.pdfbox.pdmodel.PDDocument document
+ /// The returned object must be released after use, by calling the [release] method.
+ pddocument_.PDDocument get document => const pddocument_.$PDDocumentType()
+ .fromRef(_get_document(reference).object);
+
+ /// from: protected org.apache.pdfbox.pdmodel.PDDocument document
+ /// The returned object must be released after use, by calling the [release] method.
+ set document(pddocument_.PDDocument value) =>
+ _set_document(reference, value.reference).check();
+
+ static final _get_output = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_PDFTextStripper__output")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_output = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(jni.JObjectPtr,
+ ffi.Pointer<ffi.Void>)>>("set_PDFTextStripper__output")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected java.io.Writer output
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject get output =>
+ const jni.JObjectType().fromRef(_get_output(reference).object);
+
+ /// from: protected java.io.Writer output
+ /// The returned object must be released after use, by calling the [release] method.
+ set output(jni.JObject value) =>
+ _set_output(reference, value.reference).check();
+
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "PDFTextStripper__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Instantiate a new PDFTextStripper object.
+ ///@throws IOException If there is an error loading the properties.
+ factory PDFTextStripper() {
+ return PDFTextStripper.fromRef(_new0().object);
+ }
+
+ static final _getText = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__getText")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getText(org.apache.pdfbox.pdmodel.PDDocument doc)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will return the text of a document. See writeText. <br>
+ /// NOTE: The document must not be encrypted when coming into this method.
+ ///
+ /// IMPORTANT: By default, text extraction is done in the same sequence as the text in the PDF page content stream.
+ /// PDF is a graphic format, not a text format, and unlike HTML, it has no requirements that text one on page
+ /// be rendered in a certain order. The order is the one that was determined by the software that created the
+ /// PDF. To get text sorted from left to right and top to botton, use \#setSortByPosition(boolean).
+ ///@param doc The document to get the text from.
+ ///@return The text of the PDF document.
+ ///@throws IOException if the doc state is invalid or it is encrypted.
+ jni.JString getText(
+ pddocument_.PDDocument doc,
+ ) {
+ return const jni.JStringType()
+ .fromRef(_getText(reference, doc.reference).object);
+ }
+
+ static final _writeText = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__writeText")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void writeText(org.apache.pdfbox.pdmodel.PDDocument doc, java.io.Writer outputStream)
+ ///
+ /// This will take a PDDocument and write the text of that document to the print writer.
+ ///@param doc The document to get the data from.
+ ///@param outputStream The location to put the text.
+ ///@throws IOException If the doc is in an invalid state.
+ void writeText(
+ pddocument_.PDDocument doc,
+ jni.JObject outputStream,
+ ) {
+ return _writeText(reference, doc.reference, outputStream.reference).check();
+ }
+
+ static final _processPages = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__processPages")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void processPages(org.apache.pdfbox.pdmodel.PDPageTree pages)
+ ///
+ /// This will process all of the pages and the text that is in them.
+ ///@param pages The pages object in the document.
+ ///@throws IOException If there is an error parsing the text.
+ void processPages(
+ jni.JObject pages,
+ ) {
+ return _processPages(reference, pages.reference).check();
+ }
+
+ static final _startDocument = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__startDocument")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void startDocument(org.apache.pdfbox.pdmodel.PDDocument document)
+ ///
+ /// This method is available for subclasses of this class. It will be called before processing of the document start.
+ ///@param document The PDF document that is being processed.
+ ///@throws IOException If an IO error occurs.
+ void startDocument(
+ pddocument_.PDDocument document,
+ ) {
+ return _startDocument(reference, document.reference).check();
+ }
+
+ static final _endDocument = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__endDocument")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void endDocument(org.apache.pdfbox.pdmodel.PDDocument document)
+ ///
+ /// This method is available for subclasses of this class. It will be called after processing of the document
+ /// finishes.
+ ///@param document The PDF document that is being processed.
+ ///@throws IOException If an IO error occurs.
+ void endDocument(
+ pddocument_.PDDocument document,
+ ) {
+ return _endDocument(reference, document.reference).check();
+ }
+
+ static final _processPage = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__processPage")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void processPage(org.apache.pdfbox.pdmodel.PDPage page)
+ ///
+ /// This will process the contents of a page.
+ ///@param page The page to process.
+ ///@throws IOException If there is an error processing the page.
+ void processPage(
+ jni.JObject page,
+ ) {
+ return _processPage(reference, page.reference).check();
+ }
+
+ static final _startArticle = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__startArticle")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void startArticle()
+ ///
+ /// Start a new article, which is typically defined as a column on a single page (also referred to as a bead). This
+ /// assumes that the primary direction of text is left to right. Default implementation is to do nothing. Subclasses
+ /// may provide additional information.
+ ///@throws IOException If there is any error writing to the stream.
+ void startArticle() {
+ return _startArticle(reference).check();
+ }
+
+ static final _startArticle1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Uint8)>>("PDFTextStripper__startArticle1")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: protected void startArticle(boolean isLTR)
+ ///
+ /// Start a new article, which is typically defined as a column on a single page (also referred to as a bead).
+ /// Default implementation is to do nothing. Subclasses may provide additional information.
+ ///@param isLTR true if primary direction of text is left to right.
+ ///@throws IOException If there is any error writing to the stream.
+ void startArticle1(
+ bool isLTR,
+ ) {
+ return _startArticle1(reference, isLTR ? 1 : 0).check();
+ }
+
+ static final _endArticle = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__endArticle")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void endArticle()
+ ///
+ /// End an article. Default implementation is to do nothing. Subclasses may provide additional information.
+ ///@throws IOException If there is any error writing to the stream.
+ void endArticle() {
+ return _endArticle(reference).check();
+ }
+
+ static final _startPage = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__startPage")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void startPage(org.apache.pdfbox.pdmodel.PDPage page)
+ ///
+ /// Start a new page. Default implementation is to do nothing. Subclasses may provide additional information.
+ ///@param page The page we are about to process.
+ ///@throws IOException If there is any error writing to the stream.
+ void startPage(
+ jni.JObject page,
+ ) {
+ return _startPage(reference, page.reference).check();
+ }
+
+ static final _endPage = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__endPage")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void endPage(org.apache.pdfbox.pdmodel.PDPage page)
+ ///
+ /// End a page. Default implementation is to do nothing. Subclasses may provide additional information.
+ ///@param page The page we are about to process.
+ ///@throws IOException If there is any error writing to the stream.
+ void endPage(
+ jni.JObject page,
+ ) {
+ return _endPage(reference, page.reference).check();
+ }
+
+ static final _writePage = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__writePage")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void writePage()
+ ///
+ /// This will print the text of the processed page to "output". It will estimate, based on the coordinates of the
+ /// text, where newlines and word spacings should be placed. The text will be sorted only if that feature was
+ /// enabled.
+ ///@throws IOException If there is an error writing the text.
+ void writePage() {
+ return _writePage(reference).check();
+ }
+
+ static final _writeLineSeparator = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__writeLineSeparator")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void writeLineSeparator()
+ ///
+ /// Write the line separator value to the output stream.
+ ///@throws IOException If there is a problem writing out the line separator to the document.
+ void writeLineSeparator() {
+ return _writeLineSeparator(reference).check();
+ }
+
+ static final _writeWordSeparator = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__writeWordSeparator")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void writeWordSeparator()
+ ///
+ /// Write the word separator value to the output stream.
+ ///@throws IOException If there is a problem writing out the word separator to the document.
+ void writeWordSeparator() {
+ return _writeWordSeparator(reference).check();
+ }
+
+ static final _writeCharacters = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__writeCharacters")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void writeCharacters(org.apache.pdfbox.text.TextPosition text)
+ ///
+ /// Write the string in TextPosition to the output stream.
+ ///@param text The text to write to the stream.
+ ///@throws IOException If there is an error when writing the text.
+ void writeCharacters(
+ jni.JObject text,
+ ) {
+ return _writeCharacters(reference, text.reference).check();
+ }
+
+ static final _writeString = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__writeString")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void writeString(java.lang.String text, java.util.List<org.apache.pdfbox.text.TextPosition> textPositions)
+ ///
+ /// Write a Java string to the output stream. The default implementation will ignore the <code>textPositions</code>
+ /// and just calls \#writeString(String).
+ ///@param text The text to write to the stream.
+ ///@param textPositions The TextPositions belonging to the text.
+ ///@throws IOException If there is an error when writing the text.
+ void writeString(
+ jni.JString text,
+ jni.JList<jni.JObject> textPositions,
+ ) {
+ return _writeString(reference, text.reference, textPositions.reference)
+ .check();
+ }
+
+ static final _writeString1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__writeString1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void writeString(java.lang.String text)
+ ///
+ /// Write a Java string to the output stream.
+ ///@param text The text to write to the stream.
+ ///@throws IOException If there is an error when writing the text.
+ void writeString1(
+ jni.JString text,
+ ) {
+ return _writeString1(reference, text.reference).check();
+ }
+
+ static final _processTextPosition = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__processTextPosition")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void processTextPosition(org.apache.pdfbox.text.TextPosition text)
+ ///
+ /// This will process a TextPosition object and add the text to the list of characters on a page. It takes care of
+ /// overlapping text.
+ ///@param text The text to process.
+ void processTextPosition(
+ jni.JObject text,
+ ) {
+ return _processTextPosition(reference, text.reference).check();
+ }
+
+ static final _getStartPage = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getStartPage")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int getStartPage()
+ ///
+ /// This is the page that the text extraction will start on. The pages start at page 1. For example in a 5 page PDF
+ /// document, if the start page is 1 then all pages will be extracted. If the start page is 4 then pages 4 and 5 will
+ /// be extracted. The default value is 1.
+ ///@return Value of property startPage.
+ int getStartPage() {
+ return _getStartPage(reference).integer;
+ }
+
+ static final _setStartPage = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Int32)>>("PDFTextStripper__setStartPage")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public void setStartPage(int startPageValue)
+ ///
+ /// This will set the first page to be extracted by this class.
+ ///@param startPageValue New value of 1-based startPage property.
+ void setStartPage(
+ int startPageValue,
+ ) {
+ return _setStartPage(reference, startPageValue).check();
+ }
+
+ static final _getEndPage = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getEndPage")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int getEndPage()
+ ///
+ /// This will get the last page that will be extracted. This is inclusive, for example if a 5 page PDF an endPage
+ /// value of 5 would extract the entire document, an end page of 2 would extract pages 1 and 2. This defaults to
+ /// Integer.MAX_VALUE such that all pages of the pdf will be extracted.
+ ///@return Value of property endPage.
+ int getEndPage() {
+ return _getEndPage(reference).integer;
+ }
+
+ static final _setEndPage = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Int32)>>("PDFTextStripper__setEndPage")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public void setEndPage(int endPageValue)
+ ///
+ /// This will set the last page to be extracted by this class.
+ ///@param endPageValue New value of 1-based endPage property.
+ void setEndPage(
+ int endPageValue,
+ ) {
+ return _setEndPage(reference, endPageValue).check();
+ }
+
+ static final _setLineSeparator = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__setLineSeparator")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setLineSeparator(java.lang.String separator)
+ ///
+ /// Set the desired line separator for output text. The line.separator system property is used if the line separator
+ /// preference is not set explicitly using this method.
+ ///@param separator The desired line separator string.
+ void setLineSeparator(
+ jni.JString separator,
+ ) {
+ return _setLineSeparator(reference, separator.reference).check();
+ }
+
+ static final _getLineSeparator = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getLineSeparator")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getLineSeparator()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the line separator.
+ ///@return The desired line separator string.
+ jni.JString getLineSeparator() {
+ return const jni.JStringType().fromRef(_getLineSeparator(reference).object);
+ }
+
+ static final _getWordSeparator = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getWordSeparator")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getWordSeparator()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// This will get the word separator.
+ ///@return The desired word separator string.
+ jni.JString getWordSeparator() {
+ return const jni.JStringType().fromRef(_getWordSeparator(reference).object);
+ }
+
+ static final _setWordSeparator = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__setWordSeparator")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setWordSeparator(java.lang.String separator)
+ ///
+ /// Set the desired word separator for output text. The PDFBox text extraction algorithm will output a space
+ /// character if there is enough space between two words. By default a space character is used. If you need and
+ /// accurate count of characters that are found in a PDF document then you might want to set the word separator to
+ /// the empty string.
+ ///@param separator The desired page separator string.
+ void setWordSeparator(
+ jni.JString separator,
+ ) {
+ return _setWordSeparator(reference, separator.reference).check();
+ }
+
+ static final _getSuppressDuplicateOverlappingText = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getSuppressDuplicateOverlappingText")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean getSuppressDuplicateOverlappingText()
+ ///
+ /// @return Returns the suppressDuplicateOverlappingText.
+ bool getSuppressDuplicateOverlappingText() {
+ return _getSuppressDuplicateOverlappingText(reference).boolean;
+ }
+
+ static final _getCurrentPageNo = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getCurrentPageNo")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected int getCurrentPageNo()
+ ///
+ /// Get the current page number that is being processed.
+ ///@return A 1 based number representing the current page.
+ int getCurrentPageNo() {
+ return _getCurrentPageNo(reference).integer;
+ }
+
+ static final _getOutput = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getOutput")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected java.io.Writer getOutput()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// The output stream that is being written to.
+ ///@return The stream that output is being written to.
+ jni.JObject getOutput() {
+ return const jni.JObjectType().fromRef(_getOutput(reference).object);
+ }
+
+ static final _getCharactersByArticle = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getCharactersByArticle")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected java.util.List<java.util.List<org.apache.pdfbox.text.TextPosition>> getCharactersByArticle()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Character strings are grouped by articles. It is quite common that there will only be a single article. This
+ /// returns a List that contains List objects, the inner lists will contain TextPosition objects.
+ ///@return A double List of TextPositions for all text strings on the page.
+ jni.JList<jni.JList<jni.JObject>> getCharactersByArticle() {
+ return const jni.JListType(jni.JListType(jni.JObjectType()))
+ .fromRef(_getCharactersByArticle(reference).object);
+ }
+
+ static final _setSuppressDuplicateOverlappingText = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Uint8)>>(
+ "PDFTextStripper__setSuppressDuplicateOverlappingText")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public void setSuppressDuplicateOverlappingText(boolean suppressDuplicateOverlappingTextValue)
+ ///
+ /// By default the text stripper will attempt to remove text that overlapps each other. Word paints the same
+ /// character several times in order to make it look bold. By setting this to false all text will be extracted, which
+ /// means that certain sections will be duplicated, but better performance will be noticed.
+ ///@param suppressDuplicateOverlappingTextValue The suppressDuplicateOverlappingText to set.
+ void setSuppressDuplicateOverlappingText(
+ bool suppressDuplicateOverlappingTextValue,
+ ) {
+ return _setSuppressDuplicateOverlappingText(
+ reference, suppressDuplicateOverlappingTextValue ? 1 : 0)
+ .check();
+ }
+
+ static final _getSeparateByBeads = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getSeparateByBeads")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean getSeparateByBeads()
+ ///
+ /// This will tell if the text stripper should separate by beads.
+ ///@return If the text will be grouped by beads.
+ bool getSeparateByBeads() {
+ return _getSeparateByBeads(reference).boolean;
+ }
+
+ static final _setShouldSeparateByBeads = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Uint8)>>("PDFTextStripper__setShouldSeparateByBeads")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public void setShouldSeparateByBeads(boolean aShouldSeparateByBeads)
+ ///
+ /// Set if the text stripper should group the text output by a list of beads. The default value is true!
+ ///@param aShouldSeparateByBeads The new grouping of beads.
+ void setShouldSeparateByBeads(
+ bool aShouldSeparateByBeads,
+ ) {
+ return _setShouldSeparateByBeads(reference, aShouldSeparateByBeads ? 1 : 0)
+ .check();
+ }
+
+ static final _getEndBookmark = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getEndBookmark")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem getEndBookmark()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Get the bookmark where text extraction should end, inclusive. Default is null.
+ ///@return The ending bookmark.
+ jni.JObject getEndBookmark() {
+ return const jni.JObjectType().fromRef(_getEndBookmark(reference).object);
+ }
+
+ static final _setEndBookmark = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__setEndBookmark")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setEndBookmark(org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem aEndBookmark)
+ ///
+ /// Set the bookmark where the text extraction should stop.
+ ///@param aEndBookmark The ending bookmark.
+ void setEndBookmark(
+ jni.JObject aEndBookmark,
+ ) {
+ return _setEndBookmark(reference, aEndBookmark.reference).check();
+ }
+
+ static final _getStartBookmark = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getStartBookmark")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem getStartBookmark()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Get the bookmark where text extraction should start, inclusive. Default is null.
+ ///@return The starting bookmark.
+ jni.JObject getStartBookmark() {
+ return const jni.JObjectType().fromRef(_getStartBookmark(reference).object);
+ }
+
+ static final _setStartBookmark = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__setStartBookmark")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setStartBookmark(org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem aStartBookmark)
+ ///
+ /// Set the bookmark where text extraction should start, inclusive.
+ ///@param aStartBookmark The starting bookmark.
+ void setStartBookmark(
+ jni.JObject aStartBookmark,
+ ) {
+ return _setStartBookmark(reference, aStartBookmark.reference).check();
+ }
+
+ static final _getAddMoreFormatting = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getAddMoreFormatting")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean getAddMoreFormatting()
+ ///
+ /// This will tell if the text stripper should add some more text formatting.
+ ///@return true if some more text formatting will be added
+ bool getAddMoreFormatting() {
+ return _getAddMoreFormatting(reference).boolean;
+ }
+
+ static final _setAddMoreFormatting = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Uint8)>>("PDFTextStripper__setAddMoreFormatting")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public void setAddMoreFormatting(boolean newAddMoreFormatting)
+ ///
+ /// There will some additional text formatting be added if addMoreFormatting is set to true. Default is false.
+ ///@param newAddMoreFormatting Tell PDFBox to add some more text formatting
+ void setAddMoreFormatting(
+ bool newAddMoreFormatting,
+ ) {
+ return _setAddMoreFormatting(reference, newAddMoreFormatting ? 1 : 0)
+ .check();
+ }
+
+ static final _getSortByPosition = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getSortByPosition")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean getSortByPosition()
+ ///
+ /// This will tell if the text stripper should sort the text tokens before writing to the stream.
+ ///@return true If the text tokens will be sorted before being written.
+ bool getSortByPosition() {
+ return _getSortByPosition(reference).boolean;
+ }
+
+ static final _setSortByPosition = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Uint8)>>("PDFTextStripper__setSortByPosition")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public void setSortByPosition(boolean newSortByPosition)
+ ///
+ /// The order of the text tokens in a PDF file may not be in the same as they appear visually on the screen. For
+ /// example, a PDF writer may write out all text by font, so all bold or larger text, then make a second pass and
+ /// write out the normal text.<br>
+ /// The default is to __not__ sort by position.<br>
+ /// <br>
+ /// A PDF writer could choose to write each character in a different order. By default PDFBox does __not__ sort
+ /// the text tokens before processing them due to performance reasons.
+ ///@param newSortByPosition Tell PDFBox to sort the text positions.
+ void setSortByPosition(
+ bool newSortByPosition,
+ ) {
+ return _setSortByPosition(reference, newSortByPosition ? 1 : 0).check();
+ }
+
+ static final _getSpacingTolerance = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getSpacingTolerance")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public float getSpacingTolerance()
+ ///
+ /// Get the current space width-based tolerance value that is being used to estimate where spaces in text should be
+ /// added. Note that the default value for this has been determined from trial and error.
+ ///@return The current tolerance / scaling factor
+ double getSpacingTolerance() {
+ return _getSpacingTolerance(reference).float;
+ }
+
+ static final _setSpacingTolerance = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Float)>>("PDFTextStripper__setSpacingTolerance")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, double)>();
+
+ /// from: public void setSpacingTolerance(float spacingToleranceValue)
+ ///
+ /// Set the space width-based tolerance value that is used to estimate where spaces in text should be added. Note
+ /// that the default value for this has been determined from trial and error. Setting this value larger will reduce
+ /// the number of spaces added.
+ ///@param spacingToleranceValue tolerance / scaling factor to use
+ void setSpacingTolerance(
+ double spacingToleranceValue,
+ ) {
+ return _setSpacingTolerance(reference, spacingToleranceValue).check();
+ }
+
+ static final _getAverageCharTolerance = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getAverageCharTolerance")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public float getAverageCharTolerance()
+ ///
+ /// Get the current character width-based tolerance value that is being used to estimate where spaces in text should
+ /// be added. Note that the default value for this has been determined from trial and error.
+ ///@return The current tolerance / scaling factor
+ double getAverageCharTolerance() {
+ return _getAverageCharTolerance(reference).float;
+ }
+
+ static final _setAverageCharTolerance = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Float)>>("PDFTextStripper__setAverageCharTolerance")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, double)>();
+
+ /// from: public void setAverageCharTolerance(float averageCharToleranceValue)
+ ///
+ /// Set the character width-based tolerance value that is used to estimate where spaces in text should be added. Note
+ /// that the default value for this has been determined from trial and error. Setting this value larger will reduce
+ /// the number of spaces added.
+ ///@param averageCharToleranceValue average tolerance / scaling factor to use
+ void setAverageCharTolerance(
+ double averageCharToleranceValue,
+ ) {
+ return _setAverageCharTolerance(reference, averageCharToleranceValue)
+ .check();
+ }
+
+ static final _getIndentThreshold = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getIndentThreshold")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public float getIndentThreshold()
+ ///
+ /// returns the multiple of whitespace character widths for the current text which the current line start can be
+ /// indented from the previous line start beyond which the current line start is considered to be a paragraph start.
+ ///@return the number of whitespace character widths to use when detecting paragraph indents.
+ double getIndentThreshold() {
+ return _getIndentThreshold(reference).float;
+ }
+
+ static final _setIndentThreshold = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Float)>>("PDFTextStripper__setIndentThreshold")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, double)>();
+
+ /// from: public void setIndentThreshold(float indentThresholdValue)
+ ///
+ /// sets the multiple of whitespace character widths for the current text which the current line start can be
+ /// indented from the previous line start beyond which the current line start is considered to be a paragraph start.
+ /// The default value is 2.0.
+ ///@param indentThresholdValue the number of whitespace character widths to use when detecting paragraph indents.
+ void setIndentThreshold(
+ double indentThresholdValue,
+ ) {
+ return _setIndentThreshold(reference, indentThresholdValue).check();
+ }
+
+ static final _getDropThreshold = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getDropThreshold")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public float getDropThreshold()
+ ///
+ /// the minimum whitespace, as a multiple of the max height of the current characters beyond which the current line
+ /// start is considered to be a paragraph start.
+ ///@return the character height multiple for max allowed whitespace between lines in the same paragraph.
+ double getDropThreshold() {
+ return _getDropThreshold(reference).float;
+ }
+
+ static final _setDropThreshold = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Float)>>("PDFTextStripper__setDropThreshold")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, double)>();
+
+ /// from: public void setDropThreshold(float dropThresholdValue)
+ ///
+ /// sets the minimum whitespace, as a multiple of the max height of the current characters beyond which the current
+ /// line start is considered to be a paragraph start. The default value is 2.5.
+ ///@param dropThresholdValue the character height multiple for max allowed whitespace between lines in the same
+ /// paragraph.
+ void setDropThreshold(
+ double dropThresholdValue,
+ ) {
+ return _setDropThreshold(reference, dropThresholdValue).check();
+ }
+
+ static final _getParagraphStart = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getParagraphStart")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getParagraphStart()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Returns the string which will be used at the beginning of a paragraph.
+ ///@return the paragraph start string
+ jni.JString getParagraphStart() {
+ return const jni.JStringType()
+ .fromRef(_getParagraphStart(reference).object);
+ }
+
+ static final _setParagraphStart = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__setParagraphStart")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setParagraphStart(java.lang.String s)
+ ///
+ /// Sets the string which will be used at the beginning of a paragraph.
+ ///@param s the paragraph start string
+ void setParagraphStart(
+ jni.JString s,
+ ) {
+ return _setParagraphStart(reference, s.reference).check();
+ }
+
+ static final _getParagraphEnd = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getParagraphEnd")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getParagraphEnd()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Returns the string which will be used at the end of a paragraph.
+ ///@return the paragraph end string
+ jni.JString getParagraphEnd() {
+ return const jni.JStringType().fromRef(_getParagraphEnd(reference).object);
+ }
+
+ static final _setParagraphEnd = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__setParagraphEnd")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setParagraphEnd(java.lang.String s)
+ ///
+ /// Sets the string which will be used at the end of a paragraph.
+ ///@param s the paragraph end string
+ void setParagraphEnd(
+ jni.JString s,
+ ) {
+ return _setParagraphEnd(reference, s.reference).check();
+ }
+
+ static final _getPageStart = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getPageStart")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getPageStart()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Returns the string which will be used at the beginning of a page.
+ ///@return the page start string
+ jni.JString getPageStart() {
+ return const jni.JStringType().fromRef(_getPageStart(reference).object);
+ }
+
+ static final _setPageStart = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__setPageStart")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setPageStart(java.lang.String pageStartValue)
+ ///
+ /// Sets the string which will be used at the beginning of a page.
+ ///@param pageStartValue the page start string
+ void setPageStart(
+ jni.JString pageStartValue,
+ ) {
+ return _setPageStart(reference, pageStartValue.reference).check();
+ }
+
+ static final _getPageEnd = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getPageEnd")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getPageEnd()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Returns the string which will be used at the end of a page.
+ ///@return the page end string
+ jni.JString getPageEnd() {
+ return const jni.JStringType().fromRef(_getPageEnd(reference).object);
+ }
+
+ static final _setPageEnd = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__setPageEnd")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setPageEnd(java.lang.String pageEndValue)
+ ///
+ /// Sets the string which will be used at the end of a page.
+ ///@param pageEndValue the page end string
+ void setPageEnd(
+ jni.JString pageEndValue,
+ ) {
+ return _setPageEnd(reference, pageEndValue.reference).check();
+ }
+
+ static final _getArticleStart = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getArticleStart")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getArticleStart()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Returns the string which will be used at the beginning of an article.
+ ///@return the article start string
+ jni.JString getArticleStart() {
+ return const jni.JStringType().fromRef(_getArticleStart(reference).object);
+ }
+
+ static final _setArticleStart = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__setArticleStart")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setArticleStart(java.lang.String articleStartValue)
+ ///
+ /// Sets the string which will be used at the beginning of an article.
+ ///@param articleStartValue the article start string
+ void setArticleStart(
+ jni.JString articleStartValue,
+ ) {
+ return _setArticleStart(reference, articleStartValue.reference).check();
+ }
+
+ static final _getArticleEnd = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getArticleEnd")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getArticleEnd()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Returns the string which will be used at the end of an article.
+ ///@return the article end string
+ jni.JString getArticleEnd() {
+ return const jni.JStringType().fromRef(_getArticleEnd(reference).object);
+ }
+
+ static final _setArticleEnd = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__setArticleEnd")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setArticleEnd(java.lang.String articleEndValue)
+ ///
+ /// Sets the string which will be used at the end of an article.
+ ///@param articleEndValue the article end string
+ void setArticleEnd(
+ jni.JString articleEndValue,
+ ) {
+ return _setArticleEnd(reference, articleEndValue.reference).check();
+ }
+
+ static final _writeParagraphSeparator = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__writeParagraphSeparator")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void writeParagraphSeparator()
+ ///
+ /// writes the paragraph separator string to the output.
+ ///@throws IOException if something went wrong
+ void writeParagraphSeparator() {
+ return _writeParagraphSeparator(reference).check();
+ }
+
+ static final _writeParagraphStart = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__writeParagraphStart")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void writeParagraphStart()
+ ///
+ /// Write something (if defined) at the start of a paragraph.
+ ///@throws IOException if something went wrong
+ void writeParagraphStart() {
+ return _writeParagraphStart(reference).check();
+ }
+
+ static final _writeParagraphEnd = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__writeParagraphEnd")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void writeParagraphEnd()
+ ///
+ /// Write something (if defined) at the end of a paragraph.
+ ///@throws IOException if something went wrong
+ void writeParagraphEnd() {
+ return _writeParagraphEnd(reference).check();
+ }
+
+ static final _writePageStart = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__writePageStart")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void writePageStart()
+ ///
+ /// Write something (if defined) at the start of a page.
+ ///@throws IOException if something went wrong
+ void writePageStart() {
+ return _writePageStart(reference).check();
+ }
+
+ static final _writePageEnd = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__writePageEnd")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void writePageEnd()
+ ///
+ /// Write something (if defined) at the end of a page.
+ ///@throws IOException if something went wrong
+ void writePageEnd() {
+ return _writePageEnd(reference).check();
+ }
+
+ static final _setListItemPatterns = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__setListItemPatterns")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void setListItemPatterns(java.util.List<java.util.regex.Pattern> patterns)
+ ///
+ /// use to supply a different set of regular expression patterns for matching list item starts.
+ ///@param patterns list of patterns
+ void setListItemPatterns(
+ jni.JList<jni.JObject> patterns,
+ ) {
+ return _setListItemPatterns(reference, patterns.reference).check();
+ }
+
+ static final _getListItemPatterns = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "PDFTextStripper__getListItemPatterns")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected java.util.List<java.util.regex.Pattern> getListItemPatterns()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// returns a list of regular expression Patterns representing different common list item formats. For example
+ /// numbered items of form:
+ /// <ol>
+ /// <li>some text</li>
+ /// <li>more text</li>
+ /// </ol>
+ /// or
+ /// <ul>
+ /// <li>some text</li>
+ /// <li>more text</li>
+ /// </ul>
+ /// etc., all begin with some character pattern. The pattern "\\d+\." (matches "1.", "2.", ...) or "\[\\d+\]"
+ /// (matches "[1]", "[2]", ...).
+ ///
+ /// This method returns a list of such regular expression Patterns.
+ ///@return a list of Pattern objects.
+ jni.JList<jni.JObject> getListItemPatterns() {
+ return const jni.JListType(jni.JObjectType())
+ .fromRef(_getListItemPatterns(reference).object);
+ }
+
+ static final _matchPattern = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("PDFTextStripper__matchPattern")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: static protected java.util.regex.Pattern matchPattern(java.lang.String string, java.util.List<java.util.regex.Pattern> patterns)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// iterates over the specified list of Patterns until it finds one that matches the specified string. Then returns
+ /// the Pattern.
+ ///
+ /// Order of the supplied list of patterns is important as most common patterns should come first. Patterns should be
+ /// strict in general, and all will be used with case sensitivity on.
+ ///
+ ///
+ ///@param string the string to be searched
+ ///@param patterns list of patterns
+ ///@return matching pattern
+ static jni.JObject matchPattern(
+ jni.JString string,
+ jni.JList<jni.JObject> patterns,
+ ) {
+ return const jni.JObjectType()
+ .fromRef(_matchPattern(string.reference, patterns.reference).object);
+ }
+}
+
+final class $PDFTextStripperType extends jni.JObjType<PDFTextStripper> {
+ const $PDFTextStripperType();
+
+ @override
+ String get signature => r"Lorg/apache/pdfbox/text/PDFTextStripper;";
+
+ @override
+ PDFTextStripper fromRef(jni.JObjectPtr ref) => PDFTextStripper.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($PDFTextStripperType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($PDFTextStripperType) &&
+ other is $PDFTextStripperType;
+ }
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/_package.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/_package.dart
new file mode 100644
index 0000000..07c57f7
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/_package.dart
@@ -0,0 +1 @@
+export "PDFTextStripper.dart";
diff --git a/pkgs/jnigen/example/pdfbox_plugin/linux/CMakeLists.txt b/pkgs/jnigen/example/pdfbox_plugin/linux/CMakeLists.txt
new file mode 100644
index 0000000..986e388
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/linux/CMakeLists.txt
@@ -0,0 +1,22 @@
+# 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)
+
+# Project-level configuration.
+set(PROJECT_NAME "pdfbox_plugin")
+project(${PROJECT_NAME} LANGUAGES CXX)
+
+# Invoke the build for native code shared with the other target platforms.
+# This can be changed to accomodate different builds.
+add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared")
+
+# 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.
+set(pdfbox_plugin_bundled_libraries
+ # Defined in ../src/CMakeLists.txt.
+ # This can be changed to accomodate different builds.
+ $<TARGET_FILE:pdfbox_plugin>
+ PARENT_SCOPE
+)
diff --git a/pkgs/jnigen/example/pdfbox_plugin/pubspec.yaml b/pkgs/jnigen/example/pdfbox_plugin/pubspec.yaml
new file mode 100644
index 0000000..a269d5a
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/pubspec.yaml
@@ -0,0 +1,38 @@
+name: pdfbox_plugin
+description: |
+ Example of using jnigen to generate bindings for a non-trivial Java library.
+version: 0.0.1
+publish_to: none
+homepage: https://github.com/dart-lang/jnigen
+
+environment:
+ sdk: '>=3.1.0 <4.0.0'
+ #flutter: ">=2.11.0"
+
+dependencies:
+ jni:
+ path: ../../../jni/
+ #flutter:
+ #sdk: flutter
+ plugin_platform_interface: ^2.0.2
+
+dev_dependencies:
+ ## Path dependency for sake of the example
+ jnigen:
+ path: ../../
+ test: any
+ lints: ^2.0.0
+
+flutter:
+ # A JNI plugin uses FFI for calling into C code. Thus the relevant shared
+ # library artifacts must be bundled with final application.
+ # Please refer to README.md for a detailed explanation.
+ plugin:
+ platforms:
+ android:
+ ffiPlugin: true
+ linux:
+ ffiPlugin: true
+ windows:
+ ffiPlugin: true
+
diff --git a/pkgs/jnigen/example/pdfbox_plugin/src/CMakeLists.txt b/pkgs/jnigen/example/pdfbox_plugin/src/CMakeLists.txt
new file mode 100644
index 0000000..f353765
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/src/CMakeLists.txt
@@ -0,0 +1,32 @@
+# jni_native_build (Build with jni:setup. Do not delete this line.)
+
+# 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)
+
+project(pdfbox_plugin VERSION 0.0.1 LANGUAGES C)
+
+add_library(pdfbox_plugin SHARED
+ "third_party//pdfbox_plugin.c"
+)
+
+set_target_properties(pdfbox_plugin PROPERTIES
+ OUTPUT_NAME "pdfbox_plugin"
+)
+
+target_compile_definitions(pdfbox_plugin PUBLIC DART_SHARED_LIB)
+
+if(WIN32)
+ set_target_properties(${TARGET_NAME} PROPERTIES
+ LINK_FLAGS "/DELAYLOAD:jvm.dll")
+endif()
+
+if (ANDROID)
+ target_link_libraries(pdfbox_plugin log)
+else()
+ find_package(Java REQUIRED)
+ find_package(JNI REQUIRED)
+ include_directories(${JNI_INCLUDE_DIRS})
+ target_link_libraries(pdfbox_plugin ${JNI_LIBRARIES})
+endif()
diff --git a/pkgs/jnigen/example/pdfbox_plugin/src/third_party/.clang-format b/pkgs/jnigen/example/pdfbox_plugin/src/third_party/.clang-format
new file mode 100644
index 0000000..a256c2f
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/src/third_party/.clang-format
@@ -0,0 +1,15 @@
+# From dart SDK: https://github.com/dart-lang/sdk/blob/main/.clang-format
+
+# Defines the Chromium style for automatic reformatting.
+# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
+BasedOnStyle: Chromium
+
+# clang-format doesn't seem to do a good job of this for longer comments.
+ReflowComments: 'false'
+
+# We have lots of these. Though we need to put them all in curly braces,
+# clang-format can't do that.
+AllowShortIfStatementsOnASingleLine: 'true'
+
+# Put escaped newlines into the rightmost column.
+AlignEscapedNewlinesLeft: false
diff --git a/pkgs/jnigen/example/pdfbox_plugin/src/third_party/dartjni.h b/pkgs/jnigen/example/pdfbox_plugin/src/third_party/dartjni.h
new file mode 100644
index 0000000..8f1dc74
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/src/third_party/dartjni.h
@@ -0,0 +1,424 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#pragma once
+
+// Note: include appropriate system jni.h as found by CMake, not third_party/jni.h.
+#include <jni.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if _WIN32
+#include <windows.h>
+#else
+#include <pthread.h>
+#include <unistd.h>
+#endif
+
+#if _WIN32
+#define FFI_PLUGIN_EXPORT __declspec(dllexport)
+#else
+#define FFI_PLUGIN_EXPORT
+#endif
+
+#if defined _WIN32
+#define thread_local __declspec(thread)
+#else
+#define thread_local __thread
+#endif
+
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
+
+#ifdef __ANDROID__
+#define __ENVP_CAST (JNIEnv**)
+#else
+#define __ENVP_CAST (void**)
+#endif
+
+/// Locking functions for windows and pthread.
+
+#if defined _WIN32
+#include <windows.h>
+
+typedef CRITICAL_SECTION MutexLock;
+typedef CONDITION_VARIABLE ConditionVariable;
+
+static inline void init_lock(MutexLock* lock) {
+ InitializeCriticalSection(lock);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+ EnterCriticalSection(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+ LeaveCriticalSection(lock);
+}
+
+static inline void destroy_lock(MutexLock* lock) {
+ DeleteCriticalSection(lock);
+}
+
+static inline void init_cond(ConditionVariable* cond) {
+ InitializeConditionVariable(cond);
+}
+
+static inline void signal_cond(ConditionVariable* cond) {
+ WakeConditionVariable(cond);
+}
+
+static inline void wait_for(ConditionVariable* cond, MutexLock* lock) {
+ SleepConditionVariableCS(cond, lock, INFINITE);
+}
+
+static inline void destroy_cond(ConditionVariable* cond) {
+ // Not available.
+}
+
+#elif defined __APPLE__ || defined __LINUX__ || defined __ANDROID__ || \
+ defined __GNUC__
+#include <pthread.h>
+
+typedef pthread_mutex_t MutexLock;
+typedef pthread_cond_t ConditionVariable;
+
+static inline void init_lock(MutexLock* lock) {
+ pthread_mutex_init(lock, NULL);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+ pthread_mutex_lock(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+ pthread_mutex_unlock(lock);
+}
+
+static inline void destroy_lock(MutexLock* lock) {
+ pthread_mutex_destroy(lock);
+}
+
+static inline void init_cond(ConditionVariable* cond) {
+ pthread_cond_init(cond, NULL);
+}
+
+static inline void signal_cond(ConditionVariable* cond) {
+ pthread_cond_signal(cond);
+}
+
+static inline void wait_for(ConditionVariable* cond, MutexLock* lock) {
+ pthread_cond_wait(cond, lock);
+}
+
+static inline void destroy_cond(ConditionVariable* cond) {
+ pthread_cond_destroy(cond);
+}
+
+#else
+
+#error "No locking/condition variable support; Possibly unsupported platform"
+
+#endif
+
+typedef struct CallbackResult {
+ MutexLock lock;
+ ConditionVariable cond;
+ int ready;
+ jobject object;
+} CallbackResult;
+
+typedef struct JniLocks {
+ MutexLock classLoadingLock;
+ MutexLock methodLoadingLock;
+ MutexLock fieldLoadingLock;
+} JniLocks;
+
+/// Represents the error when dart-jni layer has already spawned singleton VM.
+#define DART_JNI_SINGLETON_EXISTS (-99);
+
+/// Stores the global state of the JNI.
+typedef struct JniContext {
+ JavaVM* jvm;
+ jobject classLoader;
+ jmethodID loadClassMethod;
+ jobject currentActivity;
+ jobject appContext;
+ JniLocks locks;
+} JniContext;
+
+// jniEnv for this thread, used by inline functions in this header,
+// therefore declared as extern.
+extern thread_local JNIEnv* jniEnv;
+
+extern JniContext* jni;
+
+/// Types used by JNI API to distinguish between primitive types.
+enum JniType {
+ booleanType = 0,
+ byteType = 1,
+ shortType = 2,
+ charType = 3,
+ intType = 4,
+ longType = 5,
+ floatType = 6,
+ doubleType = 7,
+ objectType = 8,
+ voidType = 9,
+};
+
+/// Result type for use by JNI.
+///
+/// If [exception] is null, it means the result is valid.
+/// It's assumed that the caller knows the expected type in [result].
+typedef struct JniResult {
+ jvalue value;
+ jthrowable exception;
+} JniResult;
+
+/// Similar to [JniResult] but for class lookups.
+typedef struct JniClassLookupResult {
+ jclass value;
+ jthrowable exception;
+} JniClassLookupResult;
+
+/// Similar to [JniResult] but for method/field ID lookups.
+typedef struct JniPointerResult {
+ const void* value;
+ jthrowable exception;
+} JniPointerResult;
+
+/// JniExceptionDetails holds 2 jstring objects, one is the result of
+/// calling `toString` on exception object, other is stack trace;
+typedef struct JniExceptionDetails {
+ jstring message;
+ jstring stacktrace;
+} JniExceptionDetails;
+
+/// This struct contains functions which wrap method call / field access conveniently along with
+/// exception checking.
+///
+/// Flutter embedding checks for pending JNI exceptions before an FFI transition, which requires us
+/// to check for and clear the exception before returning to dart code, which requires these functions
+/// to return result types.
+typedef struct JniAccessorsStruct {
+ JniClassLookupResult (*getClass)(char* internalName);
+ JniPointerResult (*getFieldID)(jclass cls, char* fieldName, char* signature);
+ JniPointerResult (*getStaticFieldID)(jclass cls,
+ char* fieldName,
+ char* signature);
+ JniPointerResult (*getMethodID)(jclass cls,
+ char* methodName,
+ char* signature);
+ JniPointerResult (*getStaticMethodID)(jclass cls,
+ char* methodName,
+ char* signature);
+ JniResult (*newObject)(jclass cls, jmethodID ctor, jvalue* args);
+ JniResult (*newPrimitiveArray)(jsize length, int type);
+ JniResult (*newObjectArray)(jsize length,
+ jclass elementClass,
+ jobject initialElement);
+ JniResult (*getArrayElement)(jarray array, int index, int type);
+ JniResult (*callMethod)(jobject obj,
+ jmethodID methodID,
+ int callType,
+ jvalue* args);
+ JniResult (*callStaticMethod)(jclass cls,
+ jmethodID methodID,
+ int callType,
+ jvalue* args);
+ JniResult (*getField)(jobject obj, jfieldID fieldID, int callType);
+ JniResult (*getStaticField)(jclass cls, jfieldID fieldID, int callType);
+ JniExceptionDetails (*getExceptionDetails)(jthrowable exception);
+} JniAccessorsStruct;
+
+FFI_PLUGIN_EXPORT JniAccessorsStruct* GetAccessors();
+
+FFI_PLUGIN_EXPORT JavaVM* GetJavaVM(void);
+
+FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv(void);
+
+/// Spawn a JVM with given arguments.
+///
+/// Returns JNI_OK on success, and one of the documented JNI error codes on
+/// failure. It returns DART_JNI_SINGLETON_EXISTS if an attempt to spawn multiple
+/// JVMs is made, even if the underlying API potentially supports multiple VMs.
+FFI_PLUGIN_EXPORT int SpawnJvm(JavaVMInitArgs* args);
+
+/// Load class through platform-specific mechanism.
+///
+/// Currently uses application classloader on android,
+/// and JNIEnv->FindClass on other platforms.
+FFI_PLUGIN_EXPORT jclass FindClass(const char* name);
+
+/// Returns Application classLoader (on Android),
+/// which can be used to load application and platform classes.
+///
+/// On other platforms, NULL is returned.
+FFI_PLUGIN_EXPORT jobject GetClassLoader(void);
+
+/// Returns application context on Android.
+///
+/// On other platforms, NULL is returned.
+FFI_PLUGIN_EXPORT jobject GetApplicationContext(void);
+
+/// Returns current activity of the app on Android.
+FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
+
+static inline void attach_thread() {
+ if (jniEnv == NULL) {
+ (*jni->jvm)->AttachCurrentThread(jni->jvm, __ENVP_CAST & jniEnv, NULL);
+ }
+}
+
+/// Load class into [cls] using platform specific mechanism
+static inline void load_class_platform(jclass* cls, const char* name) {
+#ifdef __ANDROID__
+ jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
+ *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni->classLoader,
+ jni->loadClassMethod, className);
+ (*jniEnv)->DeleteLocalRef(jniEnv, className);
+#else
+ *cls = (*jniEnv)->FindClass(jniEnv, name);
+#endif
+}
+
+static inline void load_class_local_ref(jclass* cls, const char* name) {
+ if (*cls == NULL) {
+ acquire_lock(&jni->locks.classLoadingLock);
+ if (*cls == NULL) {
+ load_class_platform(cls, name);
+ }
+ release_lock(&jni->locks.classLoadingLock);
+ }
+}
+
+static inline void load_class_global_ref(jclass* cls, const char* name) {
+ if (*cls == NULL) {
+ jclass tmp = NULL;
+ acquire_lock(&jni->locks.classLoadingLock);
+ if (*cls == NULL) {
+ load_class_platform(&tmp, name);
+ if (!(*jniEnv)->ExceptionCheck(jniEnv)) {
+ *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
+ (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
+ }
+ }
+ release_lock(&jni->locks.classLoadingLock);
+ }
+}
+
+static inline void load_method(jclass cls,
+ jmethodID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.methodLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.methodLoadingLock);
+ }
+}
+
+static inline void load_static_method(jclass cls,
+ jmethodID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.methodLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.methodLoadingLock);
+ }
+}
+
+static inline void load_field(jclass cls,
+ jfieldID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.fieldLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.fieldLoadingLock);
+ }
+}
+
+static inline void load_static_field(jclass cls,
+ jfieldID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.fieldLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.fieldLoadingLock);
+ }
+}
+
+static inline jobject to_global_ref(jobject ref) {
+ jobject g = (*jniEnv)->NewGlobalRef(jniEnv, ref);
+ (*jniEnv)->DeleteLocalRef(jniEnv, ref);
+ return g;
+}
+
+// These functions are useful for C+Dart bindings, and not required for pure dart bindings.
+
+FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr();
+
+/// For use by jni_gen's generated code
+/// don't use these.
+
+// these 2 fn ptr vars will be defined by generated code library
+extern JniContext* (*context_getter)(void);
+extern JNIEnv* (*env_getter)(void);
+
+// this function will be exported by generated code library
+// it will set above 2 variables.
+FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext* (*cg)(void),
+ JNIEnv* (*eg)(void));
+
+static inline void load_env() {
+ if (jniEnv == NULL) {
+ jni = context_getter();
+ jniEnv = env_getter();
+ }
+}
+
+static inline jthrowable check_exception() {
+ jthrowable exception = (*jniEnv)->ExceptionOccurred(jniEnv);
+ if (exception != NULL) (*jniEnv)->ExceptionClear(jniEnv);
+ if (exception == NULL) return NULL;
+ return to_global_ref(exception);
+}
+
+static inline JniResult to_global_ref_result(jobject ref) {
+ JniResult result;
+ result.exception = check_exception();
+ if (result.exception == NULL) {
+ result.value.l = to_global_ref(ref);
+ }
+ return result;
+}
+
+FFI_PLUGIN_EXPORT intptr_t InitDartApiDL(void* data);
+
+FFI_PLUGIN_EXPORT
+JniResult DartException__ctor(jstring message);
+
+FFI_PLUGIN_EXPORT
+JniResult PortContinuation__ctor(int64_t j);
+
+FFI_PLUGIN_EXPORT
+JniResult PortProxy__newInstance(jobject binaryName,
+ int64_t port,
+ int64_t functionPtr);
+
+FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
diff --git a/pkgs/jnigen/example/pdfbox_plugin/src/third_party/pdfbox_plugin.c b/pkgs/jnigen/example/pdfbox_plugin/src/third_party/pdfbox_plugin.c
new file mode 100644
index 0000000..6b11133
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/src/third_party/pdfbox_plugin.c
@@ -0,0 +1,2872 @@
+// Generated from Apache PDFBox library which is licensed under the Apache License 2.0.
+// The following copyright from the original authors applies.
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+#include <stdint.h>
+#include "dartjni.h"
+#include "jni.h"
+
+thread_local JNIEnv* jniEnv;
+JniContext* jni;
+
+JniContext* (*context_getter)(void);
+JNIEnv* (*env_getter)(void);
+
+void setJniGetters(JniContext* (*cg)(void), JNIEnv* (*eg)(void)) {
+ context_getter = cg;
+ env_getter = eg;
+}
+
+// org.apache.pdfbox.pdmodel.PDDocument
+jclass _c_PDDocument = NULL;
+
+jmethodID _m_PDDocument__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__new0() {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__new0, "<init>", "()V");
+ if (_m_PDDocument__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_PDDocument, _m_PDDocument__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__new1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__new1(jobject memUsageSetting) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__new1, "<init>",
+ "(Lorg/apache/pdfbox/io/MemoryUsageSetting;)V");
+ if (_m_PDDocument__new1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_PDDocument,
+ _m_PDDocument__new1, memUsageSetting);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__new2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__new2(jobject doc) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__new2, "<init>",
+ "(Lorg/apache/pdfbox/cos/COSDocument;)V");
+ if (_m_PDDocument__new2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_PDDocument, _m_PDDocument__new2, doc);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__new3 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__new3(jobject doc, jobject source) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__new3, "<init>",
+ "(Lorg/apache/pdfbox/cos/COSDocument;Lorg/apache/pdfbox/io/"
+ "RandomAccessRead;)V");
+ if (_m_PDDocument__new3 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_PDDocument,
+ _m_PDDocument__new3, doc, source);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__new4 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__new4(jobject doc, jobject source, jobject permission) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__new4, "<init>",
+ "(Lorg/apache/pdfbox/cos/COSDocument;Lorg/apache/pdfbox/io/"
+ "RandomAccessRead;Lorg/apache/pdfbox/pdmodel/encryption/"
+ "AccessPermission;)V");
+ if (_m_PDDocument__new4 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(
+ jniEnv, _c_PDDocument, _m_PDDocument__new4, doc, source, permission);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__addPage = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__addPage(jobject self_, jobject page) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__addPage, "addPage",
+ "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
+ if (_m_PDDocument__addPage == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__addPage, page);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__addSignature = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__addSignature(jobject self_, jobject sigObject) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__addSignature, "addSignature",
+ "(Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/"
+ "PDSignature;)V");
+ if (_m_PDDocument__addSignature == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__addSignature,
+ sigObject);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__addSignature1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__addSignature1(jobject self_,
+ jobject sigObject,
+ jobject options) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__addSignature1, "addSignature",
+ "(Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/"
+ "PDSignature;Lorg/apache/pdfbox/pdmodel/interactive/"
+ "digitalsignature/SignatureOptions;)V");
+ if (_m_PDDocument__addSignature1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__addSignature1,
+ sigObject, options);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__addSignature2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__addSignature2(jobject self_,
+ jobject sigObject,
+ jobject signatureInterface) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__addSignature2, "addSignature",
+ "(Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/"
+ "PDSignature;Lorg/apache/pdfbox/pdmodel/interactive/"
+ "digitalsignature/SignatureInterface;)V");
+ if (_m_PDDocument__addSignature2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__addSignature2,
+ sigObject, signatureInterface);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__addSignature3 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__addSignature3(jobject self_,
+ jobject sigObject,
+ jobject signatureInterface,
+ jobject options) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__addSignature3, "addSignature",
+ "(Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/"
+ "PDSignature;Lorg/apache/pdfbox/pdmodel/interactive/"
+ "digitalsignature/SignatureInterface;Lorg/apache/pdfbox/pdmodel/"
+ "interactive/digitalsignature/SignatureOptions;)V");
+ if (_m_PDDocument__addSignature3 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__addSignature3,
+ sigObject, signatureInterface, options);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__addSignatureField = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__addSignatureField(jobject self_,
+ jobject sigFields,
+ jobject signatureInterface,
+ jobject options) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__addSignatureField,
+ "addSignatureField",
+ "(Ljava/util/List;Lorg/apache/pdfbox/pdmodel/interactive/"
+ "digitalsignature/SignatureInterface;Lorg/apache/pdfbox/pdmodel/"
+ "interactive/digitalsignature/SignatureOptions;)V");
+ if (_m_PDDocument__addSignatureField == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__addSignatureField,
+ sigFields, signatureInterface, options);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__removePage = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__removePage(jobject self_, jobject page) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__removePage, "removePage",
+ "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
+ if (_m_PDDocument__removePage == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__removePage, page);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__removePage1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__removePage1(jobject self_, int32_t pageNumber) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__removePage1, "removePage", "(I)V");
+ if (_m_PDDocument__removePage1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__removePage1,
+ pageNumber);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__importPage = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__importPage(jobject self_, jobject page) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_PDDocument, &_m_PDDocument__importPage, "importPage",
+ "(Lorg/apache/pdfbox/pdmodel/PDPage;)Lorg/apache/pdfbox/pdmodel/PDPage;");
+ if (_m_PDDocument__importPage == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocument__importPage, page);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__getDocument = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__getDocument(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__getDocument, "getDocument",
+ "()Lorg/apache/pdfbox/cos/COSDocument;");
+ if (_m_PDDocument__getDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_PDDocument__getDocument);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__getDocumentInformation = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__getDocumentInformation(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__getDocumentInformation,
+ "getDocumentInformation",
+ "()Lorg/apache/pdfbox/pdmodel/PDDocumentInformation;");
+ if (_m_PDDocument__getDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocument__getDocumentInformation);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__setDocumentInformation = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__setDocumentInformation(jobject self_, jobject info) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__setDocumentInformation,
+ "setDocumentInformation",
+ "(Lorg/apache/pdfbox/pdmodel/PDDocumentInformation;)V");
+ if (_m_PDDocument__setDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDDocument__setDocumentInformation, info);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__getDocumentCatalog = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__getDocumentCatalog(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__getDocumentCatalog,
+ "getDocumentCatalog",
+ "()Lorg/apache/pdfbox/pdmodel/PDDocumentCatalog;");
+ if (_m_PDDocument__getDocumentCatalog == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocument__getDocumentCatalog);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__isEncrypted = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__isEncrypted(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__isEncrypted, "isEncrypted", "()Z");
+ if (_m_PDDocument__isEncrypted == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result =
+ (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_PDDocument__isEncrypted);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__getEncryption = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__getEncryption(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__getEncryption, "getEncryption",
+ "()Lorg/apache/pdfbox/pdmodel/encryption/PDEncryption;");
+ if (_m_PDDocument__getEncryption == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_PDDocument__getEncryption);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__setEncryptionDictionary = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__setEncryptionDictionary(jobject self_,
+ jobject encryption) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__setEncryptionDictionary,
+ "setEncryptionDictionary",
+ "(Lorg/apache/pdfbox/pdmodel/encryption/PDEncryption;)V");
+ if (_m_PDDocument__setEncryptionDictionary == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDDocument__setEncryptionDictionary, encryption);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__getLastSignatureDictionary = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__getLastSignatureDictionary(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_PDDocument, &_m_PDDocument__getLastSignatureDictionary,
+ "getLastSignatureDictionary",
+ "()Lorg/apache/pdfbox/pdmodel/interactive/digitalsignature/PDSignature;");
+ if (_m_PDDocument__getLastSignatureDictionary == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocument__getLastSignatureDictionary);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__getSignatureFields = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__getSignatureFields(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__getSignatureFields,
+ "getSignatureFields", "()Ljava/util/List;");
+ if (_m_PDDocument__getSignatureFields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocument__getSignatureFields);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__getSignatureDictionaries = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__getSignatureDictionaries(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__getSignatureDictionaries,
+ "getSignatureDictionaries", "()Ljava/util/List;");
+ if (_m_PDDocument__getSignatureDictionaries == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocument__getSignatureDictionaries);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__registerTrueTypeFontForClosing = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__registerTrueTypeFontForClosing(jobject self_,
+ jobject ttf) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__registerTrueTypeFontForClosing,
+ "registerTrueTypeFontForClosing",
+ "(Lorg/apache/fontbox/ttf/TrueTypeFont;)V");
+ if (_m_PDDocument__registerTrueTypeFontForClosing == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDDocument__registerTrueTypeFontForClosing, ttf);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__load = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__load(jobject file) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_PDDocument, &_m_PDDocument__load, "load",
+ "(Ljava/io/File;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+ if (_m_PDDocument__load == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PDDocument, _m_PDDocument__load, file);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__load1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__load1(jobject file, jobject memUsageSetting) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_PDDocument, &_m_PDDocument__load1, "load",
+ "(Ljava/io/File;Lorg/apache/pdfbox/io/MemoryUsageSetting;)Lorg/apache/"
+ "pdfbox/pdmodel/PDDocument;");
+ if (_m_PDDocument__load1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PDDocument, _m_PDDocument__load1, file, memUsageSetting);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__load2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__load2(jobject file, jobject password) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_PDDocument, &_m_PDDocument__load2, "load",
+ "(Ljava/io/File;Ljava/lang/String;)Lorg/apache/pdfbox/"
+ "pdmodel/PDDocument;");
+ if (_m_PDDocument__load2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PDDocument, _m_PDDocument__load2, file, password);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__load3 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__load3(jobject file,
+ jobject password,
+ jobject memUsageSetting) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_PDDocument, &_m_PDDocument__load3, "load",
+ "(Ljava/io/File;Ljava/lang/String;Lorg/apache/pdfbox/io/"
+ "MemoryUsageSetting;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+ if (_m_PDDocument__load3 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PDDocument, _m_PDDocument__load3, file, password,
+ memUsageSetting);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__load4 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__load4(jobject file,
+ jobject password,
+ jobject keyStore,
+ jobject alias) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_PDDocument, &_m_PDDocument__load4, "load",
+ "(Ljava/io/File;Ljava/lang/String;Ljava/io/InputStream;Ljava/lang/"
+ "String;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+ if (_m_PDDocument__load4 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PDDocument, _m_PDDocument__load4, file, password, keyStore,
+ alias);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__load5 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__load5(jobject file,
+ jobject password,
+ jobject keyStore,
+ jobject alias,
+ jobject memUsageSetting) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_PDDocument, &_m_PDDocument__load5, "load",
+ "(Ljava/io/File;Ljava/lang/String;Ljava/io/InputStream;Ljava/lang/"
+ "String;Lorg/apache/pdfbox/io/MemoryUsageSetting;)Lorg/apache/pdfbox/"
+ "pdmodel/PDDocument;");
+ if (_m_PDDocument__load5 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PDDocument, _m_PDDocument__load5, file, password, keyStore,
+ alias, memUsageSetting);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__load6 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__load6(jobject input) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_PDDocument, &_m_PDDocument__load6, "load",
+ "(Ljava/io/InputStream;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+ if (_m_PDDocument__load6 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PDDocument, _m_PDDocument__load6, input);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__load7 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__load7(jobject input, jobject memUsageSetting) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_PDDocument, &_m_PDDocument__load7, "load",
+ "(Ljava/io/InputStream;Lorg/apache/pdfbox/io/MemoryUsageSetting;)Lorg/"
+ "apache/pdfbox/pdmodel/PDDocument;");
+ if (_m_PDDocument__load7 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PDDocument, _m_PDDocument__load7, input, memUsageSetting);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__load8 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__load8(jobject input, jobject password) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_PDDocument, &_m_PDDocument__load8, "load",
+ "(Ljava/io/InputStream;Ljava/lang/String;)Lorg/apache/"
+ "pdfbox/pdmodel/PDDocument;");
+ if (_m_PDDocument__load8 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PDDocument, _m_PDDocument__load8, input, password);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__load9 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__load9(jobject input,
+ jobject password,
+ jobject keyStore,
+ jobject alias) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_PDDocument, &_m_PDDocument__load9, "load",
+ "(Ljava/io/InputStream;Ljava/lang/String;Ljava/io/InputStream;Ljava/lang/"
+ "String;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+ if (_m_PDDocument__load9 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PDDocument, _m_PDDocument__load9, input, password, keyStore,
+ alias);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__load10 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__load10(jobject input,
+ jobject password,
+ jobject memUsageSetting) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_PDDocument, &_m_PDDocument__load10, "load",
+ "(Ljava/io/InputStream;Ljava/lang/String;Lorg/apache/pdfbox/io/"
+ "MemoryUsageSetting;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+ if (_m_PDDocument__load10 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PDDocument, _m_PDDocument__load10, input, password,
+ memUsageSetting);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__load11 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__load11(jobject input,
+ jobject password,
+ jobject keyStore,
+ jobject alias,
+ jobject memUsageSetting) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_PDDocument, &_m_PDDocument__load11, "load",
+ "(Ljava/io/InputStream;Ljava/lang/String;Ljava/io/InputStream;Ljava/lang/"
+ "String;Lorg/apache/pdfbox/io/MemoryUsageSetting;)Lorg/apache/pdfbox/"
+ "pdmodel/PDDocument;");
+ if (_m_PDDocument__load11 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PDDocument, _m_PDDocument__load11, input, password, keyStore,
+ alias, memUsageSetting);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__load12 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__load12(jobject input) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_PDDocument, &_m_PDDocument__load12, "load",
+ "([B)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+ if (_m_PDDocument__load12 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PDDocument, _m_PDDocument__load12, input);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__load13 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__load13(jobject input, jobject password) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_PDDocument, &_m_PDDocument__load13, "load",
+ "([BLjava/lang/String;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+ if (_m_PDDocument__load13 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PDDocument, _m_PDDocument__load13, input, password);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__load14 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__load14(jobject input,
+ jobject password,
+ jobject keyStore,
+ jobject alias) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_PDDocument, &_m_PDDocument__load14, "load",
+ "([BLjava/lang/String;Ljava/io/InputStream;Ljava/lang/"
+ "String;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+ if (_m_PDDocument__load14 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PDDocument, _m_PDDocument__load14, input, password, keyStore,
+ alias);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__load15 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__load15(jobject input,
+ jobject password,
+ jobject keyStore,
+ jobject alias,
+ jobject memUsageSetting) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_PDDocument, &_m_PDDocument__load15, "load",
+ "([BLjava/lang/String;Ljava/io/InputStream;Ljava/lang/String;Lorg/apache/"
+ "pdfbox/io/MemoryUsageSetting;)Lorg/apache/pdfbox/pdmodel/PDDocument;");
+ if (_m_PDDocument__load15 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PDDocument, _m_PDDocument__load15, input, password, keyStore,
+ alias, memUsageSetting);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__save = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__save(jobject self_, jobject fileName) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__save, "save",
+ "(Ljava/lang/String;)V");
+ if (_m_PDDocument__save == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__save, fileName);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__save1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__save1(jobject self_, jobject file) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__save1, "save",
+ "(Ljava/io/File;)V");
+ if (_m_PDDocument__save1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__save1, file);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__save2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__save2(jobject self_, jobject output) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__save2, "save",
+ "(Ljava/io/OutputStream;)V");
+ if (_m_PDDocument__save2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__save2, output);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__saveIncremental = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__saveIncremental(jobject self_, jobject output) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__saveIncremental, "saveIncremental",
+ "(Ljava/io/OutputStream;)V");
+ if (_m_PDDocument__saveIncremental == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__saveIncremental,
+ output);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__saveIncremental1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__saveIncremental1(jobject self_,
+ jobject output,
+ jobject objectsToWrite) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__saveIncremental1,
+ "saveIncremental", "(Ljava/io/OutputStream;Ljava/util/Set;)V");
+ if (_m_PDDocument__saveIncremental1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__saveIncremental1,
+ output, objectsToWrite);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__saveIncrementalForExternalSigning = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__saveIncrementalForExternalSigning(jobject self_,
+ jobject output) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__saveIncrementalForExternalSigning,
+ "saveIncrementalForExternalSigning",
+ "(Ljava/io/OutputStream;)Lorg/apache/pdfbox/pdmodel/interactive/"
+ "digitalsignature/ExternalSigningSupport;");
+ if (_m_PDDocument__saveIncrementalForExternalSigning == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocument__saveIncrementalForExternalSigning, output);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__getPage = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__getPage(jobject self_, int32_t pageIndex) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__getPage, "getPage",
+ "(I)Lorg/apache/pdfbox/pdmodel/PDPage;");
+ if (_m_PDDocument__getPage == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocument__getPage, pageIndex);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__getPages = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__getPages(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__getPages, "getPages",
+ "()Lorg/apache/pdfbox/pdmodel/PDPageTree;");
+ if (_m_PDDocument__getPages == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_PDDocument__getPages);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__getNumberOfPages = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__getNumberOfPages(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__getNumberOfPages,
+ "getNumberOfPages", "()I");
+ if (_m_PDDocument__getNumberOfPages == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_PDDocument__getNumberOfPages);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__close = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__close(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__close, "close", "()V");
+ if (_m_PDDocument__close == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__close);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__protect = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__protect(jobject self_, jobject policy) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__protect, "protect",
+ "(Lorg/apache/pdfbox/pdmodel/encryption/ProtectionPolicy;)V");
+ if (_m_PDDocument__protect == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__protect, policy);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__getCurrentAccessPermission = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__getCurrentAccessPermission(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__getCurrentAccessPermission,
+ "getCurrentAccessPermission",
+ "()Lorg/apache/pdfbox/pdmodel/encryption/AccessPermission;");
+ if (_m_PDDocument__getCurrentAccessPermission == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocument__getCurrentAccessPermission);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__isAllSecurityToBeRemoved = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__isAllSecurityToBeRemoved(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__isAllSecurityToBeRemoved,
+ "isAllSecurityToBeRemoved", "()Z");
+ if (_m_PDDocument__isAllSecurityToBeRemoved == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_PDDocument__isAllSecurityToBeRemoved);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__setAllSecurityToBeRemoved = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__setAllSecurityToBeRemoved(jobject self_,
+ uint8_t removeAllSecurity) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__setAllSecurityToBeRemoved,
+ "setAllSecurityToBeRemoved", "(Z)V");
+ if (_m_PDDocument__setAllSecurityToBeRemoved == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDDocument__setAllSecurityToBeRemoved,
+ removeAllSecurity);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__getDocumentId = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__getDocumentId(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__getDocumentId, "getDocumentId",
+ "()Ljava/lang/Long;");
+ if (_m_PDDocument__getDocumentId == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_PDDocument__getDocumentId);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__setDocumentId = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__setDocumentId(jobject self_, jobject docId) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__setDocumentId, "setDocumentId",
+ "(Ljava/lang/Long;)V");
+ if (_m_PDDocument__setDocumentId == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__setDocumentId, docId);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__getVersion = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__getVersion(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__getVersion, "getVersion", "()F");
+ if (_m_PDDocument__getVersion == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ float _result =
+ (*jniEnv)->CallFloatMethod(jniEnv, self_, _m_PDDocument__getVersion);
+ return (JniResult){.value = {.f = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__setVersion = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__setVersion(jobject self_, float newVersion) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__setVersion, "setVersion", "(F)V");
+ if (_m_PDDocument__setVersion == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__setVersion,
+ newVersion);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocument__getResourceCache = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__getResourceCache(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__getResourceCache,
+ "getResourceCache",
+ "()Lorg/apache/pdfbox/pdmodel/ResourceCache;");
+ if (_m_PDDocument__getResourceCache == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocument__getResourceCache);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocument__setResourceCache = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocument__setResourceCache(jobject self_, jobject resourceCache) {
+ load_env();
+ load_class_global_ref(&_c_PDDocument, "org/apache/pdfbox/pdmodel/PDDocument");
+ if (_c_PDDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocument, &_m_PDDocument__setResourceCache,
+ "setResourceCache",
+ "(Lorg/apache/pdfbox/pdmodel/ResourceCache;)V");
+ if (_m_PDDocument__setResourceCache == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocument__setResourceCache,
+ resourceCache);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// org.apache.pdfbox.pdmodel.PDDocumentInformation
+jclass _c_PDDocumentInformation = NULL;
+
+jmethodID _m_PDDocumentInformation__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__new0() {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__new0,
+ "<init>", "()V");
+ if (_m_PDDocumentInformation__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_PDDocumentInformation,
+ _m_PDDocumentInformation__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocumentInformation__new1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__new1(jobject dic) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__new1,
+ "<init>", "(Lorg/apache/pdfbox/cos/COSDictionary;)V");
+ if (_m_PDDocumentInformation__new1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_PDDocumentInformation,
+ _m_PDDocumentInformation__new1, dic);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocumentInformation__getCOSObject = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__getCOSObject(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__getCOSObject,
+ "getCOSObject", "()Lorg/apache/pdfbox/cos/COSDictionary;");
+ if (_m_PDDocumentInformation__getCOSObject == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocumentInformation__getCOSObject);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocumentInformation__getPropertyStringValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__getPropertyStringValue(jobject self_,
+ jobject propertyKey) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation,
+ &_m_PDDocumentInformation__getPropertyStringValue,
+ "getPropertyStringValue",
+ "(Ljava/lang/String;)Ljava/lang/Object;");
+ if (_m_PDDocumentInformation__getPropertyStringValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocumentInformation__getPropertyStringValue,
+ propertyKey);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocumentInformation__getTitle = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__getTitle(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__getTitle,
+ "getTitle", "()Ljava/lang/String;");
+ if (_m_PDDocumentInformation__getTitle == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocumentInformation__getTitle);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocumentInformation__setTitle = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__setTitle(jobject self_, jobject title) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__setTitle,
+ "setTitle", "(Ljava/lang/String;)V");
+ if (_m_PDDocumentInformation__setTitle == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocumentInformation__setTitle,
+ title);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocumentInformation__getAuthor = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__getAuthor(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__getAuthor,
+ "getAuthor", "()Ljava/lang/String;");
+ if (_m_PDDocumentInformation__getAuthor == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocumentInformation__getAuthor);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocumentInformation__setAuthor = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__setAuthor(jobject self_, jobject author) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__setAuthor,
+ "setAuthor", "(Ljava/lang/String;)V");
+ if (_m_PDDocumentInformation__setAuthor == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocumentInformation__setAuthor,
+ author);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocumentInformation__getSubject = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__getSubject(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__getSubject,
+ "getSubject", "()Ljava/lang/String;");
+ if (_m_PDDocumentInformation__getSubject == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocumentInformation__getSubject);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocumentInformation__setSubject = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__setSubject(jobject self_, jobject subject) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__setSubject,
+ "setSubject", "(Ljava/lang/String;)V");
+ if (_m_PDDocumentInformation__setSubject == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocumentInformation__setSubject,
+ subject);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocumentInformation__getKeywords = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__getKeywords(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__getKeywords,
+ "getKeywords", "()Ljava/lang/String;");
+ if (_m_PDDocumentInformation__getKeywords == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocumentInformation__getKeywords);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocumentInformation__setKeywords = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__setKeywords(jobject self_, jobject keywords) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__setKeywords,
+ "setKeywords", "(Ljava/lang/String;)V");
+ if (_m_PDDocumentInformation__setKeywords == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDDocumentInformation__setKeywords, keywords);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocumentInformation__getCreator = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__getCreator(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__getCreator,
+ "getCreator", "()Ljava/lang/String;");
+ if (_m_PDDocumentInformation__getCreator == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocumentInformation__getCreator);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocumentInformation__setCreator = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__setCreator(jobject self_, jobject creator) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__setCreator,
+ "setCreator", "(Ljava/lang/String;)V");
+ if (_m_PDDocumentInformation__setCreator == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocumentInformation__setCreator,
+ creator);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocumentInformation__getProducer = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__getProducer(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__getProducer,
+ "getProducer", "()Ljava/lang/String;");
+ if (_m_PDDocumentInformation__getProducer == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocumentInformation__getProducer);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocumentInformation__setProducer = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__setProducer(jobject self_, jobject producer) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__setProducer,
+ "setProducer", "(Ljava/lang/String;)V");
+ if (_m_PDDocumentInformation__setProducer == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDDocumentInformation__setProducer, producer);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocumentInformation__getCreationDate = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__getCreationDate(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation,
+ &_m_PDDocumentInformation__getCreationDate, "getCreationDate",
+ "()Ljava/util/Calendar;");
+ if (_m_PDDocumentInformation__getCreationDate == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocumentInformation__getCreationDate);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocumentInformation__setCreationDate = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__setCreationDate(jobject self_, jobject date) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation,
+ &_m_PDDocumentInformation__setCreationDate, "setCreationDate",
+ "(Ljava/util/Calendar;)V");
+ if (_m_PDDocumentInformation__setCreationDate == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDDocumentInformation__setCreationDate, date);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocumentInformation__getModificationDate = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__getModificationDate(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation,
+ &_m_PDDocumentInformation__getModificationDate,
+ "getModificationDate", "()Ljava/util/Calendar;");
+ if (_m_PDDocumentInformation__getModificationDate == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocumentInformation__getModificationDate);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocumentInformation__setModificationDate = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__setModificationDate(jobject self_,
+ jobject date) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation,
+ &_m_PDDocumentInformation__setModificationDate,
+ "setModificationDate", "(Ljava/util/Calendar;)V");
+ if (_m_PDDocumentInformation__setModificationDate == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(
+ jniEnv, self_, _m_PDDocumentInformation__setModificationDate, date);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocumentInformation__getTrapped = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__getTrapped(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__getTrapped,
+ "getTrapped", "()Ljava/lang/String;");
+ if (_m_PDDocumentInformation__getTrapped == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocumentInformation__getTrapped);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocumentInformation__getMetadataKeys = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__getMetadataKeys(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation,
+ &_m_PDDocumentInformation__getMetadataKeys, "getMetadataKeys",
+ "()Ljava/util/Set;");
+ if (_m_PDDocumentInformation__getMetadataKeys == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocumentInformation__getMetadataKeys);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocumentInformation__getCustomMetadataValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__getCustomMetadataValue(jobject self_,
+ jobject fieldName) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation,
+ &_m_PDDocumentInformation__getCustomMetadataValue,
+ "getCustomMetadataValue",
+ "(Ljava/lang/String;)Ljava/lang/String;");
+ if (_m_PDDocumentInformation__getCustomMetadataValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDDocumentInformation__getCustomMetadataValue,
+ fieldName);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDDocumentInformation__setCustomMetadataValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__setCustomMetadataValue(jobject self_,
+ jobject fieldName,
+ jobject fieldValue) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation,
+ &_m_PDDocumentInformation__setCustomMetadataValue,
+ "setCustomMetadataValue",
+ "(Ljava/lang/String;Ljava/lang/String;)V");
+ if (_m_PDDocumentInformation__setCustomMetadataValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDDocumentInformation__setCustomMetadataValue,
+ fieldName, fieldValue);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDDocumentInformation__setTrapped = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDDocumentInformation__setTrapped(jobject self_, jobject value) {
+ load_env();
+ load_class_global_ref(&_c_PDDocumentInformation,
+ "org/apache/pdfbox/pdmodel/PDDocumentInformation");
+ if (_c_PDDocumentInformation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDDocumentInformation, &_m_PDDocumentInformation__setTrapped,
+ "setTrapped", "(Ljava/lang/String;)V");
+ if (_m_PDDocumentInformation__setTrapped == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDDocumentInformation__setTrapped,
+ value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// org.apache.pdfbox.text.PDFTextStripper
+jclass _c_PDFTextStripper = NULL;
+
+jmethodID _m_PDFTextStripper__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__new0() {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__new0, "<init>", "()V");
+ if (_m_PDFTextStripper__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_PDFTextStripper,
+ _m_PDFTextStripper__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDFTextStripper__getText = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getText(jobject self_, jobject doc) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getText, "getText",
+ "(Lorg/apache/pdfbox/pdmodel/PDDocument;)Ljava/lang/String;");
+ if (_m_PDFTextStripper__getText == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDFTextStripper__getText, doc);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDFTextStripper__writeText = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__writeText(jobject self_,
+ jobject doc,
+ jobject outputStream) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeText, "writeText",
+ "(Lorg/apache/pdfbox/pdmodel/PDDocument;Ljava/io/Writer;)V");
+ if (_m_PDFTextStripper__writeText == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__writeText, doc,
+ outputStream);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__processPages = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__processPages(jobject self_, jobject pages) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__processPages,
+ "processPages", "(Lorg/apache/pdfbox/pdmodel/PDPageTree;)V");
+ if (_m_PDFTextStripper__processPages == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__processPages,
+ pages);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__startDocument = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__startDocument(jobject self_, jobject document) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__startDocument,
+ "startDocument", "(Lorg/apache/pdfbox/pdmodel/PDDocument;)V");
+ if (_m_PDFTextStripper__startDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__startDocument,
+ document);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__endDocument = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__endDocument(jobject self_, jobject document) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__endDocument,
+ "endDocument", "(Lorg/apache/pdfbox/pdmodel/PDDocument;)V");
+ if (_m_PDFTextStripper__endDocument == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__endDocument,
+ document);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__processPage = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__processPage(jobject self_, jobject page) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__processPage,
+ "processPage", "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
+ if (_m_PDFTextStripper__processPage == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__processPage,
+ page);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__startArticle = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__startArticle(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__startArticle,
+ "startArticle", "()V");
+ if (_m_PDFTextStripper__startArticle == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__startArticle);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__startArticle1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__startArticle1(jobject self_, uint8_t isLTR) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__startArticle1,
+ "startArticle", "(Z)V");
+ if (_m_PDFTextStripper__startArticle1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__startArticle1,
+ isLTR);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__endArticle = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__endArticle(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__endArticle, "endArticle",
+ "()V");
+ if (_m_PDFTextStripper__endArticle == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__endArticle);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__startPage = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__startPage(jobject self_, jobject page) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__startPage, "startPage",
+ "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
+ if (_m_PDFTextStripper__startPage == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__startPage, page);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__endPage = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__endPage(jobject self_, jobject page) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__endPage, "endPage",
+ "(Lorg/apache/pdfbox/pdmodel/PDPage;)V");
+ if (_m_PDFTextStripper__endPage == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__endPage, page);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__writePage = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__writePage(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writePage, "writePage",
+ "()V");
+ if (_m_PDFTextStripper__writePage == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__writePage);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__writeLineSeparator = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__writeLineSeparator(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeLineSeparator,
+ "writeLineSeparator", "()V");
+ if (_m_PDFTextStripper__writeLineSeparator == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDFTextStripper__writeLineSeparator);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__writeWordSeparator = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__writeWordSeparator(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeWordSeparator,
+ "writeWordSeparator", "()V");
+ if (_m_PDFTextStripper__writeWordSeparator == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDFTextStripper__writeWordSeparator);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__writeCharacters = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__writeCharacters(jobject self_, jobject text) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeCharacters,
+ "writeCharacters", "(Lorg/apache/pdfbox/text/TextPosition;)V");
+ if (_m_PDFTextStripper__writeCharacters == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__writeCharacters,
+ text);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__writeString = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__writeString(jobject self_,
+ jobject text,
+ jobject textPositions) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeString,
+ "writeString", "(Ljava/lang/String;Ljava/util/List;)V");
+ if (_m_PDFTextStripper__writeString == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__writeString,
+ text, textPositions);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__writeString1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__writeString1(jobject self_, jobject text) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeString1,
+ "writeString", "(Ljava/lang/String;)V");
+ if (_m_PDFTextStripper__writeString1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__writeString1,
+ text);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__processTextPosition = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__processTextPosition(jobject self_, jobject text) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__processTextPosition,
+ "processTextPosition",
+ "(Lorg/apache/pdfbox/text/TextPosition;)V");
+ if (_m_PDFTextStripper__processTextPosition == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDFTextStripper__processTextPosition, text);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getStartPage = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getStartPage(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getStartPage,
+ "getStartPage", "()I");
+ if (_m_PDFTextStripper__getStartPage == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_PDFTextStripper__getStartPage);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__setStartPage = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setStartPage(jobject self_, int32_t startPageValue) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setStartPage,
+ "setStartPage", "(I)V");
+ if (_m_PDFTextStripper__setStartPage == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setStartPage,
+ startPageValue);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getEndPage = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getEndPage(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getEndPage, "getEndPage",
+ "()I");
+ if (_m_PDFTextStripper__getEndPage == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_PDFTextStripper__getEndPage);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__setEndPage = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setEndPage(jobject self_, int32_t endPageValue) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setEndPage, "setEndPage",
+ "(I)V");
+ if (_m_PDFTextStripper__setEndPage == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setEndPage,
+ endPageValue);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__setLineSeparator = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setLineSeparator(jobject self_, jobject separator) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setLineSeparator,
+ "setLineSeparator", "(Ljava/lang/String;)V");
+ if (_m_PDFTextStripper__setLineSeparator == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setLineSeparator,
+ separator);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getLineSeparator = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getLineSeparator(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getLineSeparator,
+ "getLineSeparator", "()Ljava/lang/String;");
+ if (_m_PDFTextStripper__getLineSeparator == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDFTextStripper__getLineSeparator);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDFTextStripper__getWordSeparator = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getWordSeparator(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getWordSeparator,
+ "getWordSeparator", "()Ljava/lang/String;");
+ if (_m_PDFTextStripper__getWordSeparator == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDFTextStripper__getWordSeparator);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDFTextStripper__setWordSeparator = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setWordSeparator(jobject self_, jobject separator) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setWordSeparator,
+ "setWordSeparator", "(Ljava/lang/String;)V");
+ if (_m_PDFTextStripper__setWordSeparator == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setWordSeparator,
+ separator);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getSuppressDuplicateOverlappingText = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getSuppressDuplicateOverlappingText(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper,
+ &_m_PDFTextStripper__getSuppressDuplicateOverlappingText,
+ "getSuppressDuplicateOverlappingText", "()Z");
+ if (_m_PDFTextStripper__getSuppressDuplicateOverlappingText == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_PDFTextStripper__getSuppressDuplicateOverlappingText);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getCurrentPageNo = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getCurrentPageNo(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getCurrentPageNo,
+ "getCurrentPageNo", "()I");
+ if (_m_PDFTextStripper__getCurrentPageNo == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(
+ jniEnv, self_, _m_PDFTextStripper__getCurrentPageNo);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getOutput = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getOutput(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getOutput, "getOutput",
+ "()Ljava/io/Writer;");
+ if (_m_PDFTextStripper__getOutput == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_PDFTextStripper__getOutput);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDFTextStripper__getCharactersByArticle = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getCharactersByArticle(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getCharactersByArticle,
+ "getCharactersByArticle", "()Ljava/util/List;");
+ if (_m_PDFTextStripper__getCharactersByArticle == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDFTextStripper__getCharactersByArticle);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDFTextStripper__setSuppressDuplicateOverlappingText = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setSuppressDuplicateOverlappingText(
+ jobject self_,
+ uint8_t suppressDuplicateOverlappingTextValue) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper,
+ &_m_PDFTextStripper__setSuppressDuplicateOverlappingText,
+ "setSuppressDuplicateOverlappingText", "(Z)V");
+ if (_m_PDFTextStripper__setSuppressDuplicateOverlappingText == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(
+ jniEnv, self_, _m_PDFTextStripper__setSuppressDuplicateOverlappingText,
+ suppressDuplicateOverlappingTextValue);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getSeparateByBeads = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getSeparateByBeads(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getSeparateByBeads,
+ "getSeparateByBeads", "()Z");
+ if (_m_PDFTextStripper__getSeparateByBeads == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_PDFTextStripper__getSeparateByBeads);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__setShouldSeparateByBeads = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setShouldSeparateByBeads(
+ jobject self_,
+ uint8_t aShouldSeparateByBeads) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setShouldSeparateByBeads,
+ "setShouldSeparateByBeads", "(Z)V");
+ if (_m_PDFTextStripper__setShouldSeparateByBeads == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDFTextStripper__setShouldSeparateByBeads,
+ aShouldSeparateByBeads);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getEndBookmark = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getEndBookmark(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getEndBookmark,
+ "getEndBookmark",
+ "()Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/"
+ "outline/PDOutlineItem;");
+ if (_m_PDFTextStripper__getEndBookmark == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDFTextStripper__getEndBookmark);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDFTextStripper__setEndBookmark = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setEndBookmark(jobject self_, jobject aEndBookmark) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setEndBookmark,
+ "setEndBookmark",
+ "(Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/"
+ "outline/PDOutlineItem;)V");
+ if (_m_PDFTextStripper__setEndBookmark == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setEndBookmark,
+ aEndBookmark);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getStartBookmark = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getStartBookmark(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getStartBookmark,
+ "getStartBookmark",
+ "()Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/"
+ "outline/PDOutlineItem;");
+ if (_m_PDFTextStripper__getStartBookmark == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDFTextStripper__getStartBookmark);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDFTextStripper__setStartBookmark = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setStartBookmark(jobject self_,
+ jobject aStartBookmark) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setStartBookmark,
+ "setStartBookmark",
+ "(Lorg/apache/pdfbox/pdmodel/interactive/documentnavigation/"
+ "outline/PDOutlineItem;)V");
+ if (_m_PDFTextStripper__setStartBookmark == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setStartBookmark,
+ aStartBookmark);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getAddMoreFormatting = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getAddMoreFormatting(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getAddMoreFormatting,
+ "getAddMoreFormatting", "()Z");
+ if (_m_PDFTextStripper__getAddMoreFormatting == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_PDFTextStripper__getAddMoreFormatting);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__setAddMoreFormatting = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setAddMoreFormatting(jobject self_,
+ uint8_t newAddMoreFormatting) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setAddMoreFormatting,
+ "setAddMoreFormatting", "(Z)V");
+ if (_m_PDFTextStripper__setAddMoreFormatting == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDFTextStripper__setAddMoreFormatting,
+ newAddMoreFormatting);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getSortByPosition = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getSortByPosition(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getSortByPosition,
+ "getSortByPosition", "()Z");
+ if (_m_PDFTextStripper__getSortByPosition == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_PDFTextStripper__getSortByPosition);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__setSortByPosition = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setSortByPosition(jobject self_,
+ uint8_t newSortByPosition) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setSortByPosition,
+ "setSortByPosition", "(Z)V");
+ if (_m_PDFTextStripper__setSortByPosition == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(
+ jniEnv, self_, _m_PDFTextStripper__setSortByPosition, newSortByPosition);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getSpacingTolerance = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getSpacingTolerance(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getSpacingTolerance,
+ "getSpacingTolerance", "()F");
+ if (_m_PDFTextStripper__getSpacingTolerance == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ float _result = (*jniEnv)->CallFloatMethod(
+ jniEnv, self_, _m_PDFTextStripper__getSpacingTolerance);
+ return (JniResult){.value = {.f = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__setSpacingTolerance = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setSpacingTolerance(jobject self_,
+ float spacingToleranceValue) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setSpacingTolerance,
+ "setSpacingTolerance", "(F)V");
+ if (_m_PDFTextStripper__setSpacingTolerance == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDFTextStripper__setSpacingTolerance,
+ spacingToleranceValue);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getAverageCharTolerance = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getAverageCharTolerance(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getAverageCharTolerance,
+ "getAverageCharTolerance", "()F");
+ if (_m_PDFTextStripper__getAverageCharTolerance == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ float _result = (*jniEnv)->CallFloatMethod(
+ jniEnv, self_, _m_PDFTextStripper__getAverageCharTolerance);
+ return (JniResult){.value = {.f = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__setAverageCharTolerance = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setAverageCharTolerance(
+ jobject self_,
+ float averageCharToleranceValue) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setAverageCharTolerance,
+ "setAverageCharTolerance", "(F)V");
+ if (_m_PDFTextStripper__setAverageCharTolerance == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDFTextStripper__setAverageCharTolerance,
+ averageCharToleranceValue);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getIndentThreshold = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getIndentThreshold(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getIndentThreshold,
+ "getIndentThreshold", "()F");
+ if (_m_PDFTextStripper__getIndentThreshold == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ float _result = (*jniEnv)->CallFloatMethod(
+ jniEnv, self_, _m_PDFTextStripper__getIndentThreshold);
+ return (JniResult){.value = {.f = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__setIndentThreshold = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setIndentThreshold(jobject self_,
+ float indentThresholdValue) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setIndentThreshold,
+ "setIndentThreshold", "(F)V");
+ if (_m_PDFTextStripper__setIndentThreshold == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDFTextStripper__setIndentThreshold,
+ indentThresholdValue);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getDropThreshold = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getDropThreshold(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getDropThreshold,
+ "getDropThreshold", "()F");
+ if (_m_PDFTextStripper__getDropThreshold == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ float _result = (*jniEnv)->CallFloatMethod(
+ jniEnv, self_, _m_PDFTextStripper__getDropThreshold);
+ return (JniResult){.value = {.f = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__setDropThreshold = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setDropThreshold(jobject self_,
+ float dropThresholdValue) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setDropThreshold,
+ "setDropThreshold", "(F)V");
+ if (_m_PDFTextStripper__setDropThreshold == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setDropThreshold,
+ dropThresholdValue);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getParagraphStart = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getParagraphStart(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getParagraphStart,
+ "getParagraphStart", "()Ljava/lang/String;");
+ if (_m_PDFTextStripper__getParagraphStart == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDFTextStripper__getParagraphStart);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDFTextStripper__setParagraphStart = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setParagraphStart(jobject self_, jobject s) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setParagraphStart,
+ "setParagraphStart", "(Ljava/lang/String;)V");
+ if (_m_PDFTextStripper__setParagraphStart == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDFTextStripper__setParagraphStart, s);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getParagraphEnd = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getParagraphEnd(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getParagraphEnd,
+ "getParagraphEnd", "()Ljava/lang/String;");
+ if (_m_PDFTextStripper__getParagraphEnd == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDFTextStripper__getParagraphEnd);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDFTextStripper__setParagraphEnd = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setParagraphEnd(jobject self_, jobject s) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setParagraphEnd,
+ "setParagraphEnd", "(Ljava/lang/String;)V");
+ if (_m_PDFTextStripper__setParagraphEnd == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setParagraphEnd,
+ s);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getPageStart = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getPageStart(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getPageStart,
+ "getPageStart", "()Ljava/lang/String;");
+ if (_m_PDFTextStripper__getPageStart == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDFTextStripper__getPageStart);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDFTextStripper__setPageStart = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setPageStart(jobject self_, jobject pageStartValue) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setPageStart,
+ "setPageStart", "(Ljava/lang/String;)V");
+ if (_m_PDFTextStripper__setPageStart == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setPageStart,
+ pageStartValue);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getPageEnd = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getPageEnd(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getPageEnd, "getPageEnd",
+ "()Ljava/lang/String;");
+ if (_m_PDFTextStripper__getPageEnd == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_,
+ _m_PDFTextStripper__getPageEnd);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDFTextStripper__setPageEnd = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setPageEnd(jobject self_, jobject pageEndValue) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setPageEnd, "setPageEnd",
+ "(Ljava/lang/String;)V");
+ if (_m_PDFTextStripper__setPageEnd == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setPageEnd,
+ pageEndValue);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getArticleStart = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getArticleStart(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getArticleStart,
+ "getArticleStart", "()Ljava/lang/String;");
+ if (_m_PDFTextStripper__getArticleStart == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDFTextStripper__getArticleStart);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDFTextStripper__setArticleStart = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setArticleStart(jobject self_,
+ jobject articleStartValue) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setArticleStart,
+ "setArticleStart", "(Ljava/lang/String;)V");
+ if (_m_PDFTextStripper__setArticleStart == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setArticleStart,
+ articleStartValue);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getArticleEnd = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getArticleEnd(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getArticleEnd,
+ "getArticleEnd", "()Ljava/lang/String;");
+ if (_m_PDFTextStripper__getArticleEnd == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDFTextStripper__getArticleEnd);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDFTextStripper__setArticleEnd = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setArticleEnd(jobject self_,
+ jobject articleEndValue) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setArticleEnd,
+ "setArticleEnd", "(Ljava/lang/String;)V");
+ if (_m_PDFTextStripper__setArticleEnd == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__setArticleEnd,
+ articleEndValue);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__writeParagraphSeparator = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__writeParagraphSeparator(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeParagraphSeparator,
+ "writeParagraphSeparator", "()V");
+ if (_m_PDFTextStripper__writeParagraphSeparator == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDFTextStripper__writeParagraphSeparator);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__writeParagraphStart = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__writeParagraphStart(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeParagraphStart,
+ "writeParagraphStart", "()V");
+ if (_m_PDFTextStripper__writeParagraphStart == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDFTextStripper__writeParagraphStart);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__writeParagraphEnd = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__writeParagraphEnd(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writeParagraphEnd,
+ "writeParagraphEnd", "()V");
+ if (_m_PDFTextStripper__writeParagraphEnd == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDFTextStripper__writeParagraphEnd);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__writePageStart = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__writePageStart(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writePageStart,
+ "writePageStart", "()V");
+ if (_m_PDFTextStripper__writePageStart == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__writePageStart);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__writePageEnd = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__writePageEnd(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__writePageEnd,
+ "writePageEnd", "()V");
+ if (_m_PDFTextStripper__writePageEnd == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_PDFTextStripper__writePageEnd);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__setListItemPatterns = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__setListItemPatterns(jobject self_,
+ jobject patterns) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__setListItemPatterns,
+ "setListItemPatterns", "(Ljava/util/List;)V");
+ if (_m_PDFTextStripper__setListItemPatterns == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_PDFTextStripper__setListItemPatterns, patterns);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_PDFTextStripper__getListItemPatterns = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__getListItemPatterns(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_PDFTextStripper, &_m_PDFTextStripper__getListItemPatterns,
+ "getListItemPatterns", "()Ljava/util/List;");
+ if (_m_PDFTextStripper__getListItemPatterns == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_PDFTextStripper__getListItemPatterns);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_PDFTextStripper__matchPattern = NULL;
+FFI_PLUGIN_EXPORT
+JniResult PDFTextStripper__matchPattern(jobject string, jobject patterns) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_PDFTextStripper, &_m_PDFTextStripper__matchPattern, "matchPattern",
+ "(Ljava/lang/String;Ljava/util/List;)Ljava/util/regex/Pattern;");
+ if (_m_PDFTextStripper__matchPattern == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_PDFTextStripper, _m_PDFTextStripper__matchPattern, string,
+ patterns);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_PDFTextStripper__LINE_SEPARATOR = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_PDFTextStripper__LINE_SEPARATOR(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_PDFTextStripper, &_f_PDFTextStripper__LINE_SEPARATOR,
+ "LINE_SEPARATOR", "Ljava/lang/String;");
+ jobject _result = (*jniEnv)->GetObjectField(
+ jniEnv, self_, _f_PDFTextStripper__LINE_SEPARATOR);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_PDFTextStripper__charactersByArticle = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_PDFTextStripper__charactersByArticle(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_PDFTextStripper, &_f_PDFTextStripper__charactersByArticle,
+ "charactersByArticle", "Ljava/util/ArrayList;");
+ jobject _result = (*jniEnv)->GetObjectField(
+ jniEnv, self_, _f_PDFTextStripper__charactersByArticle);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_PDFTextStripper__charactersByArticle(jobject self_,
+ jobject value) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_PDFTextStripper, &_f_PDFTextStripper__charactersByArticle,
+ "charactersByArticle", "Ljava/util/ArrayList;");
+ (*jniEnv)->SetObjectField(jniEnv, self_,
+ _f_PDFTextStripper__charactersByArticle, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_PDFTextStripper__document = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_PDFTextStripper__document(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_PDFTextStripper, &_f_PDFTextStripper__document, "document",
+ "Lorg/apache/pdfbox/pdmodel/PDDocument;");
+ jobject _result =
+ (*jniEnv)->GetObjectField(jniEnv, self_, _f_PDFTextStripper__document);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_PDFTextStripper__document(jobject self_, jobject value) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_PDFTextStripper, &_f_PDFTextStripper__document, "document",
+ "Lorg/apache/pdfbox/pdmodel/PDDocument;");
+ (*jniEnv)->SetObjectField(jniEnv, self_, _f_PDFTextStripper__document, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_PDFTextStripper__output = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_PDFTextStripper__output(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_PDFTextStripper, &_f_PDFTextStripper__output, "output",
+ "Ljava/io/Writer;");
+ jobject _result =
+ (*jniEnv)->GetObjectField(jniEnv, self_, _f_PDFTextStripper__output);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_PDFTextStripper__output(jobject self_, jobject value) {
+ load_env();
+ load_class_global_ref(&_c_PDFTextStripper,
+ "org/apache/pdfbox/text/PDFTextStripper");
+ if (_c_PDFTextStripper == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_PDFTextStripper, &_f_PDFTextStripper__output, "output",
+ "Ljava/io/Writer;");
+ (*jniEnv)->SetObjectField(jniEnv, self_, _f_PDFTextStripper__output, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
diff --git a/pkgs/jnigen/example/pdfbox_plugin/windows/.gitignore b/pkgs/jnigen/example/pdfbox_plugin/windows/.gitignore
new file mode 100644
index 0000000..b3eb2be
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/windows/.gitignore
@@ -0,0 +1,17 @@
+flutter/
+
+# Visual Studio user-specific files.
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# Visual Studio build-related files.
+x64/
+x86/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
diff --git a/pkgs/jnigen/example/pdfbox_plugin/windows/CMakeLists.txt b/pkgs/jnigen/example/pdfbox_plugin/windows/CMakeLists.txt
new file mode 100644
index 0000000..3d9bd5c
--- /dev/null
+++ b/pkgs/jnigen/example/pdfbox_plugin/windows/CMakeLists.txt
@@ -0,0 +1,23 @@
+# The Flutter tooling requires that developers have a version of Visual Studio
+# installed that includes CMake 3.14 or later. 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.14)
+
+# Project-level configuration.
+set(PROJECT_NAME "pdfbox_plugin")
+project(${PROJECT_NAME} LANGUAGES CXX)
+
+# Invoke the build for native code shared with the other target platforms.
+# This can be changed to accomodate different builds.
+add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../src" "${CMAKE_CURRENT_BINARY_DIR}/shared")
+
+# 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.
+set(pdfbox_plugin_bundled_libraries
+ # Defined in ../src/CMakeLists.txt.
+ # This can be changed to accomodate different builds.
+ $<TARGET_FILE:pdfbox_plugin>
+ PARENT_SCOPE
+)
diff --git a/pkgs/jnigen/java/.gitignore b/pkgs/jnigen/java/.gitignore
new file mode 100644
index 0000000..5ccba17
--- /dev/null
+++ b/pkgs/jnigen/java/.gitignore
@@ -0,0 +1,12 @@
+target/*
+*.class
+*.jar
+
+.idea/compiler.xml
+.idea/dictionaries
+.idea/inspectionProfiles/
+.idea/jarRepositories.xml
+.idea/misc.xml
+.idea/runConfigurations.xml
+
+.classpath ## Used for experimenting with JShell REPL
diff --git a/pkgs/jnigen/java/README.md b/pkgs/jnigen/java/README.md
new file mode 100644
index 0000000..8b15049
--- /dev/null
+++ b/pkgs/jnigen/java/README.md
@@ -0,0 +1,51 @@
+## ApiSummarizer
+
+An early version of ApiSummarizer.
+
+It analyzes java source code / jars and outputs a JSON representation of the public API.
+
+It's currently used in `jnigen` to get the information of the Java API.
+
+## Build
+
+When using it via `jnigen`, the `jnigen:setup` script will take care of building the jar in appropriate location.
+
+To build the jar manually, run `mvn compile` in project root. To build the jar and run the tests as well, run `mvn test`. The jar will be created in `target/` directory.
+
+## Command line
+
+```
+usage: java -jar <JAR> [-s <SOURCE_DIR=.>] [-c <CLASSES_JAR>]
+<CLASS_OR_PACKAGE_NAMES>
+Class or package names should be fully qualified.
+
+-b,--backend <arg> backend to use for summary generation ('doclet'
+or 'asm').
+-c,--classes <arg> paths to search for compiled classes
+-D,--doctool-args <arg> Arguments to pass to the documentation tool
+-M,--use-modules use Java modules
+-m,--module-names <arg> comma separated list of module names
+-r,--recursive Include dependencies of classes
+-s,--sources <arg> paths to search for source files
+-v,--verbose Enable verbose output
+```
+
+Here class or package names are specified as fully qualified names, for example `org.apache.pdfbox.pdmodel.PDDocument` will load `org/apache/pdfbox/pdmodel/PDDocument.java`. It assumes the package naming reflects directory structure. If such mapping results in a directory, for example `android.os` is given and a directory `android/os` is found under the source path, it is considered as a package and all Java source files under that directory are loaded recursively.
+
+Note that some options are directly forwarded to the underlying tool.
+
+ApiSummarizer's current use is in `jnigen` for obtaining public API of java packages. Only the features strictly required for that purpose are focused upon.
+
+## Running tests
+
+Run `mvn surefire:test`
+
+There are not many tests at the moment. We plan to add some later.
+
+## ASM backend
+
+The main backend is based on javadoc API and generates summary based on java sources. A more experimental ASM backend also exists, and works somewhat okay-ish. It can summarize the compiled JARs. However, compiled jars without debug information do not include method parameter names. Some basic renaming is applied, i.e If type is `Object`, the parameter name will be output as `object` if an actual name is absent.
+
+## TODO
+
+See issue #23.
diff --git a/pkgs/jnigen/java/pom.xml b/pkgs/jnigen/java/pom.xml
new file mode 100644
index 0000000..226bb03
--- /dev/null
+++ b/pkgs/jnigen/java/pom.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>com.github.dart_lang.jnigen</groupId>
+ <artifactId>ApiSummarizer</artifactId>
+ <description>Summarize public APIs of java packages in JSON or protobuf.</description>
+ <version>0.0.1-SNAPSHOT</version>
+
+ <properties>
+ <maven.compiler.source>11</maven.compiler.source>
+ <maven.compiler.target>11</maven.compiler.target>
+ <jackson.version>2.14.0-rc2</jackson.version>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <buildDir>${user.dir}</buildDir>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-cli</groupId>
+ <artifactId>commons-cli</artifactId>
+ <version>1.5.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-tree</artifactId>
+ <version>9.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlinx</groupId>
+ <artifactId>kotlinx-metadata-jvm</artifactId>
+ <version>0.6.2</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.13.2</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <directory>${buildDir}/target</directory>
+ <finalName>ApiSummarizer</finalName>
+ <pluginManagement><!-- Lock down plugins versions to avoid using Maven defaults -->
+ <plugins>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <version>3.2.0</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>3.3.1</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>3.3.0</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>3.0.0-M7</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>3.5.0</version>
+ <configuration>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ <appendAssemblyId>false</appendAssemblyId>
+ <archive>
+ <manifest>
+ <mainClass>com.github.dart_lang.jnigen.apisummarizer.Main</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.10.1</version>
+ <configuration>
+ <source>11</source>
+ <target>11</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/Main.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/Main.java
new file mode 100644
index 0000000..0077fd7
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/Main.java
@@ -0,0 +1,151 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer;
+
+import com.github.dart_lang.jnigen.apisummarizer.disasm.AsmSummarizer;
+import com.github.dart_lang.jnigen.apisummarizer.doclet.SummarizerDoclet;
+import com.github.dart_lang.jnigen.apisummarizer.elements.ClassDecl;
+import com.github.dart_lang.jnigen.apisummarizer.util.ClassFinder;
+import com.github.dart_lang.jnigen.apisummarizer.util.InputStreamProvider;
+import com.github.dart_lang.jnigen.apisummarizer.util.JsonWriter;
+import com.github.dart_lang.jnigen.apisummarizer.util.StreamUtil;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import javax.tools.DocumentationTool;
+import javax.tools.JavaFileObject;
+import javax.tools.ToolProvider;
+import jdk.javadoc.doclet.Doclet;
+
+public class Main {
+ public enum Backend {
+ /** Produce API descriptions from source files using Doclet API. */
+ DOCLET,
+ /** Produce API descriptions from class files under classpath. */
+ ASM,
+ /** Prefer source but fall back to JARs in classpath if sources not found. */
+ AUTO,
+ }
+
+ static SummarizerOptions options;
+
+ public static List<ClassDecl> runDocletWithClass(
+ DocumentationTool javaDoc,
+ Class<? extends Doclet> docletClass,
+ List<JavaFileObject> fileObjects,
+ SummarizerOptions options) {
+ var fileManager = javaDoc.getStandardFileManager(null, null, null);
+ var cli = new ArrayList<String>();
+ cli.add((options.useModules ? "--module-" : "--") + "source-path=" + options.sourcePath);
+ if (options.classPath != null) {
+ cli.add("--class-path=" + options.classPath);
+ }
+ cli.addAll(List.of("-encoding", "utf8"));
+
+ if (options.toolArgs != null) {
+ cli.addAll(List.of(options.toolArgs.split(" ")));
+ }
+
+ javaDoc.getTask(null, fileManager, System.err::println, docletClass, cli, fileObjects).call();
+
+ return SummarizerDoclet.getClasses();
+ }
+
+ public static List<ClassDecl> runDoclet(
+ DocumentationTool javaDoc, List<JavaFileObject> javaFileObjects, SummarizerOptions options) {
+ return runDocletWithClass(javaDoc, SummarizerDoclet.class, javaFileObjects, options);
+ }
+
+ public static void main(String[] args) throws FileNotFoundException {
+ options = SummarizerOptions.parseArgs(args);
+ OutputStream output;
+
+ if (options.outputFile == null || options.outputFile.equals("-")) {
+ output = System.out;
+ } else {
+ output = new FileOutputStream(options.outputFile);
+ }
+ List<String> sourcePaths =
+ options.sourcePath != null
+ ? Arrays.asList(options.sourcePath.split(File.pathSeparator))
+ : List.of();
+ List<String> classPaths =
+ options.classPath != null
+ ? Arrays.asList(options.classPath.split(File.pathSeparator))
+ : List.of();
+
+ var javaDoc = ToolProvider.getSystemDocumentationTool();
+
+ var sourceClasses = new LinkedHashMap<String, List<JavaFileObject>>();
+ var binaryClasses = new LinkedHashMap<String, List<InputStreamProvider>>();
+
+ for (var qualifiedName : options.args) {
+ sourceClasses.put(qualifiedName, null);
+ binaryClasses.put(qualifiedName, null);
+ }
+
+ if (options.backend != Backend.ASM) {
+ ClassFinder.findJavaSources(
+ sourceClasses, sourcePaths, javaDoc.getStandardFileManager(null, null, null));
+ }
+
+ // remove found classes from binaryClasses, so that they don't need to be searched again.
+ // TODO: Tidy up this logic, move to ClassFinder class
+ for (var qualifiedName : options.args) {
+ if (sourceClasses.get(qualifiedName) != null) {
+ binaryClasses.remove(qualifiedName);
+ }
+ }
+
+ if (options.backend != Backend.DOCLET) {
+ ClassFinder.findJavaClasses(binaryClasses, classPaths);
+ }
+
+ // remove duplicates (found as both source & binary), and determine if any class is not found.
+ var notFound = new ArrayList<String>();
+ for (var qualifiedName : options.args) {
+ var foundSource = sourceClasses.get(qualifiedName) != null;
+ var foundBinary = binaryClasses.get(qualifiedName) != null;
+ if (foundSource) {
+ binaryClasses.remove(qualifiedName);
+ }
+ if (!foundBinary && !foundSource) {
+ notFound.add(qualifiedName);
+ }
+ }
+
+ if (!notFound.isEmpty()) {
+ System.err.println("Not found: " + notFound);
+ System.exit(1);
+ }
+
+ var classStreamProviders = StreamUtil.flattenListValues(binaryClasses);
+ var sourceFiles = StreamUtil.flattenListValues(sourceClasses);
+
+ switch (options.backend) {
+ case DOCLET:
+ JsonWriter.writeJSON(runDoclet(javaDoc, sourceFiles, options), output);
+ break;
+ case ASM:
+ JsonWriter.writeJSON(AsmSummarizer.run(classStreamProviders), output);
+ break;
+ case AUTO:
+ List<ClassDecl> decls = new ArrayList<>();
+ if (!sourceFiles.isEmpty()) {
+ decls.addAll(runDoclet(javaDoc, sourceFiles, options));
+ }
+ if (!classStreamProviders.isEmpty()) {
+ decls.addAll(AsmSummarizer.run(classStreamProviders));
+ }
+ JsonWriter.writeJSON(decls, output);
+ break;
+ }
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/SummarizerOptions.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/SummarizerOptions.java
new file mode 100644
index 0000000..8a3e545
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/SummarizerOptions.java
@@ -0,0 +1,80 @@
+package com.github.dart_lang.jnigen.apisummarizer;
+
+import java.util.Arrays;
+import org.apache.commons.cli.*;
+
+public class SummarizerOptions {
+ private static final CommandLineParser parser = new DefaultParser();
+ String sourcePath;
+ String classPath;
+ boolean useModules;
+ Main.Backend backend;
+ String modulesList;
+ String toolArgs;
+ boolean verbose;
+ String outputFile;
+ String[] args;
+
+ SummarizerOptions() {}
+
+ public static SummarizerOptions fromCommandLine(CommandLine cmd) {
+ var opts = new SummarizerOptions();
+ opts.sourcePath = cmd.getOptionValue("sources", null);
+ var backendString = cmd.getOptionValue("backend", "auto");
+ opts.backend = Main.Backend.valueOf(backendString.toUpperCase());
+ opts.classPath = cmd.getOptionValue("classes", null);
+ opts.useModules = cmd.hasOption("use-modules");
+ opts.modulesList = cmd.getOptionValue("module-names", null);
+ opts.toolArgs = cmd.getOptionValue("doctool-args", null);
+ opts.outputFile = cmd.getOptionValue("output-file", null);
+ opts.args = cmd.getArgs();
+ if (opts.args.length == 0) {
+ throw new IllegalArgumentException("Need one or more class or package names as arguments");
+ }
+ return opts;
+ }
+
+ public static SummarizerOptions parseArgs(String[] args) {
+ var options = new Options();
+ Option sources = new Option("s", "sources", true, "paths to search for source files");
+ Option classes = new Option("c", "classes", true, "paths to search for compiled classes");
+ Option backend =
+ new Option(
+ "b",
+ "backend",
+ true,
+ "backend to use for summary generation ('doclet', 'asm' or 'auto' (default)).");
+ Option useModules = new Option("M", "use-modules", false, "use Java modules");
+ Option moduleNames =
+ new Option("m", "module-names", true, "comma separated list of module names");
+ Option doctoolArgs =
+ new Option("D", "doctool-args", true, "arguments to pass to the documentation tool");
+ Option outputFile =
+ new Option("o", "output-file", true, "write JSON to file instead of stdout");
+ Option[] allOptions = {
+ sources, classes, backend, useModules, moduleNames, doctoolArgs, outputFile
+ };
+ Arrays.stream(allOptions).forEach(options::addOption);
+
+ HelpFormatter help = new HelpFormatter();
+
+ CommandLine cmd;
+
+ try {
+ cmd = parser.parse(options, args);
+ if (cmd.getArgs().length < 1) {
+ throw new ParseException("Need to specify paths to source files");
+ }
+ } catch (ParseException e) {
+ System.out.println(e.getMessage());
+ help.printHelp(
+ "java -jar <JAR> [-s <SOURCE_DIR=.>] "
+ + "[-c <CLASSES_JAR>] <CLASS_OR_PACKAGE_NAMES>\n"
+ + "Class or package names should be fully qualified.\n\n",
+ options);
+ System.exit(1);
+ throw new RuntimeException("Unreachable code");
+ }
+ return fromCommandLine(cmd);
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmAnnotatedElementVisitor.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmAnnotatedElementVisitor.java
new file mode 100644
index 0000000..0a723b3
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmAnnotatedElementVisitor.java
@@ -0,0 +1,23 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.disasm;
+
+import com.github.dart_lang.jnigen.apisummarizer.elements.JavaAnnotation;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Type;
+
+// This interface removes some repetitive code using default methods
+
+public interface AsmAnnotatedElementVisitor {
+ void addAnnotation(JavaAnnotation annotation);
+
+ default AnnotationVisitor visitAnnotationDefault(String descriptor, boolean visible) {
+ var annotation = new JavaAnnotation();
+ var aType = Type.getType(descriptor);
+ annotation.binaryName = aType.getClassName();
+ addAnnotation(annotation);
+ return new AsmAnnotationVisitor(annotation);
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmAnnotationVisitor.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmAnnotationVisitor.java
new file mode 100644
index 0000000..1323a45
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmAnnotationVisitor.java
@@ -0,0 +1,84 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.disasm;
+
+import com.github.dart_lang.jnigen.apisummarizer.elements.JavaAnnotation;
+import java.util.ArrayList;
+import java.util.List;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Type;
+
+public class AsmAnnotationVisitor extends AnnotationVisitor {
+
+ JavaAnnotation annotation;
+
+ protected AsmAnnotationVisitor(JavaAnnotation annotation) {
+ super(AsmConstants.API);
+ this.annotation = annotation;
+ }
+
+ @Override
+ public void visit(String name, Object value) {
+ annotation.properties.put(name, value);
+ }
+
+ @Override
+ public void visitEnum(String name, String descriptor, String value) {
+ annotation.properties.put(
+ name, new JavaAnnotation.EnumVal(Type.getType(descriptor).getClassName(), value));
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String name, String descriptor) {
+ var type = Type.getType(descriptor);
+ var nested = new JavaAnnotation();
+ nested.binaryName = type.getClassName();
+ annotation.properties.put(name, nested);
+ return new AsmAnnotationVisitor(nested);
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(String name) {
+ List<Object> list = new ArrayList<>();
+ annotation.properties.put(name, list);
+ return new AnnotationArrayVisitor(list);
+ }
+
+ public static class AnnotationArrayVisitor extends AnnotationVisitor {
+ List<Object> list;
+
+ protected AnnotationArrayVisitor(List<Object> list) {
+ super(AsmConstants.API);
+ this.list = list;
+ }
+
+ @Override
+ public void visit(String unused, Object value) {
+ list.add(value);
+ }
+
+ @Override
+ public void visitEnum(String unused, String descriptor, String value) {
+ var type = Type.getType(descriptor);
+ list.add(new JavaAnnotation.EnumVal(type.getClassName(), value));
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String unused, String descriptor) {
+ var type = Type.getType(descriptor);
+ var nested = new JavaAnnotation();
+ nested.binaryName = type.getClassName();
+ list.add(nested);
+ return new AsmAnnotationVisitor(nested);
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(String unused) {
+ List<Object> nested = new ArrayList<>();
+ list.add(nested);
+ return new AnnotationArrayVisitor(nested);
+ }
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmClassSignatureVisitor.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmClassSignatureVisitor.java
new file mode 100644
index 0000000..8805c7f
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmClassSignatureVisitor.java
@@ -0,0 +1,54 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.disasm;
+
+import com.github.dart_lang.jnigen.apisummarizer.elements.ClassDecl;
+import com.github.dart_lang.jnigen.apisummarizer.elements.TypeParam;
+import com.github.dart_lang.jnigen.apisummarizer.elements.TypeUsage;
+import org.objectweb.asm.signature.SignatureVisitor;
+
+public class AsmClassSignatureVisitor extends SignatureVisitor {
+ private final ClassDecl decl;
+ private int interfaceIndex = -1;
+
+ public AsmClassSignatureVisitor(ClassDecl decl) {
+ super(AsmConstants.API);
+ this.decl = decl;
+ }
+
+ @Override
+ public void visitFormalTypeParameter(String name) {
+ var typeParam = new TypeParam();
+ typeParam.name = name;
+ decl.typeParams.add(typeParam);
+ }
+
+ @Override
+ public SignatureVisitor visitClassBound() {
+ var typeUsage = new TypeUsage();
+ // ClassDecl initially has no type parameters. In visitFormalTypeParameter we add them
+ // and sequentially visitClassBound and visitInterfaceBound.
+ decl.typeParams.get(decl.typeParams.size() - 1).bounds.add(typeUsage);
+ return new AsmTypeUsageSignatureVisitor(typeUsage);
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ var typeUsage = new TypeUsage();
+ decl.typeParams.get(decl.typeParams.size() - 1).bounds.add(typeUsage);
+ return new AsmTypeUsageSignatureVisitor(typeUsage);
+ }
+
+ @Override
+ public SignatureVisitor visitSuperclass() {
+ return new AsmTypeUsageSignatureVisitor(decl.superclass);
+ }
+
+ @Override
+ public SignatureVisitor visitInterface() {
+ interfaceIndex++;
+ return new AsmTypeUsageSignatureVisitor(decl.interfaces.get(interfaceIndex));
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmClassVisitor.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmClassVisitor.java
new file mode 100644
index 0000000..d5a730b
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmClassVisitor.java
@@ -0,0 +1,180 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.disasm;
+
+import static org.objectweb.asm.Opcodes.ACC_ENUM;
+
+import com.github.dart_lang.jnigen.apisummarizer.elements.*;
+import com.github.dart_lang.jnigen.apisummarizer.util.SkipException;
+import com.github.dart_lang.jnigen.apisummarizer.util.StreamUtil;
+import java.util.*;
+import java.util.stream.Collectors;
+import org.objectweb.asm.*;
+import org.objectweb.asm.signature.SignatureReader;
+
+public class AsmClassVisitor extends ClassVisitor implements AsmAnnotatedElementVisitor {
+ private static Param param(
+ Type type, String name, @SuppressWarnings("SameParameterValue") String signature) {
+ var param = new Param();
+ param.name = name;
+ param.type = TypeUtils.typeUsage(type, signature);
+ return param;
+ }
+
+ public List<ClassDecl> getVisited() {
+ return visited;
+ }
+
+ List<ClassDecl> visited = new ArrayList<>();
+ Stack<ClassDecl> visiting = new Stack<>();
+
+ /// Actual access for the inner classes as originally defined.
+ Map<String, Integer> actualAccess = new HashMap<>();
+
+ public AsmClassVisitor() {
+ super(AsmConstants.API);
+ }
+
+ @Override
+ public void visit(
+ int version,
+ int access,
+ String name,
+ String signature,
+ String superName,
+ String[] interfaces) {
+ var current = new ClassDecl();
+ visiting.push(current);
+ current.binaryName = name.replace('/', '.');
+ current.modifiers = TypeUtils.access(actualAccess.getOrDefault(current.binaryName, access));
+ current.declKind = TypeUtils.declKind(access);
+ current.superclass = TypeUtils.typeUsage(Type.getObjectType(superName), null);
+ current.interfaces =
+ StreamUtil.map(interfaces, i -> TypeUtils.typeUsage(Type.getObjectType(i), null));
+ if (signature != null) {
+ var reader = new SignatureReader(signature);
+ reader.accept(new AsmClassSignatureVisitor(current));
+ }
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ @Override
+ public void visitInnerClass(String name, String outerName, String innerName, int access) {
+ var binaryName = name.replace('/', '.');
+ actualAccess.put(binaryName, access);
+ var alreadyVisitedInnerClass =
+ visited.stream()
+ .filter(decl -> decl.binaryName.equals(binaryName))
+ .collect(Collectors.toList());
+ // If the order of visit is outer first inner second.
+ // We still want to correct the modifiers.
+ if (!alreadyVisitedInnerClass.isEmpty()) {
+ alreadyVisitedInnerClass.get(0).modifiers = TypeUtils.access(access);
+ }
+ }
+
+ @Override
+ public FieldVisitor visitField(
+ int access, String name, String descriptor, String signature, Object value) {
+ if (name.contains("$")) {
+ return null;
+ }
+
+ var field = new Field();
+ field.name = name;
+ field.type = TypeUtils.typeUsage(Type.getType(descriptor), signature);
+ field.defaultValue = value;
+ field.modifiers = TypeUtils.access(access);
+ if ((access & ACC_ENUM) != 0) {
+ peekVisiting().values.add(name);
+ }
+ if (signature != null) {
+ var reader = new SignatureReader(signature);
+ reader.accept(new AsmTypeUsageSignatureVisitor(field.type));
+ }
+ peekVisiting().fields.add(field);
+ return new AsmFieldVisitor(field);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(
+ int access, String name, String descriptor, String signature, String[] exceptions) {
+ var method = new Method();
+ if (name.contains("$")) {
+ return null;
+ }
+ method.name = name;
+ method.descriptor = descriptor;
+ var type = Type.getType(descriptor);
+ var params = new ArrayList<Param>();
+ var paramTypes = type.getArgumentTypes();
+ var paramNames = new HashMap<String, Integer>();
+ for (var pt : paramTypes) {
+ var paramName = TypeUtils.defaultParamName(pt);
+ if (paramNames.containsKey(paramName)) {
+ var nth = paramNames.get(paramName);
+ paramNames.put(paramName, nth + 1);
+ paramName = paramName + nth;
+ } else {
+ paramNames.put(paramName, 1);
+ }
+ params.add(param(pt, paramName, null));
+ }
+ method.returnType = TypeUtils.typeUsage(type.getReturnType(), signature);
+ method.modifiers = TypeUtils.access(access);
+ method.params = params;
+ if (signature != null) {
+ var reader = new SignatureReader(signature);
+ reader.accept(new AsmMethodSignatureVisitor(method));
+ }
+ peekVisiting().methods.add(method);
+ return new AsmMethodVisitor(method);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
+ if (descriptor.equals("Lkotlin/Metadata;")) {
+ return new KotlinMetadataAnnotationVisitor(peekVisiting());
+ }
+ return super.visitAnnotation(descriptor, visible);
+ }
+
+ @Override
+ public void addAnnotation(JavaAnnotation annotation) {
+ peekVisiting().annotations.add(annotation);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault(String descriptor, boolean visible) {
+ return super.visitAnnotation(descriptor, visible);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ int typeRef, TypePath typePath, String descriptor, boolean visible) {
+ return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible);
+ }
+
+ @Override
+ public void visitEnd() {
+ visited.add(popVisiting());
+ }
+
+ private ClassDecl peekVisiting() {
+ try {
+ return visiting.peek();
+ } catch (EmptyStackException e) {
+ throw new SkipException("Error: stack was empty when visitEnd was called.");
+ }
+ }
+
+ private ClassDecl popVisiting() {
+ try {
+ return visiting.pop();
+ } catch (EmptyStackException e) {
+ throw new SkipException("Error: stack was empty when visitEnd was called.");
+ }
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmConstants.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmConstants.java
new file mode 100644
index 0000000..e3d8165
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmConstants.java
@@ -0,0 +1,11 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.disasm;
+
+import static org.objectweb.asm.Opcodes.ASM9;
+
+public class AsmConstants {
+ static final int API = ASM9;
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmFieldVisitor.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmFieldVisitor.java
new file mode 100644
index 0000000..eb72302
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmFieldVisitor.java
@@ -0,0 +1,29 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.disasm;
+
+import com.github.dart_lang.jnigen.apisummarizer.elements.Field;
+import com.github.dart_lang.jnigen.apisummarizer.elements.JavaAnnotation;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.FieldVisitor;
+
+public class AsmFieldVisitor extends FieldVisitor implements AsmAnnotatedElementVisitor {
+ Field field;
+
+ public AsmFieldVisitor(Field field) {
+ super(AsmConstants.API);
+ this.field = field;
+ }
+
+ @Override
+ public void addAnnotation(JavaAnnotation annotation) {
+ field.annotations.add(annotation);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
+ return AsmAnnotatedElementVisitor.super.visitAnnotationDefault(descriptor, visible);
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmMethodSignatureVisitor.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmMethodSignatureVisitor.java
new file mode 100644
index 0000000..5410acf
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmMethodSignatureVisitor.java
@@ -0,0 +1,71 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.disasm;
+
+import com.github.dart_lang.jnigen.apisummarizer.elements.Method;
+import com.github.dart_lang.jnigen.apisummarizer.elements.TypeParam;
+import com.github.dart_lang.jnigen.apisummarizer.elements.TypeUsage;
+import java.util.ArrayList;
+import java.util.List;
+import org.objectweb.asm.signature.SignatureVisitor;
+
+public class AsmMethodSignatureVisitor extends SignatureVisitor {
+ private final Method method;
+ private final List<TypeUsage> paramTypes = new ArrayList<>();
+
+ public AsmMethodSignatureVisitor(Method method) {
+ super(AsmConstants.API);
+ this.method = method;
+ }
+
+ @Override
+ public void visitFormalTypeParameter(String name) {
+ var typeParam = new TypeParam();
+ typeParam.name = name;
+ method.typeParams.add(typeParam);
+ }
+
+ @Override
+ public SignatureVisitor visitClassBound() {
+ var typeUsage = new TypeUsage();
+ // Method initially has no type parameters. In visitFormalTypeParameter we add them
+ // and sequentially visitClassBound and visitInterfaceBound.
+ method.typeParams.get(method.typeParams.size() - 1).bounds.add(typeUsage);
+ return new AsmTypeUsageSignatureVisitor(typeUsage);
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ var typeUsage = new TypeUsage();
+ method.typeParams.get(method.typeParams.size() - 1).bounds.add(typeUsage);
+ return new AsmTypeUsageSignatureVisitor(typeUsage);
+ }
+
+ @Override
+ public SignatureVisitor visitReturnType() {
+ // Visiting params finished.
+ //
+ // In case of non-static inner class constructor, there is an extra parent parameter
+ // at the beginning which is not accounted for by the signature. So we fill the types
+ // for the last [paramTypes.size()] params.
+ int startIndex = method.params.size() - paramTypes.size();
+ for (int i = 0; i < paramTypes.size(); ++i) {
+ method.params.get(startIndex + i).type = paramTypes.get(i);
+ }
+ return new AsmTypeUsageSignatureVisitor(method.returnType);
+ }
+
+ @Override
+ public SignatureVisitor visitParameterType() {
+ paramTypes.add(new TypeUsage());
+ return new AsmTypeUsageSignatureVisitor(paramTypes.get(paramTypes.size() - 1));
+ }
+
+ @Override
+ public SignatureVisitor visitExceptionType() {
+ // Do nothing.
+ return new AsmTypeUsageSignatureVisitor(new TypeUsage());
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmMethodVisitor.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmMethodVisitor.java
new file mode 100644
index 0000000..6d66fd6
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmMethodVisitor.java
@@ -0,0 +1,61 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.disasm;
+
+import com.github.dart_lang.jnigen.apisummarizer.elements.JavaAnnotation;
+import com.github.dart_lang.jnigen.apisummarizer.elements.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.TypePath;
+
+public class AsmMethodVisitor extends MethodVisitor implements AsmAnnotatedElementVisitor {
+ Method method;
+ List<String> paramNames = new ArrayList<>();
+
+ protected AsmMethodVisitor(Method method) {
+ super(AsmConstants.API);
+ this.method = method;
+ }
+
+ @Override
+ public void visitParameter(String name, int access) {
+ paramNames.add(name);
+ }
+
+ @Override
+ public void addAnnotation(JavaAnnotation annotation) {
+ method.annotations.add(annotation);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault(String descriptor, boolean visible) {
+ return AsmAnnotatedElementVisitor.super.visitAnnotationDefault(descriptor, visible);
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(
+ int typeRef, TypePath typePath, String descriptor, boolean visible) {
+ // TODO(#23): Collect annotation on type parameter
+ return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible);
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(
+ int parameter, String descriptor, boolean visible) {
+ // TODO(#23): collect and attach it to parameters
+ return super.visitParameterAnnotation(parameter, descriptor, visible);
+ }
+
+ @Override
+ public void visitEnd() {
+ if (paramNames.size() == method.params.size()) {
+ for (int i = 0; i < paramNames.size(); i++) {
+ method.params.get(i).name = paramNames.get(i);
+ }
+ }
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmSummarizer.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmSummarizer.java
new file mode 100644
index 0000000..485c442
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmSummarizer.java
@@ -0,0 +1,26 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.disasm;
+
+import static com.github.dart_lang.jnigen.apisummarizer.util.ExceptionUtil.wrapCheckedException;
+
+import com.github.dart_lang.jnigen.apisummarizer.elements.ClassDecl;
+import com.github.dart_lang.jnigen.apisummarizer.util.InputStreamProvider;
+import java.util.List;
+import org.objectweb.asm.ClassReader;
+
+public class AsmSummarizer {
+
+ public static List<ClassDecl> run(List<InputStreamProvider> inputProviders) {
+ var visitor = new AsmClassVisitor();
+ for (var provider : inputProviders) {
+ var inputStream = provider.getInputStream();
+ var classReader = wrapCheckedException(ClassReader::new, inputStream);
+ classReader.accept(visitor, 0);
+ provider.close();
+ }
+ return visitor.getVisited();
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmTypeUsageSignatureVisitor.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmTypeUsageSignatureVisitor.java
new file mode 100644
index 0000000..6ddda45
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/AsmTypeUsageSignatureVisitor.java
@@ -0,0 +1,100 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.disasm;
+
+import com.github.dart_lang.jnigen.apisummarizer.elements.TypeUsage;
+import java.util.ArrayList;
+import org.objectweb.asm.signature.SignatureVisitor;
+
+public class AsmTypeUsageSignatureVisitor extends SignatureVisitor {
+ private final TypeUsage typeUsage;
+
+ public AsmTypeUsageSignatureVisitor(TypeUsage typeUsage) {
+ super(AsmConstants.API);
+ this.typeUsage = typeUsage;
+ }
+
+ @Override
+ public void visitBaseType(char descriptor) {
+ typeUsage.kind = TypeUsage.Kind.PRIMITIVE;
+ var name = "";
+ switch (descriptor) {
+ case 'Z':
+ name = "boolean";
+ break;
+ case 'B':
+ name = "byte";
+ break;
+ case 'C':
+ name = "char";
+ break;
+ case 'D':
+ name = "double";
+ break;
+ case 'F':
+ name = "float";
+ break;
+ case 'I':
+ name = "int";
+ break;
+ case 'J':
+ name = "long";
+ break;
+ case 'L':
+ name = "object";
+ break;
+ case 'S':
+ name = "short";
+ break;
+ case 'V':
+ name = "void";
+ break;
+ }
+ typeUsage.shorthand = name;
+ typeUsage.type = new TypeUsage.PrimitiveType(name);
+ }
+
+ @Override
+ public SignatureVisitor visitArrayType() {
+ typeUsage.kind = TypeUsage.Kind.ARRAY;
+ typeUsage.shorthand = "java.lang.Object[]";
+ var elementType = new TypeUsage();
+ typeUsage.type = new TypeUsage.Array(elementType);
+ return new AsmTypeUsageSignatureVisitor(elementType);
+ }
+
+ @Override
+ public void visitTypeVariable(String name) {
+ typeUsage.kind = TypeUsage.Kind.TYPE_VARIABLE;
+ typeUsage.shorthand = name;
+ typeUsage.type = new TypeUsage.TypeVar(name);
+ }
+
+ @Override
+ public void visitClassType(String name) {
+ typeUsage.kind = TypeUsage.Kind.DECLARED;
+ typeUsage.shorthand = name.substring(0, name.length()).replace('/', '.');
+ var components = name.split("[/$]");
+ var simpleName = components[components.length - 1];
+ typeUsage.type = new TypeUsage.DeclaredType(typeUsage.shorthand, simpleName, new ArrayList<>());
+ }
+
+ @Override
+ public SignatureVisitor visitTypeArgument(char wildcard) {
+ // TODO(#141) support wildcards
+ // TODO(#144) support extend/super clauses
+ assert (typeUsage.type instanceof TypeUsage.DeclaredType);
+ var typeArg = new TypeUsage();
+ ((TypeUsage.DeclaredType) typeUsage.type).params.add(typeArg);
+ return new AsmTypeUsageSignatureVisitor(typeArg);
+ }
+
+ @Override
+ public void visitInnerClassType(String name) {
+ typeUsage.shorthand += "." + name;
+ ((TypeUsage.DeclaredType) typeUsage.type).binaryName += "$" + name;
+ ((TypeUsage.DeclaredType) typeUsage.type).simpleName = name;
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/KotlinMetadataAnnotationVisitor.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/KotlinMetadataAnnotationVisitor.java
new file mode 100644
index 0000000..c4aa8a1
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/KotlinMetadataAnnotationVisitor.java
@@ -0,0 +1,105 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.disasm;
+
+import com.github.dart_lang.jnigen.apisummarizer.elements.ClassDecl;
+import com.github.dart_lang.jnigen.apisummarizer.elements.KotlinClass;
+import java.util.ArrayList;
+import java.util.List;
+import kotlinx.metadata.jvm.KotlinClassHeader;
+import kotlinx.metadata.jvm.KotlinClassMetadata;
+import org.objectweb.asm.AnnotationVisitor;
+
+/**
+ * The format of Kotlin's metadata can be found here:
+ * https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-metadata/
+ */
+public class KotlinMetadataAnnotationVisitor extends AnnotationVisitor {
+ private ClassDecl decl;
+
+ private int kind;
+ private int[] metadataVersion;
+ private List<String> data1 = new ArrayList<>();
+ private List<String> data2 = new ArrayList<>();
+ private String extraString;
+ private String packageName;
+ private int extraInt;
+
+ public KotlinMetadataAnnotationVisitor(ClassDecl decl) {
+ super(AsmConstants.API);
+ this.decl = decl;
+ }
+
+ @Override
+ public void visit(String name, Object value) {
+ switch (name) {
+ case "k":
+ kind = (int) value;
+ return;
+ case "mv":
+ metadataVersion = (int[]) value;
+ return;
+ case "xs":
+ extraString = (String) value;
+ return;
+ case "pn":
+ packageName = (String) value;
+ return;
+ case "xi":
+ extraInt = (int) value;
+ }
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(String name) {
+ List<String> arr;
+ switch (name) {
+ case "d1":
+ arr = data1;
+ break;
+ case "d2":
+ arr = data2;
+ break;
+ default:
+ return super.visitArray(name);
+ }
+ return new AnnotationVisitor(AsmConstants.API) {
+ @Override
+ public void visit(String name, Object value) {
+ arr.add((String) value);
+ super.visit(name, value);
+ }
+ };
+ }
+
+ @Override
+ public void visitEnd() {
+ var header =
+ new KotlinClassHeader(
+ kind,
+ metadataVersion,
+ data1.toArray(String[]::new),
+ data2.toArray(String[]::new),
+ extraString,
+ packageName,
+ extraInt);
+ var metadata = KotlinClassMetadata.read(header);
+ if (metadata instanceof KotlinClassMetadata.Class) {
+ decl.kotlinClass =
+ KotlinClass.fromKmClass(((KotlinClassMetadata.Class) metadata).toKmClass());
+ } else if (metadata instanceof KotlinClassMetadata.FileFacade) {
+ // TODO(#301): Handle file facades.
+ } else if (metadata instanceof KotlinClassMetadata.SyntheticClass) {
+ // Ignore synthetic classes such as lambdas.
+ } else if (metadata instanceof KotlinClassMetadata.MultiFileClassFacade) {
+ // Ignore multi-file classes
+ } else if (metadata instanceof KotlinClassMetadata.MultiFileClassPart) {
+ // Ignore multi-file classes
+ } else if (metadata instanceof KotlinClassMetadata.Unknown) {
+ // Unsupported
+ }
+ super.visitEnd();
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/TypeUtils.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/TypeUtils.java
new file mode 100644
index 0000000..8f18565
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/disasm/TypeUtils.java
@@ -0,0 +1,106 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.disasm;
+
+import static org.objectweb.asm.Opcodes.*;
+import static org.objectweb.asm.Type.ARRAY;
+import static org.objectweb.asm.Type.OBJECT;
+
+import com.github.dart_lang.jnigen.apisummarizer.elements.DeclKind;
+import com.github.dart_lang.jnigen.apisummarizer.elements.TypeUsage;
+import com.github.dart_lang.jnigen.apisummarizer.util.SkipException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.objectweb.asm.Type;
+
+class TypeUtils {
+
+ public static String simpleName(Type type) {
+ var internalName = type.getInternalName();
+ if (type.getInternalName().length() == 1) {
+ return type.getClassName();
+ }
+ var components = internalName.split("[/$]");
+ if (components.length == 0) {
+ throw new SkipException("Cannot derive simple name: " + internalName);
+ }
+ return components[components.length - 1];
+ }
+
+ public static TypeUsage typeUsage(Type type, @SuppressWarnings("unused") String signature) {
+ var usage = new TypeUsage();
+ usage.shorthand = type.getClassName();
+ switch (type.getSort()) {
+ case OBJECT:
+ usage.kind = TypeUsage.Kind.DECLARED;
+ usage.type =
+ new TypeUsage.DeclaredType(
+ type.getInternalName().replace('/', '.'), TypeUtils.simpleName(type), null);
+ break;
+ case ARRAY:
+ usage.kind = TypeUsage.Kind.ARRAY;
+ usage.type = new TypeUsage.Array(TypeUtils.typeUsage(type.getElementType(), null));
+ break;
+ default:
+ usage.kind = TypeUsage.Kind.PRIMITIVE;
+ usage.type = new TypeUsage.PrimitiveType(type.getClassName());
+ }
+ // TODO(#23): generics
+ return usage;
+ }
+
+ public static Set<String> access(int access) {
+ var result = new HashSet<String>();
+ for (var ac : acc.entrySet()) {
+ if ((ac.getValue() & access) != 0) {
+ result.add(ac.getKey());
+ }
+ }
+ return result;
+ }
+
+ private static final Map<String, Integer> acc = new HashMap<>();
+
+ static {
+ acc.put("static", ACC_STATIC);
+ acc.put("private", ACC_PRIVATE);
+ acc.put("protected", ACC_PROTECTED);
+ acc.put("public", ACC_PUBLIC);
+ acc.put("abstract", ACC_ABSTRACT);
+ acc.put("final", ACC_FINAL);
+ acc.put("native", ACC_NATIVE);
+ }
+
+ static DeclKind declKind(int access) {
+ if ((access & ACC_ENUM) != 0) return DeclKind.ENUM;
+ if ((access & ACC_INTERFACE) != 0) return DeclKind.INTERFACE;
+ if ((access & ACC_ANNOTATION) != 0) return DeclKind.ANNOTATION_TYPE;
+ return DeclKind.CLASS;
+ }
+
+ static String defaultParamName(Type type) {
+ switch (type.getSort()) {
+ case ARRAY:
+ return defaultParamName(type.getElementType()) + 's';
+ case OBJECT:
+ return unCapitalize(simpleName(type));
+ case Type.METHOD:
+ throw new SkipException("unexpected method type" + type);
+ default: // Primitive type
+ var typeCh = type.getInternalName().charAt(0);
+ return String.valueOf(Character.toLowerCase(typeCh));
+ }
+ }
+
+ private static String unCapitalize(String s) {
+ var first = Character.toLowerCase(s.charAt(0));
+ if (s.length() == 1) {
+ return String.valueOf(first);
+ }
+ return first + s.substring(1);
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/doclet/AnnotationVisitor.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/doclet/AnnotationVisitor.java
new file mode 100644
index 0000000..f5343ee
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/doclet/AnnotationVisitor.java
@@ -0,0 +1,100 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.doclet;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.AnnotationValueVisitor;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+
+public class AnnotationVisitor implements AnnotationValueVisitor<Object, Void> {
+ private final ElementBuilders builders;
+ AstEnv env;
+
+ public AnnotationVisitor(ElementBuilders builders) {
+ this.builders = builders;
+ this.env = builders.env;
+ }
+
+ @Override
+ public Object visit(AnnotationValue annotationValue, Void unused) {
+ return null;
+ }
+
+ @Override
+ public Object visitBoolean(boolean b, Void unused) {
+ return b;
+ }
+
+ @Override
+ public Object visitByte(byte b, Void unused) {
+ return b;
+ }
+
+ @Override
+ public Object visitChar(char c, Void unused) {
+ return c;
+ }
+
+ @Override
+ public Object visitDouble(double v, Void unused) {
+ return v;
+ }
+
+ @Override
+ public Object visitFloat(float v, Void unused) {
+ return v;
+ }
+
+ @Override
+ public Object visitInt(int i, Void unused) {
+ return i;
+ }
+
+ @Override
+ public Object visitLong(long l, Void unused) {
+ return l;
+ }
+
+ @Override
+ public Object visitShort(short i, Void unused) {
+ return i;
+ }
+
+ @Override
+ public Object visitString(String s, Void unused) {
+ return s;
+ }
+
+ @Override
+ public Object visitType(TypeMirror typeMirror, Void unused) {
+ return builders.typeUsage(typeMirror);
+ }
+
+ @Override
+ public Object visitEnumConstant(VariableElement variableElement, Void unused) {
+ // TODO(#23): Perhaps simple name is not enough. We need to return qualified
+ // name + enum constant name for completeness.
+ return variableElement.getSimpleName();
+ }
+
+ @Override
+ public Object visitAnnotation(AnnotationMirror mirror, Void unused) {
+ return builders.annotation(mirror);
+ }
+
+ @Override
+ public Object visitArray(List<? extends AnnotationValue> list, Void unused) {
+ return list.stream().map(x -> x.accept(this, null)).collect(Collectors.toList());
+ }
+
+ @Override
+ public Object visitUnknown(AnnotationValue annotationValue, Void unused) {
+ return null;
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/doclet/AstEnv.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/doclet/AstEnv.java
new file mode 100644
index 0000000..71e31c4
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/doclet/AstEnv.java
@@ -0,0 +1,27 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.doclet;
+
+import com.sun.source.util.DocTrees;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+import jdk.javadoc.doclet.DocletEnvironment;
+
+/** Class to hold utility classes initialized from DocletEnvironment. */
+public class AstEnv {
+ public final Types types;
+ public final Elements elements;
+ public final DocTrees trees;
+
+ public AstEnv(Types types, Elements elements, DocTrees trees) {
+ this.types = types;
+ this.elements = elements;
+ this.trees = trees;
+ }
+
+ public static AstEnv fromEnvironment(DocletEnvironment env) {
+ return new AstEnv(env.getTypeUtils(), env.getElementUtils(), env.getDocTrees());
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/doclet/ElementBuilders.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/doclet/ElementBuilders.java
new file mode 100644
index 0000000..675da7b
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/doclet/ElementBuilders.java
@@ -0,0 +1,204 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.doclet;
+
+import com.github.dart_lang.jnigen.apisummarizer.elements.*;
+import com.github.dart_lang.jnigen.apisummarizer.util.StreamUtil;
+import com.sun.source.doctree.DocCommentTree;
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+
+public class ElementBuilders {
+ AstEnv env;
+
+ public ElementBuilders(AstEnv env) {
+ this.env = env;
+ }
+
+ private void fillInFromTypeElement(TypeElement e, ClassDecl c) {
+ c.modifiers = e.getModifiers().stream().map(Modifier::toString).collect(Collectors.toSet());
+ c.binaryName = env.elements.getBinaryName(e).toString();
+ switch (e.getKind()) {
+ case INTERFACE:
+ c.declKind = DeclKind.INTERFACE;
+ break;
+ case CLASS:
+ c.declKind = DeclKind.CLASS;
+ break;
+ case ENUM:
+ c.declKind = DeclKind.ENUM;
+ break;
+ case ANNOTATION_TYPE:
+ c.declKind = DeclKind.ANNOTATION_TYPE;
+ break;
+ default:
+ throw new RuntimeException(
+ "Unexpected element kind " + e.getKind() + " on " + c.binaryName);
+ }
+ c.javadoc = docComment(env.trees.getDocCommentTree(e));
+ c.typeParams = StreamUtil.map(e.getTypeParameters(), this::typeParam);
+ var superclass = e.getSuperclass();
+ if (superclass instanceof DeclaredType) {
+ c.superclass = typeUsage(superclass);
+ }
+ c.annotations = StreamUtil.map(e.getAnnotationMirrors(), this::annotation);
+ c.interfaces = StreamUtil.map(e.getInterfaces(), this::typeUsage);
+ }
+
+ public ClassDecl classDecl(TypeElement e) {
+ var c = new ClassDecl();
+ fillInFromTypeElement(e, c);
+ return c;
+ }
+
+ public Field field(VariableElement e) {
+ assert e.getKind() == ElementKind.FIELD;
+ var field = new Field();
+ field.name = e.getSimpleName().toString();
+ field.modifiers = e.getModifiers().stream().map(Modifier::toString).collect(Collectors.toSet());
+ field.defaultValue = e.getConstantValue();
+ if (field.defaultValue instanceof Character) {
+ field.defaultValue = (int) (Character) field.defaultValue;
+ }
+ field.type = typeUsage(e.asType());
+ field.javadoc = docComment(env.trees.getDocCommentTree(e));
+ field.annotations = annotations(e.getAnnotationMirrors());
+ return field;
+ }
+
+ public List<JavaAnnotation> annotations(List<? extends AnnotationMirror> mirrors) {
+ return mirrors.stream().map(this::annotation).collect(Collectors.toList());
+ }
+
+ public JavaAnnotation annotation(AnnotationMirror mirror) {
+ var annotation = new JavaAnnotation();
+ var type = mirror.getAnnotationType();
+ var typeElement = (TypeElement) (env.types.asElement(type));
+ annotation.binaryName = env.elements.getBinaryName(typeElement).toString();
+ var values = env.elements.getElementValuesWithDefaults(mirror);
+ if (values.isEmpty()) {
+ return annotation;
+ }
+
+ // This is not perfect, but some metadata is better than none.
+ annotation.properties = new HashMap<>();
+ for (var key : values.keySet()) {
+ var val = values.get(key);
+ var obj = val.getValue();
+ // TODO(#23): Accurately represent more complex annotation values
+ if (obj instanceof Number) {
+ annotation.properties.put(key.getSimpleName().toString(), obj);
+ } else {
+ annotation.properties.put(key.getSimpleName().toString(), obj.toString());
+ }
+ }
+ return annotation;
+ }
+
+ public JavaDocComment docComment(DocCommentTree tree) {
+ if (tree == null) {
+ return null;
+ }
+ return new JavaDocComment(tree.toString());
+ }
+
+ public TypeParam typeParam(TypeParameterElement tpe) {
+ var tp = new TypeParam();
+ tp.name = tpe.getSimpleName().toString();
+ tp.bounds = tpe.getBounds().stream().map(this::typeUsage).collect(Collectors.toList());
+ return tp;
+ }
+
+ public Param param(VariableElement e) {
+ var param = new Param();
+ param.javadoc = docComment(env.trees.getDocCommentTree(e));
+ param.name = e.getSimpleName().toString();
+ param.type = typeUsage(e.asType());
+ param.annotations = annotations(e.getAnnotationMirrors());
+ return param;
+ }
+
+ public TypeUsage typeUsage(TypeMirror type) {
+ var u = new TypeUsage();
+ u.shorthand = type.toString();
+ var element = env.types.asElement(type);
+ switch (type.getKind()) {
+ case DECLARED:
+ // Unique name that's binary name not qualified name
+ // (It's somewhat confusing but qualified name does not need to be unique,
+ // because of nesting)
+ u.kind = TypeUsage.Kind.DECLARED;
+ var name =
+ element instanceof TypeElement
+ ? env.elements.getBinaryName((TypeElement) element).toString()
+ : element.getSimpleName().toString();
+ List<TypeUsage> params = null;
+ if (type instanceof DeclaredType) { // it will be
+ params =
+ ((DeclaredType) type)
+ .getTypeArguments().stream().map(this::typeUsage).collect(Collectors.toList());
+ }
+ u.type = new TypeUsage.DeclaredType(name, element.getSimpleName().toString(), params);
+ break;
+ case TYPEVAR:
+ u.kind = TypeUsage.Kind.TYPE_VARIABLE;
+ // TODO(#23): Encode bounds of type variable.
+ // A straightforward approach will cause infinite recursion very
+ // easily. Another approach I can think of is only encoding the
+ // erasure of the type variable per JLS.
+ u.type = new TypeUsage.TypeVar(element.getSimpleName().toString());
+ break;
+ case ARRAY:
+ u.kind = TypeUsage.Kind.ARRAY;
+ var arr = ((ArrayType) type);
+ u.type = new TypeUsage.Array(typeUsage(arr.getComponentType()));
+ break;
+ case VOID:
+ u.type = new TypeUsage.PrimitiveType("void");
+ u.kind = TypeUsage.Kind.PRIMITIVE;
+ break;
+ case WILDCARD:
+ u.kind = TypeUsage.Kind.WILDCARD;
+ var wildcard = ((WildcardType) type);
+ var extendsBound = wildcard.getExtendsBound();
+ var superBound = wildcard.getSuperBound();
+ u.type =
+ new TypeUsage.Wildcard(
+ extendsBound != null ? typeUsage(extendsBound) : null,
+ superBound != null ? typeUsage(superBound) : null);
+ break;
+ case INTERSECTION:
+ u.kind = TypeUsage.Kind.INTERSECTION;
+ u.type =
+ new TypeUsage.Intersection(
+ ((IntersectionType) type)
+ .getBounds().stream().map(this::typeUsage).collect(Collectors.toList()));
+ break;
+ default:
+ u.kind = TypeUsage.Kind.PRIMITIVE;
+ if (type instanceof PrimitiveType) {
+ u.type = new TypeUsage.PrimitiveType(type.toString());
+ } else {
+ System.out.println("Unsupported type: " + type);
+ // throw exception.
+ }
+ }
+ return u;
+ }
+
+ public Method method(ExecutableElement e) {
+ var m = new Method();
+ m.name = e.getSimpleName().toString();
+ m.modifiers = e.getModifiers().stream().map(Modifier::toString).collect(Collectors.toSet());
+ m.typeParams = e.getTypeParameters().stream().map(this::typeParam).collect(Collectors.toList());
+ m.returnType = typeUsage(e.getReturnType());
+ m.javadoc = docComment(env.trees.getDocCommentTree(e));
+ m.annotations = annotations(e.getAnnotationMirrors());
+ return m;
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/doclet/SummarizerDoclet.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/doclet/SummarizerDoclet.java
new file mode 100644
index 0000000..abbc7cc
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/doclet/SummarizerDoclet.java
@@ -0,0 +1,165 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.doclet;
+
+import com.github.dart_lang.jnigen.apisummarizer.elements.ClassDecl;
+import com.github.dart_lang.jnigen.apisummarizer.elements.Method;
+import com.github.dart_lang.jnigen.apisummarizer.elements.Package;
+import com.github.dart_lang.jnigen.apisummarizer.util.Log;
+import com.github.dart_lang.jnigen.apisummarizer.util.SkipException;
+import java.util.*;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.*;
+import javax.lang.model.util.ElementScanner9;
+import jdk.javadoc.doclet.Doclet;
+import jdk.javadoc.doclet.DocletEnvironment;
+import jdk.javadoc.doclet.Reporter;
+
+public class SummarizerDoclet implements Doclet {
+ private AstEnv utils;
+
+ @Override
+ public void init(Locale locale, Reporter reporter) {}
+
+ @Override
+ public String getName() {
+ return "ApiSummarizer";
+ }
+
+ @Override
+ public Set<? extends Option> getSupportedOptions() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.RELEASE_11;
+ }
+
+ public static List<ClassDecl> getClasses() {
+ return classes;
+ }
+
+ public static List<ClassDecl> classes;
+
+ @Override
+ public boolean run(DocletEnvironment docletEnvironment) {
+ Log.info("Initializing doclet");
+ utils = AstEnv.fromEnvironment(docletEnvironment);
+ SummarizingScanner scanner = new SummarizingScanner();
+ docletEnvironment.getSpecifiedElements().forEach(e -> scanner.scan(e, new SummaryCollector()));
+ classes = scanner.types;
+ return true;
+ }
+
+ public static class SummaryCollector {
+ Stack<Package> packages = new Stack<>();
+ Stack<ClassDecl> types = new Stack<>();
+ Method method;
+ }
+
+ public class SummarizingScanner extends ElementScanner9<Void, SummaryCollector> {
+ List<Package> packages = new ArrayList<>();
+ List<ClassDecl> types = new ArrayList<>();
+ ElementBuilders builders = new ElementBuilders(utils);
+
+ // Each element in collector is a stack
+ // which is used to get topmost element
+ // and append the child to it.
+ // Eg: A variable element is always appended to topmost
+ // class
+ @Override
+ public Void scan(Element e, SummaryCollector collector) {
+ return super.scan(e, collector);
+ }
+
+ @Override
+ public Void visitPackage(PackageElement e, SummaryCollector collector) {
+ Log.info("Visiting package: %s", e.getQualifiedName());
+ collector.packages.push(new Package());
+ System.out.println("package: " + e.getQualifiedName());
+ var result = super.visitPackage(e, collector);
+ var collectedPackage = collector.packages.pop();
+ packages.add(collectedPackage);
+ return result;
+ }
+
+ @Override
+ public Void visitType(TypeElement e, SummaryCollector collector) {
+ if (!collector.types.isEmpty()) {
+ return null;
+ }
+ Log.info("Visiting class: %s, %s", e.getQualifiedName(), collector.types);
+ switch (e.getKind()) {
+ case CLASS:
+ case INTERFACE:
+ case ENUM:
+ try {
+ var cls = builders.classDecl(e);
+ collector.types.push(cls);
+ super.visitType(e, collector);
+ types.add(collector.types.pop());
+ } catch (SkipException skip) {
+ Log.info("Skip type: %s", e.getQualifiedName());
+ }
+ break;
+ case ANNOTATION_TYPE:
+ Log.info("Skip annotation type: %s", e.getQualifiedName());
+ break;
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitVariable(VariableElement e, SummaryCollector collector) {
+ var vk = e.getKind();
+ var cls = collector.types.peek();
+ switch (vk) {
+ case ENUM_CONSTANT:
+ cls.values.add(e.getSimpleName().toString());
+ break;
+ case FIELD:
+ cls.fields.add(builders.field(e));
+ break;
+ case PARAMETER:
+ if (collector.method == null) {
+ throw new RuntimeException("Parameter encountered outside executable element");
+ }
+ var method = collector.method;
+ method.params.add(builders.param(e));
+ break;
+ default:
+ System.out.println("Unknown type of variable element: " + vk);
+ }
+ return null;
+ }
+
+ @Override
+ public Void visitExecutable(ExecutableElement element, SummaryCollector collector) {
+ var cls = collector.types.peek();
+ switch (element.getKind()) {
+ case METHOD:
+ case CONSTRUCTOR:
+ try {
+ var method = builders.method(element);
+ collector.method = method;
+ super.visitExecutable(element, collector);
+ collector.method = null;
+ cls.methods.add(method);
+ } catch (SkipException skip) {
+ Log.info("Skip method: %s", element.getSimpleName());
+ }
+ break;
+ case STATIC_INIT:
+ cls.hasStaticInit = true;
+ break;
+ case INSTANCE_INIT:
+ cls.hasInstanceInit = true;
+ break;
+ }
+ return null;
+ }
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/ClassDecl.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/ClassDecl.java
new file mode 100644
index 0000000..746b913
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/ClassDecl.java
@@ -0,0 +1,43 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A class or interface declaration.
+ *
+ * <p>Here's an example for various kinds of names stored in this structure: { simpleName :
+ * "Example", binaryName : "dev.dart.sample.Example", parentName : null, packageName :
+ * "dev.dart.sample", }
+ */
+public class ClassDecl {
+ public DeclKind declKind;
+
+ /** Modifiers eg: static, public and abstract. */
+ public Set<String> modifiers;
+
+ /**
+ * Unique, fully qualified name of the class, it's like a qualified name used in a program but
+ * uses $ instead of dot (.) before nested classes.
+ */
+ public String binaryName;
+
+ public List<TypeParam> typeParams = new ArrayList<>();
+ public List<Method> methods = new ArrayList<>();
+ public List<Field> fields = new ArrayList<>();
+ public TypeUsage superclass;
+ public List<TypeUsage> interfaces = new ArrayList<>();
+ public boolean hasStaticInit;
+ public boolean hasInstanceInit;
+ public JavaDocComment javadoc;
+ public List<JavaAnnotation> annotations;
+ public KotlinClass kotlinClass;
+
+ /** In case of enum, names of enum constants */
+ public List<String> values = new ArrayList<>();
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/DeclKind.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/DeclKind.java
new file mode 100644
index 0000000..e2e533e
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/DeclKind.java
@@ -0,0 +1,12 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+public enum DeclKind {
+ CLASS,
+ ENUM,
+ INTERFACE,
+ ANNOTATION_TYPE
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Field.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Field.java
new file mode 100644
index 0000000..ced5cea
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Field.java
@@ -0,0 +1,20 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class Field {
+ public Set<String> modifiers = new HashSet<>();
+ public String name;
+ public TypeUsage type;
+ public Object defaultValue;
+
+ public JavaDocComment javadoc;
+ public List<JavaAnnotation> annotations = new ArrayList<>();
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/JavaAnnotation.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/JavaAnnotation.java
new file mode 100644
index 0000000..c463cba
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/JavaAnnotation.java
@@ -0,0 +1,23 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class JavaAnnotation {
+ public String binaryName;
+ public Map<String, Object> properties = new HashMap<>();
+
+ public static class EnumVal {
+ public String enumClass;
+ public String value;
+
+ public EnumVal(String enumClass, String value) {
+ this.enumClass = enumClass;
+ this.value = value;
+ }
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/JavaDocComment.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/JavaDocComment.java
new file mode 100644
index 0000000..c882c97
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/JavaDocComment.java
@@ -0,0 +1,15 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+public class JavaDocComment {
+ // TODO(#28): Build a detailed tree representation of JavaDocComment
+ // which can be processed by tools in other languages as well.
+ public String comment;
+
+ public JavaDocComment(String comment) {
+ this.comment = comment;
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinClass.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinClass.java
new file mode 100644
index 0000000..22906f7
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinClass.java
@@ -0,0 +1,62 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import kotlinx.metadata.KmClass;
+import kotlinx.metadata.jvm.JvmExtensionsKt;
+
+public class KotlinClass {
+ public String name;
+ public String moduleName;
+ public List<KotlinFunction> functions;
+ public List<KotlinProperty> properties;
+ public List<KotlinConstructor> constructors;
+ public List<KotlinTypeParameter> typeParameters;
+ public List<KotlinType> contextReceiverTypes;
+ public List<KotlinType> superTypes;
+ public List<String> nestedClasses;
+ public List<String> enumEntries;
+ public List<String> sealedClasses;
+ public String companionObject;
+ public String inlineClassUnderlyingPropertyName;
+ public KotlinType inlineClassUnderlyingType;
+ public int flags;
+ public int jvmFlags;
+
+ public static KotlinClass fromKmClass(KmClass c) {
+ var klass = new KotlinClass();
+ klass.name = c.getName();
+ klass.moduleName = JvmExtensionsKt.getModuleName(c);
+ klass.functions =
+ c.getFunctions().stream().map(KotlinFunction::fromKmFunction).collect(Collectors.toList());
+ klass.properties =
+ c.getProperties().stream().map(KotlinProperty::fromKmProperty).collect(Collectors.toList());
+ klass.constructors =
+ c.getConstructors().stream()
+ .map(KotlinConstructor::fromKmConstructor)
+ .collect(Collectors.toList());
+ klass.typeParameters =
+ c.getTypeParameters().stream()
+ .map(KotlinTypeParameter::fromKmTypeParameter)
+ .collect(Collectors.toList());
+ klass.contextReceiverTypes =
+ c.getContextReceiverTypes().stream()
+ .map(KotlinType::fromKmType)
+ .collect(Collectors.toList());
+ klass.superTypes =
+ c.getSupertypes().stream().map(KotlinType::fromKmType).collect(Collectors.toList());
+ klass.enumEntries = c.getEnumEntries();
+ klass.flags = c.getFlags();
+ klass.jvmFlags = JvmExtensionsKt.getJvmFlags(c);
+ klass.nestedClasses = c.getNestedClasses();
+ klass.companionObject = c.getCompanionObject();
+ klass.inlineClassUnderlyingPropertyName = c.getInlineClassUnderlyingPropertyName();
+ klass.inlineClassUnderlyingType = KotlinType.fromKmType(c.getInlineClassUnderlyingType());
+ klass.sealedClasses = c.getSealedSubclasses();
+ return klass;
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinConstructor.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinConstructor.java
new file mode 100644
index 0000000..dae3a2f
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinConstructor.java
@@ -0,0 +1,30 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import kotlinx.metadata.KmConstructor;
+import kotlinx.metadata.jvm.JvmExtensionsKt;
+
+public class KotlinConstructor {
+ public String name;
+ public String descriptor;
+ public List<KotlinValueParameter> valueParameters;
+ public int flags;
+
+ public static KotlinConstructor fromKmConstructor(KmConstructor c) {
+ var ctor = new KotlinConstructor();
+ ctor.flags = c.getFlags();
+ var signature = JvmExtensionsKt.getSignature(c);
+ ctor.name = signature == null ? null : signature.getName();
+ ctor.descriptor = signature == null ? null : signature.getDesc();
+ ctor.valueParameters =
+ c.getValueParameters().stream()
+ .map(KotlinValueParameter::fromKmValueParameter)
+ .collect(Collectors.toList());
+ return ctor;
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinFunction.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinFunction.java
new file mode 100644
index 0000000..87cdc7b
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinFunction.java
@@ -0,0 +1,55 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import kotlinx.metadata.Flag;
+import kotlinx.metadata.KmFunction;
+import kotlinx.metadata.jvm.JvmExtensionsKt;
+
+public class KotlinFunction {
+ /** Name in the byte code. */
+ public String name;
+
+ public String descriptor;
+
+ /** Name in the Kotlin's metadata. */
+ public String kotlinName;
+
+ public List<KotlinValueParameter> valueParameters;
+ public KotlinType returnType;
+ public KotlinType receiverParameterType;
+ public List<KotlinType> contextReceiverTypes;
+ public List<KotlinTypeParameter> typeParameters;
+ public int flags;
+ public boolean isSuspend;
+
+ public static KotlinFunction fromKmFunction(KmFunction f) {
+ var fun = new KotlinFunction();
+ var signature = JvmExtensionsKt.getSignature(f);
+ fun.descriptor = signature == null ? null : signature.getDesc();
+ fun.name = signature == null ? null : signature.getName();
+ fun.kotlinName = f.getName();
+ fun.flags = f.getFlags();
+ // Processing the information needed from the flags.
+ fun.isSuspend = Flag.Function.IS_SUSPEND.invoke(fun.flags);
+ fun.valueParameters =
+ f.getValueParameters().stream()
+ .map(KotlinValueParameter::fromKmValueParameter)
+ .collect(Collectors.toList());
+ fun.returnType = KotlinType.fromKmType(f.getReturnType());
+ fun.receiverParameterType = KotlinType.fromKmType(f.getReceiverParameterType());
+ fun.contextReceiverTypes =
+ f.getContextReceiverTypes().stream()
+ .map(KotlinType::fromKmType)
+ .collect(Collectors.toList());
+ fun.typeParameters =
+ f.getTypeParameters().stream()
+ .map(KotlinTypeParameter::fromKmTypeParameter)
+ .collect(Collectors.toList());
+ return fun;
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinProperty.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinProperty.java
new file mode 100644
index 0000000..2858be4
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinProperty.java
@@ -0,0 +1,68 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import kotlinx.metadata.KmProperty;
+import kotlinx.metadata.jvm.JvmExtensionsKt;
+
+public class KotlinProperty {
+ public String fieldName;
+ public String fieldDescriptor;
+
+ /** Getter's name in the byte code. */
+ public String getterName;
+
+ public String getterDescriptor;
+
+ /** Setter's name in the byte code. */
+ public String setterName;
+
+ public String setterDescriptor;
+
+ /** Name in the Kotlin's metadata. */
+ public String kotlinName;
+
+ public KotlinType returnType;
+ public KotlinType receiverParameterType;
+ public List<KotlinType> contextReceiverTypes;
+ public int jvmFlags;
+ public int flags;
+ public int setterFlags;
+ public int getterFlags;
+ public List<KotlinTypeParameter> typeParameters;
+ public KotlinValueParameter setterParameter;
+
+ public static KotlinProperty fromKmProperty(KmProperty p) {
+ var prop = new KotlinProperty();
+ var fieldSignature = JvmExtensionsKt.getFieldSignature(p);
+ prop.fieldDescriptor = fieldSignature == null ? null : fieldSignature.getDesc();
+ prop.fieldName = fieldSignature == null ? null : fieldSignature.getName();
+ var getterSignature = JvmExtensionsKt.getGetterSignature(p);
+ prop.getterDescriptor = getterSignature == null ? null : getterSignature.getDesc();
+ prop.getterName = getterSignature == null ? null : getterSignature.getName();
+ var setterSignature = JvmExtensionsKt.getSetterSignature(p);
+ prop.setterDescriptor = setterSignature == null ? null : setterSignature.getDesc();
+ prop.setterName = setterSignature == null ? null : setterSignature.getName();
+ prop.kotlinName = p.getName();
+ prop.returnType = KotlinType.fromKmType(p.getReturnType());
+ prop.receiverParameterType = KotlinType.fromKmType(p.getReceiverParameterType());
+ prop.contextReceiverTypes =
+ p.getContextReceiverTypes().stream()
+ .map(KotlinType::fromKmType)
+ .collect(Collectors.toList());
+ prop.jvmFlags = JvmExtensionsKt.getJvmFlags(p);
+ prop.flags = p.getFlags();
+ prop.setterFlags = p.getSetterFlags();
+ prop.getterFlags = p.getGetterFlags();
+ prop.typeParameters =
+ p.getTypeParameters().stream()
+ .map(KotlinTypeParameter::fromKmTypeParameter)
+ .collect(Collectors.toList());
+ prop.setterParameter = KotlinValueParameter.fromKmValueParameter(p.getSetterParameter());
+ return prop;
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinType.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinType.java
new file mode 100644
index 0000000..8e91122
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinType.java
@@ -0,0 +1,40 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import kotlinx.metadata.KmClassifier;
+import kotlinx.metadata.KmType;
+
+public class KotlinType {
+ public int flags;
+ public String kind;
+ public String name;
+ public int id;
+ public List<KotlinTypeProjection> arguments;
+
+ public static KotlinType fromKmType(KmType t) {
+ if (t == null) return null;
+ var type = new KotlinType();
+ type.flags = t.getFlags();
+ var classifier = t.getClassifier();
+ if (classifier instanceof KmClassifier.Class) {
+ type.kind = "class";
+ type.name = ((KmClassifier.Class) classifier).getName();
+ } else if (classifier instanceof KmClassifier.TypeAlias) {
+ type.kind = "typeAlias";
+ type.name = ((KmClassifier.TypeAlias) classifier).getName();
+ } else if (classifier instanceof KmClassifier.TypeParameter) {
+ type.kind = "typeParameter";
+ type.id = ((KmClassifier.TypeParameter) classifier).getId();
+ }
+ type.arguments =
+ t.getArguments().stream()
+ .map(KotlinTypeProjection::fromKmTypeProjection)
+ .collect(Collectors.toList());
+ return type;
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinTypeParameter.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinTypeParameter.java
new file mode 100644
index 0000000..449aef1
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinTypeParameter.java
@@ -0,0 +1,29 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import kotlinx.metadata.KmTypeParameter;
+import kotlinx.metadata.KmVariance;
+
+public class KotlinTypeParameter {
+ public String name;
+ public int id;
+ public int flags;
+ public List<KotlinType> upperBounds;
+ public KmVariance variance;
+
+ public static KotlinTypeParameter fromKmTypeParameter(KmTypeParameter t) {
+ var typeParam = new KotlinTypeParameter();
+ typeParam.name = t.getName();
+ typeParam.id = t.getId();
+ typeParam.flags = t.getFlags();
+ typeParam.upperBounds =
+ t.getUpperBounds().stream().map(KotlinType::fromKmType).collect(Collectors.toList());
+ typeParam.variance = t.getVariance();
+ return typeParam;
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinTypeProjection.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinTypeProjection.java
new file mode 100644
index 0000000..364634c
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinTypeProjection.java
@@ -0,0 +1,20 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+import kotlinx.metadata.KmTypeProjection;
+import kotlinx.metadata.KmVariance;
+
+public class KotlinTypeProjection {
+ public KotlinType type;
+ public KmVariance variance;
+
+ public static KotlinTypeProjection fromKmTypeProjection(KmTypeProjection t) {
+ var proj = new KotlinTypeProjection();
+ proj.type = KotlinType.fromKmType(t.getType());
+ proj.variance = t.getVariance();
+ return proj;
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinValueParameter.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinValueParameter.java
new file mode 100644
index 0000000..1fba28d
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/KotlinValueParameter.java
@@ -0,0 +1,24 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+import kotlinx.metadata.KmValueParameter;
+
+public class KotlinValueParameter {
+ public String name;
+ public int flags;
+ public KotlinType type;
+ public KotlinType varargElementType;
+
+ public static KotlinValueParameter fromKmValueParameter(KmValueParameter p) {
+ if (p == null) return null;
+ var param = new KotlinValueParameter();
+ param.name = p.getName();
+ param.flags = p.getFlags();
+ param.type = KotlinType.fromKmType(p.getType());
+ param.varargElementType = KotlinType.fromKmType(p.getVarargElementType());
+ return param;
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Method.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Method.java
new file mode 100644
index 0000000..33bb0fb
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Method.java
@@ -0,0 +1,22 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class Method {
+ public Set<String> modifiers = new HashSet<>();
+ public String name;
+ public String descriptor;
+ public List<TypeParam> typeParams = new ArrayList<>();
+ public List<Param> params = new ArrayList<>();
+ public TypeUsage returnType;
+
+ public JavaDocComment javadoc;
+ public List<JavaAnnotation> annotations = new ArrayList<>();
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Package.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Package.java
new file mode 100644
index 0000000..ca2bfce
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Package.java
@@ -0,0 +1,9 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+public class Package {
+ public String name;
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Param.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Param.java
new file mode 100644
index 0000000..433f6bf
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/Param.java
@@ -0,0 +1,16 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Param {
+ public String name;
+ public TypeUsage type;
+
+ public JavaDocComment javadoc;
+ public List<JavaAnnotation> annotations = new ArrayList<>();
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/TypeParam.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/TypeParam.java
new file mode 100644
index 0000000..8172ee6
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/TypeParam.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TypeParam {
+ public String name;
+ public List<TypeUsage> bounds = new ArrayList<>();
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/TypeUsage.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/TypeUsage.java
new file mode 100644
index 0000000..a60407c
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/elements/TypeUsage.java
@@ -0,0 +1,87 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.elements;
+
+import java.util.List;
+
+public class TypeUsage {
+ public TypeUsage(String shorthand, Kind kind, ReferredType type) {
+ this.shorthand = shorthand;
+ this.kind = kind;
+ this.type = type;
+ }
+
+ public TypeUsage() {}
+
+ public enum Kind {
+ DECLARED,
+ TYPE_VARIABLE,
+ WILDCARD,
+ ARRAY,
+ INTERSECTION,
+ PRIMITIVE,
+ }
+
+ // Could've made it just a type hierarchy, but client code parsing JSON
+ // needs to know the type beforehand, before it can deserialize the `type` field.
+ public String shorthand;
+ public Kind kind;
+ public ReferredType type;
+
+ public abstract static class ReferredType {}
+
+ public static class PrimitiveType extends ReferredType {
+ public String name;
+
+ public PrimitiveType(String name) {
+ this.name = name;
+ }
+ }
+
+ public static class DeclaredType extends ReferredType {
+ public String binaryName;
+ public String simpleName;
+ public List<TypeUsage> params;
+
+ public DeclaredType(String binaryName, String simpleName, List<TypeUsage> params) {
+ this.binaryName = binaryName;
+ this.simpleName = simpleName;
+ this.params = params;
+ }
+ }
+
+ public static class TypeVar extends ReferredType {
+ public String name;
+
+ public TypeVar(String name) {
+ this.name = name;
+ }
+ }
+
+ public static class Wildcard extends ReferredType {
+ public TypeUsage extendsBound, superBound;
+
+ public Wildcard(TypeUsage extendsBound, TypeUsage superBound) {
+ this.extendsBound = extendsBound;
+ this.superBound = superBound;
+ }
+ }
+
+ public static class Intersection extends ReferredType {
+ public List<TypeUsage> types;
+
+ public Intersection(List<TypeUsage> types) {
+ this.types = types;
+ }
+ }
+
+ public static class Array extends ReferredType {
+ public TypeUsage type;
+
+ public Array(TypeUsage type) {
+ this.type = type;
+ }
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/ClassFinder.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/ClassFinder.java
new file mode 100644
index 0000000..23c1ca5
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/ClassFinder.java
@@ -0,0 +1,199 @@
+package com.github.dart_lang.jnigen.apisummarizer.util;
+
+import static com.github.dart_lang.jnigen.apisummarizer.util.ExceptionUtil.wrapCheckedException;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.*;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+
+public class ClassFinder {
+ // If class is A$B$C, simpleName can be B$C or A$B$C. Doesn't matter much, because
+ // A can't be anonymous class.
+ private static boolean isNonAnonymousNestedClassName(String simpleName) {
+ String[] nestedParts = simpleName.split("\\$");
+ return Arrays.stream(nestedParts).allMatch(part -> part.matches("[a-zA-Z_][a-zA-Z0-9_]*"));
+ }
+
+ public static boolean isNestedClassOf(String pathString, String fqnWithSlashes, String suffix) {
+ var fqnWithSlashesDollarSign = fqnWithSlashes + "$";
+ if (!pathString.startsWith(fqnWithSlashesDollarSign) || !pathString.endsWith(suffix)) {
+ return false;
+ }
+ String nested =
+ pathString.substring(
+ fqnWithSlashesDollarSign.length(), pathString.length() - suffix.length());
+ return isNonAnonymousNestedClassName(nested);
+ }
+
+ private static boolean isNonAnonymousClassFullPath(String path) {
+ String[] pathParts = path.split("[/\\\\]");
+ String simpleNameWithExt = pathParts[pathParts.length - 1];
+ int extIndex = simpleNameWithExt.indexOf('.');
+ assert extIndex != -1 : "Should've passed full path with extension to this method";
+ String simpleName = simpleNameWithExt.substring(0, extIndex);
+ return isNonAnonymousNestedClassName(simpleName);
+ }
+
+ // Finds [fqn] and its children with [suffix] in [entries].
+ public static Optional<List<String>> findClassAndChildren(
+ TreeSet<String> entries, String fqn, String sep, String suffix) {
+ String fqnWithSlashes = fqn.replace(".", sep);
+ String fqnWithSlashesSuffix = fqnWithSlashes + suffix;
+ String fqnWithSlashesSlash = fqnWithSlashes + sep;
+ String fqnWithSlashesDollarSign = fqnWithSlashes + "$";
+ if (entries.contains(fqnWithSlashesSuffix)) {
+ List<String> classes = new ArrayList<>();
+ // Add nested classes first, because they're alphabetically first
+ entries.tailSet(fqnWithSlashesDollarSign).stream()
+ .takeWhile(entry -> entry.startsWith(fqnWithSlashesDollarSign))
+ // Note: filter comes after takeWhile, because it can filter out additional elements
+ // eg: Class$1 - but there may be valid nested classes after Class$1.
+ .filter(entry -> isNestedClassOf(entry, fqnWithSlashes, suffix))
+ .forEach(classes::add);
+ classes.add(fqnWithSlashesSuffix);
+ return Optional.of(classes);
+ }
+
+ // consider fqnWithSlashes as a directory
+ List<String> children =
+ entries.tailSet(fqnWithSlashesSlash).stream()
+ // takeWhile instead of filter - the difference is O(log n + k) instead of O(n)
+ // so always use takeWhile when doing a treeSet subset stream.
+ .takeWhile(entry -> entry.startsWith(fqnWithSlashesSlash))
+ .filter(entry -> entry.endsWith(suffix))
+ .filter(ClassFinder::isNonAnonymousClassFullPath)
+ .collect(Collectors.toList());
+ return children.isEmpty() ? Optional.empty() : Optional.of(children);
+ }
+
+ public static <E> void findFilesInPath(
+ String searchLocation,
+ String suffix,
+ Map<String, List<E>> classes,
+ Function<List<Path>, List<E>> mapper) {
+ Path searchPath = Path.of(searchLocation);
+
+ TreeSet<String> filePaths;
+ try (var walk = Files.walk(searchPath)) {
+ filePaths =
+ walk.map(searchPath::relativize)
+ .map(Path::toString)
+ .collect(Collectors.toCollection(TreeSet::new));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ for (var className : classes.keySet()) {
+ if (classes.get(className) != null) { // Already found by other method of searching
+ continue;
+ }
+ var resultPaths = findClassAndChildren(filePaths, className, File.separator, suffix);
+ if (resultPaths.isPresent()) {
+ // [filePaths] and [resultPaths] are relativized to searchPath.
+ // perform opposite operation (resolve) to get full paths.
+ var fullPaths =
+ resultPaths.get().stream().map(searchPath::resolve).collect(Collectors.toList());
+ classes.put(className, mapper.apply(fullPaths));
+ }
+ }
+ }
+
+ public static <E> boolean findFilesInJar(
+ Map<String, List<E>> classes,
+ JarFile jar,
+ String suffix,
+ BiFunction<JarFile, List<ZipEntry>, List<E>> mapper) {
+
+ // It appears JAR file entries are always separated by "/"
+ var jarSeparator = "/";
+ var entryNames =
+ jar.stream().map(JarEntry::getName).collect(Collectors.toCollection(TreeSet::new));
+ boolean foundClassesInThisJar = false;
+ for (var fqn : classes.keySet()) {
+ if (classes.get(fqn) != null) { // already found
+ continue;
+ }
+ var resultPaths = findClassAndChildren(entryNames, fqn, jarSeparator, suffix);
+ if (resultPaths.isPresent()) {
+ var jarEntries = resultPaths.get().stream().map(jar::getEntry).collect(Collectors.toList());
+ classes.put(fqn, mapper.apply(jar, jarEntries));
+ foundClassesInThisJar = true;
+ }
+ }
+ return foundClassesInThisJar;
+ }
+
+ public static <T> void find(
+ Map<String, List<T>> classes,
+ List<String> searchPaths,
+ String suffix,
+ Function<List<Path>, List<T>> fileMapper,
+ BiFunction<JarFile, List<ZipEntry>, List<T>> entryMapper) {
+ for (var searchPath : searchPaths) {
+ File searchFile = new File(searchPath);
+ if (searchFile.isDirectory()) {
+ findFilesInPath(searchPath, suffix, classes, fileMapper);
+ } else if (searchFile.isFile() && searchPath.endsWith(".jar")) {
+ var jarFile = wrapCheckedException(JarFile::new, searchPath);
+ var useful = findFilesInJar(classes, jarFile, suffix, entryMapper);
+ if (!useful) {
+ wrapCheckedException(jarFile::close);
+ }
+ }
+ }
+ }
+
+ private static List<JavaFileObject> getJavaFileObjectsFromFiles(
+ List<Path> paths, StandardJavaFileManager fm) {
+ var result = new ArrayList<JavaFileObject>();
+ var files = StreamUtil.map(paths, Path::toFile);
+ fm.getJavaFileObjectsFromFiles(files).forEach(result::add);
+ return result;
+ }
+
+ private static List<JavaFileObject> getJavaFileObjectsFromJar(
+ JarFile jarFile, List<ZipEntry> entries) {
+ return StreamUtil.map(entries, (entry) -> new JarEntryFileObject(jarFile, entry));
+ }
+
+ private static List<InputStreamProvider> getInputStreamProvidersFromFiles(List<Path> files) {
+ return StreamUtil.map(files, (path) -> new FileInputStreamProvider(path.toFile()));
+ }
+
+ private static List<InputStreamProvider> getInputStreamProvidersFromJar(
+ JarFile jarFile, List<ZipEntry> entries) {
+ return StreamUtil.map(entries, entry -> new JarEntryInputStreamProvider(jarFile, entry));
+ }
+
+ public static void findJavaSources(
+ Map<String, List<JavaFileObject>> classes,
+ List<String> searchPaths,
+ StandardJavaFileManager fm) {
+ find(
+ classes,
+ searchPaths,
+ ".java",
+ files -> getJavaFileObjectsFromFiles(files, fm),
+ ClassFinder::getJavaFileObjectsFromJar);
+ }
+
+ public static void findJavaClasses(
+ Map<String, List<InputStreamProvider>> classes, List<String> searchPaths) {
+ find(
+ classes,
+ searchPaths,
+ ".class",
+ ClassFinder::getInputStreamProvidersFromFiles,
+ ClassFinder::getInputStreamProvidersFromJar);
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/ExceptionUtil.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/ExceptionUtil.java
new file mode 100644
index 0000000..6b4c8bd
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/ExceptionUtil.java
@@ -0,0 +1,33 @@
+package com.github.dart_lang.jnigen.apisummarizer.util;
+
+public class ExceptionUtil {
+ @FunctionalInterface
+ public interface CheckedFunction<T, R> {
+ R function(T value) throws Exception;
+ }
+
+ @FunctionalInterface
+ public interface CheckedRunnable {
+ void run() throws Exception;
+ }
+
+ /**
+ * Wraps a function throwing a checked exception and throws all checked exceptions as runtime
+ * exceptions.
+ */
+ public static <T, R> R wrapCheckedException(CheckedFunction<T, R> function, T value) {
+ try {
+ return function.function(value);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void wrapCheckedException(CheckedRunnable runnable) {
+ try {
+ runnable.run();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/FileInputStreamProvider.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/FileInputStreamProvider.java
new file mode 100644
index 0000000..da5cadf
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/FileInputStreamProvider.java
@@ -0,0 +1,38 @@
+package com.github.dart_lang.jnigen.apisummarizer.util;
+
+import java.io.*;
+
+/** Implementation of InputStreamProvider backed by a File. */
+public class FileInputStreamProvider implements InputStreamProvider {
+ File file;
+ InputStream stream;
+
+ public FileInputStreamProvider(File file) {
+ this.file = file;
+ }
+
+ @Override
+ public InputStream getInputStream() {
+ if (stream == null) {
+ try {
+ stream = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return stream;
+ }
+
+ @Override
+ public void close() {
+ if (stream == null) {
+ return;
+ }
+ try {
+ stream.close();
+ stream = null;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/InputStreamProvider.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/InputStreamProvider.java
new file mode 100644
index 0000000..85ba15b
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/InputStreamProvider.java
@@ -0,0 +1,17 @@
+package com.github.dart_lang.jnigen.apisummarizer.util;
+
+import java.io.InputStream;
+
+/**
+ * Implementers of this interface provide an InputStream on-demand for writing, and provide a way to
+ * close the same. <br>
+ * The implementation doesn't need to be thread-safe, since this is only used in AsmSummarizer,
+ * which reads the classes serially.
+ */
+public interface InputStreamProvider {
+ /** Return the input stream, initializing it if needed. */
+ InputStream getInputStream();
+
+ /** close the underlying InputStream. */
+ void close();
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/JarEntryFileObject.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/JarEntryFileObject.java
new file mode 100644
index 0000000..49f187f
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/JarEntryFileObject.java
@@ -0,0 +1,41 @@
+package com.github.dart_lang.jnigen.apisummarizer.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+import javax.tools.SimpleJavaFileObject;
+
+/** Implements JavaFileObject for use by Doclet summarizer. */
+class JarEntryFileObject extends SimpleJavaFileObject {
+ JarFile jarFile;
+ String relativePath;
+
+ protected JarEntryFileObject(JarFile jarFile, ZipEntry entry) {
+ super(URI.create(new File(jarFile.getName()).toURI() + "/" + entry.getName()), Kind.SOURCE);
+ this.jarFile = jarFile;
+ this.relativePath = entry.getName();
+ }
+
+ private int getEntrySize(ZipEntry entry) {
+ long limit = 1024L * 1024L * 16L; // Arbitrary limit, how long can be a source file?
+ long size = entry.getSize();
+ return (int) Long.min(size, limit);
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ var entry = jarFile.getEntry(relativePath);
+ var out = new ByteArrayOutputStream(getEntrySize(entry));
+
+ try (var stream = jarFile.getInputStream(entry)) {
+ stream.transferTo(out);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return out.toString(StandardCharsets.UTF_8);
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/JarEntryInputStreamProvider.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/JarEntryInputStreamProvider.java
new file mode 100644
index 0000000..cba3f76
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/JarEntryInputStreamProvider.java
@@ -0,0 +1,29 @@
+package com.github.dart_lang.jnigen.apisummarizer.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+
+public class JarEntryInputStreamProvider implements InputStreamProvider {
+
+ private final JarFile jarFile;
+ private final ZipEntry zipEntry;
+
+ public JarEntryInputStreamProvider(JarFile jarFile, ZipEntry zipEntry) {
+ this.jarFile = jarFile;
+ this.zipEntry = zipEntry;
+ }
+
+ @Override
+ public InputStream getInputStream() {
+ try {
+ return jarFile.getInputStream(zipEntry);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void close() {}
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/JsonWriter.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/JsonWriter.java
new file mode 100644
index 0000000..112e241
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/JsonWriter.java
@@ -0,0 +1,24 @@
+package com.github.dart_lang.jnigen.apisummarizer.util;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.github.dart_lang.jnigen.apisummarizer.elements.ClassDecl;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+public class JsonWriter {
+ public static void writeJSON(List<ClassDecl> classes, OutputStream output) {
+ var mapper = new ObjectMapper();
+ Log.info("Writing JSON for %d classes", classes.size());
+ mapper.enable(SerializationFeature.INDENT_OUTPUT);
+ mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+ try {
+ mapper.writeValue(output, classes);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ Log.info("Finished");
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/Log.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/Log.java
new file mode 100644
index 0000000..dfb48e1
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/Log.java
@@ -0,0 +1,25 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.util;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class Log {
+ private static final Logger logger = Logger.getLogger("ApiSummarizer");
+
+ private static void log(Level level, String format, Object... args) {
+ String formatted = String.format(format, args);
+ logger.log(level, formatted);
+ }
+
+ public static void info(String format, Object... args) {
+ log(Level.INFO, format, args);
+ }
+
+ public static void warning(String format, Object... args) {
+ log(Level.WARNING, format, args);
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/SkipException.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/SkipException.java
new file mode 100644
index 0000000..1f253b0
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/SkipException.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.util;
+
+// Generic skip exception when the code cannot decide how to handle an element.
+// The caller in some above layer can catch this and skip to appropriate extent.
+public class SkipException extends RuntimeException {
+ public SkipException(String message) {
+ super(message);
+ }
+}
diff --git a/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/StreamUtil.java b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/StreamUtil.java
new file mode 100644
index 0000000..30a8fa0
--- /dev/null
+++ b/pkgs/jnigen/java/src/main/java/com/github/dart_lang/jnigen/apisummarizer/util/StreamUtil.java
@@ -0,0 +1,26 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.apisummarizer.util;
+
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+public class StreamUtil {
+ public static <T, R> List<R> map(List<T> list, Function<T, R> function) {
+ return list.stream().map(function).collect(Collectors.toList());
+ }
+
+ public static <T, R> List<R> map(T[] array, Function<T, R> function) {
+ return Arrays.stream(array).map(function).collect(Collectors.toList());
+ }
+
+ public static <K, E> List<E> flattenListValues(Map<K, List<E>> map) {
+ return map.values().stream()
+ .filter(Objects::nonNull)
+ .flatMap(Collection::stream)
+ .collect(Collectors.toList());
+ }
+}
diff --git a/pkgs/jnigen/java/src/test/java/com/github/dart_lang/jnigen/apisummarizer/ClassFinderTest.java b/pkgs/jnigen/java/src/test/java/com/github/dart_lang/jnigen/apisummarizer/ClassFinderTest.java
new file mode 100644
index 0000000..4209e3a
--- /dev/null
+++ b/pkgs/jnigen/java/src/test/java/com/github/dart_lang/jnigen/apisummarizer/ClassFinderTest.java
@@ -0,0 +1,95 @@
+package com.github.dart_lang.jnigen.apisummarizer;
+
+import static com.github.dart_lang.jnigen.apisummarizer.util.ClassFinder.findClassAndChildren;
+import static com.github.dart_lang.jnigen.apisummarizer.util.ClassFinder.isNestedClassOf;
+import static org.junit.Assert.*;
+
+import java.util.*;
+import java.util.stream.Collectors;
+import org.junit.Test;
+
+public class ClassFinderTest {
+ @Test
+ public void testNestedClassCheck() {
+ assertTrue(
+ "Single nested class",
+ isNestedClassOf("com/abc/Class$Nested.class", "com/abc/Class", ".class"));
+ assertTrue(
+ "Nested twice",
+ isNestedClassOf("com/abc/Class$Nested$Twice.class", "com/abc/Class", ".class"));
+ assertTrue(
+ "Single nested class - backslash separator",
+ isNestedClassOf("com\\abc\\Class$Nested.class", "com\\abc\\Class", ".class"));
+ assertFalse(
+ "Anon inner class", isNestedClassOf("com/abc/Class$1.class", "com/abc/Class", ".class"));
+ assertFalse(
+ "Anon inner class inside nested class",
+ isNestedClassOf("com/abc/Class$Nested$1.class", "com/abc/Class", ".class"));
+ assertFalse(
+ "Different class name",
+ isNestedClassOf("com/abc/AClass$Nested.class", "com/abc/Class", ".class"));
+ }
+
+ private Optional<List<String>> pathListOf(String sep, String... paths) {
+ List<String> pathList =
+ Arrays.stream(paths).map(path -> path.replace("/", sep)).collect(Collectors.toList());
+ return Optional.of(pathList);
+ }
+
+ @Test
+ public void testFindChildren() {
+ TreeSet<String> entriesWithSlash =
+ new TreeSet<>(
+ List.of(
+ "random/os/App.class",
+ "random/os/App$1.class",
+ "random/os/App$1$3.class",
+ "random/os/Process.class",
+ "random/os/Process$Fork.class",
+ "random/os/Process$Fork$1.class",
+ "random/os/Process$Fork$A$B$C$2.class",
+ "random/widget/Dialog.class",
+ "random/widget/Dialog$Button.class",
+ "random/widget/Dialog$Button$2.class",
+ "random/widget/Dialog$Button$Color.class",
+ "random/widget/Dialogue$Button.class",
+ "random/time/Clock.class",
+ "random/time/Clock$1.class",
+ "random/time/Calendar.class",
+ "random/time/Calendar$Month$1.class",
+ "random/time/Calendar$Month.class"));
+ TreeSet<String> entriesWithBackslash =
+ entriesWithSlash.stream()
+ .map(x -> x.replace('/', '\\'))
+ .collect(Collectors.toCollection(TreeSet::new));
+ Map<String, TreeSet<String>> bySeparater =
+ Map.of("/", entriesWithSlash, "\\", entriesWithBackslash);
+
+ for (var sep : bySeparater.keySet()) {
+ var entries = bySeparater.get(sep);
+ assertEquals(
+ pathListOf(sep, "random/os/Process$Fork.class", "random/os/Process.class"),
+ findClassAndChildren(entries, "random.os.Process", sep, ".class"));
+ assertEquals(
+ pathListOf(
+ sep,
+ "random/time/Calendar$Month.class",
+ "random/time/Calendar.class",
+ "random/time/Clock.class"),
+ findClassAndChildren(entries, "random.time", sep, ".class"));
+ assertEquals(
+ pathListOf(
+ sep,
+ "random/widget/Dialog$Button$Color.class",
+ "random/widget/Dialog$Button.class",
+ "random/widget/Dialog.class"),
+ findClassAndChildren(entries, "random.widget.Dialog", sep, ".class"));
+ assertEquals(
+ pathListOf(sep, "random/os/App.class"),
+ findClassAndChildren(entries, "random.os.App", sep, ".class"));
+ assertEquals(
+ pathListOf(sep, "random/os/App.class"),
+ findClassAndChildren(entries, "random.os.App", sep, ".class"));
+ }
+ }
+}
diff --git a/pkgs/jnigen/java/src/test/java/com/github/dart_lang/jnigen/apisummarizer/JSONComparisonTest.java b/pkgs/jnigen/java/src/test/java/com/github/dart_lang/jnigen/apisummarizer/JSONComparisonTest.java
new file mode 100644
index 0000000..b02ee15
--- /dev/null
+++ b/pkgs/jnigen/java/src/test/java/com/github/dart_lang/jnigen/apisummarizer/JSONComparisonTest.java
@@ -0,0 +1,53 @@
+package com.github.dart_lang.jnigen.apisummarizer;
+
+import com.github.dart_lang.jnigen.apisummarizer.util.Log;
+import java.io.File;
+import java.io.IOException;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class JSONComparisonTest {
+ static final File exampleClassJsonOutput =
+ new File("src/test/resources/exampleClassSummary.json");
+
+ @SuppressWarnings("SameParameterValue")
+ private int gitDiff(File a, File b) throws IOException, InterruptedException {
+ return gitDiff(a.getPath(), b.getPath());
+ }
+
+ private int gitDiff(String a, String b) throws IOException, InterruptedException {
+ String colorSupport = "--color=never";
+ if (System.console() != null && System.getenv().get("TERM") != null) {
+ colorSupport = "--color=always";
+ }
+ String[] compareCommand = {
+ "git", "diff", colorSupport, "--no-index", a, b,
+ };
+ var compare = Runtime.getRuntime().exec(compareCommand);
+ compare.getErrorStream().transferTo(System.err);
+ compare.getInputStream().transferTo(System.out);
+ return compare.waitFor();
+ }
+
+ @Test
+ public void testExampleSummary() throws IOException, InterruptedException {
+ var tempFile = File.createTempFile("summarizer_test", ".json");
+ Log.info("Temporary file: %s", tempFile.getPath());
+ Main.main(
+ new String[] {
+ "-s", "src/test/resources", "com.example.Example", "-o", tempFile.getPath(),
+ });
+ int comparison = gitDiff(exampleClassJsonOutput, tempFile);
+ if (comparison != 0) {
+ Log.warning("New output (%s) is different than reference output.", tempFile.getPath());
+ }
+
+ // Fail test if git diff exited with 1
+ Assert.assertEquals(0, comparison);
+
+ var deleted = tempFile.delete();
+ if (!deleted) {
+ Log.warning("Cannot delete temp file %s", tempFile.getPath());
+ }
+ }
+}
diff --git a/pkgs/jnigen/java/src/test/resources/com/example/Example.java b/pkgs/jnigen/java/src/test/resources/com/example/Example.java
new file mode 100644
index 0000000..b5856a2
--- /dev/null
+++ b/pkgs/jnigen/java/src/test/resources/com/example/Example.java
@@ -0,0 +1,39 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.example;
+
+public class Example {
+ public static final boolean staticFinalField = true;
+
+ public Example(int instanceField) {
+ this.instanceField = instanceField;
+ }
+
+ public static String staticField = "hello";
+
+ public static String getStaticField() {
+ return staticField;
+ }
+
+ public int instanceField;
+
+ public int getInstanceField() {
+ return instanceField;
+ }
+
+ protected int overrideableMethod(int x, int y) {}
+
+ int defaultAccessNotVisible();
+
+ private int privateAccessNotVisible();
+
+ public static class Aux extends Example {
+ public static int nothing = 0;
+
+ public static Example getAnExample() {
+ return new Example();
+ }
+ }
+}
diff --git a/pkgs/jnigen/java/src/test/resources/exampleClassSummary.json b/pkgs/jnigen/java/src/test/resources/exampleClassSummary.json
new file mode 100644
index 0000000..6786a26
--- /dev/null
+++ b/pkgs/jnigen/java/src/test/resources/exampleClassSummary.json
@@ -0,0 +1,185 @@
+[ {
+ "declKind" : "CLASS",
+ "modifiers" : [ "public" ],
+ "binaryName" : "com.example.Example",
+ "methods" : [ {
+ "modifiers" : [ "public" ],
+ "name" : "<init>",
+ "params" : [ {
+ "name" : "instanceField",
+ "type" : {
+ "shorthand" : "int",
+ "kind" : "PRIMITIVE",
+ "type" : {
+ "name" : "int"
+ }
+ }
+ } ],
+ "returnType" : {
+ "shorthand" : "void",
+ "kind" : "PRIMITIVE",
+ "type" : {
+ "name" : "void"
+ }
+ }
+ }, {
+ "modifiers" : [ "static", "public" ],
+ "name" : "getStaticField",
+ "returnType" : {
+ "shorthand" : "java.lang.String",
+ "kind" : "DECLARED",
+ "type" : {
+ "binaryName" : "java.lang.String",
+ "simpleName" : "String"
+ }
+ }
+ }, {
+ "modifiers" : [ "public" ],
+ "name" : "getInstanceField",
+ "returnType" : {
+ "shorthand" : "int",
+ "kind" : "PRIMITIVE",
+ "type" : {
+ "name" : "int"
+ }
+ }
+ }, {
+ "modifiers" : [ "protected" ],
+ "name" : "overrideableMethod",
+ "params" : [ {
+ "name" : "x",
+ "type" : {
+ "shorthand" : "int",
+ "kind" : "PRIMITIVE",
+ "type" : {
+ "name" : "int"
+ }
+ }
+ }, {
+ "name" : "y",
+ "type" : {
+ "shorthand" : "int",
+ "kind" : "PRIMITIVE",
+ "type" : {
+ "name" : "int"
+ }
+ }
+ } ],
+ "returnType" : {
+ "shorthand" : "int",
+ "kind" : "PRIMITIVE",
+ "type" : {
+ "name" : "int"
+ }
+ }
+ }, {
+ "name" : "defaultAccessNotVisible",
+ "returnType" : {
+ "shorthand" : "int",
+ "kind" : "PRIMITIVE",
+ "type" : {
+ "name" : "int"
+ }
+ }
+ }, {
+ "modifiers" : [ "private" ],
+ "name" : "privateAccessNotVisible",
+ "returnType" : {
+ "shorthand" : "int",
+ "kind" : "PRIMITIVE",
+ "type" : {
+ "name" : "int"
+ }
+ }
+ } ],
+ "fields" : [ {
+ "modifiers" : [ "static", "public", "final" ],
+ "name" : "staticFinalField",
+ "type" : {
+ "shorthand" : "boolean",
+ "kind" : "PRIMITIVE",
+ "type" : {
+ "name" : "boolean"
+ }
+ },
+ "defaultValue" : true
+ }, {
+ "modifiers" : [ "static", "public" ],
+ "name" : "staticField",
+ "type" : {
+ "shorthand" : "java.lang.String",
+ "kind" : "DECLARED",
+ "type" : {
+ "binaryName" : "java.lang.String",
+ "simpleName" : "String"
+ }
+ }
+ }, {
+ "modifiers" : [ "public" ],
+ "name" : "instanceField",
+ "type" : {
+ "shorthand" : "int",
+ "kind" : "PRIMITIVE",
+ "type" : {
+ "name" : "int"
+ }
+ }
+ } ],
+ "superclass" : {
+ "shorthand" : "java.lang.Object",
+ "kind" : "DECLARED",
+ "type" : {
+ "binaryName" : "java.lang.Object",
+ "simpleName" : "Object"
+ }
+ },
+ "hasStaticInit" : false,
+ "hasInstanceInit" : false
+}, {
+ "declKind" : "CLASS",
+ "modifiers" : [ "static", "public" ],
+ "binaryName" : "com.example.Example$Aux",
+ "methods" : [ {
+ "modifiers" : [ "public" ],
+ "name" : "<init>",
+ "returnType" : {
+ "shorthand" : "void",
+ "kind" : "PRIMITIVE",
+ "type" : {
+ "name" : "void"
+ }
+ }
+ }, {
+ "modifiers" : [ "static", "public" ],
+ "name" : "getAnExample",
+ "returnType" : {
+ "shorthand" : "com.example.Example",
+ "kind" : "DECLARED",
+ "type" : {
+ "binaryName" : "com.example.Example",
+ "simpleName" : "Example"
+ }
+ }
+ } ],
+ "fields" : [ {
+ "modifiers" : [ "static", "public" ],
+ "name" : "nothing",
+ "type" : {
+ "shorthand" : "int",
+ "kind" : "PRIMITIVE",
+ "type" : {
+ "name" : "int"
+ }
+ }
+ } ],
+ "superclass" : {
+ "shorthand" : "com.example.Example",
+ "kind" : "DECLARED",
+ "type" : {
+ "binaryName" : "com.example.Example",
+ "simpleName" : "Example"
+ }
+ },
+ "hasStaticInit" : false,
+ "hasInstanceInit" : false
+} ]
\ No newline at end of file
diff --git a/pkgs/jnigen/lib/jnigen.dart b/pkgs/jnigen/lib/jnigen.dart
new file mode 100644
index 0000000..8e2ebe0
--- /dev/null
+++ b/pkgs/jnigen/lib/jnigen.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This library exports a high level programmatic API to jnigen, the entry
+/// point of which is runJniGenTask function, which takes run configuration as
+/// a JniGenTask.
+library jnigen;
+
+export 'src/elements/elements.dart';
+export 'src/config/config.dart';
+export 'src/config/filters.dart';
+export 'src/generate_bindings.dart';
diff --git a/pkgs/jnigen/lib/src/bindings/c_generator.dart b/pkgs/jnigen/lib/src/bindings/c_generator.dart
new file mode 100644
index 0000000..79b07c8
--- /dev/null
+++ b/pkgs/jnigen/lib/src/bindings/c_generator.dart
@@ -0,0 +1,383 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import '../config/config.dart';
+import '../elements/elements.dart';
+import '../logging/logging.dart';
+import '../util/find_package.dart';
+import '../util/string_util.dart';
+import 'visitor.dart';
+
+class CFieldName extends Visitor<Field, String> {
+ const CFieldName();
+
+ @override
+ String visit(Field node) {
+ final className = node.classDecl.uniqueName;
+ final fieldName = node.finalName;
+ return '${className}__$fieldName';
+ }
+}
+
+class CMethodName extends Visitor<Method, String> {
+ const CMethodName();
+
+ @override
+ String visit(Method node) {
+ final className = node.classDecl.uniqueName;
+ final methodName = node.finalName;
+ return '${className}__$methodName';
+ }
+}
+
+class CGenerator extends Visitor<Classes, Future<void>> {
+ static const _prelude = '''// Autogenerated by jnigen. DO NOT EDIT!
+
+#include <stdint.h>
+#include "jni.h"
+#include "dartjni.h"
+
+thread_local JNIEnv *jniEnv;
+JniContext *jni;
+
+JniContext *(*context_getter)(void);
+JNIEnv *(*env_getter)(void);
+
+void setJniGetters(JniContext *(*cg)(void),
+ JNIEnv *(*eg)(void)) {
+ context_getter = cg;
+ env_getter = eg;
+}
+
+''';
+
+ final Config config;
+
+ CGenerator(this.config);
+
+ Future<void> _copyFileFromPackage(String package, String relPath, Uri target,
+ {String Function(String)? transform}) async {
+ final packagePath = await findPackageRoot(package);
+ if (packagePath != null) {
+ final sourceFile = File.fromUri(packagePath.resolve(relPath));
+ final targetFile = await File.fromUri(target).create(recursive: true);
+ var source = await sourceFile.readAsString();
+ if (transform != null) {
+ source = transform(source);
+ }
+ await targetFile.writeAsString(source);
+ } else {
+ log.warning('package $package not found! '
+ 'skipped copying ${target.toFilePath()}');
+ }
+ }
+
+ @override
+ Future<void> visit(Classes node) async {
+ // Write C file and init file.
+ final cConfig = config.outputConfig.cConfig!;
+ final cRoot = cConfig.path;
+ final preamble = config.preamble;
+ log.info("Using c root = $cRoot");
+ final libraryName = cConfig.libraryName;
+ log.info('Creating dart init file ...');
+ // Create C file.
+ final subdir = cConfig.subdir ?? '.';
+ final cFileRelativePath = '$subdir/$libraryName.c';
+ final cFile = await File.fromUri(cRoot.resolve(cFileRelativePath))
+ .create(recursive: true);
+ final cFileStream = cFile.openWrite();
+ // Write C Bindings.
+ if (preamble != null) {
+ cFileStream.writeln(preamble);
+ }
+ cFileStream.write(_prelude);
+ final classGenerator = _CClassGenerator(config, cFileStream);
+ for (final classDecl in node.decls.values) {
+ classDecl.accept(classGenerator);
+ }
+ await cFileStream.close();
+ log.info('Copying auxiliary files...');
+ for (final file in ['dartjni.h', '.clang-format']) {
+ await _copyFileFromPackage(
+ 'jni', 'src/$file', cRoot.resolve('$subdir/$file'));
+ }
+ await _copyFileFromPackage(
+ 'jnigen', 'cmake/CMakeLists.txt.tmpl', cRoot.resolve('CMakeLists.txt'),
+ transform: (s) {
+ return s
+ .replaceAll('{{LIBRARY_NAME}}', libraryName)
+ .replaceAll('{{SUBDIR}}', subdir);
+ });
+ log.info('Running clang-format on C bindings');
+ try {
+ final clangFormat = Process.runSync('clang-format', ['-i', cFile.path]);
+ if (clangFormat.exitCode != 0) {
+ printError(clangFormat.stderr);
+ log.warning('clang-format exited with ${clangFormat.exitCode}');
+ }
+ } on ProcessException catch (e) {
+ log.warning('cannot run clang-format: $e');
+ }
+ }
+}
+
+const _classVarPrefix = '_c_';
+const _jniResultType = 'JniResult';
+const _loadEnvCall = 'load_env();';
+const _ifError =
+ '(JniResult){.value = {.j = 0}, .exception = check_exception()}';
+
+class _CClassGenerator extends Visitor<ClassDecl, void> {
+ final Config config;
+ final StringSink s;
+
+ _CClassGenerator(this.config, this.s);
+
+ @override
+ void visit(ClassDecl node) {
+ final classNameInC = node.uniqueName;
+ final classVar = '$_classVarPrefix$classNameInC';
+ // Global variable in C that holds the reference to class.
+ s.write('''// ${node.binaryName}
+jclass $classVar = NULL;
+
+''');
+
+ final methodGenerator = _CMethodGenerator(config, s);
+ for (final method in node.methods) {
+ method.accept(methodGenerator);
+ }
+
+ final fieldGenerator = _CFieldGenerator(config, s);
+ for (final field in node.fields) {
+ field.accept(fieldGenerator);
+ }
+ }
+}
+
+class _CLoadClassGenerator extends Visitor<ClassDecl, String> {
+ _CLoadClassGenerator();
+
+ @override
+ String visit(ClassDecl node) {
+ final classVar = '$_classVarPrefix${node.uniqueName}';
+ return ''' load_class_global_ref(&$classVar, "${node.internalName}");
+ if ($classVar == NULL) return $_ifError;''';
+ }
+}
+
+class _CMethodGenerator extends Visitor<Method, void> {
+ static const _methodVarPrefix = '_m_';
+
+ final Config config;
+ final StringSink s;
+
+ _CMethodGenerator(this.config, this.s);
+
+ @override
+ void visit(Method node) {
+ final classNameInC = node.classDecl.uniqueName;
+
+ final cMethodName = node.accept(const CMethodName());
+ final classRef = '$_classVarPrefix$classNameInC';
+ final methodId = '$_methodVarPrefix$cMethodName';
+ final cMethodParams = [
+ if (!node.isCtor && !node.isStatic) 'jobject self_',
+ ...node.params.accept(const _CParamGenerator(addReturnType: true)),
+ ].join(',');
+ final jniSignature = node.descriptor;
+ final ifStaticMethodID = node.isStatic ? 'static_' : '';
+
+ var javaReturnType = node.returnType.type;
+ if (node.isCtor) {
+ javaReturnType = DeclaredType(
+ binaryName: node.classDecl.binaryName,
+ );
+ }
+ final callType = node.returnType.accept(const _CTypeCallSite());
+ final callArgs = [
+ 'jniEnv',
+ if (!node.isCtor && !node.isStatic) 'self_' else classRef,
+ methodId,
+ ...node.params.accept(const _CParamGenerator(addReturnType: false))
+ ].join(', ');
+
+ var ifAssignResult = '';
+ if (javaReturnType.name != 'void') {
+ ifAssignResult =
+ '${javaReturnType.accept(const _CReturnType())} _result = ';
+ }
+
+ final ifStaticCall = node.isStatic ? 'Static' : '';
+ final envMethod =
+ node.isCtor ? 'NewObject' : 'Call$ifStaticCall${callType}Method';
+ final returnResultIfAny = javaReturnType.accept(const _CResult());
+ s.write('''
+jmethodID $methodId = NULL;
+FFI_PLUGIN_EXPORT
+$_jniResultType $cMethodName($cMethodParams) {
+ $_loadEnvCall
+ ${node.classDecl.accept(_CLoadClassGenerator())}
+ load_${ifStaticMethodID}method($classRef,
+ &$methodId, "${node.name}", "$jniSignature");
+ if ($methodId == NULL) return $_ifError;
+ $ifAssignResult(*jniEnv)->$envMethod($callArgs);
+ $returnResultIfAny
+}
+
+''');
+ }
+}
+
+class _CFieldGenerator extends Visitor<Field, void> {
+ static const _fieldVarPrefix = '_f_';
+
+ final Config config;
+ final StringSink s;
+
+ _CFieldGenerator(this.config, this.s);
+
+ @override
+ void visit(Field node) {
+ final cClassName = node.classDecl.uniqueName;
+
+ final fieldName = node.finalName;
+ final fieldNameInC = node.accept(const CFieldName());
+ final fieldVar = "$_fieldVarPrefix$fieldNameInC";
+
+ // If the field is final and default is assigned, then no need to wrap
+ // this field. It should then be a constant in dart code.
+ if (node.isStatic && node.isFinal && node.defaultValue != null) {
+ return;
+ }
+
+ s.write('jfieldID $fieldVar = NULL;\n');
+
+ final classVar = '$_classVarPrefix$cClassName';
+ void writeAccessor({bool isSetter = false}) {
+ const cReturnType = _jniResultType;
+ final cMethodPrefix = isSetter ? 'set' : 'get';
+ final formalArgs = [
+ if (!node.isStatic) 'jobject self_',
+ if (isSetter) '${node.type.accept(const _CReturnType())} value',
+ ].join(', ');
+ final ifStaticField = node.isStatic ? 'static_' : '';
+ final ifStaticCall = node.isStatic ? 'Static' : '';
+ final callType = node.type.accept(const _CTypeCallSite());
+ final objectArgument = node.isStatic ? classVar : 'self_';
+
+ String accessorStatements;
+ if (isSetter) {
+ accessorStatements =
+ ' (*jniEnv)->Set$ifStaticCall${callType}Field(jniEnv, '
+ '$objectArgument, $fieldVar, value);\n'
+ ' return $_ifError;';
+ } else {
+ final getterExpr =
+ '(*jniEnv)->Get$ifStaticCall${callType}Field(jniEnv, '
+ '$objectArgument, $fieldVar)';
+ final cResultType = node.type.accept(const _CReturnType());
+ final result = node.type.accept(const _CResult());
+ accessorStatements = ''' $cResultType _result = $getterExpr;
+ $result''';
+ }
+ s.write('''
+FFI_PLUGIN_EXPORT
+$cReturnType ${cMethodPrefix}_$fieldNameInC($formalArgs) {
+ $_loadEnvCall
+ ${node.classDecl.accept(_CLoadClassGenerator())}
+ load_${ifStaticField}field($classVar, &$fieldVar, "$fieldName",
+ "${node.type.descriptor}");
+$accessorStatements
+}
+
+''');
+ }
+
+ writeAccessor(isSetter: false);
+ if (node.isFinal) {
+ return;
+ }
+ writeAccessor(isSetter: true);
+ }
+}
+
+class _CParamGenerator extends Visitor<Param, String> {
+ /// These should be avoided in parameter names.
+ static const _cTypeKeywords = {
+ 'short',
+ 'char',
+ 'int',
+ 'long',
+ 'float',
+ 'double',
+ };
+
+ const _CParamGenerator({required this.addReturnType});
+
+ final bool addReturnType;
+
+ @override
+ String visit(Param node) {
+ final paramName =
+ (_cTypeKeywords.contains(node.name) ? '${node.name}0' : node.name)
+ .replaceAll('\$', '_');
+ if (addReturnType) {
+ final type = node.type.accept(const _CReturnType());
+ return '$type $paramName';
+ }
+ return paramName;
+ }
+}
+
+class _CReturnType extends TypeVisitor<String> {
+ const _CReturnType();
+
+ @override
+ String visitNonPrimitiveType(ReferredType node) {
+ return 'jobject';
+ }
+
+ @override
+ String visitPrimitiveType(PrimitiveType node) {
+ return node.cType;
+ }
+}
+
+class _CTypeCallSite extends TypeVisitor<String> {
+ const _CTypeCallSite();
+
+ @override
+ String visitNonPrimitiveType(ReferredType node) {
+ return 'Object';
+ }
+
+ @override
+ String visitPrimitiveType(PrimitiveType node) {
+ return node.name.capitalize();
+ }
+}
+
+class _CResult extends TypeVisitor<String> {
+ const _CResult();
+
+ @override
+ String visitNonPrimitiveType(ReferredType node) {
+ return 'return to_global_ref_result(_result);';
+ }
+
+ @override
+ String visitPrimitiveType(PrimitiveType node) {
+ if (node.name == 'void') {
+ return 'return $_ifError;';
+ }
+ // The union field is the same as the type's signature, but in lowercase.
+ final unionField = node.signature.toLowerCase();
+ return 'return (JniResult){.value = {.$unionField = _result}, '
+ '.exception = check_exception()};';
+ }
+}
diff --git a/pkgs/jnigen/lib/src/bindings/dart_generator.dart b/pkgs/jnigen/lib/src/bindings/dart_generator.dart
new file mode 100644
index 0000000..b202293
--- /dev/null
+++ b/pkgs/jnigen/lib/src/bindings/dart_generator.dart
@@ -0,0 +1,1732 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:meta/meta.dart';
+
+import '../config/config.dart';
+import '../config/experiments.dart';
+import '../elements/elements.dart';
+import '../logging/logging.dart';
+import '../util/string_util.dart';
+import 'c_generator.dart';
+import 'resolver.dart';
+import 'visitor.dart';
+
+// Import prefixes.
+const _jni = 'jni';
+const _ffi = 'ffi';
+
+// package:jni types.
+const _jType = '$_jni.JObjType';
+const _jPointer = '$_jni.JObjectPtr';
+const _jArray = '$_jni.JArray';
+const _jObject = '$_jni.JObject';
+const _jResult = '$_jni.JniResult';
+const _jCallType = '$_jni.JniCallType';
+
+// package:ffi types.
+const _voidPointer = '$_ffi.Pointer<$_ffi.Void>';
+
+// Prefixes and suffixes.
+const _typeParamPrefix = '\$';
+
+// Misc.
+const _protectedExtension = 'ProtectedJniExtensions';
+const _classRef = '_class.reference';
+const _env = '$_jni.Jni.env';
+const _accessors = '$_jni.Jni.accessors';
+const _lookup = 'jniLookup';
+const _selfPointer = 'reference';
+
+// Docs.
+const _releaseInstruction =
+ ' /// The returned object must be released after use, '
+ 'by calling the [release] method.';
+
+extension on Iterable<String> {
+ /// Similar to [join] but adds the [separator] to the end as well.
+ String delimited([String separator = '']) {
+ return map((e) => '$e$separator').join();
+ }
+}
+
+/// Encloses [inside] in the middle of [open] and [close]
+/// if [inside] is not empty.
+String _encloseIfNotEmpty(String open, String inside, String close) {
+ if (inside == '') return '';
+ return '$open$inside$close';
+}
+
+String _newLine({int depth = 0}) {
+ return '\n${' ' * depth}';
+}
+
+/// Merges two maps. For the same keys, their value lists will be concatenated.
+///
+/// ** After calling this, the original maps might get modified! **
+Map<K, List<V>> _mergeMapValues<K, V>(Map<K, List<V>> a, Map<K, List<V>> b) {
+ final merged = <K, List<V>>{};
+ for (final key in {...a.keys, ...b.keys}) {
+ if (!a.containsKey(key)) {
+ merged[key] = b[key]!;
+ continue;
+ }
+ if (!b.containsKey(key)) {
+ merged[key] = a[key]!;
+ continue;
+ }
+
+ // Merging the smaller one to the bigger one
+ if (a[key]!.length > b[key]!.length) {
+ merged[key] = a[key]!;
+ merged[key]!.addAll(b[key]!);
+ } else {
+ merged[key] = b[key]!;
+ merged[key]!.addAll(a[key]!);
+ }
+ }
+ return merged;
+}
+
+/// **Naming Convention**
+///
+/// Let's take the following code as an example:
+///
+/// ```dart
+/// Method definition
+/// void f<T extends num, U>(JType<T> $T, JType<U> $U, T t, U u) {
+/// // ...
+/// }
+/// f<int, String>($T, $U, t, u); // Calling the Method
+/// ```
+///
+/// Here `f` will be replaced according to the place of usage.
+///
+/// * `fArgsDef` refers to `T t, U u` – the arguments in the method
+/// definition.
+/// * `fArgsCall` refer to `t, u` – the arguments passed to call the method.
+/// * `fTypeParamsDef` refers to `<T extends num, U>` – the type parameters
+/// of the method at the point of definition.
+/// * `fTypeParamsCall` refers to `<int, String>` – the type parameters when
+/// calling, or whenever we don't want to have the `extends` keyword.
+/// * `fTypeClassesDef` refers to `JType<T> $T, JType<U> $U`.
+/// * `fTypeClassesCall` refers to `$T, $U` when calling the method.
+class DartGenerator extends Visitor<Classes, Future<void>> {
+ final Config config;
+
+ DartGenerator(this.config);
+
+ static const cInitImport = 'import "dart:ffi" as ffi;\n'
+ 'import "package:jni/internal_helpers_for_jnigen.dart";\n';
+
+ /// Initialization code for C based bindings.
+ ///
+ /// Should be called once in a package. In package-structured bindings
+ /// this is placed in _init.dart in package root.
+ String get cInitCode => '''
+// Auto-generated initialization code.
+
+final $_ffi.Pointer<T> Function<T extends $_ffi.NativeType>(String sym) $_lookup =
+ $_protectedExtension.initGeneratedLibrary("${config.outputConfig.cConfig!.libraryName}");
+
+
+''';
+
+ static const autoGeneratedNotice = '// Autogenerated by jnigen. '
+ 'DO NOT EDIT!\n\n';
+ static const defaultImports = '''
+import "dart:isolate" show ReceivePort;
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+import "package:jni/jni.dart" as jni;
+
+''';
+
+ // Sort alphabetically.
+ static const defaultLintSuppressions = '''
+// ignore_for_file: annotate_overrides
+// ignore_for_file: camel_case_extensions
+// ignore_for_file: camel_case_types
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: doc_directive_unknown
+// ignore_for_file: file_names
+// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: overridden_fields
+// ignore_for_file: unnecessary_cast
+// ignore_for_file: unused_element
+// ignore_for_file: unused_field
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: unused_shown_name
+
+''';
+ static const preImportBoilerplate =
+ autoGeneratedNotice + defaultLintSuppressions + defaultImports;
+
+ /// Run dart format command on [path].
+ Future<void> _runDartFormat(String path) async {
+ log.info('Running dart format...');
+ final formatRes = await Process.run('dart', ['format', path]);
+ // if negative exit code, likely due to an interrupt.
+ if (formatRes.exitCode > 0) {
+ log.fatal('Dart format completed with exit code ${formatRes.exitCode} '
+ 'This usually means there\'s a syntax error in bindings.\n'
+ 'Please look at the generated files and report a bug: \n'
+ 'https://github.com/dart-lang/jnigen/issues/new\n');
+ }
+ }
+
+ @override
+ Future<void> visit(Classes node) async {
+ final cBased = config.outputConfig.bindingsType == BindingsType.cBased;
+ final root = config.outputConfig.dartConfig.path;
+ final preamble = config.preamble ?? '';
+ if (config.outputConfig.dartConfig.structure ==
+ OutputStructure.singleFile) {
+ final file = File.fromUri(root);
+ await file.create(recursive: true);
+ log.info("Generating ${cBased ? "C + Dart" : "Pure Dart"} Bindings");
+ final s = file.openWrite();
+ s.writeln(preamble);
+ s.writeln(autoGeneratedNotice);
+ s.writeln(defaultLintSuppressions);
+ s.writeln(defaultImports);
+ if (cBased) {
+ s.writeln(cInitCode);
+ }
+ final resolver = Resolver(
+ importedClasses: config.importedClasses,
+ currentClass: null, // Single file mode.
+ inputClassNames: node.decls.keys.toSet(),
+ );
+ final classGenerator = _ClassGenerator(config, s, resolver);
+ for (final classDecl in node.decls.values) {
+ classDecl.accept(classGenerator);
+ }
+ await s.close();
+ await _runDartFormat(file.path);
+ return;
+ }
+ final files = <String, List<ClassDecl>>{};
+ final packages = <String, Set<String>>{};
+ for (final classDecl in node.decls.values) {
+ final fileClass = Resolver.getFileClassName(classDecl.binaryName);
+
+ files.putIfAbsent(fileClass, () => <ClassDecl>[]);
+ files[fileClass]!.add(classDecl);
+
+ packages.putIfAbsent(classDecl.packageName, () => {});
+ packages[classDecl.packageName]!.add(fileClass.split('.').last);
+ }
+
+ log.info("Using dart root = $root");
+ const initFileName = '_init.dart';
+ if (cBased) {
+ final initFileUri = root.resolve(initFileName);
+ final initFile = File.fromUri(initFileUri);
+ await initFile.create(recursive: true);
+ final initStream = initFile.openWrite();
+ initStream.writeln(preamble);
+ initStream.writeln(cInitImport);
+ initStream.writeln(cInitCode);
+ await initStream.close();
+ }
+ for (var fileClassName in files.keys) {
+ final relativeFileName = '${fileClassName.replaceAll('.', '/')}.dart';
+ final dartFileUri = root.resolve(relativeFileName);
+ final dartFile = await File.fromUri(dartFileUri).create(recursive: true);
+ log.fine('$fileClassName -> ${dartFile.path}');
+
+ final classesInFile = files[fileClassName]!;
+ final dartFileStream = dartFile.openWrite();
+ dartFileStream.writeln(preamble);
+ dartFileStream.writeln(autoGeneratedNotice);
+ dartFileStream.writeln(defaultLintSuppressions);
+ dartFileStream.writeln(defaultImports);
+ final s = StringBuffer();
+ if (cBased) {
+ final initFilePath = ('../' *
+ relativeFileName.codeUnits
+ .where((cu) => cu == '/'.codeUnitAt(0))
+ .length) +
+ initFileName;
+ s.write('import "$initFilePath";');
+ }
+ final resolver = Resolver(
+ importedClasses: config.importedClasses,
+ currentClass: fileClassName,
+ inputClassNames: node.decls.keys.toSet(),
+ );
+ final classGenerator = _ClassGenerator(config, s, resolver);
+ for (final classDecl in classesInFile) {
+ classDecl.accept(classGenerator);
+ }
+ dartFileStream.writeAll(resolver.getImportStrings(), '\n');
+ dartFileStream.writeln(s.toString());
+ await dartFileStream.close();
+ }
+
+ // write _package.dart export files
+ for (var package in packages.keys) {
+ final dirUri = root.resolve('${package.replaceAll('.', '/')}/');
+ final exportFileUri = dirUri.resolve("_package.dart");
+ final exportFile = File.fromUri(exportFileUri);
+ exportFile.createSync(recursive: true);
+ final exports =
+ packages[package]!.map((cls) => 'export "$cls.dart";').join('\n');
+ exportFile.writeAsStringSync(exports);
+ }
+ await _runDartFormat(root.toFilePath());
+ log.info('Completed.');
+ }
+}
+
+/// Generates the Dart class definition, type class, and the array extension.
+class _ClassGenerator extends Visitor<ClassDecl, void> {
+ final Config config;
+ final StringSink s;
+ final Resolver resolver;
+
+ _ClassGenerator(
+ this.config,
+ this.s,
+ this.resolver,
+ );
+
+ static const staticTypeGetter = 'type';
+ static const instanceTypeGetter = '\$$staticTypeGetter';
+
+ @override
+ void visit(ClassDecl node) {
+ final isDartOnly =
+ config.outputConfig.bindingsType == BindingsType.dartOnly;
+
+ // Docs.
+ s.write('/// from: ${node.binaryName}\n');
+ node.javadoc?.accept(_DocGenerator(s, depth: 0));
+
+ // Class definition.
+ final name = node.finalName;
+ final superName = node.superclass!.accept(_TypeGenerator(resolver));
+ final implClassName = '\$${name}Impl';
+ final typeParamsDef = _encloseIfNotEmpty(
+ '<',
+ node.allTypeParams
+ .accept(const _TypeParamGenerator(withExtends: true))
+ .join(', '),
+ '>',
+ );
+ final typeParams = node.allTypeParams
+ .accept(const _TypeParamGenerator(withExtends: false));
+ final typeParamsCall = _encloseIfNotEmpty(
+ '<',
+ typeParams.map((typeParam) => '$_typeParamPrefix$typeParam').join(', '),
+ '>',
+ );
+ final staticTypeGetterCallArgs = _encloseIfNotEmpty(
+ '(',
+ typeParams.join(', '),
+ ')',
+ );
+ final typeClassesDef = typeParams
+ .map((typeParam) =>
+ 'final $_jType<$_typeParamPrefix$typeParam> $typeParam;')
+ .join(_newLine(depth: 1));
+ final ctorTypeClassesDef = typeParams
+ .map((typeParam) => 'this.$typeParam,')
+ .join(_newLine(depth: 2));
+ final superClass = (node.classDecl.superclass!.type as DeclaredType);
+ final superTypeClassesCall = superClass.classDecl.isObject
+ ? ''
+ : superClass.params
+ .accept(_TypeClassGenerator(resolver))
+ .map((typeClass) => '${typeClass.name},')
+ .join(_newLine(depth: 2));
+ s.write('''
+class $name$typeParamsDef extends $superName {
+ @override
+ late final $_jType<$name$typeParamsCall> $instanceTypeGetter = $staticTypeGetter$staticTypeGetterCallArgs;
+
+ $typeClassesDef
+
+ $name.fromRef(
+ $ctorTypeClassesDef
+ $_jPointer ref,
+ ): super.fromRef(
+ $superTypeClassesCall
+ ref
+ );
+
+''');
+
+ if (isDartOnly) {
+ final internalName = node.internalName;
+ s.write('''
+ static final _class = $_jni.Jni.findJClass(r"$internalName");
+
+''');
+ }
+
+ // Static TypeClass getter.
+ s.writeln(
+ ' /// The type which includes information such as the signature of this class.');
+ final typeClassName = node.typeClassName;
+ if (typeParams.isEmpty) {
+ s.writeln('static const $staticTypeGetter = $typeClassName();');
+ } else {
+ final staticTypeGetterTypeClassesDef = typeParams
+ .map(
+ (typeParam) => '$_jType<$_typeParamPrefix$typeParam> $typeParam,')
+ .join(_newLine(depth: 2));
+ final typeClassesCall =
+ typeParams.map((typeParam) => '$typeParam,').join(_newLine(depth: 3));
+ s.write('''
+ static $typeClassName$typeParamsCall $staticTypeGetter$typeParamsDef(
+ $staticTypeGetterTypeClassesDef
+ ) {
+ return $typeClassName(
+ $typeClassesCall
+ );
+ }
+
+''');
+ }
+
+ // Fields and Methods
+ final fieldGenerator = _FieldGenerator(config, resolver, s);
+ for (final field in node.fields) {
+ field.accept(fieldGenerator);
+ }
+ final methodGenerator = _MethodGenerator(config, resolver, s);
+ for (final method in node.methods) {
+ method.accept(methodGenerator);
+ }
+
+ // Experimental: Interface implementation.
+ if (node.declKind == DeclKind.interfaceKind &&
+ (config.experiments?.contains(Experiment.interfaceImplementation) ??
+ false)) {
+ s.write('''
+ /// Maps a specific port to the implemented interface.
+ static final Map<int, $implClassName> _\$impls = {};
+''');
+ s.write(r'''
+ ReceivePort? _$p;
+
+ static jni.JObjectPtr _$invoke(
+ int port,
+ jni.JObjectPtr descriptor,
+ jni.JObjectPtr args,
+ ) {
+ return _$invokeMethod(
+ port,
+ $MethodInvocation.fromAddresses(
+ 0,
+ descriptor.address,
+ args.address,
+ ),
+ );
+ }
+
+ static final ffi.Pointer<
+ ffi.NativeFunction<
+ jni.JObjectPtr Function(
+ ffi.Uint64, jni.JObjectPtr, jni.JObjectPtr)>>
+ _$invokePointer = ffi.Pointer.fromFunction(_$invoke);
+
+ static ffi.Pointer<ffi.Void> _$invokeMethod(
+ int $p,
+ $MethodInvocation $i,
+ ) {
+ try {
+ final $d = $i.methodDescriptor.toDartString(releaseOriginal: true);
+ final $a = $i.args;
+ ''');
+ final proxyMethodIf = _InterfaceMethodIf(resolver, s);
+ for (final method in node.methods) {
+ method.accept(proxyMethodIf);
+ }
+ s.write('''
+ } catch (e) {
+ return $_protectedExtension.newDartException(e.toString());
+ }
+ return jni.nullptr;
+ }
+
+ factory $name.implement(
+ $implClassName$typeParamsCall \$impl,
+ ) {
+''');
+ final typeClassesCall = typeParams
+ .map((typeParam) => '\$impl.$typeParam,')
+ .join(_newLine(depth: 3));
+ s.write('''
+ final \$p = ReceivePort();
+ final \$x = $name.fromRef(
+ $typeClassesCall
+ $_protectedExtension.newPortProxy(
+ r"${node.binaryName}",
+ \$p,
+ _\$invokePointer,
+ ),
+ ).._\$p = \$p;
+ final \$a = \$p.sendPort.nativePort;
+ _\$impls[\$a] = \$impl;
+ \$p.listen((\$m) {
+ if (\$m == null) {
+ _\$impls.remove(\$p.sendPort.nativePort);
+ \$p.close();
+ return;
+ }
+ final \$i = \$MethodInvocation.fromMessage(\$m as List<dynamic>);
+ final \$r = _\$invokeMethod(\$p.sendPort.nativePort, \$i);
+ $_protectedExtension.returnResult(\$i.result, \$r);
+ });
+ return \$x;
+ }
+ ''');
+ }
+
+ // Writing any custom code provided for this class.
+ if (config.customClassBody?.containsKey(node.binaryName) ?? false) {
+ s.writeln(config.customClassBody![node.binaryName]);
+ }
+
+ // End of Class definition.
+ s.writeln('}');
+
+ // Experimental: Interface implementation
+ // Abstract and concrete Impl class definition.
+ // Used for interface implementation.
+ if (node.declKind == DeclKind.interfaceKind &&
+ (config.experiments?.contains(Experiment.interfaceImplementation) ??
+ false)) {
+ // Abstract Impl class.
+ final typeClassGetters = typeParams
+ .map((typeParam) =>
+ '$_jType<$_typeParamPrefix$typeParam> get $typeParam;')
+ .join(_newLine(depth: 1));
+ final abstractFactoryArgs = _encloseIfNotEmpty(
+ '{',
+ [
+ ...typeParams
+ .map((typeParam) => 'required $_jType<\$$typeParam> $typeParam,'),
+ ...node.methods.accept(_ConcreteImplClosureCtorArg(resolver)),
+ ].join(_newLine(depth: 2)),
+ '}',
+ );
+ s.write('''
+abstract interface class $implClassName$typeParamsDef {
+ factory $implClassName(
+ $abstractFactoryArgs
+ ) = _$implClassName;
+
+ $typeClassGetters
+
+''');
+ final abstractImplMethod = _AbstractImplMethod(resolver, s);
+ for (final method in node.methods) {
+ method.accept(abstractImplMethod);
+ }
+ s.writeln('}');
+
+ // Concrete Impl class.
+ // This is for passing closures instead of implementing the class.
+ final concreteCtorArgs = _encloseIfNotEmpty(
+ '{',
+ [
+ ...typeParams.map((typeParam) => 'required this.$typeParam,'),
+ ...node.methods.accept(_ConcreteImplClosureCtorArg(resolver)),
+ ].join(_newLine(depth: 2)),
+ '}',
+ );
+ final setClosures = _encloseIfNotEmpty(
+ ' : ',
+ node.methods
+ .map((method) => '_${method.finalName} = ${method.finalName}')
+ .join(', '),
+ '',
+ );
+ final typeClassesDef = typeParams.map((typeParam) => '''
+@override
+final $_jType<\$$typeParam> $typeParam;
+''').join(_newLine(depth: 1));
+ s.write('''
+
+class _$implClassName$typeParamsDef implements $implClassName$typeParamsCall {
+ _$implClassName(
+ $concreteCtorArgs
+ )$setClosures;
+
+ $typeClassesDef
+
+''');
+ final concreteClosureDef = _ConcreteImplClosureDef(resolver, s);
+ for (final method in node.methods) {
+ method.accept(concreteClosureDef);
+ }
+ s.writeln();
+ final concreteMethodDef = _ConcreteImplMethod(resolver, s);
+ for (final method in node.methods) {
+ method.accept(concreteMethodDef);
+ }
+ s.writeln('}');
+ }
+ // TypeClass definition.
+ final typeClassesCall =
+ typeParams.map((typeParam) => '$typeParam,').join(_newLine(depth: 2));
+ final signature = node.signature;
+ final superTypeClass = superClass.accept(_TypeClassGenerator(resolver));
+ final hashCodeTypeClasses = typeParams.join(', ');
+ final equalityTypeClasses = typeParams
+ .map((typeParam) => ' &&\n $typeParam == other.$typeParam')
+ .join();
+ final hashCode = typeParams.isEmpty
+ ? '($typeClassName).hashCode'
+ : 'Object.hash($typeClassName, $hashCodeTypeClasses)';
+ s.write('''
+final class $typeClassName$typeParamsDef extends $_jType<$name$typeParamsCall> {
+ $typeClassesDef
+
+ const $typeClassName(
+ $ctorTypeClassesDef
+ );
+
+ @override
+ String get signature => r"$signature";
+
+ @override
+ $name$typeParamsCall fromRef($_jPointer ref) => $name.fromRef(
+ $typeClassesCall
+ ref
+ );
+
+ @override
+ $_jType get superType => ${superTypeClass.name};
+
+ @override
+ final superCount = ${node.superCount};
+
+ @override
+ int get hashCode => $hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($typeClassName$typeParamsCall) &&
+ other is $typeClassName$typeParamsCall$equalityTypeClasses;
+ }
+}
+
+''');
+ log.finest('Generated bindings for class ${node.binaryName}');
+ }
+}
+
+/// Generates the JavaDoc comments.
+class _DocGenerator extends Visitor<JavaDocComment, void> {
+ final StringSink s;
+ final int depth;
+
+ const _DocGenerator(this.s, {required this.depth});
+
+ @override
+ void visit(JavaDocComment node) {
+ final link = RegExp('{@link ([^{}]+)}');
+ final indent = ' ' * depth;
+ final comments = node.comment
+ .replaceAllMapped(link, (match) => match.group(1) ?? '')
+ .replaceAll('#', '\\#')
+ .replaceAll('<p>', '')
+ .replaceAll('</p>', '\n')
+ .replaceAll('<b>', '__')
+ .replaceAll('</b>', '__')
+ .replaceAll('<em>', '_')
+ .replaceAll('</em>', '_')
+ .split('\n')
+ .join('\n$indent///');
+ s.write('''
+$indent///
+$indent/// $comments
+''');
+ }
+}
+
+/// Generates the user-facing Dart type.
+class _TypeGenerator extends TypeVisitor<String> {
+ final Resolver? resolver;
+
+ const _TypeGenerator(this.resolver);
+
+ @override
+ String visitArrayType(ArrayType node) {
+ final innerType = node.type;
+ if (innerType.kind == Kind.primitive) {
+ return '$_jArray<$_jni.j${(innerType.type as PrimitiveType).name}>';
+ }
+ return '$_jArray<${innerType.accept(this)}>';
+ }
+
+ @override
+ String visitDeclaredType(DeclaredType node) {
+ if (node.classDecl.binaryName == 'java.lang.Object' ||
+ node.classDecl.binaryName == 'java.lang.String') {
+ return '$_jni.${node.classDecl.finalName}';
+ }
+
+ // All type parameters of this type
+ final allTypeParams = node.classDecl.allTypeParams
+ .accept(const _TypeParamGenerator(withExtends: false))
+ .toList();
+ // The ones that are declared.
+ final definedTypeParams = node.params.accept(this).toList();
+
+ // Replacing the declared ones. They come at the end.
+ // The rest will be JObject.
+ if (allTypeParams.length >= node.params.length) {
+ allTypeParams.replaceRange(
+ 0,
+ allTypeParams.length - node.params.length,
+ List.filled(
+ allTypeParams.length - node.params.length,
+ _jObject,
+ ),
+ );
+ allTypeParams.replaceRange(
+ allTypeParams.length - node.params.length,
+ allTypeParams.length,
+ definedTypeParams,
+ );
+ }
+
+ final typeParams = _encloseIfNotEmpty('<', allTypeParams.join(', '), '>');
+ final prefix = resolver?.resolvePrefix(node.classDecl) ?? '';
+ return '$prefix${node.classDecl.finalName}$typeParams';
+ }
+
+ @override
+ String visitPrimitiveType(PrimitiveType node) {
+ return node.dartType;
+ }
+
+ @override
+ String visitTypeVar(TypeVar node) {
+ return '$_typeParamPrefix${node.name}';
+ }
+
+ @override
+ String visitWildcard(Wildcard node) {
+ // TODO(#141): Support wildcards
+ return super.visitWildcard(node);
+ }
+
+ @override
+ String visitNonPrimitiveType(ReferredType node) {
+ return _jObject;
+ }
+}
+
+class _TypeClass {
+ final String name;
+ final bool canBeConst;
+
+ const _TypeClass(this.name, this.canBeConst);
+}
+
+/// Generates the type class.
+class _TypeClassGenerator extends TypeVisitor<_TypeClass> {
+ final bool isConst;
+
+ /// Whether or not to return the equivalent boxed type class for primitives.
+ /// Only for interface implemetation.
+ final bool boxPrimitives;
+
+ /// Whether or not to find the correct type variable from the static map.
+ /// Only for interface implemetation.
+ final bool typeVarFromMap;
+
+ final Resolver resolver;
+
+ _TypeClassGenerator(
+ this.resolver, {
+ this.isConst = true,
+ this.boxPrimitives = false,
+ this.typeVarFromMap = false,
+ });
+
+ @override
+ _TypeClass visitArrayType(ArrayType node) {
+ final innerTypeClass = node.type.accept(_TypeClassGenerator(
+ resolver,
+ isConst: false,
+ boxPrimitives: false,
+ typeVarFromMap: typeVarFromMap,
+ ));
+ final ifConst = innerTypeClass.canBeConst && isConst ? 'const ' : '';
+ return _TypeClass(
+ '$ifConst${_jArray}Type(${innerTypeClass.name})',
+ innerTypeClass.canBeConst,
+ );
+ }
+
+ @override
+ _TypeClass visitDeclaredType(DeclaredType node) {
+ final allTypeParams = node.classDecl.allTypeParams
+ .accept(const _TypeParamGenerator(withExtends: false))
+ .toList();
+
+ // The ones that are declared.
+ final definedTypeClasses = node.params.accept(_TypeClassGenerator(
+ resolver,
+ isConst: false,
+ boxPrimitives: false,
+ typeVarFromMap: typeVarFromMap,
+ ));
+
+ // Can be const if all the type parameters are defined and each of them are
+ // also const.
+ final canBeConst =
+ allTypeParams.isEmpty || definedTypeClasses.every((e) => e.canBeConst);
+
+ // Replacing the declared ones. They come at the end.
+ // The rest will be `JObjectType`.
+ if (allTypeParams.length >= node.params.length) {
+ allTypeParams.replaceRange(
+ 0,
+ allTypeParams.length - node.params.length,
+ List.filled(
+ allTypeParams.length - node.params.length,
+ // Adding const to subexpressions if the entire expression is not const.
+ '${canBeConst ? '' : 'const '}${_jObject}Type()',
+ ),
+ );
+ allTypeParams.replaceRange(
+ allTypeParams.length - node.params.length,
+ allTypeParams.length,
+ // Adding const to subexpressions if the entire expression is not const.
+ definedTypeClasses.map((param) =>
+ '${param.canBeConst && !canBeConst ? 'const ' : ''}${param.name}'),
+ );
+ }
+
+ final args = allTypeParams.join(', ');
+ final ifConst = isConst && canBeConst ? 'const ' : '';
+ final prefix = resolver.resolvePrefix(node.classDecl);
+ return _TypeClass(
+ '$ifConst$prefix${node.classDecl.typeClassName}($args)',
+ canBeConst,
+ );
+ }
+
+ @override
+ _TypeClass visitPrimitiveType(PrimitiveType node) {
+ final ifConst = isConst ? 'const ' : '';
+ final name = boxPrimitives ? 'J${node.boxedName}' : 'j${node.name}';
+ return _TypeClass('$ifConst$_jni.${name}Type()', true);
+ }
+
+ @override
+ _TypeClass visitTypeVar(TypeVar node) {
+ if (typeVarFromMap) {
+ return _TypeClass('_\$impls[\$p]!.${node.name}', false);
+ }
+ return _TypeClass(node.name, false);
+ }
+
+ @override
+ _TypeClass visitWildcard(Wildcard node) {
+ // TODO(#141): Support wildcards
+ return super.visitWildcard(node);
+ }
+
+ @override
+ _TypeClass visitNonPrimitiveType(ReferredType node) {
+ final ifConst = isConst ? 'const ' : '';
+ return _TypeClass('$ifConst${_jObject}Type()', true);
+ }
+}
+
+class _TypeParamGenerator extends Visitor<TypeParam, String> {
+ final bool withExtends;
+
+ const _TypeParamGenerator({required this.withExtends});
+
+ @override
+ String visit(TypeParam node) {
+ if (!withExtends) {
+ return node.name;
+ }
+ // TODO(#144): resolve the actual type being extended, if any.
+ return '$_typeParamPrefix${node.name} extends $_jObject';
+ }
+}
+
+class _JniResultGetter extends TypeVisitor<String> {
+ const _JniResultGetter();
+
+ @override
+ String visitPrimitiveType(PrimitiveType node) {
+ if (node.name == 'void') return 'check()';
+ if (node.name == 'double') return 'doubleFloat';
+ if (node.name == 'int') return 'integer';
+ return node.name;
+ }
+
+ @override
+ String visitNonPrimitiveType(ReferredType node) {
+ return 'object';
+ }
+}
+
+/// Type signature for C-based bindings.
+///
+/// When `isFFi` is `true`, it generates the ffi type signature and when it's
+/// false, it generates the dart type signature.
+///
+/// For example `ffi.Int32` is an ffi type signature while `int` is a Dart one:
+/// ```dart
+/// jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Int32, ffi.Int32)>>(
+/// "sum")
+/// .asFunction<jni.JniResult Function(int, int)>();
+/// ```
+class _TypeSig extends TypeVisitor<String> {
+ final bool isFfi;
+
+ const _TypeSig({required this.isFfi});
+
+ @override
+ String visitPrimitiveType(PrimitiveType node) {
+ if (isFfi) return '$_ffi.${node.ffiType}';
+ if (node.name == 'boolean') return 'int';
+ return node.dartType;
+ }
+
+ @override
+ String visitNonPrimitiveType(ReferredType node) {
+ return _voidPointer;
+ }
+}
+
+class _TypeName extends TypeVisitor<String> {
+ const _TypeName();
+
+ @override
+ String visitPrimitiveType(PrimitiveType node) {
+ return node.name;
+ }
+
+ @override
+ String visitNonPrimitiveType(ReferredType node) {
+ return 'object';
+ }
+}
+
+class _CallType extends TypeVisitor<String> {
+ const _CallType();
+
+ @override
+ String visitPrimitiveType(PrimitiveType node) {
+ return '$_jCallType.${node.name}Type';
+ }
+
+ @override
+ String visitNonPrimitiveType(ReferredType node) {
+ return '$_jCallType.objectType';
+ }
+}
+
+class _ToNativeSuffix extends TypeVisitor<String> {
+ const _ToNativeSuffix();
+
+ @override
+ String visitPrimitiveType(PrimitiveType node) {
+ if (node.name == 'boolean') {
+ return ' ? 1 : 0';
+ }
+ return '';
+ }
+
+ @override
+ String visitNonPrimitiveType(ReferredType node) {
+ return '.$_selfPointer';
+ }
+}
+
+class _FromNative extends TypeVisitor<String> {
+ final Resolver resolver;
+ final String value;
+
+ const _FromNative(this.resolver, this.value);
+
+ @override
+ String visitPrimitiveType(PrimitiveType node) {
+ return value;
+ }
+
+ @override
+ String visitNonPrimitiveType(ReferredType node) {
+ final typeClass = node.accept(_TypeClassGenerator(resolver)).name;
+ return '$typeClass.fromRef($value)';
+ }
+}
+
+class _FieldGenerator extends Visitor<Field, void> {
+ final Config config;
+ final Resolver resolver;
+ final StringSink s;
+
+ const _FieldGenerator(this.config, this.resolver, this.s);
+
+ void writeCAccessor(Field node) {
+ final name = node.finalName;
+ final cName = node.accept(const CFieldName());
+ final ifRef = node.isStatic ? '' : '$_jPointer, ';
+
+ s.write('''
+ static final _get_$name =
+ $_lookup<$_ffi.NativeFunction<$_jResult Function($ifRef)>>(
+ "get_$cName")
+ .asFunction<$_jResult Function($ifRef)>();
+
+''');
+
+ if (!node.isFinal) {
+ final ffiSig = node.type.accept(const _TypeSig(isFfi: true));
+ final dartSig = node.type.accept(const _TypeSig(isFfi: false));
+ s.write('''
+ static final _set_$name =
+ $_lookup<$_ffi.NativeFunction<$_jResult Function($ifRef$ffiSig)>>(
+ "set_$cName")
+ .asFunction<$_jResult Function($ifRef$dartSig)>();
+
+''');
+ }
+ }
+
+ String cGetter(Field node) {
+ final name = node.finalName;
+ final getter = node.type.accept(const _JniResultGetter());
+ final self = node.isStatic ? '' : _selfPointer;
+ return '_get_$name($self).$getter';
+ }
+
+ String cSetter(Field node) {
+ final name = node.finalName;
+ final self = node.isStatic ? '' : '$_selfPointer, ';
+ final toNativeSuffix = node.type.accept(const _ToNativeSuffix());
+ return '_set_$name(${self}value$toNativeSuffix).check()';
+ }
+
+ void writeDartOnlyAccessor(Field node) {
+ final name = node.finalName;
+ final ifStatic = node.isStatic ? 'Static' : '';
+ final descriptor = node.type.descriptor;
+ s.write('''
+ static final _id_$name =
+ $_accessors.get${ifStatic}FieldIDOf(
+ $_classRef,
+ r"${node.name}",
+ r"$descriptor",
+ );
+''');
+ }
+
+ String dartOnlyGetter(Field node) {
+ final name = node.finalName;
+ final self = node.isStatic ? _classRef : _selfPointer;
+ final ifStatic = node.isStatic ? 'Static' : '';
+ final callType = node.type.accept(const _CallType());
+ final resultGetter = node.type.accept(const _JniResultGetter());
+ return '$_accessors.get${ifStatic}Field($self, _id_$name, $callType)'
+ '.$resultGetter';
+ }
+
+ String dartOnlySetter(Field node) {
+ final name = node.finalName;
+ final self = node.isStatic ? _classRef : _selfPointer;
+ final ifStatic = node.isStatic ? 'Static' : '';
+ final fieldType = node.type.accept(const _TypeName()).capitalize();
+ final toNativeSuffix = node.type.accept(const _ToNativeSuffix());
+ return '$_env.Set$ifStatic${fieldType}Field($self, _id_$name, value$toNativeSuffix)';
+ }
+
+ void writeDocs(Field node, {required bool writeReleaseInstructions}) {
+ final originalDecl = '${node.type.shorthand} ${node.name}';
+ s.writeln(' /// from: ${node.modifiers.join(' ')} $originalDecl');
+ if (node.type.kind != Kind.primitive && writeReleaseInstructions) {
+ s.writeln(_releaseInstruction);
+ }
+ node.javadoc?.accept(_DocGenerator(s, depth: 1));
+ }
+
+ @override
+ void visit(Field node) {
+ final isCBased = config.outputConfig.bindingsType == BindingsType.cBased;
+
+ // Check if it should be a `static const` getter.
+ if (node.isFinal && node.isStatic && node.defaultValue != null) {
+ final name = node.finalName;
+ final value = node.defaultValue!;
+ // TODO(#31): Should we leave String as a normal getter instead?
+ if (value is String || value is num || value is bool) {
+ writeDocs(node, writeReleaseInstructions: false);
+ s.write(' static const $name = ');
+ if (value is String) {
+ s.write('r"""$value"""');
+ } else {
+ s.write(value);
+ }
+ s.writeln(';\n');
+ return;
+ }
+ }
+
+ // Accessors.
+ (isCBased ? writeCAccessor : writeDartOnlyAccessor)(node);
+
+ // Getter docs.
+ writeDocs(node, writeReleaseInstructions: true);
+
+ final name = node.finalName;
+ final ifStatic = node.isStatic ? 'static ' : '';
+ final type = node.type.accept(_TypeGenerator(resolver));
+ s.write('$ifStatic$type get $name => ');
+ s.write(node.type.accept(
+ _FromNative(resolver, (isCBased ? cGetter : dartOnlyGetter)(node)),
+ ));
+ s.writeln(';\n');
+ if (!node.isFinal) {
+ // Setter docs.
+ writeDocs(node, writeReleaseInstructions: true);
+
+ s.write('${ifStatic}set $name($type value) => ');
+ s.write((isCBased ? cSetter : dartOnlySetter)(node));
+ s.writeln(';\n');
+ }
+ }
+}
+
+class _MethodTypeSig extends Visitor<Method, String> {
+ final bool isFfi;
+
+ const _MethodTypeSig({required this.isFfi});
+
+ @override
+ String visit(Method node) {
+ final args = [
+ if (!node.isCtor && !node.isStatic) _voidPointer,
+ ...node.params.map((param) => param.type).accept(
+ _TypeSig(isFfi: isFfi),
+ )
+ ].join(', ');
+ return '$_jResult Function($args)';
+ }
+}
+
+/// Generates Dart bindings for Java methods.
+class _MethodGenerator extends Visitor<Method, void> {
+ final Config config;
+ final Resolver resolver;
+ final StringSink s;
+
+ const _MethodGenerator(this.config, this.resolver, this.s);
+
+ void writeCAccessor(Method node) {
+ final name = node.finalName;
+ final cName = node.accept(const CMethodName());
+ final ffiSig = node.accept(const _MethodTypeSig(isFfi: true));
+ final dartSig = node.accept(const _MethodTypeSig(isFfi: false));
+ s.write('''
+ static final _$name =
+ $_lookup<$_ffi.NativeFunction<$ffiSig>>("$cName")
+ .asFunction<$dartSig>();
+
+''');
+ }
+
+ void writeDartOnlyAccessor(Method node) {
+ final name = node.finalName;
+ final ifStatic = node.isStatic ? 'Static' : '';
+ final descriptor = node.descriptor;
+ s.write('''
+ static final _id_$name = $_accessors.get${ifStatic}MethodIDOf(
+ $_classRef, r"${node.name}", r"$descriptor");
+
+''');
+ }
+
+ bool isSuspendFun(Method node) {
+ return node.asyncReturnType != null;
+ }
+
+ String cCtor(Method node) {
+ final name = node.finalName;
+ final params =
+ node.params.accept(const _ParamCall(isCBased: true)).join(', ');
+ return '_$name($params)';
+ }
+
+ String dartOnlyCtor(Method node) {
+ final name = node.finalName;
+ final params =
+ node.params.accept(const _ParamCall(isCBased: false)).join(', ');
+ return '$_accessors.newObjectWithArgs($_classRef, _id_$name, [$params])';
+ }
+
+ String cMethodCall(Method node) {
+ final name = node.finalName;
+ final params = [
+ if (!node.isStatic) _selfPointer,
+ ...node.params.accept(const _ParamCall(isCBased: true)),
+ ].join(', ');
+ final resultGetter = node.returnType.accept(const _JniResultGetter());
+ return '_$name($params).$resultGetter';
+ }
+
+ String dartOnlyMethodCall(Method node) {
+ final name = node.finalName;
+ final ifStatic = node.isStatic ? 'Static' : '';
+ final self = node.isStatic ? _classRef : _selfPointer;
+ final callType = node.returnType.accept(const _CallType());
+ final params =
+ node.params.accept(const _ParamCall(isCBased: false)).join(', ');
+ final resultGetter = node.returnType.accept(const _JniResultGetter());
+ return '$_accessors.call${ifStatic}MethodWithArgs'
+ '($self, _id_$name, $callType, [$params]).$resultGetter';
+ }
+
+ @override
+ void visit(Method node) {
+ final isCBased = config.outputConfig.bindingsType == BindingsType.cBased;
+
+ // Accessors
+ (isCBased ? writeCAccessor : writeDartOnlyAccessor)(node);
+
+ // Docs
+ s.write(' /// from: ');
+ s.writeAll(node.modifiers.map((m) => '$m '));
+ s.write('${node.returnType.shorthand} ${node.name}(');
+ s.writeAll(node.params.map((p) => '${p.type.shorthand} ${p.name}'), ', ');
+ s.writeln(')');
+ if (node.returnType.kind != Kind.primitive || node.isCtor) {
+ s.writeln(_releaseInstruction);
+ }
+ node.javadoc?.accept(_DocGenerator(s, depth: 1));
+
+ // Used for inferring the type parameter from the given parameters.
+ final typeLocators = node.params
+ .accept(_ParamTypeLocator(resolver: resolver))
+ .fold(<String, List<String>>{}, _mergeMapValues).map(
+ (key, value) => MapEntry(
+ key,
+ _encloseIfNotEmpty(
+ '[',
+ value.delimited(', '),
+ ']',
+ ),
+ ));
+
+ bool isRequired(TypeParam typeParam) {
+ return (typeLocators[typeParam.name] ?? '').isEmpty;
+ }
+
+ final typeInference =
+ (node.isCtor ? node.classDecl.allTypeParams : node.typeParams)
+ .where((tp) => !isRequired(tp))
+ .map((tp) => tp.name)
+ .map((tp) => '$tp ??= $_jni.lowestCommonSuperType'
+ '(${typeLocators[tp]}) as $_jType<$_typeParamPrefix$tp>;')
+ .join(_newLine(depth: 2));
+
+ if (node.isCtor) {
+ final className = node.classDecl.finalName;
+ final name = node.finalName;
+ final ctorName = name == 'new0' ? className : '$className.$name';
+ final paramsDef = node.params.accept(_ParamDef(resolver)).delimited(', ');
+ final typeClassDef = _encloseIfNotEmpty(
+ '{',
+ node.classDecl.allTypeParams
+ .map((typeParam) => typeParam
+ .accept(_CtorTypeClassDef(isRequired: isRequired(typeParam))))
+ .delimited(', '),
+ '}',
+ );
+ final typeClassCall = node.classDecl.allTypeParams
+ .map((typeParam) =>
+ typeParam.accept(const _TypeParamGenerator(withExtends: false)))
+ .delimited(', ');
+
+ final ctorExpr = (isCBased ? cCtor : dartOnlyCtor)(node);
+ s.write('''
+ factory $ctorName($paramsDef$typeClassDef) {
+ $typeInference
+ return ${node.classDecl.finalName}.fromRef(
+ $typeClassCall
+ $ctorExpr.object
+ );
+ }
+
+''');
+ return;
+ }
+
+ final name = node.finalName;
+ final returnType = isSuspendFun(node)
+ ? 'Future<${node.asyncReturnType!.accept(_TypeGenerator(resolver))}>'
+ : node.returnType.accept(_TypeGenerator(resolver));
+ final returnTypeClass = (node.asyncReturnType ?? node.returnType)
+ .accept(_TypeClassGenerator(resolver))
+ .name;
+ final ifStatic = node.isStatic ? 'static ' : '';
+ final defArgs = node.params.accept(_ParamDef(resolver)).toList();
+ final typeClassDef = _encloseIfNotEmpty(
+ '{',
+ node.typeParams
+ .map((typeParam) => typeParam.accept(_MethodTypeClassDef(
+ isRequired: isRequired(typeParam),
+ )))
+ .delimited(', '),
+ '}',
+ );
+ final typeParamsDef = _encloseIfNotEmpty(
+ '<',
+ node.typeParams
+ .accept(const _TypeParamGenerator(withExtends: true))
+ .join(', '),
+ '>',
+ );
+ if (isSuspendFun(node)) {
+ defArgs.removeLast();
+ }
+ final params = defArgs.delimited(', ');
+ s.write(' $ifStatic$returnType $name$typeParamsDef($params$typeClassDef)');
+ final callExpr = (isCBased ? cMethodCall : dartOnlyMethodCall)(node);
+ if (isSuspendFun(node)) {
+ final returning =
+ node.asyncReturnType!.accept(_FromNative(resolver, '\$o'));
+ s.write('''async {
+ $typeInference
+ final \$p = ReceivePort();
+ final \$c = $_jObject.fromRef($_protectedExtension.newPortContinuation(\$p));
+ $callExpr;
+ final \$o = $_jPointer.fromAddress(await \$p.first);
+ final \$k = $returnTypeClass.getClass().reference;
+ if (!$_jni.Jni.env.IsInstanceOf(\$o, \$k)) {
+ throw "Failed";
+ }
+ return $returning;
+ }
+
+''');
+ } else {
+ final returning = node.returnType.accept(_FromNative(resolver, callExpr));
+ s.writeln('''{
+ $typeInference
+ return $returning;
+ }
+''');
+ }
+ }
+}
+
+/// Generates the method type param definition.
+///
+/// For example `required JObjType<T> $T` in:
+/// ```dart
+/// void bar(..., {required JObjType<T> $T}) => ...
+/// ```
+class _MethodTypeClassDef extends Visitor<TypeParam, String> {
+ final bool isRequired;
+
+ const _MethodTypeClassDef({required this.isRequired});
+
+ @override
+ String visit(TypeParam node) {
+ return '${isRequired ? 'required ' : ''}$_jType'
+ '<$_typeParamPrefix${node.name}>${isRequired ? '' : '?'} ${node.name}';
+ }
+}
+
+/// Generates the class type param definition. Used only in constructors.
+///
+/// For example `required this.$T` in:
+/// ```dart
+/// class Foo {
+/// final JObjType<T> $T;
+/// Foo(..., {required this.$T}) => ...
+/// }
+/// ```
+class _CtorTypeClassDef extends Visitor<TypeParam, String> {
+ final bool isRequired;
+
+ const _CtorTypeClassDef({required this.isRequired});
+
+ @override
+ String visit(TypeParam node) {
+ return '${isRequired ? 'required ' : ''} $_jType'
+ '<$_typeParamPrefix${node.name}>${isRequired ? '' : '?'} ${node.name}';
+ }
+}
+
+/// Method parameter's definition.
+///
+/// For example `Foo foo` in:
+/// ```dart
+/// void bar(Foo foo) => ...
+/// ```
+class _ParamDef extends Visitor<Param, String> {
+ final Resolver resolver;
+
+ const _ParamDef(this.resolver);
+
+ @override
+ String visit(Param node) {
+ final type = node.type.accept(_TypeGenerator(resolver));
+ return '$type ${node.finalName}';
+ }
+}
+
+/// Method parameter used in calling the native method.
+///
+/// For example `foo.reference` in:
+/// ```dart
+/// void bar(Foo foo) => _bar(foo.reference);
+/// ```
+class _ParamCall extends Visitor<Param, String> {
+ final bool isCBased;
+
+ const _ParamCall({required this.isCBased});
+
+ @override
+ String visit(Param node) {
+ final nativeSuffix = node.type.accept(const _ToNativeSuffix());
+ final paramCall = '${node.finalName}$nativeSuffix';
+ if (!isCBased) {
+ // We need to wrap [paramCall] in the appropriate wrapper class.
+ return node.type.accept(_JValueWrapper(paramCall));
+ }
+ return paramCall;
+ }
+}
+
+/// Wraps the parameter in the appropriate JValue wrapper class.
+///
+/// For instance, `int` in Dart can be mapped to `long` or `int` or ... in Java.
+/// The wrapper class is how we identify the type in pure dart bindings.
+class _JValueWrapper extends TypeVisitor<String> {
+ final String param;
+
+ _JValueWrapper(this.param);
+
+ @override
+ String visitNonPrimitiveType(ReferredType node) {
+ return param;
+ }
+
+ @override
+ String visitPrimitiveType(PrimitiveType node) {
+ if (node.name == 'long' ||
+ node.name == 'double' ||
+ node.name == 'boolean') {
+ return param;
+ }
+ return '$_jni.JValue${node.name.capitalize()}($param)';
+ }
+}
+
+/// A pair of [StringBuffer]s that can create an expression from the outer layer
+/// inwards.
+///
+/// For example:
+/// ```dart
+/// final buffer = OutsideInBuffer(); // asterisk (*) is used to show the middle
+/// buffer.appendLeft('f('); // f(*
+/// buffer.prependRight('x)'); // f(*x)
+/// buffer.appendLeft('g('); // f(g(*x)
+/// buffer.prependRight('y) + '); // f(g(*y) + x)
+/// buffer.toString(); // f(g(y) + x)
+/// ```
+@visibleForTesting
+class OutsideInBuffer {
+ final StringBuffer _leftBuffer;
+ final StringBuffer _rightBuffer;
+
+ OutsideInBuffer()
+ : _leftBuffer = StringBuffer(),
+ _rightBuffer = StringBuffer();
+
+ void prependRight(Object? object) {
+ final s = object.toString();
+ for (var i = 0; i < s.length; ++i) {
+ _rightBuffer.write(s[s.length - i - 1]);
+ }
+ }
+
+ void appendLeft(Object? object) {
+ _leftBuffer.write(object);
+ }
+
+ @override
+ String toString() {
+ return _leftBuffer.toString() + _rightBuffer.toString().reversed;
+ }
+}
+
+/// The ways to locate each type parameter.
+///
+/// For example in `JArray<JMap<$T, $T>> a`, `T` can be retreived using
+/// ```dart
+/// ((((a.$type as jni.JArrayType).elementType) as $JMapType).K) as jni.JObjType<$T>
+/// ```
+/// and
+/// ```dart
+/// ((((a.$type as jni.JArrayType).elementType) as $JMapType).V) as jni.JObjType<$T>
+/// ```
+class _ParamTypeLocator extends Visitor<Param, Map<String, List<String>>> {
+ final Resolver resolver;
+
+ _ParamTypeLocator({required this.resolver});
+
+ @override
+ Map<String, List<String>> visit(Param node) {
+ return node.type.accept(_TypeVarLocator(resolver: resolver)).map(
+ (key, value) => MapEntry(
+ key,
+ value
+ .map((e) =>
+ (e..appendLeft('${node.finalName}.\$type')).toString())
+ .toList(),
+ ),
+ );
+ }
+}
+
+class _TypeVarLocator extends TypeVisitor<Map<String, List<OutsideInBuffer>>> {
+ final Resolver resolver;
+
+ _TypeVarLocator({required this.resolver});
+
+ @override
+ Map<String, List<OutsideInBuffer>> visitNonPrimitiveType(ReferredType node) {
+ return {};
+ }
+
+ @override
+ Map<String, List<OutsideInBuffer>> visitWildcard(Wildcard node) {
+ // TODO(#141): Support wildcards
+ return super.visitWildcard(node);
+ }
+
+ @override
+ Map<String, List<OutsideInBuffer>> visitTypeVar(TypeVar node) {
+ return {
+ node.name: [
+ OutsideInBuffer(),
+ ],
+ };
+ }
+
+ @override
+ Map<String, List<OutsideInBuffer>> visitDeclaredType(DeclaredType node) {
+ if (node.classDecl.isObject) {
+ return {};
+ }
+ final offset = node.classDecl.allTypeParams.length - node.params.length;
+ final result = <String, List<OutsideInBuffer>>{};
+ final prefix = resolver.resolvePrefix(node.classDecl);
+ final typeClass = '$prefix${node.classDecl.typeClassName}';
+ for (var i = 0; i < node.params.length; ++i) {
+ final typeParam = node.classDecl.allTypeParams[i + offset].name;
+ final exprs = node.params[i].accept(this);
+ for (final expr in exprs.entries) {
+ for (final buffer in expr.value) {
+ buffer.appendLeft('(');
+ buffer.prependRight(' as $typeClass).$typeParam');
+ result[expr.key] = (result[expr.key] ?? [])..add(buffer);
+ }
+ }
+ }
+ return result;
+ }
+
+ @override
+ Map<String, List<OutsideInBuffer>> visitArrayType(ArrayType node) {
+ final exprs = node.type.accept(this);
+ for (final e in exprs.values.expand((i) => i)) {
+ e.appendLeft('((');
+ e.prependRight(' as ${_jArray}Type).elementType as $_jType)');
+ }
+ return exprs;
+ }
+
+ @override
+ Map<String, List<OutsideInBuffer>> visitPrimitiveType(PrimitiveType node) {
+ return {};
+ }
+}
+
+/// Method defintion for Impl abstract class used for interface implementation.
+class _AbstractImplMethod extends Visitor<Method, void> {
+ final Resolver resolver;
+ final StringSink s;
+
+ _AbstractImplMethod(this.resolver, this.s);
+
+ @override
+ void visit(Method node) {
+ final returnType = node.returnType.accept(_TypeGenerator(resolver));
+ final name = node.finalName;
+ final args = node.params.accept(_ParamDef(resolver)).join(', ');
+ s.writeln(' $returnType $name($args);');
+ }
+}
+
+/// Closure defintion for concrete Impl class used for interface implementation.
+class _ConcreteImplClosureDef extends Visitor<Method, void> {
+ final Resolver resolver;
+ final StringSink s;
+
+ _ConcreteImplClosureDef(this.resolver, this.s);
+
+ @override
+ void visit(Method node) {
+ final returnType = node.returnType.accept(_TypeGenerator(resolver));
+ final name = node.finalName;
+ final args = node.params.accept(_ParamDef(resolver)).join(', ');
+ s.writeln(' final $returnType Function($args) _$name;');
+ }
+}
+
+/// Closure argument for concrete Impl class constructor.
+/// Used for interface implementation.
+class _ConcreteImplClosureCtorArg extends Visitor<Method, String> {
+ final Resolver resolver;
+
+ _ConcreteImplClosureCtorArg(this.resolver);
+
+ @override
+ String visit(Method node) {
+ final returnType = node.returnType.accept(_TypeGenerator(resolver));
+ final name = node.finalName;
+ final args = node.params.accept(_ParamDef(resolver)).join(', ');
+ return 'required $returnType Function($args) $name,';
+ }
+}
+
+/// Method defintion for concrete Impl class used for interface implementation.
+class _ConcreteImplMethod extends Visitor<Method, void> {
+ final Resolver resolver;
+ final StringSink s;
+
+ _ConcreteImplMethod(this.resolver, this.s);
+
+ @override
+ void visit(Method node) {
+ final returnType = node.returnType.accept(_TypeGenerator(resolver));
+ final name = node.finalName;
+ final argsDef = node.params.accept(_ParamDef(resolver)).join(', ');
+ final argsCall = node.params.map((param) => param.finalName).join(', ');
+ s.write('''
+ $returnType $name($argsDef) {
+ return _$name($argsCall);
+ }''');
+ }
+}
+
+/// The if statement to check which method has been called from the proxy class.
+class _InterfaceMethodIf extends Visitor<Method, void> {
+ final Resolver resolver;
+ final StringSink s;
+
+ _InterfaceMethodIf(this.resolver, this.s);
+
+ @override
+ void visit(Method node) {
+ final isVoid = node.returnType.name == 'void';
+ final signature = node.javaSig;
+ final saveResult = isVoid ? '' : 'final \$r = ';
+ final name = node.finalName;
+ s.write('''
+ if (\$d == r"$signature") {
+ ${saveResult}_\$impls[\$p]!.$name(
+''');
+ for (var i = 0; i < node.params.length; ++i) {
+ node.params[i].accept(_InterfaceParamCast(resolver, s, paramIndex: i));
+ }
+ const returnBox = _InterfaceReturnBox();
+ s.write('''
+ );
+ return ${node.returnType.accept(returnBox)};
+ }
+''');
+ }
+}
+
+/// Generates casting to the correct parameter type from the list of JObject
+/// arguments received from the call to the proxy class.
+class _InterfaceParamCast extends Visitor<Param, void> {
+ final Resolver resolver;
+ final StringSink s;
+ final int paramIndex;
+
+ _InterfaceParamCast(
+ this.resolver,
+ this.s, {
+ required this.paramIndex,
+ });
+
+ @override
+ void visit(Param node) {
+ final typeClass = node.type
+ .accept(_TypeClassGenerator(
+ resolver,
+ boxPrimitives: true,
+ typeVarFromMap: true,
+ ))
+ .name;
+ s.write('\$a[$paramIndex].castTo($typeClass, releaseOriginal: true)');
+ if (node.type.kind == Kind.primitive) {
+ // Convert to Dart type.
+ final name = (node.type.type as PrimitiveType).name;
+ s.write('.${name}Value(releaseOriginal: true)');
+ }
+ s.writeln(',');
+ }
+}
+
+/// Boxes the returned primitive value into the correct Boxed type.
+/// Only returns the reference for non primitive types.
+/// Returns null for void.
+///
+/// Since Dart doesn't know that this global reference is still used, it might
+/// garbage collect it via [NativeFinalizer] thus making it invalid.
+/// This passes the ownership to Java using [setAsReleased].
+///
+/// `toPointer` detaches the object from the [NativeFinalizer] and Java
+/// will clean up the global reference afterwards.
+///
+/// For example `$r.toJInteger().toPointer()` when the return
+/// type is `integer`.
+class _InterfaceReturnBox extends TypeVisitor<String> {
+ const _InterfaceReturnBox();
+
+ @override
+ String visitNonPrimitiveType(ReferredType node) {
+ // Casting is done to create a new global reference. The user might
+ // use the original reference elsewhere and so the original object
+ // should not be [setAsReleased].
+ return '(\$r as $_jObject).castTo(const ${_jObject}Type()).toPointer()';
+ }
+
+ @override
+ String visitPrimitiveType(PrimitiveType node) {
+ if (node.name == 'void') {
+ return '$_jni.nullptr';
+ }
+ return '$_jni.J${node.boxedName}(\$r).toPointer()';
+ }
+}
diff --git a/pkgs/jnigen/lib/src/bindings/descriptor.dart b/pkgs/jnigen/lib/src/bindings/descriptor.dart
new file mode 100644
index 0000000..f7d774a
--- /dev/null
+++ b/pkgs/jnigen/lib/src/bindings/descriptor.dart
@@ -0,0 +1,115 @@
+import '../elements/elements.dart';
+import 'visitor.dart';
+
+/// Adds the type and method descriptor to all methods in all of the classes.
+///
+/// ASM already fills the descriptor field for methods but doclet does not.
+class Descriptor extends Visitor<Classes, void> {
+ const Descriptor();
+
+ @override
+ void visit(Classes node) {
+ for (final classDecl in node.decls.values) {
+ classDecl.accept(const _ClassDescriptor());
+ }
+ }
+}
+
+class _ClassDescriptor extends Visitor<ClassDecl, void> {
+ const _ClassDescriptor();
+
+ @override
+ void visit(ClassDecl node) {
+ final methodDescriptor = MethodDescriptor(node.allTypeParams);
+ for (final method in node.methods) {
+ method.descriptor ??= method.accept(methodDescriptor);
+ }
+ final typeDescriptor = TypeDescriptor(node.allTypeParams);
+ for (final field in node.fields) {
+ field.type.descriptor = field.type.accept(typeDescriptor);
+ }
+ for (final interface in node.interfaces) {
+ interface.descriptor = interface.accept(typeDescriptor);
+ }
+ }
+}
+
+/// Generates JNI Method descriptor.
+///
+/// https://docs.oracle.com/en/java/javase/18/docs/specs/jni/types.html#type-signatures
+/// Also see: [TypeDescriptor]
+class MethodDescriptor extends Visitor<Method, String> {
+ final List<TypeParam> typeParams;
+
+ MethodDescriptor(this.typeParams);
+
+ @override
+ String visit(Method node) {
+ final s = StringBuffer();
+ final typeParamsIncludingThis = [...typeParams, ...node.typeParams];
+ final typeDescriptor = TypeDescriptor(typeParamsIncludingThis);
+ s.write('(');
+ for (final param in node.params) {
+ final desc = param.type.accept(typeDescriptor);
+ param.type.descriptor = desc;
+ s.write(desc);
+ }
+ s.write(')');
+ final returnTypeDesc =
+ node.returnType.accept(TypeDescriptor(typeParamsIncludingThis));
+ node.returnType.descriptor = returnTypeDesc;
+ s.write(returnTypeDesc);
+ return s.toString();
+ }
+}
+
+/// JVM representation of type signatures.
+///
+/// https://docs.oracle.com/en/java/javase/18/docs/specs/jni/types.html#type-signatures
+class TypeDescriptor extends TypeVisitor<String> {
+ final List<TypeParam> typeParams;
+
+ TypeDescriptor(this.typeParams);
+
+ @override
+ String visitArrayType(ArrayType node) {
+ final inner = node.type.accept(this);
+ return '[$inner';
+ }
+
+ @override
+ String visitDeclaredType(DeclaredType node) {
+ final internalName = node.binaryName.replaceAll('.', '/');
+ return 'L$internalName;';
+ }
+
+ @override
+ String visitPrimitiveType(PrimitiveType node) {
+ return node.signature;
+ }
+
+ @override
+ String visitTypeVar(TypeVar node) {
+ final typeParam = typeParams.lastWhere(
+ (typeParam) => typeParam.name == node.name,
+ orElse: () {
+ print('${node.name} was not found!');
+ throw 'error';
+ },
+ );
+ return typeParam.bounds.isEmpty
+ ? super.visitTypeVar(node)
+ : typeParam.bounds.first.accept(this);
+ }
+
+ @override
+ String visitWildcard(Wildcard node) {
+ final extendsBound = node.extendsBound?.accept(this);
+ return extendsBound ?? super.visitWildcard(node);
+ }
+
+ @override
+ String visitNonPrimitiveType(ReferredType node) {
+ return 'Ljava/lang/Object;';
+ }
+}
diff --git a/pkgs/jnigen/lib/src/bindings/excluder.dart b/pkgs/jnigen/lib/src/bindings/excluder.dart
new file mode 100644
index 0000000..1568bd3
--- /dev/null
+++ b/pkgs/jnigen/lib/src/bindings/excluder.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../config/config.dart';
+import '../elements/elements.dart';
+import '../logging/logging.dart';
+import 'visitor.dart';
+
+bool _isPrivate(ClassMember classMember) =>
+ !classMember.isPublic && !classMember.isProtected;
+
+class Excluder extends Visitor<Classes, void> {
+ final Config config;
+
+ const Excluder(this.config);
+
+ @override
+ void visit(Classes node) {
+ node.decls.removeWhere((_, classDecl) {
+ final excluded = _isPrivate(classDecl) ||
+ !(config.exclude?.classes?.included(classDecl) ?? true);
+ if (excluded) {
+ log.fine('Excluded class ${classDecl.binaryName}');
+ }
+ return excluded;
+ });
+ final classExcluder = _ClassExcluder(config);
+ for (final classDecl in node.decls.values) {
+ classDecl.accept(classExcluder);
+ }
+ }
+}
+
+class _ClassExcluder extends Visitor<ClassDecl, void> {
+ final Config config;
+
+ _ClassExcluder(this.config);
+
+ @override
+ void visit(ClassDecl node) {
+ node.methods = node.methods.where((method) {
+ final included = !_isPrivate(method) &&
+ !method.name.startsWith('_') &&
+ (config.exclude?.methods?.included(node, method) ?? true);
+ if (!included) {
+ log.fine('Excluded method ${node.binaryName}#${method.name}');
+ }
+ return included;
+ }).toList();
+ node.fields = node.fields.where((field) {
+ final included = !_isPrivate(field) &&
+ !field.name.startsWith('_') &&
+ (config.exclude?.fields?.included(node, field) ?? true);
+ if (!included) {
+ log.fine('Excluded field ${node.binaryName}#${field.name}');
+ }
+ return included;
+ }).toList();
+ }
+}
diff --git a/pkgs/jnigen/lib/src/bindings/kotlin_processor.dart b/pkgs/jnigen/lib/src/bindings/kotlin_processor.dart
new file mode 100644
index 0000000..4a48aa8
--- /dev/null
+++ b/pkgs/jnigen/lib/src/bindings/kotlin_processor.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../elements/elements.dart';
+import 'visitor.dart';
+
+/// A [Visitor] that adds the the information from Kotlin's metadata to the Java
+/// classes and methods.
+class KotlinProcessor extends Visitor<Classes, void> {
+ @override
+ void visit(Classes node) {
+ final classProcessor = _KotlinClassProcessor();
+ for (final classDecl in node.decls.values) {
+ classDecl.accept(classProcessor);
+ }
+ }
+}
+
+class _KotlinClassProcessor extends Visitor<ClassDecl, void> {
+ @override
+ void visit(ClassDecl node) {
+ if (node.kotlinClass == null) {
+ return;
+ }
+ // This [ClassDecl] is actually a Kotlin class.
+ // Matching methods and functions from the metadata.
+ final functions = <String, KotlinFunction>{};
+ for (final function in node.kotlinClass!.functions) {
+ final signature = function.name + function.descriptor;
+ functions[signature] = function;
+ }
+ for (final method in node.methods) {
+ final signature = method.name + method.descriptor!;
+ if (functions.containsKey(signature)) {
+ method.accept(_KotlinMethodProcessor(functions[signature]!));
+ }
+ }
+ }
+}
+
+class _KotlinMethodProcessor extends Visitor<Method, void> {
+ final KotlinFunction function;
+
+ _KotlinMethodProcessor(this.function);
+
+ @override
+ void visit(Method node) {
+ if (function.isSuspend) {
+ const kotlinContinutationType = 'kotlin.coroutines.Continuation';
+ assert(node.params.isNotEmpty &&
+ node.params.last.type.kind == Kind.declared &&
+ node.params.last.type.name == kotlinContinutationType);
+ final continuationType = node.params.last.type.type as DeclaredType;
+ node.asyncReturnType = continuationType.params.isEmpty
+ ? TypeUsage.object
+ : continuationType.params.first;
+ }
+ }
+}
diff --git a/pkgs/jnigen/lib/src/bindings/linker.dart b/pkgs/jnigen/lib/src/bindings/linker.dart
new file mode 100644
index 0000000..8e90910
--- /dev/null
+++ b/pkgs/jnigen/lib/src/bindings/linker.dart
@@ -0,0 +1,203 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../config/config.dart';
+import '../elements/elements.dart';
+import '../logging/logging.dart';
+import 'visitor.dart';
+
+typedef _Resolver = ClassDecl Function(String? binaryName);
+
+/// A [Visitor] that adds the correct [ClassDecl] references from the
+/// string binary names.
+///
+/// It adds the following references:
+/// * Links [ClassDecl] objects from imported dependencies.
+/// * Adds references from child elements back to their parent elements.
+/// * Resolves Kotlin specific `asyncReturnType` for methods.
+class Linker extends Visitor<Classes, Future<void>> {
+ Linker(this.config);
+
+ final Config config;
+
+ @override
+ Future<void> visit(Classes node) async {
+ // Specify paths for this package's classes.
+ final root = config.outputConfig.dartConfig.path;
+ if (config.outputConfig.dartConfig.structure ==
+ OutputStructure.singleFile) {
+ // Connect all to the root if the output is in single file mode.
+ final path = root.toFilePath();
+ for (final decl in node.decls.values) {
+ decl.path = path;
+ }
+ } else {
+ for (final decl in node.decls.values) {
+ final dollarSign = decl.binaryName.indexOf('\$');
+ final className = dollarSign != -1
+ ? decl.binaryName.substring(0, dollarSign)
+ : decl.binaryName;
+ final path = className.replaceAll('.', '/');
+ decl.path = root.resolve(path).toFilePath();
+ }
+ }
+
+ // Find all the imported classes.
+ await config.importClasses();
+
+ if (config.importedClasses.keys
+ .toSet()
+ .intersection(node.decls.keys.toSet())
+ .isNotEmpty) {
+ log.fatal(
+ 'Trying to re-import the generated classes.\n'
+ 'Try hiding the class(es) in import.',
+ );
+ }
+
+ for (final className in config.importedClasses.keys) {
+ log.finest('Imported $className successfully.');
+ }
+
+ ClassDecl resolve(String? binaryName) {
+ return config.importedClasses[binaryName] ??
+ node.decls[binaryName] ??
+ resolve(TypeUsage.object.name);
+ }
+
+ final classLinker = _ClassLinker(
+ config,
+ resolve,
+ );
+ for (final classDecl in node.decls.values) {
+ classDecl.accept(classLinker);
+ }
+ }
+}
+
+class _ClassLinker extends Visitor<ClassDecl, void> {
+ final Config config;
+ final _Resolver resolve;
+ final Set<ClassDecl> _linked;
+
+ _ClassLinker(
+ this.config,
+ this.resolve,
+ ) : _linked = {...config.importedClasses.values};
+
+ @override
+ void visit(ClassDecl node) {
+ if (_linked.contains(node)) return;
+ log.finest('Linking ${node.binaryName}.');
+ _linked.add(node);
+
+ node.parent = node.parentName == null ? null : resolve(node.parentName);
+
+ final typeLinker = _TypeLinker(resolve);
+ node.superclass ??= TypeUsage.object;
+ node.superclass!.type.accept(typeLinker);
+ final superclass = (node.superclass!.type as DeclaredType).classDecl;
+ superclass.accept(this);
+
+ node.superCount = superclass.superCount + 1;
+
+ final fieldLinker = _FieldLinker(typeLinker);
+ for (final field in node.fields) {
+ field.classDecl = node;
+ field.accept(fieldLinker);
+ }
+ final methodLinker = _MethodLinker(config, typeLinker);
+ for (final method in node.methods) {
+ method.classDecl = node;
+ method.accept(methodLinker);
+ }
+ node.interfaces.accept(typeLinker).toList();
+ node.typeParams.accept(_TypeParamLinker(typeLinker)).toList();
+ }
+}
+
+class _MethodLinker extends Visitor<Method, void> {
+ _MethodLinker(this.config, this.typeVisitor);
+
+ final Config config;
+ final TypeVisitor<void> typeVisitor;
+
+ @override
+ void visit(Method node) {
+ node.returnType.accept(typeVisitor);
+ final typeParamLinker = _TypeParamLinker(typeVisitor);
+ final paramLinker = _ParamLinker(typeVisitor);
+ node.typeParams.accept(typeParamLinker).toList();
+ node.params.accept(paramLinker).toList();
+ node.asyncReturnType?.accept(typeVisitor);
+ }
+}
+
+class _TypeLinker extends TypeVisitor<void> {
+ const _TypeLinker(this.resolve);
+
+ final _Resolver resolve;
+
+ @override
+ void visitDeclaredType(DeclaredType node) {
+ node.params.accept(this).toList();
+ node.classDecl = resolve(node.binaryName);
+ }
+
+ @override
+ void visitWildcard(Wildcard node) {
+ node.superBound?.type.accept(this);
+ node.extendsBound?.type.accept(this);
+ }
+
+ @override
+ void visitArrayType(ArrayType node) {
+ node.type.accept(this);
+ }
+
+ @override
+ void visitPrimitiveType(PrimitiveType node) {
+ // Do nothing
+ }
+
+ @override
+ void visitNonPrimitiveType(ReferredType node) {
+ // Do nothing
+ }
+}
+
+class _FieldLinker extends Visitor<Field, void> {
+ _FieldLinker(this.typeVisitor);
+
+ final TypeVisitor<void> typeVisitor;
+
+ @override
+ void visit(Field node) {
+ node.type.accept(typeVisitor);
+ }
+}
+
+class _TypeParamLinker extends Visitor<TypeParam, void> {
+ _TypeParamLinker(this.typeVisitor);
+
+ final TypeVisitor<void> typeVisitor;
+
+ @override
+ void visit(TypeParam node) {
+ for (final bound in node.bounds) {
+ bound.accept(typeVisitor);
+ }
+ }
+}
+
+class _ParamLinker extends Visitor<Param, void> {
+ _ParamLinker(this.typeVisitor);
+
+ final TypeVisitor<void> typeVisitor;
+
+ @override
+ void visit(Param node) {
+ node.type.accept(typeVisitor);
+ }
+}
diff --git a/pkgs/jnigen/lib/src/bindings/renamer.dart b/pkgs/jnigen/lib/src/bindings/renamer.dart
new file mode 100644
index 0000000..56fea0a
--- /dev/null
+++ b/pkgs/jnigen/lib/src/bindings/renamer.dart
@@ -0,0 +1,261 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../config/config.dart';
+import '../elements/elements.dart';
+import '../logging/logging.dart';
+import 'visitor.dart';
+
+const Set<String> _keywords = {
+ 'abstract',
+ 'as',
+ 'assert',
+ 'async',
+ 'await',
+ 'break',
+ 'case',
+ 'catch',
+ 'class',
+ 'const',
+ 'continue',
+ 'covariant',
+ 'default',
+ 'deferred',
+ 'do',
+ 'dynamic',
+ 'else',
+ 'enum',
+ 'export',
+ 'extends',
+ 'extension',
+ 'external',
+ 'factory',
+ 'false',
+ 'final',
+ 'finally',
+ 'for',
+ 'Function',
+ 'get',
+ 'hide',
+ 'if',
+ 'implements',
+ 'import',
+ 'in',
+ 'interface',
+ 'is',
+ 'late',
+ 'library',
+ 'mixin',
+ 'new',
+ 'null',
+ 'on',
+ 'operator',
+ 'part',
+ 'required',
+ 'rethrow',
+ 'return',
+ 'set',
+ 'show',
+ 'static',
+ 'super',
+ 'switch',
+ 'sync',
+ 'this',
+ 'throw',
+ 'true',
+ 'try',
+ 'type', // Is used for type classes.
+ 'typedef',
+ 'var',
+ 'void',
+ 'while',
+ 'with',
+ 'yield',
+};
+
+/// Methods & properties already defined by dart JObject base class.
+const Map<String, int> _definedSyms = {
+ 'equals': 1,
+ 'toString': 1,
+ 'hashCode': 1,
+ 'runtimeType': 1,
+ 'noSuchMethod': 1,
+ 'reference': 1,
+ 'isReleased': 1,
+ 'isNull': 1,
+ 'use': 1,
+ 'release': 1,
+ 'releasedBy': 1,
+ 'getFieldID': 1,
+ 'getStaticFieldID': 1,
+ 'getMethodID': 1,
+ 'getStaticMethodID': 1,
+ 'getField': 1,
+ 'getFieldByName': 1,
+ 'getStaticField': 1,
+ 'getStaticFieldByName': 1,
+ 'callMethod': 1,
+ 'callMethodByName': 1,
+ 'callStaticMethod': 1,
+ 'callStaticMethodByName': 1,
+};
+
+/// Appends 0 to [name] if [name] is a keyword.
+///
+/// Examples:
+/// * `int` -> `int0`
+/// * `i` -> `i`
+String _keywordRename(String name) =>
+ _keywords.contains(name) ? '${name}0' : name;
+
+String _renameConflict(Map<String, int> counts, String name) {
+ if (counts.containsKey(name)) {
+ final count = counts[name]!;
+ final renamed = '$name$count';
+ counts[name] = count + 1;
+ return renamed;
+ }
+ counts[name] = 1;
+ return _keywordRename(name);
+}
+
+class Renamer implements Visitor<Classes, void> {
+ final Config config;
+
+ Renamer(this.config);
+
+ @override
+ void visit(Classes node) {
+ final classRenamer = _ClassRenamer(config);
+
+ for (final classDecl in node.decls.values) {
+ classDecl.accept(classRenamer);
+ }
+ }
+}
+
+class _ClassRenamer implements Visitor<ClassDecl, void> {
+ final Config config;
+ final Set<ClassDecl> renamed;
+ final Map<String, int> classNameCounts = {};
+ final Map<ClassDecl, Map<String, int>> nameCounts = {};
+
+ _ClassRenamer(
+ this.config,
+ ) : renamed = {...config.importedClasses.values};
+
+ /// Returns class name as useful in dart.
+ ///
+ /// Eg -> a.b.X.Y -> X_Y
+ static String _getSimplifiedClassName(String binaryName) =>
+ binaryName.split('.').last.replaceAll('\$', '_');
+
+ @override
+ void visit(ClassDecl node) {
+ if (renamed.contains(node)) return;
+ log.finest('Renaming ${node.binaryName}.');
+ renamed.add(node);
+
+ nameCounts[node] = {..._definedSyms};
+ node.methodNumsAfterRenaming = {};
+
+ final className = _getSimplifiedClassName(node.binaryName);
+ node.uniqueName = _renameConflict(classNameCounts, className);
+
+ // When generating all the classes in a single file
+ // the names need to be unique.
+ final uniquifyName =
+ config.outputConfig.dartConfig.structure == OutputStructure.singleFile;
+ node.finalName = uniquifyName ? node.uniqueName : className;
+ // TODO(#143): $ at the beginning is a temporary fix for the name collision.
+ node.typeClassName = '\$${node.finalName}Type';
+ log.fine('Class ${node.binaryName} is named ${node.finalName}');
+
+ final superClass = (node.superclass!.type as DeclaredType).classDecl;
+ superClass.accept(this);
+ nameCounts[node]!.addAll(nameCounts[superClass] ?? {});
+ final methodRenamer = _MethodRenamer(
+ config,
+ nameCounts[node]!,
+ );
+ for (final method in node.methods) {
+ method.accept(methodRenamer);
+ }
+
+ final fieldRenamer = _FieldRenamer(config, nameCounts[node]!);
+ for (final field in node.fields) {
+ field.accept(fieldRenamer);
+ }
+ }
+}
+
+class _MethodRenamer implements Visitor<Method, void> {
+ _MethodRenamer(this.config, this.nameCounts);
+
+ final Config config;
+ final Map<String, int> nameCounts;
+
+ @override
+ void visit(Method node) {
+ final name = node.name == '<init>' ? 'new' : node.name;
+ final sig = node.javaSig;
+ // If node is in super class, assign its number, overriding it.
+ final superClass =
+ (node.classDecl.superclass!.type as DeclaredType).classDecl;
+ final superNum = superClass.methodNumsAfterRenaming[sig];
+ if (superNum != null) {
+ // Don't rename if superNum == 0
+ // Unless the node name is a keyword.
+ final superNumText = superNum == 0 ? '' : '$superNum';
+ final methodName = superNum == 0 ? _keywordRename(name) : name;
+ node.finalName = '$methodName$superNumText';
+ node.classDecl.methodNumsAfterRenaming[sig] = superNum;
+ } else {
+ node.finalName = _renameConflict(nameCounts, name);
+ node.classDecl.methodNumsAfterRenaming[sig] = nameCounts[name]! - 1;
+ }
+ log.fine('Method ${node.classDecl.binaryName}#${node.name}'
+ ' is named ${node.finalName}');
+
+ final paramRenamer = _ParamRenamer(config);
+ for (final param in node.params) {
+ param.accept(paramRenamer);
+ }
+
+ // Kotlin specific
+ if (node.asyncReturnType != null) {
+ // It's a suspend fun so the continuation parameter
+ // should be named $c instead
+ node.params.last.finalName = '\$c';
+ }
+ }
+}
+
+class _FieldRenamer implements Visitor<Field, void> {
+ _FieldRenamer(this.config, this.nameCounts);
+
+ final Config config;
+ final Map<String, int> nameCounts;
+
+ @override
+ void visit(Field node) {
+ node.finalName = _renameConflict(
+ nameCounts,
+ node.name,
+ );
+ log.fine('Field ${node.classDecl.binaryName}#${node.name}'
+ ' is named ${node.finalName}');
+ }
+}
+
+class _ParamRenamer implements Visitor<Param, void> {
+ _ParamRenamer(this.config);
+
+ final Config config;
+
+ @override
+ void visit(Param node) {
+ node.finalName = _keywordRename(node.name);
+ }
+}
diff --git a/pkgs/jnigen/lib/src/bindings/resolver.dart b/pkgs/jnigen/lib/src/bindings/resolver.dart
new file mode 100644
index 0000000..68b250b
--- /dev/null
+++ b/pkgs/jnigen/lib/src/bindings/resolver.dart
@@ -0,0 +1,153 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:math';
+
+import '../elements/elements.dart';
+import '../logging/logging.dart';
+
+class Resolver {
+ /// Class corresponding to currently writing file.
+ ///
+ /// Is [null] when in single file mode.
+ final String? currentClass;
+
+ /// Explicit import mappings.
+ final Map<String, ClassDecl> importedClasses;
+
+ /// Names of all classes in input.
+ final Set<String> inputClassNames;
+
+ final List<String> importStrings = [];
+
+ final Set<String> _relativeImportedClasses = {};
+ final Map<String, String> _importedNameToClass = {};
+ final Map<String, String> _classToImportedName = {};
+
+ Resolver({
+ required this.importedClasses,
+ required this.currentClass,
+ this.inputClassNames = const {},
+ });
+
+ static String getFileClassName(String binaryName) {
+ final dollarSign = binaryName.indexOf('\$');
+ if (dollarSign != -1) {
+ return binaryName.substring(0, dollarSign);
+ }
+ return binaryName;
+ }
+
+ /// splits [str] into 2 from last occurence of [sep]
+ static List<String> cutFromLast(String str, String sep) {
+ final li = str.lastIndexOf(sep);
+ if (li == -1) {
+ return ['', str];
+ }
+ return [str.substring(0, li), str.substring(li + 1)];
+ }
+
+ /// Get the prefix for the class
+ String resolvePrefix(ClassDecl classDecl) {
+ if (classDecl.path == 'package:jni/jni.dart') {
+ // For package:jni we don't use a leading underscore.
+ return 'jni.';
+ }
+ final binaryName = classDecl.binaryName;
+ final target = getFileClassName(binaryName);
+
+ // For classes we generate (inside [inputClassNames]) no import
+ // (and therefore no prefix) is necessary when:
+ // * Never necessary in single file mode
+ // * In multi file mode if the target is the same as the current class
+ if ((currentClass == null || target == currentClass) &&
+ inputClassNames.contains(binaryName)) {
+ return '';
+ }
+
+ if (_classToImportedName.containsKey(target)) {
+ // This package was already resolved
+ // but we still need to check if it was a relative import, in which case
+ // the class not in inputClassNames cannot be mapped here.
+ if (!_relativeImportedClasses.contains(target) ||
+ inputClassNames.contains(binaryName)) {
+ final importedName = _classToImportedName[target];
+ return '$importedName.';
+ }
+ }
+
+ final classImport = getImport(target, binaryName);
+ log.finest('$target resolved to $classImport for $binaryName');
+ if (classImport == null) {
+ return '';
+ }
+
+ final pkgName = cutFromLast(target, '.')[1].toLowerCase();
+ if (pkgName.isEmpty) {
+ throw UnsupportedError('No package could be deduced from '
+ 'qualified binaryName');
+ }
+
+ // We always name imports with an underscore suffix, so that they can be
+ // never shadowed by a parameter or local variable.
+ var importedName = '${pkgName}_';
+ int suffix = 0;
+ while (_importedNameToClass.containsKey(importedName)) {
+ suffix++;
+ importedName = '$pkgName${suffix}_';
+ }
+
+ _importedNameToClass[importedName] = target;
+ _classToImportedName[target] = importedName;
+ importStrings.add('import "$classImport" as $importedName;\n');
+ return '$importedName.';
+ }
+
+ /// Returns import string for [classToResolve], or `null` if the class is not
+ /// found.
+ ///
+ /// [binaryName] is the class name trying to be resolved. This parameter is
+ /// requested so that classes included in current bindings can be resolved
+ /// using relative path.
+ String? getImport(String classToResolve, String binaryName) {
+ final prefix = classToResolve;
+
+ // short circuit if the requested class is specified directly in import map.
+ if (importedClasses.containsKey(binaryName)) {
+ return importedClasses[binaryName]!.path;
+ }
+
+ if (prefix.isEmpty) {
+ throw UnsupportedError('unexpected: empty package name.');
+ }
+
+ final dest = classToResolve.split('.');
+ final src = currentClass!.split('.');
+ // Use relative import when the required class is included in current set
+ // of bindings.
+ if (inputClassNames.contains(binaryName)) {
+ int common = 0;
+ // find the common prefix path directory of current package, and directory
+ // of target package
+ // src.length - 1 simply corresponds to directory of the package.
+ for (int i = 0; i < src.length - 1 && i < dest.length - 1; i++) {
+ if (src[i] == dest[i]) {
+ common++;
+ } else {
+ break;
+ }
+ }
+ final pathToCommon = '../' * ((src.length - 1) - common);
+ final pathToClass = dest.sublist(max(common, 0)).join('/');
+ _relativeImportedClasses.add(classToResolve);
+ return '$pathToCommon$pathToClass.dart';
+ }
+
+ return null;
+ }
+
+ List<String> getImportStrings() {
+ return importStrings;
+ }
+}
diff --git a/pkgs/jnigen/lib/src/bindings/unnester.dart b/pkgs/jnigen/lib/src/bindings/unnester.dart
new file mode 100644
index 0000000..d9323df
--- /dev/null
+++ b/pkgs/jnigen/lib/src/bindings/unnester.dart
@@ -0,0 +1,90 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../elements/elements.dart';
+import 'visitor.dart';
+
+/// A [Visitor] that processes nested classes.
+///
+/// Nested classes are not supported in Dart. So this "unnests" them into
+/// separate classes.
+class Unnester extends Visitor<Classes, void> {
+ const Unnester();
+
+ @override
+ void visit(node) {
+ final classProcessor = _ClassUnnester();
+ for (final classDecl in node.decls.values) {
+ classDecl.accept(classProcessor);
+ }
+ }
+}
+
+class _ClassUnnester extends Visitor<ClassDecl, void> {
+ final processed = <ClassDecl>{};
+
+ @override
+ void visit(ClassDecl node) {
+ if (processed.contains(node)) return;
+ processed.add(node);
+ // We need to visit the ancestors first.
+ node.parent?.accept(this);
+
+ // Add type params of outer classes to the nested classes.
+ final allTypeParams = <TypeParam>[];
+ if (!node.isStatic) {
+ allTypeParams.addAll(node.parent?.allTypeParams ?? []);
+ }
+ allTypeParams.addAll(node.typeParams);
+ node.allTypeParams = allTypeParams;
+
+ if (node.isNested && !node.isStatic) {
+ const methodProcessor = _MethodUnnester();
+ for (final method in node.methods) {
+ method.accept(methodProcessor);
+ }
+ }
+ }
+}
+
+class _MethodUnnester extends Visitor<Method, void> {
+ const _MethodUnnester();
+
+ @override
+ void visit(Method node) {
+ assert(!node.classDecl.isStatic);
+ assert(node.classDecl.isNested);
+ // TODO(#319): Unnest the methods in APISummarizer itself.
+ // For now the nullity of [node.descriptor] identifies if the doclet
+ // backend was used and the method would potentially need "unnesting".
+ if ((node.isCtor || node.isStatic) && node.descriptor == null) {
+ // Non-static nested classes take an instance of their outer class as the
+ // first parameter.
+ //
+ // This is not accounted for by the **doclet** summarizer, so we
+ // manually add it as the first parameter.
+ final parentTypeParamCount = node.classDecl.allTypeParams.length -
+ node.classDecl.typeParams.length;
+ final parentTypeParams = [
+ for (final typeParam
+ in node.classDecl.allTypeParams.take(parentTypeParamCount)) ...[
+ TypeUsage(
+ shorthand: typeParam.name, kind: Kind.typeVariable, typeJson: {})
+ ..type = TypeVar(name: typeParam.name),
+ ]
+ ];
+ final parentType = DeclaredType(
+ binaryName: node.classDecl.parent!.binaryName,
+ params: parentTypeParams,
+ )..classDecl = node.classDecl.parent!;
+ final parentTypeUsage = TypeUsage(
+ shorthand: parentType.binaryName, kind: Kind.declared, typeJson: {})
+ ..type = parentType;
+ final param = Param(name: '\$parent', type: parentTypeUsage);
+ // Make the list modifiable.
+ if (node.params.isEmpty) node.params = [];
+ node.params.insert(0, param);
+ }
+ }
+}
diff --git a/pkgs/jnigen/lib/src/bindings/visitor.dart b/pkgs/jnigen/lib/src/bindings/visitor.dart
new file mode 100644
index 0000000..417180c
--- /dev/null
+++ b/pkgs/jnigen/lib/src/bindings/visitor.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../elements/elements.dart';
+
+abstract class Visitor<T extends Element<T>, R> {
+ const Visitor();
+
+ R visit(T node);
+}
+
+abstract class TypeVisitor<R> {
+ const TypeVisitor();
+
+ R visitNonPrimitiveType(ReferredType node);
+ R visitPrimitiveType(PrimitiveType node);
+ R visitArrayType(ArrayType node) => visitNonPrimitiveType(node);
+ R visitDeclaredType(DeclaredType node) => visitNonPrimitiveType(node);
+ R visitTypeVar(TypeVar node) => visitNonPrimitiveType(node);
+ R visitWildcard(Wildcard node) => visitNonPrimitiveType(node);
+}
+
+extension MultiVisitor<T extends Element<T>> on Iterable<Element<T>> {
+ /// Accepts all lazily. Remember to call `.toList()` or similar methods!
+ Iterable<R> accept<R>(Visitor<T, R> v) {
+ return map((e) => e.accept(v));
+ }
+}
+
+extension MultiTypeUsageVisitor on Iterable<TypeUsage> {
+ /// Accepts all lazily. Remember to call `.toList()` or similar methods!
+ Iterable<R> accept<R>(TypeVisitor<R> v) {
+ return map((e) => e.type.accept(v));
+ }
+}
diff --git a/pkgs/jnigen/lib/src/config/config.dart b/pkgs/jnigen/lib/src/config/config.dart
new file mode 100644
index 0000000..c4168d8
--- /dev/null
+++ b/pkgs/jnigen/lib/src/config/config.dart
@@ -0,0 +1,6 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'config_types.dart';
+export 'config_exception.dart';
diff --git a/pkgs/jnigen/lib/src/config/config_exception.dart b/pkgs/jnigen/lib/src/config/config_exception.dart
new file mode 100644
index 0000000..d3518cc
--- /dev/null
+++ b/pkgs/jnigen/lib/src/config/config_exception.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Exception thrown when a configuration value is invalid.
+class ConfigException implements Exception {
+ ConfigException(this.message);
+ String message;
+
+ @override
+ String toString() => 'Error parsing configuration: $message';
+}
diff --git a/pkgs/jnigen/lib/src/config/config_types.dart b/pkgs/jnigen/lib/src/config/config_types.dart
new file mode 100644
index 0000000..02dcbc2
--- /dev/null
+++ b/pkgs/jnigen/lib/src/config/config_types.dart
@@ -0,0 +1,703 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:logging/logging.dart';
+import 'package:path/path.dart' as p;
+import 'package:pub_semver/pub_semver.dart';
+import 'package:yaml/yaml.dart';
+
+import '../elements/elements.dart';
+import '../logging/logging.dart';
+import '../util/find_package.dart';
+import 'config_exception.dart';
+import 'experiments.dart';
+import 'filters.dart';
+import 'yaml_reader.dart';
+
+/// Modify this when symbols file format changes according to pub_semver.
+final _currentVersion = Version(1, 0, 0);
+
+/// Configuration for dependencies to be downloaded using maven.
+///
+/// Dependency names should be listed in groupId:artifactId:version format.
+/// For [sourceDeps], sources will be unpacked to [sourceDir] root and JAR files
+/// will also be downloaded. For the packages in jarOnlyDeps, only JAR files
+/// will be downloaded.
+///
+/// When passed as a parameter to [Config], the downloaded sources and
+/// JAR files will be automatically added to source path and class path
+/// respectively.
+class MavenDownloads {
+ static const defaultMavenSourceDir = 'mvn_java';
+ static const defaultMavenJarDir = 'mvn_jar';
+
+ MavenDownloads({
+ this.sourceDeps = const [],
+ // ASK: Should this be changed to a gitignore'd directory like build ?
+ this.sourceDir = defaultMavenSourceDir,
+ this.jarOnlyDeps = const [],
+ this.jarDir = defaultMavenJarDir,
+ });
+ List<String> sourceDeps;
+ String sourceDir;
+ List<String> jarOnlyDeps;
+ String jarDir;
+}
+
+/// Configuration for Android SDK sources and stub JAR files.
+///
+/// The SDK directories for platform stub JARs and sources are searched in the
+/// same order in which [versions] are specified.
+///
+/// If [addGradleDeps] is true, a gradle stub is run in order to collect the
+/// actual compile classpath of the `android/` subproject.
+/// This will fail if there was no previous build of the project, or if a
+/// `clean` task was run either through flutter or gradle wrapper. In such case,
+/// it's required to run `flutter build apk` & retry running `jnigen`.
+///
+/// A configuration is invalid if [versions] is unspecified or empty, and gradle
+/// options are also false. If [sdkRoot] is not specified but versions is
+/// specified, an attempt is made to find out SDK installation directory using
+/// environment variable `ANDROID_SDK_ROOT` if it's defined, else an error
+/// will be thrown.
+class AndroidSdkConfig {
+ AndroidSdkConfig({
+ this.versions,
+ this.sdkRoot,
+ this.addGradleDeps = false,
+ this.addGradleSources = false,
+ this.androidExample,
+ }) {
+ if (versions != null && sdkRoot == null) {
+ throw ConfigException("No SDK Root specified for finding Android SDK "
+ "from version priority list $versions");
+ }
+ if (versions == null && !addGradleDeps && !addGradleSources) {
+ throw ConfigException('Neither any SDK versions nor `addGradleDeps` '
+ 'is specified. Unable to find Android libraries.');
+ }
+ }
+
+ /// Versions of android SDK to search for, in decreasing order of preference.
+ List<int>? versions;
+
+ /// Root of Android SDK installation, this should be normally given on
+ /// command line or by setting `ANDROID_SDK_ROOT`, since this varies from
+ /// system to system.
+ String? sdkRoot;
+
+ /// Attempt to determine exact compile time dependencies by running a gradle
+ /// stub in android subproject of this project.
+ ///
+ /// An Android build must have happened before we are able to obtain classpath
+ /// of Gradle dependencies. Run `flutter build apk` before running a jnigen
+ /// script with this option.
+ ///
+ /// For the same reason, if the flutter project is a plugin instead of
+ /// application, it's not possible to determine the build classpath directly.
+ /// Please provide [androidExample] pointing to an example application in
+ /// that case.
+ bool addGradleDeps;
+
+ /// Similar to [addGradleDeps], runs a stub to obtain source dependencies of
+ /// the Android project.
+ ///
+ /// This may cause additional source JAR artifacts to be downloaded. Like the
+ /// [addGradleDeps] option, plugins cannot be built so an example should be
+ /// specified.
+ bool addGradleSources;
+
+ /// Relative path to example application which will be used to determine
+ /// compile time classpath using a gradle stub. For most Android plugin
+ /// packages, 'example' will be the name of example application created inside
+ /// the package. This example should be built once before using this option,
+ /// so that gradle would have resolved all the dependencies.
+ String? androidExample;
+}
+
+extension on String {
+ /// Converts the enum name from camelCase to snake_case.
+ String toSnakeCase() {
+ return splitMapJoin(
+ RegExp('[A-Z]'),
+ onMatch: (p) => '_${p[0]!.toLowerCase()}',
+ );
+ }
+}
+
+extension<T extends Enum> on Iterable<T> {
+ Map<String, T> valuesMap() {
+ return Map.fromEntries(map((e) => MapEntry(e.name.toSnakeCase(), e)));
+ }
+}
+
+T _getEnumValueFromString<T>(
+ Map<String, T> values, String? name, T defaultVal) {
+ if (name == null) return defaultVal;
+ final value = values[name];
+ if (value == null) {
+ throw ConfigException('Got: $name, allowed: ${values.keys}');
+ }
+ return value;
+}
+
+/// Additional options to pass to the summary generator component.
+class SummarizerOptions {
+ SummarizerOptions(
+ {this.extraArgs = const [], this.workingDirectory, this.backend});
+ List<String> extraArgs;
+ Uri? workingDirectory;
+ SummarizerBackend? backend;
+}
+
+/// Backend for reading summary of Java libraries
+enum SummarizerBackend {
+ /// Generate Java API summaries using JARs in provided `classPath`s.
+ asm,
+
+ /// Generate Java API summaries using source files in provided `sourcePath`s.
+ doclet,
+}
+
+SummarizerBackend? getSummarizerBackend(
+ String? name,
+ SummarizerBackend? defaultVal,
+) {
+ return _getEnumValueFromString(
+ SummarizerBackend.values.valuesMap(),
+ name,
+ defaultVal,
+ );
+}
+
+void _ensureIsDirectory(String name, Uri path) {
+ if (!path.toFilePath().endsWith(Platform.pathSeparator)) {
+ throw ConfigException('$name must be a directory path. If using YAML '
+ 'config, please ensure the path ends with a slash (/).');
+ }
+}
+
+enum OutputStructure { packageStructure, singleFile }
+
+OutputStructure getOutputStructure(String? name, OutputStructure defaultVal) {
+ return _getEnumValueFromString(
+ OutputStructure.values.valuesMap(),
+ name,
+ defaultVal,
+ );
+}
+
+enum BindingsType { cBased, dartOnly }
+
+extension GetConfigString on BindingsType {
+ String getConfigString() {
+ return name.toSnakeCase();
+ }
+}
+
+BindingsType getBindingsType(String? name, BindingsType defaultVal) {
+ return _getEnumValueFromString(
+ BindingsType.values.valuesMap(),
+ name,
+ defaultVal,
+ );
+}
+
+class CCodeOutputConfig {
+ CCodeOutputConfig({
+ required this.path,
+ required this.libraryName,
+ this.subdir,
+ }) {
+ _ensureIsDirectory('C output path', path);
+ if (subdir != null) {
+ _ensureIsDirectory('C subdirectory', path.resolve(subdir!));
+ }
+ }
+
+ /// Directory to write JNI C Bindings, in C+Dart mode.
+ ///
+ /// Strictly speaking, this is the root to place the `CMakeLists.txt` file
+ /// for the generated C bindings. It may be desirable to use the [subdir]
+ /// options to write C files to a subdirectory of [path]. For instance,
+ /// when generated code is required to be in `third_party` directory.
+ Uri path;
+
+ /// Name of generated library in CMakeLists.txt configuration.
+ ///
+ /// This will also determine the name of shared object file.
+ String libraryName;
+
+ /// Subfolder relative to [path] to write generated C code.
+ String? subdir;
+}
+
+class DartCodeOutputConfig {
+ DartCodeOutputConfig({
+ required this.path,
+ this.structure = OutputStructure.packageStructure,
+ }) {
+ if (structure == OutputStructure.singleFile) {
+ if (p.extension(path.toFilePath()) != '.dart') {
+ throw ConfigException(
+ 'Dart\'s output path must end with ".dart" in single file mode.');
+ }
+ } else {
+ _ensureIsDirectory('Dart output path', path);
+ }
+ }
+
+ /// Path to write generated Dart bindings.
+ Uri path;
+
+ /// File structure of the generated Dart bindings.
+ OutputStructure structure;
+}
+
+class SymbolsOutputConfig {
+ /// Path to write generated Dart bindings.
+ final Uri path;
+
+ SymbolsOutputConfig(this.path) {
+ if (p.extension(path.toFilePath()) != '.yaml') {
+ throw ConfigException('Symbol\'s output path must end with ".yaml".');
+ }
+ }
+}
+
+class OutputConfig {
+ OutputConfig({
+ required this.dartConfig,
+ this.bindingsType = BindingsType.cBased,
+ this.cConfig,
+ this.symbolsConfig,
+ }) {
+ if (bindingsType == BindingsType.cBased && cConfig == null) {
+ throw ConfigException('C output config must be provided!');
+ }
+ }
+ BindingsType bindingsType;
+ DartCodeOutputConfig dartConfig;
+ CCodeOutputConfig? cConfig;
+ SymbolsOutputConfig? symbolsConfig;
+}
+
+class BindingExclusions {
+ BindingExclusions({this.methods, this.fields, this.classes});
+ MethodFilter? methods;
+ FieldFilter? fields;
+ ClassFilter? classes;
+}
+
+bool _isCapitalized(String s) {
+ final firstLetter = s.substring(0, 1);
+ return firstLetter == firstLetter.toUpperCase();
+}
+
+void _validateClassName(String className) {
+ final parts = className.split('.');
+ assert(parts.isNotEmpty);
+ const nestedClassesInfo =
+ "Nested classes cannot be specified separately. Specifying the "
+ "parent class will pull the nested classes.";
+ if (parts.length > 1 && _isCapitalized(parts[parts.length - 2])) {
+ // Try to detect possible nested classes specified using dot notation eg:
+ // `com.package.Class.NestedClass` and emit a warning.
+ log.warning("It appears a nested class $className is specified in the "
+ "config. $nestedClassesInfo");
+ }
+ if (className.contains('\$')) {
+ throw ConfigException(
+ "Nested class $className not allowed. $nestedClassesInfo");
+ }
+}
+
+/// Configuration for jnigen binding generation.
+class Config {
+ Config({
+ required this.outputConfig,
+ required this.classes,
+ this.experiments,
+ this.exclude,
+ this.sourcePath,
+ this.classPath,
+ this.preamble,
+ this.customClassBody,
+ this.androidSdkConfig,
+ this.mavenDownloads,
+ this.summarizerOptions,
+ this.logLevel = Level.INFO,
+ this.dumpJsonTo,
+ this.imports,
+ }) {
+ for (final className in classes) {
+ _validateClassName(className);
+ }
+ }
+
+ /// Output configuration for generated bindings
+ OutputConfig outputConfig;
+
+ /// List of classes or packages for which bindings have to be generated.
+ ///
+ /// The names must be fully qualified, and it's assumed that the directory
+ /// structure corresponds to package naming. For example, com.abc.MyClass
+ /// should be resolvable as `com/abc/MyClass.java` from one of the provided
+ /// source paths. Same applies if ASM backend is used, except that the file
+ /// name suffix is `.class`.
+ List<String> classes;
+
+ Set<Experiment?>? experiments;
+
+ /// Methods and fields to be excluded from generated bindings.
+ final BindingExclusions? exclude;
+
+ /// Paths to search for java source files.
+ ///
+ /// If a source package is downloaded through [mavenDownloads] option,
+ /// the corresponding source folder is automatically added and does not
+ /// need to be explicitly specified.
+ List<Uri>? sourcePath;
+
+ /// class path for scanning java libraries. If [backend] is `asm`, the
+ /// specified classpath is used to search for [classes], otherwise it's
+ /// merely used by the doclet API to find transitively referenced classes,
+ /// but not the specified classes / packages themselves.
+ List<Uri>? classPath;
+
+ /// Common text to be pasted on top of generated C and Dart files.
+ final String? preamble;
+
+ /// Configuration to search for Android SDK libraries (Experimental).
+ final AndroidSdkConfig? androidSdkConfig;
+
+ /// Configuration for auto-downloading JAR / source packages using maven,
+ /// along with their transitive dependencies.
+ final MavenDownloads? mavenDownloads;
+
+ /// Additional options for the summarizer component.
+ SummarizerOptions? summarizerOptions;
+
+ /// List of dependencies.
+ final List<Uri>? imports;
+
+ /// Call [importClasses] before using this.
+ late final Map<String, ClassDecl> importedClasses;
+
+ /// Custom code that is added to the end of the class body with the specified
+ /// binary name.
+ ///
+ /// Used for testing package:jnigen.
+ final Map<String, String>? customClassBody;
+
+ Future<void> importClasses() async {
+ importedClasses = {};
+ for (final import in [
+ // Implicitly importing package:jni symbols.
+ Uri.parse('package:jni/jni_symbols.yaml'),
+ ...?imports,
+ ]) {
+ // Getting the actual uri in case of package uris.
+ final Uri yamlUri;
+ final String importPath;
+ if (import.scheme == 'package') {
+ final packageName = import.pathSegments.first;
+ final packageRoot = await findPackageRoot(packageName);
+ if (packageRoot == null) {
+ log.fatal('package:$packageName was not found.');
+ }
+ yamlUri = packageRoot
+ .resolve('lib/')
+ .resolve(import.pathSegments.sublist(1).join('/'));
+ importPath = 'package:$packageName';
+ } else {
+ yamlUri = import;
+ importPath = ([...import.pathSegments]..removeLast()).join('/');
+ }
+ log.finest('Parsing yaml file in url $yamlUri.');
+ final YamlMap yaml;
+ try {
+ final symbolsFile = File.fromUri(yamlUri);
+ final content = symbolsFile.readAsStringSync();
+ yaml = loadYaml(content, sourceUrl: yamlUri);
+ } on UnsupportedError catch (_) {
+ log.fatal('Could not reference "$import".');
+ } catch (e, s) {
+ log.warning(e);
+ log.warning(s);
+ log.fatal('Error while parsing yaml file "$import".');
+ }
+ final version = Version.parse(yaml['version'] as String);
+ if (!VersionConstraint.compatibleWith(_currentVersion).allows(version)) {
+ log.fatal('"$import" is version "$version" which is not compatible with'
+ 'the current JNIgen symbols version $_currentVersion');
+ }
+ final files = yaml['files'] as YamlMap;
+ for (final entry in files.entries) {
+ final filePath = entry.key as String;
+ final classes = entry.value as YamlMap;
+ for (final classEntry in classes.entries) {
+ final binaryName = classEntry.key as String;
+ final decl = classEntry.value as YamlMap;
+ if (importedClasses.containsKey(binaryName)) {
+ log.fatal(
+ 'Re-importing "$binaryName" in "$import".\n'
+ 'Try hiding the class in import.',
+ );
+ }
+ final classDecl = ClassDecl(
+ declKind: DeclKind.classKind,
+ binaryName: binaryName,
+ )
+ ..path = '$importPath/$filePath'
+ ..finalName = decl['name']
+ ..typeClassName = decl['type_class']
+ ..superCount = decl['super_count']
+ ..allTypeParams = []
+ ..parent = null;
+ for (final typeParamEntry
+ in ((decl['type_params'] as YamlMap?)?.entries) ??
+ <MapEntry<dynamic, dynamic>>[]) {
+ final typeParamName = typeParamEntry.key as String;
+ final bounds = (typeParamEntry.value as YamlMap).entries.map((e) {
+ final boundName = e.key as String;
+ // Can only be DECLARED or TYPE_VARIABLE
+ if (!['DECLARED', 'TYPE_VARIABLE'].contains(e.value)) {
+ log.fatal(
+ 'Unsupported bound kind "${e.value}" for bound "$boundName" '
+ 'in type parameter "$typeParamName" '
+ 'of "$binaryName".',
+ );
+ }
+ final boundKind = (e.value as String) == 'DECLARED'
+ ? Kind.declared
+ : Kind.typeVariable;
+ final ReferredType type;
+ if (boundKind == Kind.declared) {
+ type = DeclaredType(binaryName: boundName);
+ } else {
+ type = TypeVar(name: boundName);
+ }
+ return TypeUsage(
+ shorthand: binaryName,
+ kind: boundKind,
+ typeJson: {},
+ )..type = type;
+ }).toList();
+ classDecl.allTypeParams.add(
+ TypeParam(name: typeParamName, bounds: bounds),
+ );
+ }
+ classDecl.methodNumsAfterRenaming =
+ (decl['methods'] as YamlMap?)?.cast() ?? {};
+ importedClasses[binaryName] = classDecl;
+ }
+ }
+ }
+ }
+
+ /// Directory containing the YAML configuration file, if any.
+ Uri? get configRoot => _configRoot;
+ Uri? _configRoot;
+
+ /// Log verbosity. The possible values in decreasing order of verbosity
+ /// are verbose > debug > info > warning > error. Defaults to [LogLevel.info]
+ Level logLevel = Level.INFO;
+
+ /// File to which JSON summary is written before binding generation.
+ final String? dumpJsonTo;
+
+ static final _levels = Map.fromEntries(
+ Level.LEVELS.map((l) => MapEntry(l.name.toLowerCase(), l)));
+
+ static Config parseArgs(List<String> args) {
+ final prov = YamlReader.parseArgs(args);
+
+ final List<String> missingValues = [];
+
+ T must<T>(T? Function(String) f, T ifNull, String property) {
+ final res = f(property);
+ if (res == null) {
+ missingValues.add(property);
+ return ifNull;
+ }
+ return res;
+ }
+
+ MemberFilter<T>? regexFilter<T extends ClassMember>(String property) {
+ final exclusions = prov.getStringList(property);
+ if (exclusions == null) return null;
+ final List<MemberFilter<T>> filters = [];
+ for (var exclusion in exclusions) {
+ final split = exclusion.split('#');
+ if (split.length != 2) {
+ throw ConfigException('Error parsing exclusion: "$exclusion": '
+ 'expected to be in binaryName#member format.');
+ }
+ filters.add(MemberNameFilter<T>.exclude(
+ RegExp(split[0]),
+ RegExp(split[1]),
+ ));
+ }
+ return CombinedMemberFilter<T>(filters);
+ }
+
+ String? getSdkRoot() {
+ final root = prov.getString(_Props.androidSdkRoot) ??
+ Platform.environment['ANDROID_SDK_ROOT'];
+ return root;
+ }
+
+ Level logLevelFromString(String? levelName) {
+ if (levelName == null) return Level.INFO;
+ final level = _levels[levelName.toLowerCase()];
+ if (level == null) {
+ throw ConfigException('Not a valid logging level: $levelName');
+ }
+ return level;
+ }
+
+ final configRoot = prov.getConfigRoot();
+ String resolveFromConfigRoot(String reference) =>
+ configRoot?.resolve(reference).toFilePath() ?? reference;
+
+ final config = Config(
+ sourcePath: prov.getPathList(_Props.sourcePath),
+ classPath: prov.getPathList(_Props.classPath),
+ classes: must(prov.getStringList, [], _Props.classes),
+ summarizerOptions: SummarizerOptions(
+ extraArgs: prov.getStringList(_Props.summarizerArgs) ?? const [],
+ backend: getSummarizerBackend(prov.getString(_Props.backend), null),
+ workingDirectory: prov.getPath(_Props.summarizerWorkingDir),
+ ),
+ exclude: BindingExclusions(
+ methods: regexFilter<Method>(_Props.excludeMethods),
+ fields: regexFilter<Field>(_Props.excludeFields),
+ ),
+ outputConfig: OutputConfig(
+ bindingsType: getBindingsType(
+ prov.getString(_Props.bindingsType),
+ BindingsType.cBased,
+ ),
+ cConfig: prov.hasValue(_Props.cCodeOutputConfig)
+ ? CCodeOutputConfig(
+ libraryName: must(prov.getString, '', _Props.libraryName),
+ path: must(prov.getPath, Uri.parse('.'), _Props.cRoot),
+ subdir: prov.getString(_Props.cSubdir),
+ )
+ : null,
+ dartConfig: DartCodeOutputConfig(
+ path: must(prov.getPath, Uri.parse('.'), _Props.dartRoot),
+ structure: getOutputStructure(
+ prov.getString(_Props.outputStructure),
+ OutputStructure.packageStructure,
+ ),
+ ),
+ symbolsConfig: prov.hasValue(_Props.symbolsOutputConfig)
+ ? SymbolsOutputConfig(
+ must(prov.getPath, Uri.parse('.'), _Props.symbolsOutputConfig),
+ )
+ : null,
+ ),
+ preamble: prov.getString(_Props.preamble),
+ experiments: prov
+ .getStringList(_Props.experiments)
+ ?.map(
+ (e) => Experiment.fromString(e),
+ )
+ .toSet(),
+ imports: prov.getPathList(_Props.import),
+ mavenDownloads: prov.hasValue(_Props.mavenDownloads)
+ ? MavenDownloads(
+ sourceDeps: prov.getStringList(_Props.sourceDeps) ?? const [],
+ sourceDir: prov.getPath(_Props.mavenSourceDir)?.toFilePath() ??
+ resolveFromConfigRoot(MavenDownloads.defaultMavenSourceDir),
+ jarOnlyDeps: prov.getStringList(_Props.jarOnlyDeps) ?? const [],
+ jarDir: prov.getPath(_Props.mavenJarDir)?.toFilePath() ??
+ resolveFromConfigRoot(MavenDownloads.defaultMavenJarDir),
+ )
+ : null,
+ androidSdkConfig: prov.hasValue(_Props.androidSdkConfig)
+ ? AndroidSdkConfig(
+ versions: prov
+ .getStringList(_Props.androidSdkVersions)
+ ?.map(int.parse)
+ .toList(),
+ sdkRoot: getSdkRoot(),
+ addGradleDeps: prov.getBool(_Props.addGradleDeps) ?? false,
+ addGradleSources: prov.getBool(_Props.addGradleSources) ?? false,
+ // Leaving this as getString instead of getPath, because
+ // it's resolved later in android_sdk_tools.
+ androidExample: prov.getString(_Props.androidExample),
+ )
+ : null,
+ logLevel: logLevelFromString(
+ prov.getOneOf(
+ _Props.logLevel,
+ _levels.keys.toSet(),
+ ),
+ ),
+ );
+ if (missingValues.isNotEmpty) {
+ stderr.write('Following config values are required but not provided\n'
+ 'Please provide these properties through YAML '
+ 'or use the command line switch -D<property_name>=<value>.\n');
+ for (var missing in missingValues) {
+ stderr.writeln('* $missing');
+ }
+ if (missingValues.contains(_Props.androidSdkRoot)) {
+ stderr.writeln('Please specify ${_Props.androidSdkRoot} through '
+ 'command line or ensure that the ANDROID_SDK_ROOT environment '
+ 'variable is set.');
+ }
+ exit(1);
+ }
+ config._configRoot = configRoot;
+ return config;
+ }
+}
+
+class _Props {
+ static const summarizer = 'summarizer';
+ static const summarizerArgs = '$summarizer.extra_args';
+ static const summarizerWorkingDir = '$summarizer.working_dir';
+ static const backend = '$summarizer.backend';
+
+ static const sourcePath = 'source_path';
+ static const classPath = 'class_path';
+ static const classes = 'classes';
+ static const exclude = 'exclude';
+ static const excludeMethods = '$exclude.methods';
+ static const excludeFields = '$exclude.fields';
+
+ static const experiments = 'enable_experiment';
+ static const import = 'import';
+ static const outputConfig = 'output';
+ static const bindingsType = '$outputConfig.bindings_type';
+ static const cCodeOutputConfig = '$outputConfig.c';
+ static const dartCodeOutputConfig = '$outputConfig.dart';
+ static const symbolsOutputConfig = '$outputConfig.symbols';
+ static const cRoot = '$cCodeOutputConfig.path';
+ static const cSubdir = '$cCodeOutputConfig.subdir';
+ static const dartRoot = '$dartCodeOutputConfig.path';
+ static const outputStructure = '$dartCodeOutputConfig.structure';
+ static const libraryName = '$cCodeOutputConfig.library_name';
+ static const preamble = 'preamble';
+ static const logLevel = 'log_level';
+
+ static const mavenDownloads = 'maven_downloads';
+ static const sourceDeps = '$mavenDownloads.source_deps';
+ static const mavenSourceDir = '$mavenDownloads.source_dir';
+ static const jarOnlyDeps = '$mavenDownloads.jar_only_deps';
+ static const mavenJarDir = '$mavenDownloads.jar_dir';
+
+ static const androidSdkConfig = 'android_sdk_config';
+ static const androidSdkRoot = '$androidSdkConfig.sdk_root';
+ static const androidSdkVersions = '$androidSdkConfig.versions';
+ static const addGradleDeps = '$androidSdkConfig.add_gradle_deps';
+ static const addGradleSources = '$androidSdkConfig.add_gradle_sources';
+ static const androidExample = '$androidSdkConfig.android_example';
+}
diff --git a/pkgs/jnigen/lib/src/config/experiments.dart b/pkgs/jnigen/lib/src/config/experiments.dart
new file mode 100644
index 0000000..6bb65c1
--- /dev/null
+++ b/pkgs/jnigen/lib/src/config/experiments.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Experiment {
+ static const available = [
+ interfaceImplementation,
+ ];
+
+ static const interfaceImplementation = Experiment(
+ name: 'interface_implementation',
+ description: 'Enables generation of machinery for '
+ 'implementing Java interfaces in Dart.',
+ isExpired: false,
+ );
+
+ final String name;
+ final String description;
+ final bool isExpired;
+
+ const Experiment({
+ required this.name,
+ required this.description,
+ required this.isExpired,
+ });
+
+ factory Experiment.fromString(String s) {
+ final search = available.where((element) => element.name == s);
+ if (search.isEmpty) {
+ throw 'The experiment $s is not available in this version.';
+ }
+ final result = search.single;
+ if (result.isExpired) {
+ throw 'The experiment $s can no longer be used in this version.';
+ }
+ return result;
+ }
+}
diff --git a/pkgs/jnigen/lib/src/config/filters.dart b/pkgs/jnigen/lib/src/config/filters.dart
new file mode 100644
index 0000000..1d0e1a5
--- /dev/null
+++ b/pkgs/jnigen/lib/src/config/filters.dart
@@ -0,0 +1,118 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../elements/elements.dart';
+
+bool _matchesCompletely(String string, Pattern pattern) {
+ final match = pattern.matchAsPrefix(string);
+ return match != null && match.group(0) == string;
+}
+
+/// A filter which tells if bindings for given [ClassDecl] are generated.
+abstract class ClassFilter {
+ bool included(ClassDecl decl);
+}
+
+/// This filter includes the declarations for which [predicate] returns true.
+class CustomClassFilter implements ClassFilter {
+ CustomClassFilter(this.predicate);
+ final bool Function(ClassDecl) predicate;
+ @override
+ bool included(ClassDecl decl) {
+ return predicate(decl);
+ }
+}
+
+/// Filter to include / exclude classes by matching on the binary name.
+/// A binary name is like qualified name but with a `$` used to indicate nested
+/// class instead of `.`, guaranteeing a unique name.
+class ClassNameFilter implements ClassFilter {
+ ClassNameFilter.include(this.pattern) : onMatch = true;
+ ClassNameFilter.exclude(this.pattern) : onMatch = false;
+ final bool onMatch;
+ final Pattern pattern;
+ @override
+ bool included(ClassDecl decl) {
+ if (_matchesCompletely(decl.binaryName, pattern)) {
+ return onMatch;
+ }
+ return !onMatch;
+ }
+}
+
+abstract class MemberFilter<T extends ClassMember> {
+ bool included(ClassDecl classDecl, T member);
+}
+
+/// Filter that excludes or includes members based on class and member name.
+class MemberNameFilter<T extends ClassMember> implements MemberFilter<T> {
+ MemberNameFilter.include(this.classPattern, this.namePattern)
+ : onMatch = true;
+ MemberNameFilter.exclude(this.classPattern, this.namePattern)
+ : onMatch = false;
+ final bool onMatch;
+ final Pattern classPattern, namePattern;
+ @override
+ bool included(ClassDecl classDecl, T member) {
+ final matches = _matchesCompletely(classDecl.binaryName, classPattern) &&
+ _matchesCompletely(member.name, namePattern);
+ return matches ? onMatch : !onMatch;
+ }
+}
+
+/// Filter that includes or excludes a member based on a custom callback.
+class CustomMemberFilter<T extends ClassMember> implements MemberFilter<T> {
+ CustomMemberFilter(this.predicate);
+ bool Function(ClassDecl, T) predicate;
+ @override
+ bool included(ClassDecl classDecl, T member) => predicate(classDecl, member);
+}
+
+/// Filter which excludes classes excluded by any one filter in [filters].
+class CombinedClassFilter implements ClassFilter {
+ CombinedClassFilter.all(this.filters);
+ final List<ClassFilter> filters;
+ @override
+ bool included(ClassDecl decl) => filters.every((f) => f.included(decl));
+}
+
+/// Filter which excludes members excluded by any one filter in [filters].
+class CombinedMemberFilter<T extends ClassMember> implements MemberFilter<T> {
+ CombinedMemberFilter(this.filters);
+
+ final List<MemberFilter<T>> filters;
+
+ @override
+ bool included(ClassDecl decl, T member) {
+ return filters.every((f) => f.included(decl, member));
+ }
+}
+
+typedef FieldFilter = MemberFilter<Field>;
+typedef MethodFilter = MemberFilter<Method>;
+
+/// Filter using binary name of the class and name of the field.
+typedef FieldNameFilter = MemberNameFilter<Field>;
+
+/// Filter using binary name of the class and name of the method.
+typedef MethodNameFilter = MemberNameFilter<Method>;
+
+/// Predicate based filter for field, which can access class declaration
+/// and the field.
+typedef CustomFieldFilter = CustomMemberFilter<Field>;
+
+/// Predicate based filter for method, which can access class declaration
+/// and the method.
+typedef CustomMethodFilter = CustomMemberFilter<Method>;
+
+/// This filter excludes fields if any one of sub-filters returns false.
+typedef CombinedFieldFilter = CombinedMemberFilter<Field>;
+
+/// This filter excludes methods if any one of sub-filters returns false.
+typedef CombinedMethodFilter = CombinedMemberFilter<Method>;
+
+MemberFilter<T> excludeAll<T extends ClassMember>(List<List<Pattern>> names) {
+ return CombinedMemberFilter<T>(
+ names.map((p) => MemberNameFilter<T>.exclude(p[0], p[1])).toList());
+}
diff --git a/pkgs/jnigen/lib/src/config/yaml_reader.dart b/pkgs/jnigen/lib/src/config/yaml_reader.dart
new file mode 100644
index 0000000..1cb1f46
--- /dev/null
+++ b/pkgs/jnigen/lib/src/config/yaml_reader.dart
@@ -0,0 +1,115 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:args/args.dart';
+import 'package:yaml/yaml.dart';
+import 'package:cli_config/cli_config.dart' as cli_config;
+
+import 'config_exception.dart';
+
+/// YAML Reader which enables to override specific values from command line.
+class YamlReader {
+ final cli_config.Config _config;
+
+ final Uri? _configRoot;
+
+ YamlReader.of(this._config, this._configRoot);
+
+ /// Parses the provided command line arguments and returns a [YamlReader].
+ ///
+ /// This is a utility function which does all things a program would do when
+ /// parsing command line arguments, including exiting from the program when
+ /// arguments are invalid.
+ static YamlReader parseArgs(List<String> args,
+ {bool allowYamlConfig = true}) {
+ final parser = ArgParser();
+ parser.addFlag('help', abbr: 'h', help: 'Show this help.');
+
+ // Sometimes it's required to change a config value for a single invocation,
+ // then this option can be used. Conventionally in -D switch is used in
+ // C to set preprocessor variable & in java to override a config property.
+
+ parser.addMultiOption('override',
+ abbr: 'D',
+ help: 'Override or assign a config property from command line.');
+ if (allowYamlConfig) {
+ parser.addOption('config', abbr: 'c', help: 'Path to YAML config.');
+ }
+
+ final results = parser.parse(args);
+ if (results['help']) {
+ stderr.writeln(parser.usage);
+ exit(1);
+ }
+ final configFilePath = results['config'] as String?;
+ String? configFileContents;
+ Uri? configFileUri;
+ if (configFilePath != null) {
+ try {
+ configFileContents = File(configFilePath).readAsStringSync();
+ configFileUri = File(configFilePath).uri;
+ } on Exception catch (e) {
+ stderr.writeln('Cannot read $configFilePath: $e.');
+ }
+ }
+ final regex = RegExp('([a-z-_.]+)=(.+)');
+ final properties = <String, String>{};
+ for (var prop in results['override']) {
+ final match = regex.matchAsPrefix(prop as String);
+ if (match != null && match.group(0) == prop) {
+ final propertyName = match.group(1);
+ final propertyValue = match.group(2);
+ properties[propertyName!] = propertyValue!;
+ } else {
+ throw ConfigException('override does not match expected pattern');
+ }
+ }
+ final config = cli_config.Config.fromConfigFileContents(
+ commandLineDefines: results['override'],
+ workingDirectory: Directory.current.uri,
+ environment: Platform.environment,
+ fileContents: configFileContents,
+ fileSourceUri: configFileUri,
+ );
+ return YamlReader.of(
+ config,
+ configFileUri?.resolve('.'),
+ );
+ }
+
+ bool? getBool(String property) => _config.optionalBool(property);
+
+ String? getString(String property) => _config.optionalString(property);
+
+ /// Same as [getString] but path is resolved relative to YAML config if it's
+ /// from YAML config.
+ Uri? getPath(String property) => _config.optionalPath(property);
+
+ List<String>? getStringList(String property) => _config.optionalStringList(
+ property,
+ splitCliPattern: ';',
+ combineAllConfigs: false,
+ );
+
+ List<Uri>? getPathList(String property) => _config.optionalPathList(
+ property,
+ combineAllConfigs: false,
+ splitCliPattern: ';',
+ );
+
+ String? getOneOf(String property, Set<String> values) =>
+ _config.optionalString(property, validValues: values);
+
+ Map<String, String>? getStringMap(String property) {
+ final value = _config.valueOf<YamlMap?>(property);
+ return value?.cast<String, String>();
+ }
+
+ bool hasValue(String property) => _config.valueOf<dynamic>(property) != null;
+
+ /// Returns URI of the directory containing YAML config.
+ Uri? getConfigRoot() => _configRoot;
+}
diff --git a/pkgs/jnigen/lib/src/elements/elements.dart b/pkgs/jnigen/lib/src/elements/elements.dart
new file mode 100644
index 0000000..020f05d
--- /dev/null
+++ b/pkgs/jnigen/lib/src/elements/elements.dart
@@ -0,0 +1,681 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:json_annotation/json_annotation.dart';
+
+// Types to describe java API elements
+
+import '../bindings/visitor.dart';
+
+part 'elements.g.dart';
+
+abstract class Element<T extends Element<T>> {
+ const Element();
+
+ R accept<R>(Visitor<T, R> v);
+}
+
+@JsonEnum()
+
+/// A kind describes the type of a declaration.
+enum DeclKind {
+ @JsonValue('CLASS')
+ classKind,
+ @JsonValue('INTERFACE')
+ interfaceKind,
+ @JsonValue('ENUM')
+ enumKind,
+}
+
+class Classes implements Element<Classes> {
+ const Classes(this.decls);
+
+ final Map<String, ClassDecl> decls;
+
+ factory Classes.fromJson(List<dynamic> json) {
+ final decls = <String, ClassDecl>{};
+ for (final declJson in json) {
+ final classDecl = ClassDecl.fromJson(declJson);
+ decls[classDecl.binaryName] = classDecl;
+ }
+ return Classes(decls);
+ }
+
+ @override
+ R accept<R>(Visitor<Classes, R> v) {
+ return v.visit(this);
+ }
+}
+
+// Note: We give default values in constructor, if the field is nullable in
+// JSON. this allows us to reduce JSON size by providing Include.NON_NULL
+// option in java.
+
+@JsonSerializable(createToJson: false)
+class ClassDecl extends ClassMember implements Element<ClassDecl> {
+ ClassDecl({
+ this.annotations = const [],
+ this.javadoc,
+ required this.declKind,
+ this.modifiers = const {},
+ required this.binaryName,
+ this.typeParams = const [],
+ this.methods = const [],
+ this.fields = const [],
+ this.superclass,
+ this.interfaces = const [],
+ this.hasStaticInit = false,
+ this.hasInstanceInit = false,
+ this.values,
+ this.kotlinClass,
+ });
+
+ @override
+ final Set<String> modifiers;
+
+ final List<Annotation> annotations;
+ final KotlinClass? kotlinClass;
+ final JavaDocComment? javadoc;
+ final DeclKind declKind;
+ final String binaryName;
+ List<TypeParam> typeParams;
+ List<Method> methods;
+ List<Field> fields;
+ final List<TypeUsage> interfaces;
+ final bool hasStaticInit;
+ final bool hasInstanceInit;
+
+ /// Will default to java.lang.Object if null by [Linker].
+ TypeUsage? superclass;
+
+ /// Contains enum constant names if class is an enum,
+ /// as obtained by `.values()` method in Java.
+ final List<String>? values;
+
+ String get internalName => binaryName.replaceAll(".", "/");
+
+ String get packageName => (binaryName.split('.')..removeLast()).join('.');
+
+ /// The number of super classes this type has.
+ ///
+ /// Populated by [Linker].
+ @JsonKey(includeFromJson: false)
+ late final int superCount;
+
+ /// Parent's [ClassDecl] obtained from [parentName].
+ ///
+ /// Populated by [Linker].
+ @JsonKey(includeFromJson: false)
+ late final ClassDecl? parent;
+
+ /// Final name of this class.
+ ///
+ /// Populated by [Renamer].
+ @JsonKey(includeFromJson: false)
+ late final String finalName;
+
+ /// Name of the type class.
+ ///
+ /// Populated by [Renamer].
+ @JsonKey(includeFromJson: false)
+ late final String typeClassName;
+
+ /// Unique name obtained by renaming conflicting names with a number.
+ ///
+ /// This is used by C bindings instead of fully qualified name to reduce
+ /// the verbosity of generated bindings.
+ ///
+ /// Populated by [Renamer].
+ @JsonKey(includeFromJson: false)
+ late final String uniqueName;
+
+ /// Type parameters including the ones from its ancestors
+ ///
+ /// Populated by [Linker].
+ @JsonKey(includeFromJson: false)
+ List<TypeParam> allTypeParams = const [];
+
+ /// The path which this class is generated in.
+ ///
+ /// Populated by [Linker].
+ @JsonKey(includeFromJson: false)
+ late final String path;
+
+ /// The numeric suffix of the methods.
+ ///
+ /// Populated by [Renamer].
+ @JsonKey(includeFromJson: false)
+ late final Map<String, int> methodNumsAfterRenaming;
+
+ @override
+ String toString() {
+ return 'Java class declaration for $binaryName';
+ }
+
+ String get signature => 'L$internalName;';
+
+ factory ClassDecl.fromJson(Map<String, dynamic> json) =>
+ _$ClassDeclFromJson(json);
+
+ @override
+ R accept<R>(Visitor<ClassDecl, R> v) {
+ return v.visit(this);
+ }
+
+ @override
+ ClassDecl get classDecl => this;
+
+ @override
+ String get name => finalName;
+
+ bool get isObject => superCount == 0;
+
+ @JsonKey(includeFromJson: false)
+ late final String? parentName = binaryName.contains(r'$')
+ ? binaryName.splitMapJoin(RegExp(r'\$[^$]+$'), onMatch: (_) => '')
+ : null;
+
+ @JsonKey(includeFromJson: false)
+ late final isNested = parentName != null;
+}
+
+@JsonEnum()
+enum Kind {
+ @JsonValue('PRIMITIVE')
+ primitive,
+ @JsonValue('TYPE_VARIABLE')
+ typeVariable,
+ @JsonValue('WILDCARD')
+ wildcard,
+ @JsonValue('DECLARED')
+ declared,
+ @JsonValue('ARRAY')
+ array,
+}
+
+@JsonSerializable(createToJson: false)
+class TypeUsage {
+ TypeUsage({
+ required this.shorthand,
+ required this.kind,
+ required this.typeJson,
+ });
+
+ static TypeUsage object = TypeUsage(
+ kind: Kind.declared, shorthand: 'java.lang.Object', typeJson: {})
+ ..type = DeclaredType(binaryName: 'java.lang.Object');
+
+ final String shorthand;
+ final Kind kind;
+
+ @JsonKey(name: "type")
+ final Map<String, dynamic> typeJson;
+
+ /// Populated by [TypeUsage.fromJson].
+ @JsonKey(includeFromJson: false)
+ late final ReferredType type;
+
+ /// Populated by [Descriptor].
+ @JsonKey(includeFromJson: false)
+ late String descriptor;
+
+ String get name => type.name;
+
+ // Since json_serializable doesn't directly support union types,
+ // we have to temporarily store `type` in a JSON map, and switch on the
+ // enum value received.
+ factory TypeUsage.fromJson(Map<String, dynamic> json) {
+ final t = _$TypeUsageFromJson(json);
+ switch (t.kind) {
+ case Kind.primitive:
+ t.type = PrimitiveType.fromJson(t.typeJson);
+ break;
+ case Kind.typeVariable:
+ t.type = TypeVar.fromJson(t.typeJson);
+ break;
+ case Kind.wildcard:
+ t.type = Wildcard.fromJson(t.typeJson);
+ break;
+ case Kind.declared:
+ t.type = DeclaredType.fromJson(t.typeJson);
+ break;
+ case Kind.array:
+ t.type = ArrayType.fromJson(t.typeJson);
+ break;
+ }
+ return t;
+ }
+
+ R accept<R>(TypeVisitor<R> v) {
+ return type.accept(v);
+ }
+}
+
+abstract class ReferredType {
+ const ReferredType();
+ String get name;
+
+ R accept<R>(TypeVisitor<R> v);
+}
+
+class PrimitiveType extends ReferredType {
+ static const _primitives = {
+ 'byte': PrimitiveType._(
+ name: 'byte',
+ signature: 'B',
+ dartType: 'int',
+ boxedName: 'Byte',
+ cType: 'int8_t',
+ ffiType: 'Int8',
+ ),
+ 'short': PrimitiveType._(
+ name: 'short',
+ signature: 'S',
+ dartType: 'int',
+ boxedName: 'Short',
+ cType: 'int16_t',
+ ffiType: 'Int16',
+ ),
+ 'char': PrimitiveType._(
+ name: 'char',
+ signature: 'C',
+ dartType: 'int',
+ boxedName: 'Character',
+ cType: 'uint16_t',
+ ffiType: 'Uint16',
+ ),
+ 'int': PrimitiveType._(
+ name: 'int',
+ signature: 'I',
+ dartType: 'int',
+ boxedName: 'Integer',
+ cType: 'int32_t',
+ ffiType: 'Int32',
+ ),
+ 'long': PrimitiveType._(
+ name: 'long',
+ signature: 'J',
+ dartType: 'int',
+ boxedName: 'Long',
+ cType: 'int64_t',
+ ffiType: 'Int64',
+ ),
+ 'float': PrimitiveType._(
+ name: 'float',
+ signature: 'F',
+ dartType: 'double',
+ boxedName: 'Float',
+ cType: 'float',
+ ffiType: 'Float',
+ ),
+ 'double': PrimitiveType._(
+ name: 'double',
+ signature: 'D',
+ dartType: 'double',
+ boxedName: 'Double',
+ cType: 'double',
+ ffiType: 'Double',
+ ),
+ 'boolean': PrimitiveType._(
+ name: 'boolean',
+ signature: 'Z',
+ dartType: 'bool',
+ boxedName: 'Boolean',
+ cType: 'uint8_t',
+ ffiType: 'Uint8',
+ ),
+ 'void': PrimitiveType._(
+ name: 'void',
+ signature: 'V',
+ dartType: 'void',
+ boxedName: 'Void', // Not used.
+ cType: 'void',
+ ffiType: 'Void',
+ ),
+ };
+
+ const PrimitiveType._({
+ required this.name,
+ required this.signature,
+ required this.dartType,
+ required this.boxedName,
+ required this.cType,
+ required this.ffiType,
+ });
+
+ @override
+ final String name;
+
+ final String signature;
+ final String dartType;
+ final String boxedName;
+ final String cType;
+ final String ffiType;
+
+ factory PrimitiveType.fromJson(Map<String, dynamic> json) {
+ return _primitives[json['name']]!;
+ }
+
+ @override
+ R accept<R>(TypeVisitor<R> v) {
+ return v.visitPrimitiveType(this);
+ }
+}
+
+@JsonSerializable(createToJson: false)
+class DeclaredType extends ReferredType {
+ DeclaredType({
+ required this.binaryName,
+ this.params = const [],
+ });
+
+ final String binaryName;
+ final List<TypeUsage> params;
+
+ @JsonKey(includeFromJson: false)
+ late ClassDecl classDecl;
+
+ @override
+ String get name => binaryName;
+
+ factory DeclaredType.fromJson(Map<String, dynamic> json) =>
+ _$DeclaredTypeFromJson(json);
+
+ @override
+ R accept<R>(TypeVisitor<R> v) {
+ return v.visitDeclaredType(this);
+ }
+}
+
+@JsonSerializable(createToJson: false)
+class TypeVar extends ReferredType {
+ TypeVar({required this.name});
+
+ @override
+ String name;
+
+ factory TypeVar.fromJson(Map<String, dynamic> json) =>
+ _$TypeVarFromJson(json);
+
+ @override
+ R accept<R>(TypeVisitor<R> v) {
+ return v.visitTypeVar(this);
+ }
+}
+
+@JsonSerializable(createToJson: false)
+class Wildcard extends ReferredType {
+ Wildcard({this.extendsBound, this.superBound});
+ TypeUsage? extendsBound, superBound;
+
+ @override
+ String get name => "?";
+
+ factory Wildcard.fromJson(Map<String, dynamic> json) =>
+ _$WildcardFromJson(json);
+
+ @override
+ R accept<R>(TypeVisitor<R> v) {
+ return v.visitWildcard(this);
+ }
+}
+
+@JsonSerializable(createToJson: false)
+class ArrayType extends ReferredType {
+ ArrayType({required this.type});
+ TypeUsage type;
+
+ @override
+ String get name => "[${type.name}";
+
+ factory ArrayType.fromJson(Map<String, dynamic> json) =>
+ _$ArrayTypeFromJson(json);
+
+ @override
+ R accept<R>(TypeVisitor<R> v) {
+ return v.visitArrayType(this);
+ }
+}
+
+abstract class ClassMember {
+ String get name;
+ ClassDecl get classDecl;
+ Set<String> get modifiers;
+
+ bool get isStatic => modifiers.contains('static');
+ bool get isFinal => modifiers.contains('final');
+ bool get isPublic => modifiers.contains('public');
+ bool get isProtected => modifiers.contains('protected');
+}
+
+@JsonSerializable(createToJson: false)
+class Method extends ClassMember implements Element<Method> {
+ Method({
+ this.annotations = const [],
+ this.javadoc,
+ this.modifiers = const {},
+ required this.name,
+ this.descriptor,
+ this.typeParams = const [],
+ this.params = const [],
+ required this.returnType,
+ });
+
+ @override
+ final String name;
+ @override
+ final Set<String> modifiers;
+
+ final List<Annotation> annotations;
+ final JavaDocComment? javadoc;
+ final List<TypeParam> typeParams;
+ List<Param> params;
+ final TypeUsage returnType;
+
+ /// Can be used to match with [KotlinFunction]'s descriptor.
+ ///
+ /// Can create a unique signature in combination with [name].
+ /// Populated either by the ASM backend or [Descriptor].
+ String? descriptor;
+
+ /// The [ClassDecl] where this method is defined.
+ ///
+ /// Populated by [Linker].
+ @JsonKey(includeFromJson: false)
+ @override
+ late ClassDecl classDecl;
+
+ /// Populated by [Renamer].
+ @JsonKey(includeFromJson: false)
+ late String finalName;
+
+ @JsonKey(includeFromJson: false)
+ late bool isOverridden;
+
+ /// The actual return type when the method is a Kotlin's suspend fun.
+ ///
+ /// Populated by [KotlinProcessor].
+ @JsonKey(includeFromJson: false)
+ TypeUsage? asyncReturnType;
+
+ @JsonKey(includeFromJson: false)
+ late final String javaSig = '$name$descriptor';
+
+ bool get isCtor => name == '<init>';
+
+ factory Method.fromJson(Map<String, dynamic> json) => _$MethodFromJson(json);
+
+ @override
+ R accept<R>(Visitor<Method, R> v) {
+ return v.visit(this);
+ }
+}
+
+@JsonSerializable(createToJson: false)
+class Param implements Element<Param> {
+ Param({
+ this.annotations = const [],
+ this.javadoc,
+ required this.name,
+ required this.type,
+ });
+
+ final List<Annotation> annotations;
+ final JavaDocComment? javadoc;
+ final String name;
+ final TypeUsage type;
+
+ /// Populated by [Renamer].
+ @JsonKey(includeFromJson: false)
+ late String finalName;
+
+ factory Param.fromJson(Map<String, dynamic> json) => _$ParamFromJson(json);
+
+ @override
+ R accept<R>(Visitor<Param, R> v) {
+ return v.visit(this);
+ }
+}
+
+@JsonSerializable(createToJson: false)
+class Field extends ClassMember implements Element<Field> {
+ Field({
+ this.annotations = const [],
+ this.javadoc,
+ this.modifiers = const {},
+ required this.name,
+ required this.type,
+ this.defaultValue,
+ });
+
+ @override
+ final String name;
+ @override
+ final Set<String> modifiers;
+
+ final List<Annotation> annotations;
+ final JavaDocComment? javadoc;
+ final TypeUsage type;
+ final Object? defaultValue;
+
+ /// The [ClassDecl] where this field is defined.
+ ///
+ /// Populated by [Linker].
+ @JsonKey(includeFromJson: false)
+ @override
+ late final ClassDecl classDecl;
+
+ /// Populated by [Renamer].
+ @JsonKey(includeFromJson: false)
+ late final String finalName;
+
+ factory Field.fromJson(Map<String, dynamic> json) => _$FieldFromJson(json);
+
+ @override
+ R accept<R>(Visitor<Field, R> v) {
+ return v.visit(this);
+ }
+}
+
+@JsonSerializable(createToJson: false)
+class TypeParam implements Element<TypeParam> {
+ TypeParam({required this.name, this.bounds = const []});
+
+ final String name;
+ final List<TypeUsage> bounds;
+
+ @JsonKey(includeFromJson: false)
+ late final String erasure;
+
+ factory TypeParam.fromJson(Map<String, dynamic> json) =>
+ _$TypeParamFromJson(json);
+
+ @override
+ R accept<R>(Visitor<TypeParam, R> v) {
+ return v.visit(this);
+ }
+}
+
+@JsonSerializable(createToJson: false)
+class JavaDocComment implements Element<JavaDocComment> {
+ JavaDocComment({this.comment = ''});
+
+ final String comment;
+
+ @JsonKey(includeFromJson: false)
+ late final String dartDoc;
+
+ factory JavaDocComment.fromJson(Map<String, dynamic> json) =>
+ _$JavaDocCommentFromJson(json);
+
+ @override
+ R accept<R>(Visitor<JavaDocComment, R> v) {
+ return v.visit(this);
+ }
+}
+
+@JsonSerializable(createToJson: false)
+class Annotation implements Element<Annotation> {
+ Annotation({
+ required this.binaryName,
+ this.properties = const {},
+ });
+
+ final String binaryName;
+ final Map<String, Object> properties;
+
+ factory Annotation.fromJson(Map<String, dynamic> json) =>
+ _$AnnotationFromJson(json);
+
+ @override
+ R accept<R>(Visitor<Annotation, R> v) {
+ return v.visit(this);
+ }
+}
+
+@JsonSerializable(createToJson: false)
+class KotlinClass implements Element<KotlinClass> {
+ KotlinClass({
+ required this.name,
+ this.functions = const [],
+ });
+
+ final String name;
+ final List<KotlinFunction> functions;
+
+ factory KotlinClass.fromJson(Map<String, dynamic> json) =>
+ _$KotlinClassFromJson(json);
+
+ @override
+ R accept<R>(Visitor<KotlinClass, R> v) {
+ return v.visit(this);
+ }
+}
+
+@JsonSerializable(createToJson: false)
+class KotlinFunction implements Element<KotlinFunction> {
+ KotlinFunction({
+ required this.name,
+ required this.descriptor,
+ required this.kotlinName,
+ required this.isSuspend,
+ });
+
+ final String name;
+
+ /// Used to match with [Method]'s descriptor.
+ ///
+ /// Creates a unique signature in combination with [name].
+ final String descriptor;
+ final String kotlinName;
+ final bool isSuspend;
+
+ factory KotlinFunction.fromJson(Map<String, dynamic> json) =>
+ _$KotlinFunctionFromJson(json);
+
+ @override
+ R accept<R>(Visitor<KotlinFunction, R> v) {
+ return v.visit(this);
+ }
+}
diff --git a/pkgs/jnigen/lib/src/elements/elements.g.dart b/pkgs/jnigen/lib/src/elements/elements.g.dart
new file mode 100644
index 0000000..dcd35dd
--- /dev/null
+++ b/pkgs/jnigen/lib/src/elements/elements.g.dart
@@ -0,0 +1,186 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'elements.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+ClassDecl _$ClassDeclFromJson(Map<String, dynamic> json) => ClassDecl(
+ annotations: (json['annotations'] as List<dynamic>?)
+ ?.map((e) => Annotation.fromJson(e as Map<String, dynamic>))
+ .toList() ??
+ const [],
+ javadoc: json['javadoc'] == null
+ ? null
+ : JavaDocComment.fromJson(json['javadoc'] as Map<String, dynamic>),
+ declKind: $enumDecode(_$DeclKindEnumMap, json['declKind']),
+ modifiers: (json['modifiers'] as List<dynamic>?)
+ ?.map((e) => e as String)
+ .toSet() ??
+ const {},
+ binaryName: json['binaryName'] as String,
+ typeParams: (json['typeParams'] as List<dynamic>?)
+ ?.map((e) => TypeParam.fromJson(e as Map<String, dynamic>))
+ .toList() ??
+ const [],
+ methods: (json['methods'] as List<dynamic>?)
+ ?.map((e) => Method.fromJson(e as Map<String, dynamic>))
+ .toList() ??
+ const [],
+ fields: (json['fields'] as List<dynamic>?)
+ ?.map((e) => Field.fromJson(e as Map<String, dynamic>))
+ .toList() ??
+ const [],
+ superclass: json['superclass'] == null
+ ? null
+ : TypeUsage.fromJson(json['superclass'] as Map<String, dynamic>),
+ interfaces: (json['interfaces'] as List<dynamic>?)
+ ?.map((e) => TypeUsage.fromJson(e as Map<String, dynamic>))
+ .toList() ??
+ const [],
+ hasStaticInit: json['hasStaticInit'] as bool? ?? false,
+ hasInstanceInit: json['hasInstanceInit'] as bool? ?? false,
+ values:
+ (json['values'] as List<dynamic>?)?.map((e) => e as String).toList(),
+ kotlinClass: json['kotlinClass'] == null
+ ? null
+ : KotlinClass.fromJson(json['kotlinClass'] as Map<String, dynamic>),
+ );
+
+const _$DeclKindEnumMap = {
+ DeclKind.classKind: 'CLASS',
+ DeclKind.interfaceKind: 'INTERFACE',
+ DeclKind.enumKind: 'ENUM',
+};
+
+TypeUsage _$TypeUsageFromJson(Map<String, dynamic> json) => TypeUsage(
+ shorthand: json['shorthand'] as String,
+ kind: $enumDecode(_$KindEnumMap, json['kind']),
+ typeJson: json['type'] as Map<String, dynamic>,
+ );
+
+const _$KindEnumMap = {
+ Kind.primitive: 'PRIMITIVE',
+ Kind.typeVariable: 'TYPE_VARIABLE',
+ Kind.wildcard: 'WILDCARD',
+ Kind.declared: 'DECLARED',
+ Kind.array: 'ARRAY',
+};
+
+DeclaredType _$DeclaredTypeFromJson(Map<String, dynamic> json) => DeclaredType(
+ binaryName: json['binaryName'] as String,
+ params: (json['params'] as List<dynamic>?)
+ ?.map((e) => TypeUsage.fromJson(e as Map<String, dynamic>))
+ .toList() ??
+ const [],
+ );
+
+TypeVar _$TypeVarFromJson(Map<String, dynamic> json) => TypeVar(
+ name: json['name'] as String,
+ );
+
+Wildcard _$WildcardFromJson(Map<String, dynamic> json) => Wildcard(
+ extendsBound: json['extendsBound'] == null
+ ? null
+ : TypeUsage.fromJson(json['extendsBound'] as Map<String, dynamic>),
+ superBound: json['superBound'] == null
+ ? null
+ : TypeUsage.fromJson(json['superBound'] as Map<String, dynamic>),
+ );
+
+ArrayType _$ArrayTypeFromJson(Map<String, dynamic> json) => ArrayType(
+ type: TypeUsage.fromJson(json['type'] as Map<String, dynamic>),
+ );
+
+Method _$MethodFromJson(Map<String, dynamic> json) => Method(
+ annotations: (json['annotations'] as List<dynamic>?)
+ ?.map((e) => Annotation.fromJson(e as Map<String, dynamic>))
+ .toList() ??
+ const [],
+ javadoc: json['javadoc'] == null
+ ? null
+ : JavaDocComment.fromJson(json['javadoc'] as Map<String, dynamic>),
+ modifiers: (json['modifiers'] as List<dynamic>?)
+ ?.map((e) => e as String)
+ .toSet() ??
+ const {},
+ name: json['name'] as String,
+ descriptor: json['descriptor'] as String?,
+ typeParams: (json['typeParams'] as List<dynamic>?)
+ ?.map((e) => TypeParam.fromJson(e as Map<String, dynamic>))
+ .toList() ??
+ const [],
+ params: (json['params'] as List<dynamic>?)
+ ?.map((e) => Param.fromJson(e as Map<String, dynamic>))
+ .toList() ??
+ const [],
+ returnType:
+ TypeUsage.fromJson(json['returnType'] as Map<String, dynamic>),
+ );
+
+Param _$ParamFromJson(Map<String, dynamic> json) => Param(
+ annotations: (json['annotations'] as List<dynamic>?)
+ ?.map((e) => Annotation.fromJson(e as Map<String, dynamic>))
+ .toList() ??
+ const [],
+ javadoc: json['javadoc'] == null
+ ? null
+ : JavaDocComment.fromJson(json['javadoc'] as Map<String, dynamic>),
+ name: json['name'] as String,
+ type: TypeUsage.fromJson(json['type'] as Map<String, dynamic>),
+ );
+
+Field _$FieldFromJson(Map<String, dynamic> json) => Field(
+ annotations: (json['annotations'] as List<dynamic>?)
+ ?.map((e) => Annotation.fromJson(e as Map<String, dynamic>))
+ .toList() ??
+ const [],
+ javadoc: json['javadoc'] == null
+ ? null
+ : JavaDocComment.fromJson(json['javadoc'] as Map<String, dynamic>),
+ modifiers: (json['modifiers'] as List<dynamic>?)
+ ?.map((e) => e as String)
+ .toSet() ??
+ const {},
+ name: json['name'] as String,
+ type: TypeUsage.fromJson(json['type'] as Map<String, dynamic>),
+ defaultValue: json['defaultValue'],
+ );
+
+TypeParam _$TypeParamFromJson(Map<String, dynamic> json) => TypeParam(
+ name: json['name'] as String,
+ bounds: (json['bounds'] as List<dynamic>?)
+ ?.map((e) => TypeUsage.fromJson(e as Map<String, dynamic>))
+ .toList() ??
+ const [],
+ );
+
+JavaDocComment _$JavaDocCommentFromJson(Map<String, dynamic> json) =>
+ JavaDocComment(
+ comment: json['comment'] as String? ?? '',
+ );
+
+Annotation _$AnnotationFromJson(Map<String, dynamic> json) => Annotation(
+ binaryName: json['binaryName'] as String,
+ properties: (json['properties'] as Map<String, dynamic>?)?.map(
+ (k, e) => MapEntry(k, e as Object),
+ ) ??
+ const {},
+ );
+
+KotlinClass _$KotlinClassFromJson(Map<String, dynamic> json) => KotlinClass(
+ name: json['name'] as String,
+ functions: (json['functions'] as List<dynamic>?)
+ ?.map((e) => KotlinFunction.fromJson(e as Map<String, dynamic>))
+ .toList() ??
+ const [],
+ );
+
+KotlinFunction _$KotlinFunctionFromJson(Map<String, dynamic> json) =>
+ KotlinFunction(
+ name: json['name'] as String,
+ descriptor: json['descriptor'] as String,
+ kotlinName: json['kotlinName'] as String,
+ isSuspend: json['isSuspend'] as bool,
+ );
diff --git a/pkgs/jnigen/lib/src/generate_bindings.dart b/pkgs/jnigen/lib/src/generate_bindings.dart
new file mode 100644
index 0000000..883ca85
--- /dev/null
+++ b/pkgs/jnigen/lib/src/generate_bindings.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+import 'dart:convert';
+
+import 'bindings/c_generator.dart';
+import 'bindings/dart_generator.dart';
+import 'bindings/descriptor.dart';
+import 'bindings/excluder.dart';
+import 'bindings/kotlin_processor.dart';
+import 'bindings/linker.dart';
+import 'bindings/unnester.dart';
+import 'bindings/renamer.dart';
+import 'elements/elements.dart';
+import 'summary/summary.dart';
+import 'config/config.dart';
+import 'tools/tools.dart';
+import 'logging/logging.dart';
+
+void collectOutputStream(Stream<List<int>> stream, StringBuffer buffer) =>
+ stream.transform(const Utf8Decoder()).forEach(buffer.write);
+Future<void> generateJniBindings(Config config) async {
+ setLoggingLevel(config.logLevel);
+
+ await buildSummarizerIfNotExists();
+
+ final Classes classes;
+
+ try {
+ classes = await getSummary(config);
+ } on SummaryParseException catch (e) {
+ if (e.stderr != null) {
+ printError(e.stderr);
+ }
+ log.fatal(e.message);
+ }
+
+ classes.accept(Excluder(config));
+ classes.accept(KotlinProcessor());
+ await classes.accept(Linker(config));
+ classes.accept(const Unnester());
+ classes.accept(const Descriptor());
+ classes.accept(Renamer(config));
+
+ final cBased = config.outputConfig.bindingsType == BindingsType.cBased;
+ if (cBased) {
+ await classes.accept(CGenerator(config));
+ }
+
+ try {
+ await classes.accept(DartGenerator(config));
+ log.info('Completed');
+ } on Exception catch (e, trace) {
+ stderr.writeln(trace);
+ log.fatal('Error while writing bindings: $e');
+ }
+}
diff --git a/pkgs/jnigen/lib/src/logging/logging.dart b/pkgs/jnigen/lib/src/logging/logging.dart
new file mode 100644
index 0000000..71db217
--- /dev/null
+++ b/pkgs/jnigen/lib/src/logging/logging.dart
@@ -0,0 +1,126 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// coverage:ignore-file
+
+import 'dart:io';
+import 'package:logging/logging.dart';
+
+const _ansiRed = '\x1b[31m';
+const _ansiYellow = '\x1b[33m';
+const _ansiDefault = '\x1b[39;49m';
+
+String _colorize(String message, String colorCode) {
+ if (stderr.supportsAnsiEscapes) {
+ return '$colorCode$message$_ansiDefault';
+ }
+ return message;
+}
+
+/// Format [DateTime] for use in filename
+String _formatTime(DateTime now) {
+ return '${now.year}-${now.month}-${now.day}-'
+ '${now.hour}.${now.minute}.${now.second}';
+}
+
+// We need to respect logging level for console but log everything to file.
+// Hierarchical logging is convoluted. I'm just keeping track of log level.
+var _logLevel = Level.INFO;
+
+final _logDirUri = Directory.current.uri.resolve(".dart_tool/jnigen/logs/");
+
+final _logDir = () {
+ final dir = Directory.fromUri(_logDirUri);
+ dir.createSync(recursive: true);
+ return dir;
+}();
+
+Uri _getDefaultLogFileUri() =>
+ _logDir.uri.resolve("jnigen-${_formatTime(DateTime.now())}.log");
+
+IOSink? _logStream;
+
+/// Enable saving the logs to a file.
+///
+/// This is only meant to be called from an application entry point such as
+/// `main`.
+void enableLoggingToFile() {
+ _deleteOldLogFiles();
+ if (_logStream != null) {
+ throw StateError('Log file is already set');
+ }
+ _logStream = File.fromUri(_getDefaultLogFileUri()).openWrite();
+}
+
+// Maximum number of log files to keep.
+const _maxLogFiles = 5;
+
+/// Delete log files except most recent [_maxLogFiles] files.
+void _deleteOldLogFiles() {
+ final logFiles = _logDir.listSync().map((f) => File(f.path)).toList();
+ // sort in descending order of last modified time.
+ logFiles
+ .sort((f1, f2) => f2.lastModifiedSync().compareTo(f1.lastModifiedSync()));
+ final toDelete = logFiles.length < _maxLogFiles
+ ? const <File>[]
+ : logFiles.sublist(_maxLogFiles - 1);
+ for (final oldLogFile in toDelete) {
+ oldLogFile.deleteSync();
+ }
+}
+
+Logger log = () {
+ // initialize the logger.
+ final jnigenLogger = Logger('jnigen');
+ Logger.root.level = Level.ALL;
+ Logger.root.onRecord.listen((r) {
+ // Write to file regardless of level.
+ _logStream?.writeln('${r.level} ${r.time}: ${r.message}');
+ // write to console only if level is above configured level.
+ if (r.level < _logLevel) {
+ return;
+ }
+ var message = '(${r.loggerName}) ${r.level.name}: ${r.message}';
+ if ((r.level == Level.SHOUT || r.level == Level.SEVERE)) {
+ message = _colorize(message, _ansiRed);
+ } else if (r.level == Level.WARNING) {
+ message = _colorize(message, _ansiYellow);
+ }
+ stderr.writeln(message);
+ });
+ return jnigenLogger;
+}();
+
+/// Set logging level to [level].
+void setLoggingLevel(Level level) {
+ log.fine('Set log level: $level');
+ _logLevel = level;
+}
+
+/// Prints [message] without logging information.
+///
+/// Primarily used in printing output of failed commands.
+void printError(Object? message) {
+ stderr.writeln(_colorize(message.toString(), _ansiRed));
+}
+
+extension FatalErrors on Logger {
+ Never fatal(Object? message, {int exitCode = 1}) {
+ message = _colorize('Fatal: $message', _ansiRed);
+ stderr.writeln(message);
+ return exit(exitCode);
+ }
+}
+
+extension WriteToFile on Logger {
+ void writeToFile(Object? data) {
+ _logStream?.writeln(data);
+ }
+
+ void writeSectionToFile(String? sectionName, Object? data) {
+ _logStream?.writeln("==== Begin $sectionName ====");
+ _logStream?.writeln(data);
+ _logStream?.writeln("==== End $sectionName ====");
+ }
+}
diff --git a/pkgs/jnigen/lib/src/summary/summary.dart b/pkgs/jnigen/lib/src/summary/summary.dart
new file mode 100644
index 0000000..1706275
--- /dev/null
+++ b/pkgs/jnigen/lib/src/summary/summary.dart
@@ -0,0 +1,195 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+import '../../tools.dart';
+import '../config/config.dart';
+import '../elements/elements.dart';
+import '../generate_bindings.dart';
+import '../logging/logging.dart';
+
+class SummaryParseException implements Exception {
+ final String? stderr;
+ final String message;
+ SummaryParseException(this.message) : stderr = null;
+ SummaryParseException.withStderr(this.stderr, this.message);
+
+ @override
+ String toString() => message;
+}
+
+/// A command based summary source which calls the ApiSummarizer command.
+/// [sourcePaths] and [classPaths] can be provided for the summarizer to find
+/// required dependencies. The [classes] argument specifies the fully qualified
+/// names of classes or packages included in the generated summary. when a
+/// package is specified, its contents are included recursively.
+///
+/// When the default summarizer scans the [sourcePaths], it assumes that
+/// the directory names reflect actual package paths. For example, a class name
+/// com.example.pkg.Cls will be mapped to com/example/pkg/Cls.java.
+///
+/// The default summarizer needs to be built with `jnigen:setup`
+/// script before this API is used.
+class SummarizerCommand {
+ SummarizerCommand({
+ this.command = "java -jar .dart_tool/jnigen/ApiSummarizer.jar",
+ List<Uri>? sourcePath,
+ List<Uri>? classPath,
+ this.extraArgs = const [],
+ required this.classes,
+ this.workingDirectory,
+ this.backend,
+ }) : sourcePaths = sourcePath ?? [],
+ classPaths = classPath ?? [];
+
+ static const sourcePathsOption = '-s';
+ static const classPathsOption = '-c';
+
+ String command;
+ List<Uri> sourcePaths, classPaths;
+
+ List<String> extraArgs;
+ List<String> classes;
+
+ Uri? workingDirectory;
+ SummarizerBackend? backend;
+
+ void addSourcePaths(List<Uri> paths) {
+ sourcePaths.addAll(paths);
+ }
+
+ void addClassPaths(List<Uri> paths) {
+ classPaths.addAll(paths);
+ }
+
+ void _addPathParam(List<String> args, String option, List<Uri> paths) {
+ if (paths.isNotEmpty) {
+ final joined = paths
+ .map((uri) => uri.toFilePath())
+ .join(Platform.isWindows ? ';' : ':');
+ if (option.endsWith("=")) {
+ args.add(option + joined);
+ } else {
+ args.addAll([option, joined]);
+ }
+ }
+ }
+
+ Future<Process> runProcess() async {
+ final commandSplit = command.split(" ");
+ final exec = commandSplit[0];
+ final List<String> args = commandSplit.sublist(1);
+
+ _addPathParam(args, sourcePathsOption, sourcePaths);
+ _addPathParam(args, classPathsOption, classPaths);
+ if (backend != null) {
+ args.addAll(['--backend', backend!.name]);
+ }
+ args.addAll(extraArgs);
+ args.addAll(classes);
+ log.info('execute $exec ${args.join(' ')}');
+ final proc = await Process.start(exec, args,
+ workingDirectory: workingDirectory?.toFilePath() ?? '.');
+ return proc;
+ }
+}
+
+Future<Classes> getSummary(Config config) async {
+ // This function is a potential entry point in tests, which set log level to
+ // warning.
+ setLoggingLevel(config.logLevel);
+ final summarizer = SummarizerCommand(
+ sourcePath: config.sourcePath,
+ classPath: config.classPath,
+ classes: config.classes,
+ workingDirectory: config.summarizerOptions?.workingDirectory,
+ extraArgs: config.summarizerOptions?.extraArgs ?? const [],
+ backend: config.summarizerOptions?.backend,
+ );
+
+ // Additional sources added using maven downloads and gradle trickery.
+ final extraSources = <Uri>[];
+ final extraJars = <Uri>[];
+ final mavenDl = config.mavenDownloads;
+ if (mavenDl != null) {
+ final sourcePath = mavenDl.sourceDir;
+ await Directory(sourcePath).create(recursive: true);
+ await MavenTools.downloadMavenSources(
+ MavenTools.deps(mavenDl.sourceDeps), sourcePath);
+ extraSources.add(Uri.directory(sourcePath));
+ final jarPath = mavenDl.jarDir;
+ await Directory(jarPath).create(recursive: true);
+ await MavenTools.downloadMavenJars(
+ MavenTools.deps(mavenDl.sourceDeps + mavenDl.jarOnlyDeps), jarPath);
+ extraJars.addAll(await Directory(jarPath)
+ .list()
+ .where((entry) => entry.path.endsWith('.jar'))
+ .map((entry) => entry.uri)
+ .toList());
+ }
+ final androidConfig = config.androidSdkConfig;
+ if (androidConfig != null && androidConfig.addGradleDeps) {
+ final deps = AndroidSdkTools.getGradleClasspaths(
+ configRoot: config.configRoot,
+ androidProject: androidConfig.androidExample ?? '.',
+ );
+ extraJars.addAll(deps.map(Uri.file));
+ }
+ if (androidConfig != null && androidConfig.addGradleSources) {
+ final deps = AndroidSdkTools.getGradleSources(
+ configRoot: config.configRoot,
+ androidProject: androidConfig.androidExample ?? '.',
+ );
+ extraSources.addAll(deps.map(Uri.file));
+ }
+ if (androidConfig != null && androidConfig.versions != null) {
+ final versions = androidConfig.versions!;
+ final androidSdkRoot =
+ androidConfig.sdkRoot ?? AndroidSdkTools.getAndroidSdkRoot();
+ final androidJar = await AndroidSdkTools.getAndroidJarPath(
+ sdkRoot: androidSdkRoot, versionOrder: versions);
+ if (androidJar != null) {
+ extraJars.add(Uri.directory(androidJar));
+ }
+ }
+
+ summarizer.addSourcePaths(extraSources);
+ summarizer.addClassPaths(extraJars);
+
+ Process process;
+ Stream<List<int>> input;
+ final stopwatch = Stopwatch()..start();
+ try {
+ process = await summarizer.runProcess();
+ input = process.stdout;
+ } on Exception catch (e) {
+ throw SummaryParseException('Cannot generate API summary: $e');
+ }
+ final stderrBuffer = StringBuffer();
+ collectOutputStream(process.stderr, stderrBuffer);
+ final stream = const JsonDecoder().bind(const Utf8Decoder().bind(input));
+ dynamic json;
+ try {
+ json = await stream.single;
+ stopwatch.stop();
+ log.info('Parsing inputs took ${stopwatch.elapsedMilliseconds} ms');
+ } on Exception catch (e) {
+ await process.exitCode;
+ throw SummaryParseException.withStderr(
+ stderrBuffer.toString(),
+ 'Cannot generate summary: $e',
+ );
+ } finally {
+ log.writeSectionToFile("summarizer logs", stderrBuffer.toString());
+ }
+ if (json == null) {
+ throw SummaryParseException('Expected JSON element from summarizer.');
+ }
+ final list = json as List;
+ final classes = Classes.fromJson(list);
+ return classes;
+}
diff --git a/pkgs/jnigen/lib/src/tools/android_sdk_tools.dart b/pkgs/jnigen/lib/src/tools/android_sdk_tools.dart
new file mode 100644
index 0000000..3de5575
--- /dev/null
+++ b/pkgs/jnigen/lib/src/tools/android_sdk_tools.dart
@@ -0,0 +1,226 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:path/path.dart';
+
+import '../logging/logging.dart';
+
+class _AndroidToolsException implements Exception {
+ _AndroidToolsException(this.message);
+ String message;
+ @override
+ String toString() => message;
+}
+
+class SdkNotFoundException extends _AndroidToolsException {
+ SdkNotFoundException(String message) : super(message);
+}
+
+class GradleException extends _AndroidToolsException {
+ GradleException(String message) : super(message);
+}
+
+class AndroidSdkTools {
+ static String getAndroidSdkRoot() {
+ final envVar = Platform.environment['ANDROID_SDK_ROOT'];
+ if (envVar == null) {
+ throw SdkNotFoundException('Android SDK not found. Please set '
+ 'ANDROID_SDK_ROOT environment variable or specify through command '
+ 'line override.');
+ }
+ return envVar;
+ }
+
+ static Future<String?> _getVersionDir(
+ String relative, String sdkRoot, List<int> versionOrder) async {
+ final parent = join(sdkRoot, relative);
+ for (var version in versionOrder) {
+ final dir = Directory(join(parent, 'android-$version'));
+ if (await dir.exists()) {
+ return dir.path;
+ }
+ }
+ return null;
+ }
+
+ static Future<String?> _getFile(String sdkRoot, String relative,
+ List<int> versionOrder, String file) async {
+ final platform = await _getVersionDir(relative, sdkRoot, versionOrder);
+ if (platform == null) return null;
+ final filePath = join(platform, file);
+ if (await File(filePath).exists()) {
+ log.info('Found $filePath');
+ return filePath;
+ }
+ return null;
+ }
+
+ static const _gradleCannotFindJars = 'Gradle stub cannot find JAR libraries. '
+ 'This might be because no APK build has happened yet.';
+
+ static const _leftOverStubWarning = 'If you are seeing this error in '
+ '`flutter build` output, it is likely that `jnigen` left some stubs in '
+ 'the build.gradle file. Please restore that file from your version '
+ 'control system or manually remove the stub functions named '
+ '$_gradleGetClasspathTaskName and / or $_gradleGetSourcesTaskName.';
+
+ static Future<String?> getAndroidJarPath(
+ {required String sdkRoot, required List<int> versionOrder}) async =>
+ await _getFile(sdkRoot, 'platforms', versionOrder, 'android.jar');
+
+ static const _gradleGetClasspathTaskName = 'getReleaseCompileClasspath';
+
+ static const _gradleGetClasspathStub = '''
+// Gradle stub for listing dependencies in jnigen. If found in
+// android/build.gradle, please delete the following function.
+task $_gradleGetClasspathTaskName(type: Copy) {
+ project.afterEvaluate {
+ try {
+ def app = project(':app')
+ def android = app.android
+ def cp = [android.getBootClasspath()[0]]
+ android.applicationVariants.each { variant ->
+ if (variant.name.equals('release')) {
+ cp += variant.javaCompile.classpath.getFiles()
+ }
+ }
+ cp.each { println it }
+ } catch (Exception e) {
+ System.err.println("$_gradleCannotFindJars")
+ System.err.println("$_leftOverStubWarning")
+ throw e
+ }
+ }
+}
+''';
+
+ static const _gradleGetSourcesTaskName = 'getSources';
+ // adapted from https://stackoverflow.com/questions/39975780/how-can-i-use-gradle-to-download-dependencies-and-their-source-files-and-place-t/39981143#39981143
+ // Although it appears we can use this same code for getting JAR artifacts,
+ // there is no JAR equivalent for `org.gradle.language.base.Artifact`.
+ // So it appears different methods should be used for JAR artifacts.
+ static const _gradleGetSourcesStub = '''
+// Gradle stub for fetching source dependencies in jnigen. If found in
+// android/build.gradle, please delete the following function.
+task $_gradleGetSourcesTaskName(type: Copy) {
+ project.afterEvaluate {
+ def componentIds = project(':app').configurations.releaseCompileClasspath.incoming
+ .resolutionResult.allDependencies.collect { it.selected.id }
+
+ ArtifactResolutionResult result = dependencies.createArtifactResolutionQuery()
+ .forComponents(componentIds)
+ .withArtifacts(JvmLibrary, SourcesArtifact)
+ .execute()
+
+ def sourceArtifacts = []
+
+ result.resolvedComponents.each { ComponentArtifactsResult component ->
+ Set<ArtifactResult> sources = component.getArtifacts(SourcesArtifact)
+ sources.each { ArtifactResult ar ->
+ if (ar instanceof ResolvedArtifactResult) {
+ sourceArtifacts << ar.file
+ }
+ }
+ }
+ sourceArtifacts.forEach { println it }
+ }
+ System.err.println("$_leftOverStubWarning")
+}
+''';
+
+ /// Get release compile classpath used by Gradle for android build.
+ ///
+ /// This function temporarily overwrites the build.gradle file by a stub with
+ /// function to list all dependency paths for release variant.
+ /// This function fails if no gradle build is attempted before.
+ ///
+ /// If current project is not directly buildable by gradle, eg: a plugin,
+ /// a relative path to other project can be specified using [androidProject].
+ static List<String> getGradleClasspaths(
+ {Uri? configRoot, String androidProject = '.'}) =>
+ _runGradleStub(
+ stubName: _gradleGetClasspathTaskName,
+ stubCode: _gradleGetClasspathStub,
+ androidProject: androidProject,
+ configRoot: configRoot,
+ );
+
+ /// Get source paths for all gradle dependencies.
+ ///
+ /// This function temporarily overwrites the build.gradle file by a stub with
+ /// function to list all dependency paths for release variant.
+ /// This function fails if no gradle build is attempted before.
+ static List<String> getGradleSources(
+ {Uri? configRoot, String androidProject = '.'}) {
+ return _runGradleStub(
+ stubName: _gradleGetSourcesTaskName,
+ stubCode: _gradleGetSourcesStub,
+ androidProject: androidProject,
+ configRoot: configRoot,
+ );
+ }
+
+ static String _appendStub(String script, String stub) {
+ return script.contains(stub) ? script : script + stub;
+ }
+
+ static List<String> _runGradleStub({
+ required String stubName,
+ required String stubCode,
+ Uri? configRoot,
+ String androidProject = '.',
+ }) {
+ log.info('trying to obtain gradle dependencies [$stubName]...');
+ if (configRoot != null) {
+ androidProject = configRoot.resolve(androidProject).toFilePath();
+ }
+ final android = join(androidProject, 'android');
+ final buildGradle = join(android, 'build.gradle');
+ final buildGradleOld = join(android, 'build.gradle.old');
+ final origBuild = File(buildGradle);
+ final script = origBuild.readAsStringSync();
+ origBuild.renameSync(buildGradleOld);
+ origBuild.createSync();
+ log.finer('Writing temporary gradle script with stub "$stubName"...');
+ origBuild.writeAsStringSync(_appendStub(script, stubCode));
+ log.finer('Running gradle wrapper...');
+ final gradleCommand = Platform.isWindows ? '.\\gradlew.bat' : './gradlew';
+ ProcessResult procRes;
+ try {
+ procRes = Process.runSync(gradleCommand, ['-q', stubName],
+ workingDirectory: android, runInShell: true);
+ } finally {
+ log.info('Restoring build scripts');
+ origBuild.writeAsStringSync(
+ script
+ .replaceAll(_gradleGetClasspathStub, "")
+ .replaceAll(_gradleGetSourcesStub, ""),
+ );
+ File(buildGradleOld).deleteSync();
+ }
+ if (procRes.exitCode != 0) {
+ final inAndroidProject =
+ (androidProject == '.') ? '' : ' in $androidProject';
+ throw GradleException('\n\ngradle exited with status '
+ '${procRes.exitCode}\n. This can be because the Android build is not '
+ 'yet cached. Please run `flutter build apk`$inAndroidProject and try '
+ 'again\n');
+ }
+ // Record both stdout and stderr of gradle.
+ log.writeSectionToFile("Gradle logs ($stubName)", procRes.stderr);
+ log.writeSectionToFile("Gradle output ($stubName)", procRes.stdout);
+ final output = procRes.stdout as String;
+ if (output.isEmpty) {
+ printError(procRes.stderr);
+ throw Exception("Gradle stub exited without output.");
+ }
+ final paths = (procRes.stdout as String)
+ .trim()
+ .split(Platform.isWindows ? '\r\n' : '\n');
+ log.fine('Found ${paths.length} entries');
+ return paths;
+ }
+}
diff --git a/pkgs/jnigen/lib/src/tools/build_summarizer.dart b/pkgs/jnigen/lib/src/tools/build_summarizer.dart
new file mode 100644
index 0000000..1e0ec06
--- /dev/null
+++ b/pkgs/jnigen/lib/src/tools/build_summarizer.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// TODO(#43): Address concurrently building summarizer.
+//
+// In the current state summarizer has to be built before tests, which run
+// concurrently. Ignoring coverage for this file until that issue is addressed.
+//
+// coverage:ignore-file
+
+import 'dart:io';
+
+import 'package:path/path.dart';
+
+import '../logging/logging.dart';
+import '../util/find_package.dart';
+
+final toolPath = join('.', '.dart_tool', 'jnigen');
+final mvnTargetDir = join(toolPath, 'target');
+final jarFile = join(toolPath, 'ApiSummarizer.jar');
+final targetJarFile = join(mvnTargetDir, 'ApiSummarizer.jar');
+
+Future<void> buildApiSummarizer() async {
+ final pkg = await findPackageRoot('jnigen');
+ if (pkg == null) {
+ log.fatal('package jnigen not found!');
+ }
+ final pom = pkg.resolve('java/pom.xml');
+ await Directory(toolPath).create(recursive: true);
+ final mvnArgs = [
+ 'compile',
+ '--batch-mode',
+ '--update-snapshots',
+ '-f',
+ pom.toFilePath(),
+ ];
+ log.info('execute mvn ${mvnArgs.join(" ")}');
+ try {
+ final mvnProc = await Process.run('mvn', mvnArgs,
+ workingDirectory: toolPath, runInShell: true);
+ final exitCode = mvnProc.exitCode;
+ if (exitCode == 0) {
+ await File(targetJarFile).rename(jarFile);
+ } else {
+ printError(mvnProc.stdout);
+ printError(mvnProc.stderr);
+ printError("maven exited with $exitCode");
+ }
+ } finally {
+ await Directory(mvnTargetDir).delete(recursive: true);
+ }
+}
+
+Future<void> buildSummarizerIfNotExists({bool force = false}) async {
+ // TODO(#43): This function cannot be invoked concurrently because 2 processes
+ // will start building summarizer at once. Introduce a locking mechnanism so
+ // that when one process is building summarizer JAR, other process waits using
+ // exponential backoff.
+ final jarExists = await File(jarFile).exists();
+ final isJarStale = jarExists &&
+ await isPackageModifiedAfter(
+ 'jnigen', await File(jarFile).lastModified(), 'java/');
+ if (isJarStale) {
+ log.info('Rebuilding ApiSummarizer component since sources '
+ 'have changed. This might take some time.');
+ }
+ if (!jarExists) {
+ log.info('Building ApiSummarizer component. '
+ 'This might take some time. '
+ 'The build will be cached for subsequent runs.');
+ }
+ if (!jarExists || isJarStale || force) {
+ await buildApiSummarizer();
+ } else {
+ log.info('ApiSummarizer.jar exists. Skipping build..');
+ }
+}
diff --git a/pkgs/jnigen/lib/src/tools/maven_tools.dart b/pkgs/jnigen/lib/src/tools/maven_tools.dart
new file mode 100644
index 0000000..74cb3a1
--- /dev/null
+++ b/pkgs/jnigen/lib/src/tools/maven_tools.dart
@@ -0,0 +1,142 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:path/path.dart';
+
+import '../logging/logging.dart';
+
+/// This class provides some utility methods to download a sources / jars
+/// using maven along with transitive dependencies.
+class MavenTools {
+ static final currentDir = Directory(".");
+
+ /// Helper method since we can't pass inheritStdio option to [Process.run].
+ static Future<int> _runCmd(String exec, List<String> args,
+ [String? workingDirectory]) async {
+ log.info('execute $exec ${args.join(" ")}');
+ final proc = await Process.start(exec, args,
+ workingDirectory: workingDirectory,
+ runInShell: true,
+ mode: ProcessStartMode.inheritStdio);
+ return proc.exitCode;
+ }
+
+ static Future<void> _runMavenCommand(
+ List<MavenDependency> deps,
+ List<String> mvnArgs,
+ Directory tempDir,
+ ) async {
+ final pom = _getStubPom(deps);
+ final tempPom = join(tempDir.path, "temp_pom.xml");
+ final tempTarget = join(tempDir.path, "target");
+ log.finer('using POM stub:\n$pom');
+ await File(tempPom).writeAsString(pom);
+ await Directory(tempTarget).create();
+ await _runCmd('mvn', ['-q', '-f', tempPom, ...mvnArgs]);
+ await File(tempPom).delete();
+ await Directory(tempTarget).delete(recursive: true);
+ }
+
+ /// Create a list of [MavenDependency] objects from maven coordinates in string form.
+ static List<MavenDependency> deps(List<String> depNames) =>
+ depNames.map(MavenDependency.fromString).toList();
+
+ /// Downloads and unpacks source files of [deps] into [targetDir].
+ static Future<void> downloadMavenSources(
+ List<MavenDependency> deps, String targetDir) async {
+ final tempDir = await currentDir.createTemp("maven_temp_");
+ await _runMavenCommand(
+ deps,
+ [
+ 'dependency:unpack-dependencies',
+ '-DexcludeTransitive=true',
+ '-DoutputDirectory=../$targetDir',
+ '-Dclassifier=sources',
+ ],
+ tempDir,
+ );
+ await tempDir.delete(recursive: true);
+ }
+
+ /// Downloads JAR files of all [deps] transitively into [targetDir].
+ static Future<void> downloadMavenJars(
+ List<MavenDependency> deps, String targetDir) async {
+ final tempDir = await currentDir.createTemp("maven_temp_");
+ await _runMavenCommand(
+ deps,
+ [
+ 'dependency:copy-dependencies',
+ '-DoutputDirectory=../$targetDir',
+ ],
+ tempDir,
+ );
+ await tempDir.delete(recursive: true);
+ }
+
+ static String _getStubPom(List<MavenDependency> deps,
+ {String javaVersion = '11'}) {
+ final depDecls = <String>[];
+ for (var dep in deps) {
+ final otherTags = StringBuffer();
+ for (var entry in dep.otherTags.entries) {
+ otherTags.write('''
+ <${entry.key}>
+ ${entry.value}
+ </${entry.key}>
+ ''');
+ }
+ depDecls.add('''
+ <dependency>
+ <groupId>${dep.groupID}</groupId>
+ <artifactId>${dep.artifactID}</artifactId>
+ <version>${dep.version}</version>
+ ${otherTags.toString()}
+ </dependency>''');
+ }
+ return '''
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <repositories>
+ <repository>
+ <id>google-maven-repo</id>
+ <name>Google Maven Repository</name>
+ <url>https://maven.google.com</url>
+ </repository>
+ </repositories>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>com.mycompany.app</groupId>
+ <artifactId>jnigen_maven_stub</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <properties>
+ <maven.compiler.source>$javaVersion</maven.compiler.source>
+ <maven.compiler.target>$javaVersion</maven.compiler.target>
+ </properties>
+ <dependencies>
+${depDecls.join("\n")}
+ </dependencies>
+ <build>
+ <directory>\${project.basedir}/target</directory>
+ </build>
+</project>''';
+ }
+}
+
+/// Maven dependency with group ID, artifact ID, and version.
+class MavenDependency {
+ MavenDependency(this.groupID, this.artifactID, this.version,
+ {this.otherTags = const {}});
+ factory MavenDependency.fromString(String fullName) {
+ final components = fullName.split(':');
+ if (components.length != 3) {
+ throw ArgumentError('invalid name for maven dependency: $fullName');
+ }
+ return MavenDependency(components[0], components[1], components[2]);
+ }
+ String groupID, artifactID, version;
+ Map<String, String> otherTags;
+}
diff --git a/pkgs/jnigen/lib/src/tools/tools.dart b/pkgs/jnigen/lib/src/tools/tools.dart
new file mode 100644
index 0000000..9677a3e
--- /dev/null
+++ b/pkgs/jnigen/lib/src/tools/tools.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'android_sdk_tools.dart';
+export 'maven_tools.dart';
+export 'build_summarizer.dart';
diff --git a/pkgs/jnigen/lib/src/util/find_package.dart b/pkgs/jnigen/lib/src/util/find_package.dart
new file mode 100644
index 0000000..89d95dd
--- /dev/null
+++ b/pkgs/jnigen/lib/src/util/find_package.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:package_config/package_config.dart';
+
+Future<Package?> findPackage(String packageName) async {
+ final packageConfig = await findPackageConfig(Directory.current);
+ if (packageConfig == null) {
+ return null;
+ }
+ return packageConfig[packageName];
+}
+
+Future<Uri?> findPackageRoot(String packageName) async {
+ return (await findPackage(packageName))?.root;
+}
+
+Future<bool> isPackageModifiedAfter(String packageName, DateTime time,
+ [String? subDir]) async {
+ final root = await findPackageRoot(packageName);
+ if (root == null) {
+ throw UnsupportedError('package $packageName does not exist');
+ }
+ var checkRoot = root;
+ if (subDir != null) {
+ checkRoot = root.resolve(subDir);
+ }
+ final dir = Directory.fromUri(checkRoot);
+ if (!await dir.exists()) {
+ throw UnsupportedError('can not resolve $subDir in $packageName');
+ }
+ // A directory's modification time is not helpful because one of
+ // internal files may be modified later.
+ // In case of git / pub package we might be able to check pubspec, but no
+ // such technique applies for path packages.
+ await for (final entry in dir.list(recursive: true)) {
+ final stat = await entry.stat();
+ if (stat.modified.isAfter(time)) {
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/pkgs/jnigen/lib/src/util/string_util.dart b/pkgs/jnigen/lib/src/util/string_util.dart
new file mode 100644
index 0000000..5a65bfb
--- /dev/null
+++ b/pkgs/jnigen/lib/src/util/string_util.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+extension StringUtil on String {
+ /// Makes the first letter uppercase.
+ String capitalize() {
+ return '${this[0].toUpperCase()}${substring(1)}';
+ }
+
+ /// Reverses an ASCII string.
+ String get reversed => split('').reversed.join();
+}
diff --git a/pkgs/jnigen/lib/tools.dart b/pkgs/jnigen/lib/tools.dart
new file mode 100644
index 0000000..252e4b7
--- /dev/null
+++ b/pkgs/jnigen/lib/tools.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library jnigen_tools;
+
+export 'src/tools/tools.dart';
diff --git a/pkgs/jnigen/pubspec.yaml b/pkgs/jnigen/pubspec.yaml
new file mode 100644
index 0000000..35e01bc
--- /dev/null
+++ b/pkgs/jnigen/pubspec.yaml
@@ -0,0 +1,37 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+name: jnigen
+description: A Dart bindings generator for Java and Kotlin that uses JNI under the hood to interop with Java virtual machine.
+version: 0.8.0-wip
+repository: https://github.com/dart-lang/jnigen/tree/main/jnigen
+
+environment:
+ sdk: ">=3.1.0 <4.0.0"
+
+topics:
+ - interop
+ - ffi
+ - codegen
+ - java
+ - jni
+
+dependencies:
+ json_annotation: ^4.8.0
+ package_config: ^2.1.0
+ path: ^1.8.0
+ pub_semver: ^2.1.4
+ args: ^2.3.0
+ yaml: ^3.1.0
+ logging: ^1.0.2
+ meta: ^1.8.0
+ cli_config: ^0.1.0
+
+dev_dependencies:
+ lints: ^2.0.0
+ jni:
+ path: ../jni
+ test: ^1.24.1
+ build_runner: ^2.2.0
+ json_serializable: ^6.6.0
diff --git a/pkgs/jnigen/test/.gitignore b/pkgs/jnigen/test/.gitignore
new file mode 100644
index 0000000..36f1ec5
--- /dev/null
+++ b/pkgs/jnigen/test/.gitignore
@@ -0,0 +1,4 @@
+# TODO(#166): Remove this.
+!jni.jar
+runtime_test_registrant_dartonly_generated.dart
+generated_runtime_test.dart
\ No newline at end of file
diff --git a/pkgs/jnigen/test/README.md b/pkgs/jnigen/test/README.md
new file mode 100644
index 0000000..e3ada83
--- /dev/null
+++ b/pkgs/jnigen/test/README.md
@@ -0,0 +1,13 @@
+## How to run tests?
+#### One-time setup:
+```
+dart run jnigen:setup
+```
+
+#### Running tests
+```sh
+dart run tool/generate_runtime_tests.dart ## Regenerates runtime test files
+dart test
+```
+
+Note: Tests fail if summarizer is not previously built and 2 tests try to build it concurrently. We have to address it using a lock file and exponential backoff (#43). Temporarily, run `dart run jnigen:setup` before running tests for the first time.
diff --git a/pkgs/jnigen/test/config_test.dart b/pkgs/jnigen/test/config_test.dart
new file mode 100644
index 0000000..ae2f987
--- /dev/null
+++ b/pkgs/jnigen/test/config_test.dart
@@ -0,0 +1,141 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:jnigen/src/config/config.dart';
+import 'package:test/test.dart';
+import 'package:path/path.dart' hide equals;
+import 'package:path/path.dart' as path show equals;
+
+import 'jackson_core_test/generate.dart';
+import 'test_util/test_util.dart';
+
+const packageTests = 'test';
+final jacksonCoreTests = absolute(packageTests, 'jackson_core_test');
+final thirdParty = absolute(jacksonCoreTests, 'third_party');
+final lib = absolute(thirdParty, 'c_based', 'dart_bindings');
+final src = absolute(thirdParty, 'c_based', 'c_bindings');
+final testLib = absolute(thirdParty, 'test_', 'c_based', 'dart_bindings');
+final testSrc = absolute(thirdParty, 'test_', 'c_based', 'c_bindings');
+
+/// Compares 2 [Config] objects using [expect] to give useful errors when
+/// two fields are not equal.
+void expectConfigsAreEqual(Config a, Config b) {
+ expect(a.classes, equals(b.classes), reason: "classes");
+ expect(a.outputConfig.cConfig?.libraryName,
+ equals(b.outputConfig.cConfig?.libraryName),
+ reason: "libraryName");
+ expect(a.outputConfig.cConfig?.path, equals(b.outputConfig.cConfig?.path),
+ reason: "cRoot");
+ expect(a.outputConfig.dartConfig.path, equals(b.outputConfig.dartConfig.path),
+ reason: "dartRoot");
+ expect(a.outputConfig.symbolsConfig?.path,
+ equals(b.outputConfig.symbolsConfig?.path),
+ reason: "symbolsRoot");
+ expect(a.sourcePath, equals(b.sourcePath), reason: "sourcePath");
+ expect(a.experiments, equals(b.experiments), reason: "experiments");
+ expect(a.classPath, equals(b.classPath), reason: "classPath");
+ expect(a.preamble, equals(b.preamble), reason: "preamble");
+ final am = a.mavenDownloads;
+ final bm = b.mavenDownloads;
+ if (am != null) {
+ expect(bm, isNotNull);
+ expect(am.sourceDeps, bm!.sourceDeps, reason: "mavenDownloads.sourceDeps");
+ expect(path.equals(am.sourceDir, bm.sourceDir), isTrue,
+ reason: "mavenDownloads.sourceDir");
+ expect(am.jarOnlyDeps, bm.jarOnlyDeps,
+ reason: "mavenDownloads.jarOnlyDeps");
+ expect(path.equals(am.jarDir, bm.jarDir), isTrue,
+ reason: "mavenDownloads.jarDir");
+ } else {
+ expect(bm, isNull, reason: "mavenDownloads");
+ }
+ final aa = a.androidSdkConfig;
+ final ba = b.androidSdkConfig;
+ if (aa != null) {
+ expect(ba, isNotNull, reason: "androidSdkConfig");
+ expect(aa.versions, ba!.versions, reason: "androidSdkConfig.versions");
+ expect(aa.sdkRoot, ba.sdkRoot, reason: "androidSdkConfig.sdkRoot");
+ } else {
+ expect(ba, isNull, reason: "androidSdkConfig");
+ }
+ final aso = a.summarizerOptions;
+ final bso = b.summarizerOptions;
+ if (aso != null) {
+ expect(bso, isNotNull, reason: "summarizerOptions");
+ expect(aso.extraArgs, bso!.extraArgs,
+ reason: "summarizerOptions.extraArgs");
+ expect(aso.workingDirectory, bso.workingDirectory,
+ reason: "summarizerOptions.workingDirectory");
+ expect(aso.backend, bso.backend, reason: "summarizerOptions.backend");
+ } else {
+ expect(bso, isNull, reason: "summarizerOptions");
+ }
+}
+
+final jnigenYaml = join(jacksonCoreTests, 'jnigen.yaml');
+
+Config parseYamlConfig({List<String> overrides = const []}) =>
+ Config.parseArgs(['--config', jnigenYaml, ...overrides]);
+
+void testForErrorChecking<T extends Exception>(
+ {required String name,
+ required List<String> overrides,
+ dynamic Function(Config)? function}) {
+ test(name, () {
+ expect(
+ () {
+ final config = parseYamlConfig(overrides: overrides);
+ if (function != null) {
+ function(config);
+ }
+ },
+ throwsA(isA<T>()),
+ );
+ });
+}
+
+void main() async {
+ await checkLocallyBuiltDependencies();
+ final config = Config.parseArgs([
+ '--config',
+ jnigenYaml,
+ '-Doutput.c.path=$testSrc${Platform.pathSeparator}',
+ '-Doutput.dart.path=$testLib${Platform.pathSeparator}',
+ ]);
+
+ test('compare configuration values', () {
+ expectConfigsAreEqual(
+ config,
+ getConfig(
+ root: join(thirdParty, 'test_'),
+ bindingsType: BindingsType.cBased,
+ ),
+ );
+ });
+
+ group('Test for config error checking', () {
+ testForErrorChecking<ConfigException>(
+ name: 'Invalid bindings type',
+ overrides: ['-Doutput.bindings_type=c_base'],
+ );
+ testForErrorChecking<ConfigException>(
+ name: 'Invalid output structure',
+ overrides: ['-Doutput.dart.structure=singl_file'],
+ );
+ testForErrorChecking<ConfigException>(
+ name: 'Dart path not ending with /',
+ overrides: ['-Doutput.dart.path=lib'],
+ );
+ testForErrorChecking<FormatException>(
+ name: 'Invalid log level',
+ overrides: ['-Dlog_level=inf'],
+ );
+ testForErrorChecking<ConfigException>(
+ name: 'Nested class specified',
+ overrides: ['-Dclasses=com.android.Clock\$Clock'],
+ );
+ });
+}
diff --git a/pkgs/jnigen/test/dart_generator_test.dart b/pkgs/jnigen/test/dart_generator_test.dart
new file mode 100644
index 0000000..e9bbb76
--- /dev/null
+++ b/pkgs/jnigen/test/dart_generator_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:jnigen/src/bindings/dart_generator.dart';
+import 'package:test/test.dart';
+
+import 'test_util/test_util.dart';
+
+void main() async {
+ await checkLocallyBuiltDependencies();
+
+ test('OutsideInBuffer', () {
+ final buffer = OutsideInBuffer();
+ buffer.appendLeft('f(');
+ buffer.prependRight('x)');
+ buffer.appendLeft('g(');
+ buffer.prependRight('y) + ');
+ expect(buffer.toString(), 'f(g(y) + x)');
+ });
+}
diff --git a/pkgs/jnigen/test/descriptor_test.dart b/pkgs/jnigen/test/descriptor_test.dart
new file mode 100644
index 0000000..f1b9060
--- /dev/null
+++ b/pkgs/jnigen/test/descriptor_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:jnigen/src/bindings/descriptor.dart';
+import 'package:jnigen/src/bindings/linker.dart';
+import 'package:jnigen/src/bindings/unnester.dart';
+import 'package:jnigen/src/config/config_types.dart';
+import 'package:jnigen/src/summary/summary.dart';
+import 'package:test/test.dart';
+
+import 'simple_package_test/generate.dart' as simple_package_test;
+import 'kotlin_test/generate.dart' as kotlin_test;
+import 'jackson_core_test/generate.dart' as jackson_core_test;
+import 'test_util/test_util.dart';
+
+void main() {
+ checkLocallyBuiltDependencies();
+ for (final (name, getConfig) in [
+ ('simple_package', simple_package_test.getConfig),
+ ('kotlin', kotlin_test.getConfig),
+ ('jackson_core', jackson_core_test.getConfig),
+ ]) {
+ test('Method descriptor generation for $name',
+ timeout: const Timeout.factor(3), () async {
+ final config = getConfig();
+ config.summarizerOptions =
+ SummarizerOptions(backend: SummarizerBackend.asm);
+ final classes = await getSummary(config);
+ await classes.accept(Linker(config));
+ classes.accept(const Unnester());
+ for (final decl in classes.decls.values) {
+ // Checking if the descriptor from ASM matches the one generated by
+ // [MethodDescriptor].
+ final methodDescriptor = MethodDescriptor(decl.allTypeParams);
+ for (final method in decl.methods) {
+ expect(method.descriptor, method.accept(methodDescriptor));
+ }
+ }
+ });
+ }
+}
diff --git a/pkgs/jnigen/test/jackson_core_test/.gitignore b/pkgs/jnigen/test/jackson_core_test/.gitignore
new file mode 100644
index 0000000..0215812
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/.gitignore
@@ -0,0 +1,5 @@
+*.jar
+third_party/jar/**
+third_party/java/**
+third_party/test_lib/
+third_party/test_src/
diff --git a/pkgs/jnigen/test/jackson_core_test/generate.dart b/pkgs/jnigen/test/jackson_core_test/generate.dart
new file mode 100644
index 0000000..796a760
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/generate.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:jnigen/jnigen.dart';
+import 'package:jnigen/src/config/experiments.dart';
+import 'package:logging/logging.dart';
+import 'package:path/path.dart' hide equals;
+
+const jacksonPreamble = '// Generated from jackson-core which is licensed under'
+ ' the Apache License 2.0.\n'
+ '// The following copyright from the original authors applies.\n'
+ '// See https://github.com/FasterXML/jackson-core/blob/2.14/LICENSE\n'
+ '//\n'
+ '// Copyright (c) 2007 - The Jackson Project Authors\n'
+ '// Licensed under the Apache License, Version 2.0 (the "License")\n'
+ '// you may not use this file except in compliance with the License.\n'
+ '// You may obtain a copy of the License at\n'
+ '//\n'
+ '// http://www.apache.org/licenses/LICENSE-2.0\n'
+ '//\n'
+ '// Unless required by applicable law or agreed to in writing, software\n'
+ '// distributed under the License is distributed on an "AS IS" BASIS,\n'
+ '// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n'
+ '// See the License for the specific language governing permissions and\n'
+ '// limitations under the License.\n';
+
+const testName = 'jackson_core_test';
+final thirdPartyDir = join('test', testName, 'third_party');
+const deps = ['com.fasterxml.jackson.core:jackson-core:2.13.4'];
+
+Config getConfig({
+ String? root,
+ bool generateFullVersion = false,
+ bool useAsm = false,
+ BindingsType bindingsType = BindingsType.dartOnly,
+}) {
+ final rootDir = root ?? thirdPartyDir;
+ final bindingTypeDir = bindingsType.getConfigString();
+ final config = Config(
+ mavenDownloads: MavenDownloads(
+ sourceDeps: deps,
+ sourceDir: join(thirdPartyDir, 'java'),
+ jarDir: join(thirdPartyDir, 'jar'),
+ ),
+ summarizerOptions: SummarizerOptions(
+ backend: useAsm ? SummarizerBackend.asm : null,
+ ),
+ preamble: jacksonPreamble,
+ outputConfig: OutputConfig(
+ bindingsType: bindingsType,
+ // Have to be judicious here, and ensure null when bindings type is
+ // dart-only, because config-test is also using this.
+ cConfig: bindingsType == BindingsType.cBased
+ ? CCodeOutputConfig(
+ libraryName: 'jackson_core',
+ path: Uri.directory(join(rootDir, bindingTypeDir, 'c_bindings')),
+ )
+ : null,
+ dartConfig: DartCodeOutputConfig(
+ path: Uri.directory(join(rootDir, bindingTypeDir, 'dart_bindings')),
+ ),
+ ),
+ classes: (generateFullVersion)
+ ? ['com.fasterxml.jackson.core']
+ : [
+ 'com.fasterxml.jackson.core.JsonFactory',
+ 'com.fasterxml.jackson.core.JsonParser',
+ 'com.fasterxml.jackson.core.JsonToken',
+ ],
+ logLevel: Level.INFO,
+ exclude: BindingExclusions(
+ // TODO(#31): Remove field exclusions.
+ fields: excludeAll<Field>([
+ ['com.fasterxml.jackson.core.JsonFactory', 'DEFAULT_QUOTE_CHAR'],
+ ['com.fasterxml.jackson.core.Base64Variant', 'PADDING_CHAR_NONE'],
+ ['com.fasterxml.jackson.core.base.ParserMinimalBase', 'CHAR_NULL'],
+ ['com.fasterxml.jackson.core.io.UTF32Reader', 'NC'],
+ ]),
+ // TODO(#159): Remove class exclusions.
+ classes: ClassNameFilter.exclude(
+ 'com.fasterxml.jackson.core.JsonFactoryBuilder',
+ ),
+ ),
+ experiments: {Experiment.interfaceImplementation},
+ );
+ return config;
+}
+
+void main() async {
+ await generateJniBindings(getConfig(bindingsType: BindingsType.cBased));
+ await generateJniBindings(getConfig(bindingsType: BindingsType.dartOnly));
+}
diff --git a/pkgs/jnigen/test/jackson_core_test/generated_files_test.dart b/pkgs/jnigen/test/jackson_core_test/generated_files_test.dart
new file mode 100644
index 0000000..818e5d0
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/generated_files_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+
+import 'package:jnigen/jnigen.dart';
+
+import '../test_util/test_util.dart';
+import 'generate.dart';
+
+void main() async {
+ await checkLocallyBuiltDependencies();
+
+ generateAndCompareBothModes(
+ 'Generate and compare bindings for jackson_core library',
+ getConfig(bindingsType: BindingsType.cBased),
+ getConfig(bindingsType: BindingsType.dartOnly),
+ );
+ test(
+ 'generate and analyze bindings for complete library, '
+ 'not just required classes', () async {
+ final config = getConfig(generateFullVersion: true);
+ await generateAndAnalyzeBindings(config);
+ }, timeout: const Timeout(Duration(minutes: 2)), tags: largeTestTag);
+
+ test('generate and analyze bindings using ASM', () async {
+ final config = getConfig(generateFullVersion: true, useAsm: true);
+ await generateAndAnalyzeBindings(config);
+ }, timeout: const Timeout(Duration(minutes: 2)), tags: largeTestTag);
+
+ test('Generate and analyze pure dart bindings', () async {
+ final config = getConfig(generateFullVersion: true);
+ config.outputConfig.bindingsType = BindingsType.dartOnly;
+ await generateAndAnalyzeBindings(config);
+ }, timeout: const Timeout.factor(2), tags: largeTestTag);
+}
diff --git a/pkgs/jnigen/test/jackson_core_test/jnigen.yaml b/pkgs/jnigen/test/jackson_core_test/jnigen.yaml
new file mode 100644
index 0000000..cf3b4db
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/jnigen.yaml
@@ -0,0 +1,48 @@
+maven_downloads:
+ source_deps:
+ - 'com.fasterxml.jackson.core:jackson-core:2.13.4'
+ source_dir: third_party/java/
+ jar_dir: third_party/jar/
+
+output:
+ bindings_type: c_based
+ c:
+ library_name: jackson_core
+ path: third_party/c_based/c_bindings/
+ dart:
+ path: third_party/c_based/dart_bindings/
+
+classes:
+ - 'com.fasterxml.jackson.core.JsonFactory'
+ - 'com.fasterxml.jackson.core.JsonParser'
+ - 'com.fasterxml.jackson.core.JsonToken'
+
+exclude:
+ fields:
+ - 'com.fasterxml.jackson.core.JsonFactory#DEFAULT_QUOTE_CHAR'
+ - 'com.fasterxml.jackson.core.Base64Variant#PADDING_CHAR_NONE'
+ - 'com.fasterxml.jackson.core.base.ParserMinimalBase#CHAR_NULL'
+ - 'com.fasterxml.jackson.core.io.UTF32Reader#NC'
+
+preamble: |
+ // Generated from jackson-core which is licensed under the Apache License 2.0.
+ // The following copyright from the original authors applies.
+ // See https://github.com/FasterXML/jackson-core/blob/2.14/LICENSE
+ //
+ // Copyright (c) 2007 - The Jackson Project Authors
+ // Licensed under the Apache License, Version 2.0 (the "License")
+ // you may not use this file except in compliance with the License.
+ // You may obtain a copy of the License at
+ //
+ // http://www.apache.org/licenses/LICENSE-2.0
+ //
+ // Unless required by applicable law or agreed to in writing, software
+ // distributed under the License is distributed on an "AS IS" BASIS,
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ // See the License for the specific language governing permissions and
+ // limitations under the License.
+
+log_level: warning
+
+enable_experiment:
+ - interface_implementation
diff --git a/pkgs/jnigen/test/jackson_core_test/runtime_test_registrant.dart b/pkgs/jnigen/test/jackson_core_test/runtime_test_registrant.dart
new file mode 100644
index 0000000..28e6c2b
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/runtime_test_registrant.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+import 'package:jni/jni.dart';
+
+import '../test_util/callback_types.dart';
+
+import 'third_party/c_based/dart_bindings/com/fasterxml/jackson/core/_package.dart';
+
+// This file doesn't define main, because only one JVM has to be spawned with
+// all classpaths, it's managed at a different file which calls these tests.
+
+void registerTests(String groupName, TestRunnerCallback test) {
+ group(groupName, () {
+ test('simple json parsing test', () {
+ final json = JString.fromString('[1, true, false, 2, 4]');
+ JsonFactory factory;
+ factory = JsonFactory();
+ final parser = factory.createParser6(json);
+ final values = <bool>[];
+ while (!parser.isClosed()) {
+ final next = parser.nextToken();
+ if (next.isNull) continue;
+ values.add(next.isNumeric());
+ next.release();
+ }
+ expect(values, equals([false, true, false, false, true, true, false]));
+ for (final obj in [factory, parser, json]) {
+ obj.release();
+ }
+ });
+ test("parsing invalid JSON throws JniException", () {
+ using((arena) {
+ final factory = JsonFactory()..releasedBy(arena);
+ final erroneous = factory
+ .createParser6("<html>".toJString()..releasedBy(arena))
+ ..releasedBy(arena);
+ expect(() => erroneous.nextToken(), throwsA(isA<JniException>()));
+ });
+ });
+ });
+}
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/c_based/c_bindings/.clang-format b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/c_bindings/.clang-format
new file mode 100644
index 0000000..a256c2f
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/c_bindings/.clang-format
@@ -0,0 +1,15 @@
+# From dart SDK: https://github.com/dart-lang/sdk/blob/main/.clang-format
+
+# Defines the Chromium style for automatic reformatting.
+# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
+BasedOnStyle: Chromium
+
+# clang-format doesn't seem to do a good job of this for longer comments.
+ReflowComments: 'false'
+
+# We have lots of these. Though we need to put them all in curly braces,
+# clang-format can't do that.
+AllowShortIfStatementsOnASingleLine: 'true'
+
+# Put escaped newlines into the rightmost column.
+AlignEscapedNewlinesLeft: false
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/c_based/c_bindings/CMakeLists.txt b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/c_bindings/CMakeLists.txt
new file mode 100644
index 0000000..db216f5
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/c_bindings/CMakeLists.txt
@@ -0,0 +1,32 @@
+# jni_native_build (Build with jni:setup. Do not delete this line.)
+
+# 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)
+
+project(jackson_core VERSION 0.0.1 LANGUAGES C)
+
+add_library(jackson_core SHARED
+ "./jackson_core.c"
+)
+
+set_target_properties(jackson_core PROPERTIES
+ OUTPUT_NAME "jackson_core"
+)
+
+target_compile_definitions(jackson_core PUBLIC DART_SHARED_LIB)
+
+if(WIN32)
+ set_target_properties(${TARGET_NAME} PROPERTIES
+ LINK_FLAGS "/DELAYLOAD:jvm.dll")
+endif()
+
+if (ANDROID)
+ target_link_libraries(jackson_core log)
+else()
+ find_package(Java REQUIRED)
+ find_package(JNI REQUIRED)
+ include_directories(${JNI_INCLUDE_DIRS})
+ target_link_libraries(jackson_core ${JNI_LIBRARIES})
+endif()
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/c_based/c_bindings/dartjni.h b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/c_bindings/dartjni.h
new file mode 100644
index 0000000..8f1dc74
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/c_bindings/dartjni.h
@@ -0,0 +1,424 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#pragma once
+
+// Note: include appropriate system jni.h as found by CMake, not third_party/jni.h.
+#include <jni.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if _WIN32
+#include <windows.h>
+#else
+#include <pthread.h>
+#include <unistd.h>
+#endif
+
+#if _WIN32
+#define FFI_PLUGIN_EXPORT __declspec(dllexport)
+#else
+#define FFI_PLUGIN_EXPORT
+#endif
+
+#if defined _WIN32
+#define thread_local __declspec(thread)
+#else
+#define thread_local __thread
+#endif
+
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
+
+#ifdef __ANDROID__
+#define __ENVP_CAST (JNIEnv**)
+#else
+#define __ENVP_CAST (void**)
+#endif
+
+/// Locking functions for windows and pthread.
+
+#if defined _WIN32
+#include <windows.h>
+
+typedef CRITICAL_SECTION MutexLock;
+typedef CONDITION_VARIABLE ConditionVariable;
+
+static inline void init_lock(MutexLock* lock) {
+ InitializeCriticalSection(lock);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+ EnterCriticalSection(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+ LeaveCriticalSection(lock);
+}
+
+static inline void destroy_lock(MutexLock* lock) {
+ DeleteCriticalSection(lock);
+}
+
+static inline void init_cond(ConditionVariable* cond) {
+ InitializeConditionVariable(cond);
+}
+
+static inline void signal_cond(ConditionVariable* cond) {
+ WakeConditionVariable(cond);
+}
+
+static inline void wait_for(ConditionVariable* cond, MutexLock* lock) {
+ SleepConditionVariableCS(cond, lock, INFINITE);
+}
+
+static inline void destroy_cond(ConditionVariable* cond) {
+ // Not available.
+}
+
+#elif defined __APPLE__ || defined __LINUX__ || defined __ANDROID__ || \
+ defined __GNUC__
+#include <pthread.h>
+
+typedef pthread_mutex_t MutexLock;
+typedef pthread_cond_t ConditionVariable;
+
+static inline void init_lock(MutexLock* lock) {
+ pthread_mutex_init(lock, NULL);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+ pthread_mutex_lock(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+ pthread_mutex_unlock(lock);
+}
+
+static inline void destroy_lock(MutexLock* lock) {
+ pthread_mutex_destroy(lock);
+}
+
+static inline void init_cond(ConditionVariable* cond) {
+ pthread_cond_init(cond, NULL);
+}
+
+static inline void signal_cond(ConditionVariable* cond) {
+ pthread_cond_signal(cond);
+}
+
+static inline void wait_for(ConditionVariable* cond, MutexLock* lock) {
+ pthread_cond_wait(cond, lock);
+}
+
+static inline void destroy_cond(ConditionVariable* cond) {
+ pthread_cond_destroy(cond);
+}
+
+#else
+
+#error "No locking/condition variable support; Possibly unsupported platform"
+
+#endif
+
+typedef struct CallbackResult {
+ MutexLock lock;
+ ConditionVariable cond;
+ int ready;
+ jobject object;
+} CallbackResult;
+
+typedef struct JniLocks {
+ MutexLock classLoadingLock;
+ MutexLock methodLoadingLock;
+ MutexLock fieldLoadingLock;
+} JniLocks;
+
+/// Represents the error when dart-jni layer has already spawned singleton VM.
+#define DART_JNI_SINGLETON_EXISTS (-99);
+
+/// Stores the global state of the JNI.
+typedef struct JniContext {
+ JavaVM* jvm;
+ jobject classLoader;
+ jmethodID loadClassMethod;
+ jobject currentActivity;
+ jobject appContext;
+ JniLocks locks;
+} JniContext;
+
+// jniEnv for this thread, used by inline functions in this header,
+// therefore declared as extern.
+extern thread_local JNIEnv* jniEnv;
+
+extern JniContext* jni;
+
+/// Types used by JNI API to distinguish between primitive types.
+enum JniType {
+ booleanType = 0,
+ byteType = 1,
+ shortType = 2,
+ charType = 3,
+ intType = 4,
+ longType = 5,
+ floatType = 6,
+ doubleType = 7,
+ objectType = 8,
+ voidType = 9,
+};
+
+/// Result type for use by JNI.
+///
+/// If [exception] is null, it means the result is valid.
+/// It's assumed that the caller knows the expected type in [result].
+typedef struct JniResult {
+ jvalue value;
+ jthrowable exception;
+} JniResult;
+
+/// Similar to [JniResult] but for class lookups.
+typedef struct JniClassLookupResult {
+ jclass value;
+ jthrowable exception;
+} JniClassLookupResult;
+
+/// Similar to [JniResult] but for method/field ID lookups.
+typedef struct JniPointerResult {
+ const void* value;
+ jthrowable exception;
+} JniPointerResult;
+
+/// JniExceptionDetails holds 2 jstring objects, one is the result of
+/// calling `toString` on exception object, other is stack trace;
+typedef struct JniExceptionDetails {
+ jstring message;
+ jstring stacktrace;
+} JniExceptionDetails;
+
+/// This struct contains functions which wrap method call / field access conveniently along with
+/// exception checking.
+///
+/// Flutter embedding checks for pending JNI exceptions before an FFI transition, which requires us
+/// to check for and clear the exception before returning to dart code, which requires these functions
+/// to return result types.
+typedef struct JniAccessorsStruct {
+ JniClassLookupResult (*getClass)(char* internalName);
+ JniPointerResult (*getFieldID)(jclass cls, char* fieldName, char* signature);
+ JniPointerResult (*getStaticFieldID)(jclass cls,
+ char* fieldName,
+ char* signature);
+ JniPointerResult (*getMethodID)(jclass cls,
+ char* methodName,
+ char* signature);
+ JniPointerResult (*getStaticMethodID)(jclass cls,
+ char* methodName,
+ char* signature);
+ JniResult (*newObject)(jclass cls, jmethodID ctor, jvalue* args);
+ JniResult (*newPrimitiveArray)(jsize length, int type);
+ JniResult (*newObjectArray)(jsize length,
+ jclass elementClass,
+ jobject initialElement);
+ JniResult (*getArrayElement)(jarray array, int index, int type);
+ JniResult (*callMethod)(jobject obj,
+ jmethodID methodID,
+ int callType,
+ jvalue* args);
+ JniResult (*callStaticMethod)(jclass cls,
+ jmethodID methodID,
+ int callType,
+ jvalue* args);
+ JniResult (*getField)(jobject obj, jfieldID fieldID, int callType);
+ JniResult (*getStaticField)(jclass cls, jfieldID fieldID, int callType);
+ JniExceptionDetails (*getExceptionDetails)(jthrowable exception);
+} JniAccessorsStruct;
+
+FFI_PLUGIN_EXPORT JniAccessorsStruct* GetAccessors();
+
+FFI_PLUGIN_EXPORT JavaVM* GetJavaVM(void);
+
+FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv(void);
+
+/// Spawn a JVM with given arguments.
+///
+/// Returns JNI_OK on success, and one of the documented JNI error codes on
+/// failure. It returns DART_JNI_SINGLETON_EXISTS if an attempt to spawn multiple
+/// JVMs is made, even if the underlying API potentially supports multiple VMs.
+FFI_PLUGIN_EXPORT int SpawnJvm(JavaVMInitArgs* args);
+
+/// Load class through platform-specific mechanism.
+///
+/// Currently uses application classloader on android,
+/// and JNIEnv->FindClass on other platforms.
+FFI_PLUGIN_EXPORT jclass FindClass(const char* name);
+
+/// Returns Application classLoader (on Android),
+/// which can be used to load application and platform classes.
+///
+/// On other platforms, NULL is returned.
+FFI_PLUGIN_EXPORT jobject GetClassLoader(void);
+
+/// Returns application context on Android.
+///
+/// On other platforms, NULL is returned.
+FFI_PLUGIN_EXPORT jobject GetApplicationContext(void);
+
+/// Returns current activity of the app on Android.
+FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
+
+static inline void attach_thread() {
+ if (jniEnv == NULL) {
+ (*jni->jvm)->AttachCurrentThread(jni->jvm, __ENVP_CAST & jniEnv, NULL);
+ }
+}
+
+/// Load class into [cls] using platform specific mechanism
+static inline void load_class_platform(jclass* cls, const char* name) {
+#ifdef __ANDROID__
+ jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
+ *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni->classLoader,
+ jni->loadClassMethod, className);
+ (*jniEnv)->DeleteLocalRef(jniEnv, className);
+#else
+ *cls = (*jniEnv)->FindClass(jniEnv, name);
+#endif
+}
+
+static inline void load_class_local_ref(jclass* cls, const char* name) {
+ if (*cls == NULL) {
+ acquire_lock(&jni->locks.classLoadingLock);
+ if (*cls == NULL) {
+ load_class_platform(cls, name);
+ }
+ release_lock(&jni->locks.classLoadingLock);
+ }
+}
+
+static inline void load_class_global_ref(jclass* cls, const char* name) {
+ if (*cls == NULL) {
+ jclass tmp = NULL;
+ acquire_lock(&jni->locks.classLoadingLock);
+ if (*cls == NULL) {
+ load_class_platform(&tmp, name);
+ if (!(*jniEnv)->ExceptionCheck(jniEnv)) {
+ *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
+ (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
+ }
+ }
+ release_lock(&jni->locks.classLoadingLock);
+ }
+}
+
+static inline void load_method(jclass cls,
+ jmethodID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.methodLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.methodLoadingLock);
+ }
+}
+
+static inline void load_static_method(jclass cls,
+ jmethodID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.methodLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.methodLoadingLock);
+ }
+}
+
+static inline void load_field(jclass cls,
+ jfieldID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.fieldLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.fieldLoadingLock);
+ }
+}
+
+static inline void load_static_field(jclass cls,
+ jfieldID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.fieldLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.fieldLoadingLock);
+ }
+}
+
+static inline jobject to_global_ref(jobject ref) {
+ jobject g = (*jniEnv)->NewGlobalRef(jniEnv, ref);
+ (*jniEnv)->DeleteLocalRef(jniEnv, ref);
+ return g;
+}
+
+// These functions are useful for C+Dart bindings, and not required for pure dart bindings.
+
+FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr();
+
+/// For use by jni_gen's generated code
+/// don't use these.
+
+// these 2 fn ptr vars will be defined by generated code library
+extern JniContext* (*context_getter)(void);
+extern JNIEnv* (*env_getter)(void);
+
+// this function will be exported by generated code library
+// it will set above 2 variables.
+FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext* (*cg)(void),
+ JNIEnv* (*eg)(void));
+
+static inline void load_env() {
+ if (jniEnv == NULL) {
+ jni = context_getter();
+ jniEnv = env_getter();
+ }
+}
+
+static inline jthrowable check_exception() {
+ jthrowable exception = (*jniEnv)->ExceptionOccurred(jniEnv);
+ if (exception != NULL) (*jniEnv)->ExceptionClear(jniEnv);
+ if (exception == NULL) return NULL;
+ return to_global_ref(exception);
+}
+
+static inline JniResult to_global_ref_result(jobject ref) {
+ JniResult result;
+ result.exception = check_exception();
+ if (result.exception == NULL) {
+ result.value.l = to_global_ref(ref);
+ }
+ return result;
+}
+
+FFI_PLUGIN_EXPORT intptr_t InitDartApiDL(void* data);
+
+FFI_PLUGIN_EXPORT
+JniResult DartException__ctor(jstring message);
+
+FFI_PLUGIN_EXPORT
+JniResult PortContinuation__ctor(int64_t j);
+
+FFI_PLUGIN_EXPORT
+JniResult PortProxy__newInstance(jobject binaryName,
+ int64_t port,
+ int64_t functionPtr);
+
+FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/c_based/c_bindings/jackson_core.c b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/c_bindings/jackson_core.c
new file mode 100644
index 0000000..3203612
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/c_bindings/jackson_core.c
@@ -0,0 +1,3729 @@
+// Generated from jackson-core which is licensed under the Apache License 2.0.
+// The following copyright from the original authors applies.
+// See https://github.com/FasterXML/jackson-core/blob/2.14/LICENSE
+//
+// Copyright (c) 2007 - The Jackson Project Authors
+// Licensed under the Apache License, Version 2.0 (the "License")
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+#include <stdint.h>
+#include "dartjni.h"
+#include "jni.h"
+
+thread_local JNIEnv* jniEnv;
+JniContext* jni;
+
+JniContext* (*context_getter)(void);
+JNIEnv* (*env_getter)(void);
+
+void setJniGetters(JniContext* (*cg)(void), JNIEnv* (*eg)(void)) {
+ context_getter = cg;
+ env_getter = eg;
+}
+
+// com.fasterxml.jackson.core.JsonFactory
+jclass _c_JsonFactory = NULL;
+
+jmethodID _m_JsonFactory__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__new0() {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__new0, "<init>", "()V");
+ if (_m_JsonFactory__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_JsonFactory, _m_JsonFactory__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__new1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__new1(jobject oc) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__new1, "<init>",
+ "(Lcom/fasterxml/jackson/core/ObjectCodec;)V");
+ if (_m_JsonFactory__new1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_JsonFactory, _m_JsonFactory__new1, oc);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__new2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__new2(jobject src, jobject codec) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__new2, "<init>",
+ "(Lcom/fasterxml/jackson/core/JsonFactory;Lcom/fasterxml/jackson/"
+ "core/ObjectCodec;)V");
+ if (_m_JsonFactory__new2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_JsonFactory,
+ _m_JsonFactory__new2, src, codec);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__new3 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__new3(jobject b) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__new3, "<init>",
+ "(Lcom/fasterxml/jackson/core/JsonFactoryBuilder;)V");
+ if (_m_JsonFactory__new3 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_JsonFactory, _m_JsonFactory__new3, b);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__new4 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__new4(jobject b, uint8_t bogus) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__new4, "<init>",
+ "(Lcom/fasterxml/jackson/core/TSFBuilder;Z)V");
+ if (_m_JsonFactory__new4 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_JsonFactory,
+ _m_JsonFactory__new4, b, bogus);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__rebuild = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__rebuild(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__rebuild, "rebuild",
+ "()Lcom/fasterxml/jackson/core/TSFBuilder;");
+ if (_m_JsonFactory__rebuild == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonFactory__rebuild);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__builder = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__builder() {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_JsonFactory, &_m_JsonFactory__builder, "builder",
+ "()Lcom/fasterxml/jackson/core/TSFBuilder;");
+ if (_m_JsonFactory__builder == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_JsonFactory,
+ _m_JsonFactory__builder);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__copy = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__copy(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__copy, "copy",
+ "()Lcom/fasterxml/jackson/core/JsonFactory;");
+ if (_m_JsonFactory__copy == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonFactory__copy);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__readResolve = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__readResolve(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__readResolve, "readResolve",
+ "()Ljava/lang/Object;");
+ if (_m_JsonFactory__readResolve == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonFactory__readResolve);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__requiresPropertyOrdering = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__requiresPropertyOrdering(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__requiresPropertyOrdering,
+ "requiresPropertyOrdering", "()Z");
+ if (_m_JsonFactory__requiresPropertyOrdering == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonFactory__requiresPropertyOrdering);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory__canHandleBinaryNatively = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__canHandleBinaryNatively(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__canHandleBinaryNatively,
+ "canHandleBinaryNatively", "()Z");
+ if (_m_JsonFactory__canHandleBinaryNatively == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonFactory__canHandleBinaryNatively);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory__canUseCharArrays = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__canUseCharArrays(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__canUseCharArrays,
+ "canUseCharArrays", "()Z");
+ if (_m_JsonFactory__canUseCharArrays == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonFactory__canUseCharArrays);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory__canParseAsync = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__canParseAsync(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__canParseAsync, "canParseAsync",
+ "()Z");
+ if (_m_JsonFactory__canParseAsync == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_,
+ _m_JsonFactory__canParseAsync);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory__getFormatReadFeatureType = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__getFormatReadFeatureType(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__getFormatReadFeatureType,
+ "getFormatReadFeatureType", "()Ljava/lang/Class;");
+ if (_m_JsonFactory__getFormatReadFeatureType == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__getFormatReadFeatureType);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__getFormatWriteFeatureType = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__getFormatWriteFeatureType(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__getFormatWriteFeatureType,
+ "getFormatWriteFeatureType", "()Ljava/lang/Class;");
+ if (_m_JsonFactory__getFormatWriteFeatureType == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__getFormatWriteFeatureType);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__canUseSchema = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__canUseSchema(jobject self_, jobject schema) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__canUseSchema, "canUseSchema",
+ "(Lcom/fasterxml/jackson/core/FormatSchema;)Z");
+ if (_m_JsonFactory__canUseSchema == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonFactory__canUseSchema, schema);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory__getFormatName = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__getFormatName(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__getFormatName, "getFormatName",
+ "()Ljava/lang/String;");
+ if (_m_JsonFactory__getFormatName == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonFactory__getFormatName);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__hasFormat = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__hasFormat(jobject self_, jobject acc) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__hasFormat, "hasFormat",
+ "(Lcom/fasterxml/jackson/core/format/InputAccessor;)Lcom/"
+ "fasterxml/jackson/core/format/MatchStrength;");
+ if (_m_JsonFactory__hasFormat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_,
+ _m_JsonFactory__hasFormat, acc);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__requiresCustomCodec = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__requiresCustomCodec(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__requiresCustomCodec,
+ "requiresCustomCodec", "()Z");
+ if (_m_JsonFactory__requiresCustomCodec == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonFactory__requiresCustomCodec);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory__hasJSONFormat = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__hasJSONFormat(jobject self_, jobject acc) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__hasJSONFormat, "hasJSONFormat",
+ "(Lcom/fasterxml/jackson/core/format/InputAccessor;)Lcom/"
+ "fasterxml/jackson/core/format/MatchStrength;");
+ if (_m_JsonFactory__hasJSONFormat == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__hasJSONFormat, acc);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__version = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__version(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__version, "version",
+ "()Lcom/fasterxml/jackson/core/Version;");
+ if (_m_JsonFactory__version == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonFactory__version);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__configure = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__configure(jobject self_, jobject f, uint8_t state) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__configure, "configure",
+ "(Lcom/fasterxml/jackson/core/JsonFactory$Feature;Z)Lcom/"
+ "fasterxml/jackson/core/JsonFactory;");
+ if (_m_JsonFactory__configure == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__configure, f, state);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__enable = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__enable(jobject self_, jobject f) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__enable, "enable",
+ "(Lcom/fasterxml/jackson/core/JsonFactory$Feature;)Lcom/"
+ "fasterxml/jackson/core/JsonFactory;");
+ if (_m_JsonFactory__enable == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonFactory__enable, f);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__disable = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__disable(jobject self_, jobject f) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__disable, "disable",
+ "(Lcom/fasterxml/jackson/core/JsonFactory$Feature;)Lcom/"
+ "fasterxml/jackson/core/JsonFactory;");
+ if (_m_JsonFactory__disable == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonFactory__disable, f);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__isEnabled = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__isEnabled(jobject self_, jobject f) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__isEnabled, "isEnabled",
+ "(Lcom/fasterxml/jackson/core/JsonFactory$Feature;)Z");
+ if (_m_JsonFactory__isEnabled == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result =
+ (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_JsonFactory__isEnabled, f);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory__getParserFeatures = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__getParserFeatures(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__getParserFeatures,
+ "getParserFeatures", "()I");
+ if (_m_JsonFactory__getParserFeatures == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_,
+ _m_JsonFactory__getParserFeatures);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory__getGeneratorFeatures = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__getGeneratorFeatures(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__getGeneratorFeatures,
+ "getGeneratorFeatures", "()I");
+ if (_m_JsonFactory__getGeneratorFeatures == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(
+ jniEnv, self_, _m_JsonFactory__getGeneratorFeatures);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory__getFormatParserFeatures = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__getFormatParserFeatures(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__getFormatParserFeatures,
+ "getFormatParserFeatures", "()I");
+ if (_m_JsonFactory__getFormatParserFeatures == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(
+ jniEnv, self_, _m_JsonFactory__getFormatParserFeatures);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory__getFormatGeneratorFeatures = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__getFormatGeneratorFeatures(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__getFormatGeneratorFeatures,
+ "getFormatGeneratorFeatures", "()I");
+ if (_m_JsonFactory__getFormatGeneratorFeatures == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(
+ jniEnv, self_, _m_JsonFactory__getFormatGeneratorFeatures);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory__configure1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__configure1(jobject self_, jobject f, uint8_t state) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__configure1, "configure",
+ "(Lcom/fasterxml/jackson/core/JsonParser$Feature;Z)Lcom/"
+ "fasterxml/jackson/core/JsonFactory;");
+ if (_m_JsonFactory__configure1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__configure1, f, state);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__enable1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__enable1(jobject self_, jobject f) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__enable1, "enable",
+ "(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Lcom/fasterxml/"
+ "jackson/core/JsonFactory;");
+ if (_m_JsonFactory__enable1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonFactory__enable1, f);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__disable1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__disable1(jobject self_, jobject f) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__disable1, "disable",
+ "(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Lcom/fasterxml/"
+ "jackson/core/JsonFactory;");
+ if (_m_JsonFactory__disable1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonFactory__disable1, f);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__isEnabled1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__isEnabled1(jobject self_, jobject f) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__isEnabled1, "isEnabled",
+ "(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Z");
+ if (_m_JsonFactory__isEnabled1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_,
+ _m_JsonFactory__isEnabled1, f);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory__isEnabled2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__isEnabled2(jobject self_, jobject f) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__isEnabled2, "isEnabled",
+ "(Lcom/fasterxml/jackson/core/StreamReadFeature;)Z");
+ if (_m_JsonFactory__isEnabled2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_,
+ _m_JsonFactory__isEnabled2, f);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory__getInputDecorator = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__getInputDecorator(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__getInputDecorator,
+ "getInputDecorator",
+ "()Lcom/fasterxml/jackson/core/io/InputDecorator;");
+ if (_m_JsonFactory__getInputDecorator == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__getInputDecorator);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__setInputDecorator = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__setInputDecorator(jobject self_, jobject d) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__setInputDecorator,
+ "setInputDecorator",
+ "(Lcom/fasterxml/jackson/core/io/InputDecorator;)Lcom/fasterxml/"
+ "jackson/core/JsonFactory;");
+ if (_m_JsonFactory__setInputDecorator == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__setInputDecorator, d);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__configure2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__configure2(jobject self_, jobject f, uint8_t state) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__configure2, "configure",
+ "(Lcom/fasterxml/jackson/core/JsonGenerator$Feature;Z)Lcom/"
+ "fasterxml/jackson/core/JsonFactory;");
+ if (_m_JsonFactory__configure2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__configure2, f, state);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__enable2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__enable2(jobject self_, jobject f) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__enable2, "enable",
+ "(Lcom/fasterxml/jackson/core/JsonGenerator$Feature;)Lcom/"
+ "fasterxml/jackson/core/JsonFactory;");
+ if (_m_JsonFactory__enable2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonFactory__enable2, f);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__disable2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__disable2(jobject self_, jobject f) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__disable2, "disable",
+ "(Lcom/fasterxml/jackson/core/JsonGenerator$Feature;)Lcom/"
+ "fasterxml/jackson/core/JsonFactory;");
+ if (_m_JsonFactory__disable2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonFactory__disable2, f);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__isEnabled3 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__isEnabled3(jobject self_, jobject f) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__isEnabled3, "isEnabled",
+ "(Lcom/fasterxml/jackson/core/JsonGenerator$Feature;)Z");
+ if (_m_JsonFactory__isEnabled3 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_,
+ _m_JsonFactory__isEnabled3, f);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory__isEnabled4 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__isEnabled4(jobject self_, jobject f) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__isEnabled4, "isEnabled",
+ "(Lcom/fasterxml/jackson/core/StreamWriteFeature;)Z");
+ if (_m_JsonFactory__isEnabled4 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_,
+ _m_JsonFactory__isEnabled4, f);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory__getCharacterEscapes = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__getCharacterEscapes(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__getCharacterEscapes,
+ "getCharacterEscapes",
+ "()Lcom/fasterxml/jackson/core/io/CharacterEscapes;");
+ if (_m_JsonFactory__getCharacterEscapes == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__getCharacterEscapes);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__setCharacterEscapes = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__setCharacterEscapes(jobject self_, jobject esc) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__setCharacterEscapes,
+ "setCharacterEscapes",
+ "(Lcom/fasterxml/jackson/core/io/CharacterEscapes;)Lcom/"
+ "fasterxml/jackson/core/JsonFactory;");
+ if (_m_JsonFactory__setCharacterEscapes == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__setCharacterEscapes, esc);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__getOutputDecorator = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__getOutputDecorator(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__getOutputDecorator,
+ "getOutputDecorator",
+ "()Lcom/fasterxml/jackson/core/io/OutputDecorator;");
+ if (_m_JsonFactory__getOutputDecorator == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__getOutputDecorator);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__setOutputDecorator = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__setOutputDecorator(jobject self_, jobject d) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__setOutputDecorator,
+ "setOutputDecorator",
+ "(Lcom/fasterxml/jackson/core/io/OutputDecorator;)Lcom/fasterxml/"
+ "jackson/core/JsonFactory;");
+ if (_m_JsonFactory__setOutputDecorator == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__setOutputDecorator, d);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__setRootValueSeparator = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__setRootValueSeparator(jobject self_, jobject sep) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__setRootValueSeparator,
+ "setRootValueSeparator",
+ "(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonFactory;");
+ if (_m_JsonFactory__setRootValueSeparator == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__setRootValueSeparator, sep);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__getRootValueSeparator = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__getRootValueSeparator(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__getRootValueSeparator,
+ "getRootValueSeparator", "()Ljava/lang/String;");
+ if (_m_JsonFactory__getRootValueSeparator == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__getRootValueSeparator);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__setCodec = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__setCodec(jobject self_, jobject oc) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__setCodec, "setCodec",
+ "(Lcom/fasterxml/jackson/core/ObjectCodec;)Lcom/fasterxml/"
+ "jackson/core/JsonFactory;");
+ if (_m_JsonFactory__setCodec == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonFactory__setCodec, oc);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__getCodec = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__getCodec(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__getCodec, "getCodec",
+ "()Lcom/fasterxml/jackson/core/ObjectCodec;");
+ if (_m_JsonFactory__getCodec == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonFactory__getCodec);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createParser = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createParser(jobject self_, jobject f) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createParser, "createParser",
+ "(Ljava/io/File;)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createParser, f);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createParser1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createParser1(jobject self_, jobject url) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createParser1, "createParser",
+ "(Ljava/net/URL;)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createParser1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createParser1, url);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createParser2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createParser2(jobject self_, jobject in) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createParser2, "createParser",
+ "(Ljava/io/InputStream;)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createParser2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createParser2, in);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createParser3 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createParser3(jobject self_, jobject r) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createParser3, "createParser",
+ "(Ljava/io/Reader;)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createParser3 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createParser3, r);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createParser4 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createParser4(jobject self_, jobject data) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createParser4, "createParser",
+ "([B)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createParser4 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createParser4, data);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createParser5 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createParser5(jobject self_,
+ jobject data,
+ int32_t offset,
+ int32_t len) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createParser5, "createParser",
+ "([BII)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createParser5 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createParser5, data, offset, len);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createParser6 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createParser6(jobject self_, jobject content) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createParser6, "createParser",
+ "(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createParser6 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createParser6, content);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createParser7 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createParser7(jobject self_, jobject content) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createParser7, "createParser",
+ "([C)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createParser7 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createParser7, content);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createParser8 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createParser8(jobject self_,
+ jobject content,
+ int32_t offset,
+ int32_t len) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createParser8, "createParser",
+ "([CII)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createParser8 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createParser8, content, offset, len);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createParser9 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createParser9(jobject self_, jobject in) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createParser9, "createParser",
+ "(Ljava/io/DataInput;)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createParser9 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createParser9, in);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createNonBlockingByteArrayParser = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createNonBlockingByteArrayParser(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createNonBlockingByteArrayParser,
+ "createNonBlockingByteArrayParser",
+ "()Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createNonBlockingByteArrayParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createNonBlockingByteArrayParser);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createGenerator = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createGenerator(jobject self_,
+ jobject out,
+ jobject enc) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createGenerator,
+ "createGenerator",
+ "(Ljava/io/OutputStream;Lcom/fasterxml/jackson/core/"
+ "JsonEncoding;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+ if (_m_JsonFactory__createGenerator == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createGenerator, out, enc);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createGenerator1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createGenerator1(jobject self_, jobject out) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_JsonFactory, &_m_JsonFactory__createGenerator1, "createGenerator",
+ "(Ljava/io/OutputStream;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+ if (_m_JsonFactory__createGenerator1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createGenerator1, out);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createGenerator2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createGenerator2(jobject self_, jobject w) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createGenerator2,
+ "createGenerator",
+ "(Ljava/io/Writer;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+ if (_m_JsonFactory__createGenerator2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createGenerator2, w);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createGenerator3 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createGenerator3(jobject self_, jobject f, jobject enc) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createGenerator3,
+ "createGenerator",
+ "(Ljava/io/File;Lcom/fasterxml/jackson/core/JsonEncoding;)Lcom/"
+ "fasterxml/jackson/core/JsonGenerator;");
+ if (_m_JsonFactory__createGenerator3 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createGenerator3, f, enc);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createGenerator4 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createGenerator4(jobject self_,
+ jobject out,
+ jobject enc) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createGenerator4,
+ "createGenerator",
+ "(Ljava/io/DataOutput;Lcom/fasterxml/jackson/core/"
+ "JsonEncoding;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+ if (_m_JsonFactory__createGenerator4 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createGenerator4, out, enc);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createGenerator5 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createGenerator5(jobject self_, jobject out) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_JsonFactory, &_m_JsonFactory__createGenerator5, "createGenerator",
+ "(Ljava/io/DataOutput;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+ if (_m_JsonFactory__createGenerator5 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createGenerator5, out);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createJsonParser = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createJsonParser(jobject self_, jobject f) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createJsonParser,
+ "createJsonParser",
+ "(Ljava/io/File;)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createJsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createJsonParser, f);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createJsonParser1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createJsonParser1(jobject self_, jobject url) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createJsonParser1,
+ "createJsonParser",
+ "(Ljava/net/URL;)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createJsonParser1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createJsonParser1, url);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createJsonParser2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createJsonParser2(jobject self_, jobject in) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createJsonParser2,
+ "createJsonParser",
+ "(Ljava/io/InputStream;)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createJsonParser2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createJsonParser2, in);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createJsonParser3 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createJsonParser3(jobject self_, jobject r) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createJsonParser3,
+ "createJsonParser",
+ "(Ljava/io/Reader;)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createJsonParser3 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createJsonParser3, r);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createJsonParser4 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createJsonParser4(jobject self_, jobject data) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createJsonParser4,
+ "createJsonParser",
+ "([B)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createJsonParser4 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createJsonParser4, data);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createJsonParser5 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createJsonParser5(jobject self_,
+ jobject data,
+ int32_t offset,
+ int32_t len) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createJsonParser5,
+ "createJsonParser",
+ "([BII)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createJsonParser5 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createJsonParser5, data, offset, len);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createJsonParser6 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createJsonParser6(jobject self_, jobject content) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createJsonParser6,
+ "createJsonParser",
+ "(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonFactory__createJsonParser6 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createJsonParser6, content);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createJsonGenerator = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createJsonGenerator(jobject self_,
+ jobject out,
+ jobject enc) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createJsonGenerator,
+ "createJsonGenerator",
+ "(Ljava/io/OutputStream;Lcom/fasterxml/jackson/core/"
+ "JsonEncoding;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+ if (_m_JsonFactory__createJsonGenerator == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createJsonGenerator, out, enc);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createJsonGenerator1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createJsonGenerator1(jobject self_, jobject out) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory, &_m_JsonFactory__createJsonGenerator1,
+ "createJsonGenerator",
+ "(Ljava/io/Writer;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+ if (_m_JsonFactory__createJsonGenerator1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createJsonGenerator1, out);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory__createJsonGenerator2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory__createJsonGenerator2(jobject self_, jobject out) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_JsonFactory, &_m_JsonFactory__createJsonGenerator2,
+ "createJsonGenerator",
+ "(Ljava/io/OutputStream;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+ if (_m_JsonFactory__createJsonGenerator2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonFactory__createJsonGenerator2, out);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_JsonFactory__DEFAULT_FACTORY_FEATURE_FLAGS = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_JsonFactory__DEFAULT_FACTORY_FEATURE_FLAGS() {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_JsonFactory,
+ &_f_JsonFactory__DEFAULT_FACTORY_FEATURE_FLAGS,
+ "DEFAULT_FACTORY_FEATURE_FLAGS", "I");
+ int32_t _result = (*jniEnv)->GetStaticIntField(
+ jniEnv, _c_JsonFactory, _f_JsonFactory__DEFAULT_FACTORY_FEATURE_FLAGS);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jfieldID _f_JsonFactory__DEFAULT_PARSER_FEATURE_FLAGS = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_JsonFactory__DEFAULT_PARSER_FEATURE_FLAGS() {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_JsonFactory,
+ &_f_JsonFactory__DEFAULT_PARSER_FEATURE_FLAGS,
+ "DEFAULT_PARSER_FEATURE_FLAGS", "I");
+ int32_t _result = (*jniEnv)->GetStaticIntField(
+ jniEnv, _c_JsonFactory, _f_JsonFactory__DEFAULT_PARSER_FEATURE_FLAGS);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jfieldID _f_JsonFactory__DEFAULT_GENERATOR_FEATURE_FLAGS = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_JsonFactory__DEFAULT_GENERATOR_FEATURE_FLAGS() {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_JsonFactory,
+ &_f_JsonFactory__DEFAULT_GENERATOR_FEATURE_FLAGS,
+ "DEFAULT_GENERATOR_FEATURE_FLAGS", "I");
+ int32_t _result = (*jniEnv)->GetStaticIntField(
+ jniEnv, _c_JsonFactory, _f_JsonFactory__DEFAULT_GENERATOR_FEATURE_FLAGS);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jfieldID _f_JsonFactory__DEFAULT_ROOT_VALUE_SEPARATOR = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_JsonFactory__DEFAULT_ROOT_VALUE_SEPARATOR() {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory,
+ "com/fasterxml/jackson/core/JsonFactory");
+ if (_c_JsonFactory == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_JsonFactory,
+ &_f_JsonFactory__DEFAULT_ROOT_VALUE_SEPARATOR,
+ "DEFAULT_ROOT_VALUE_SEPARATOR",
+ "Lcom/fasterxml/jackson/core/SerializableString;");
+ jobject _result = (*jniEnv)->GetStaticObjectField(
+ jniEnv, _c_JsonFactory, _f_JsonFactory__DEFAULT_ROOT_VALUE_SEPARATOR);
+ return to_global_ref_result(_result);
+}
+
+// com.fasterxml.jackson.core.JsonFactory$Feature
+jclass _c_JsonFactory_Feature = NULL;
+
+jmethodID _m_JsonFactory_Feature__values = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory_Feature__values() {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory_Feature,
+ "com/fasterxml/jackson/core/JsonFactory$Feature");
+ if (_c_JsonFactory_Feature == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_JsonFactory_Feature, &_m_JsonFactory_Feature__values,
+ "values",
+ "()[Lcom/fasterxml/jackson/core/JsonFactory$Feature;");
+ if (_m_JsonFactory_Feature__values == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_JsonFactory_Feature, _m_JsonFactory_Feature__values);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory_Feature__valueOf = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory_Feature__valueOf(jobject name) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory_Feature,
+ "com/fasterxml/jackson/core/JsonFactory$Feature");
+ if (_c_JsonFactory_Feature == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_JsonFactory_Feature, &_m_JsonFactory_Feature__valueOf, "valueOf",
+ "(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonFactory$Feature;");
+ if (_m_JsonFactory_Feature__valueOf == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_JsonFactory_Feature, _m_JsonFactory_Feature__valueOf, name);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonFactory_Feature__collectDefaults = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory_Feature__collectDefaults() {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory_Feature,
+ "com/fasterxml/jackson/core/JsonFactory$Feature");
+ if (_c_JsonFactory_Feature == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_JsonFactory_Feature,
+ &_m_JsonFactory_Feature__collectDefaults,
+ "collectDefaults", "()I");
+ if (_m_JsonFactory_Feature__collectDefaults == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallStaticIntMethod(
+ jniEnv, _c_JsonFactory_Feature, _m_JsonFactory_Feature__collectDefaults);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory_Feature__enabledByDefault = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory_Feature__enabledByDefault(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory_Feature,
+ "com/fasterxml/jackson/core/JsonFactory$Feature");
+ if (_c_JsonFactory_Feature == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory_Feature, &_m_JsonFactory_Feature__enabledByDefault,
+ "enabledByDefault", "()Z");
+ if (_m_JsonFactory_Feature__enabledByDefault == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonFactory_Feature__enabledByDefault);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory_Feature__enabledIn = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory_Feature__enabledIn(jobject self_, int32_t flags) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory_Feature,
+ "com/fasterxml/jackson/core/JsonFactory$Feature");
+ if (_c_JsonFactory_Feature == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory_Feature, &_m_JsonFactory_Feature__enabledIn,
+ "enabledIn", "(I)Z");
+ if (_m_JsonFactory_Feature__enabledIn == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonFactory_Feature__enabledIn, flags);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonFactory_Feature__getMask = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonFactory_Feature__getMask(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonFactory_Feature,
+ "com/fasterxml/jackson/core/JsonFactory$Feature");
+ if (_c_JsonFactory_Feature == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonFactory_Feature, &_m_JsonFactory_Feature__getMask,
+ "getMask", "()I");
+ if (_m_JsonFactory_Feature__getMask == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_JsonFactory_Feature__getMask);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+// com.fasterxml.jackson.core.JsonParser
+jclass _c_JsonParser = NULL;
+
+jmethodID _m_JsonParser__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__new0() {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__new0, "<init>", "()V");
+ if (_m_JsonParser__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_JsonParser, _m_JsonParser__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__new1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__new1(int32_t features) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__new1, "<init>", "(I)V");
+ if (_m_JsonParser__new1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_JsonParser,
+ _m_JsonParser__new1, features);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getCodec = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getCodec(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getCodec, "getCodec",
+ "()Lcom/fasterxml/jackson/core/ObjectCodec;");
+ if (_m_JsonParser__getCodec == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__getCodec);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__setCodec = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__setCodec(jobject self_, jobject oc) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__setCodec, "setCodec",
+ "(Lcom/fasterxml/jackson/core/ObjectCodec;)V");
+ if (_m_JsonParser__setCodec == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_JsonParser__setCodec, oc);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getInputSource = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getInputSource(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getInputSource, "getInputSource",
+ "()Ljava/lang/Object;");
+ if (_m_JsonParser__getInputSource == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__getInputSource);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__setRequestPayloadOnError = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__setRequestPayloadOnError(jobject self_, jobject payload) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__setRequestPayloadOnError,
+ "setRequestPayloadOnError",
+ "(Lcom/fasterxml/jackson/core/util/RequestPayload;)V");
+ if (_m_JsonParser__setRequestPayloadOnError == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_JsonParser__setRequestPayloadOnError, payload);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__setRequestPayloadOnError1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__setRequestPayloadOnError1(jobject self_,
+ jobject payload,
+ jobject charset) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__setRequestPayloadOnError1,
+ "setRequestPayloadOnError", "([BLjava/lang/String;)V");
+ if (_m_JsonParser__setRequestPayloadOnError1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_JsonParser__setRequestPayloadOnError1, payload,
+ charset);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__setRequestPayloadOnError2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__setRequestPayloadOnError2(jobject self_,
+ jobject payload) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__setRequestPayloadOnError2,
+ "setRequestPayloadOnError", "(Ljava/lang/String;)V");
+ if (_m_JsonParser__setRequestPayloadOnError2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_JsonParser__setRequestPayloadOnError2, payload);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__setSchema = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__setSchema(jobject self_, jobject schema) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__setSchema, "setSchema",
+ "(Lcom/fasterxml/jackson/core/FormatSchema;)V");
+ if (_m_JsonParser__setSchema == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_JsonParser__setSchema, schema);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getSchema = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getSchema(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getSchema, "getSchema",
+ "()Lcom/fasterxml/jackson/core/FormatSchema;");
+ if (_m_JsonParser__getSchema == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__getSchema);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__canUseSchema = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__canUseSchema(jobject self_, jobject schema) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__canUseSchema, "canUseSchema",
+ "(Lcom/fasterxml/jackson/core/FormatSchema;)Z");
+ if (_m_JsonParser__canUseSchema == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonParser__canUseSchema, schema);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__requiresCustomCodec = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__requiresCustomCodec(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__requiresCustomCodec,
+ "requiresCustomCodec", "()Z");
+ if (_m_JsonParser__requiresCustomCodec == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonParser__requiresCustomCodec);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__canParseAsync = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__canParseAsync(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__canParseAsync, "canParseAsync",
+ "()Z");
+ if (_m_JsonParser__canParseAsync == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result =
+ (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_JsonParser__canParseAsync);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getNonBlockingInputFeeder = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getNonBlockingInputFeeder(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getNonBlockingInputFeeder,
+ "getNonBlockingInputFeeder",
+ "()Lcom/fasterxml/jackson/core/async/NonBlockingInputFeeder;");
+ if (_m_JsonParser__getNonBlockingInputFeeder == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__getNonBlockingInputFeeder);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getReadCapabilities = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getReadCapabilities(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getReadCapabilities,
+ "getReadCapabilities",
+ "()Lcom/fasterxml/jackson/core/util/JacksonFeatureSet;");
+ if (_m_JsonParser__getReadCapabilities == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__getReadCapabilities);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__version = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__version(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__version, "version",
+ "()Lcom/fasterxml/jackson/core/Version;");
+ if (_m_JsonParser__version == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__version);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__close = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__close(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__close, "close", "()V");
+ if (_m_JsonParser__close == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_JsonParser__close);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__isClosed = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__isClosed(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__isClosed, "isClosed", "()Z");
+ if (_m_JsonParser__isClosed == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result =
+ (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_JsonParser__isClosed);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getParsingContext = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getParsingContext(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getParsingContext,
+ "getParsingContext",
+ "()Lcom/fasterxml/jackson/core/JsonStreamContext;");
+ if (_m_JsonParser__getParsingContext == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__getParsingContext);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__currentLocation = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__currentLocation(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__currentLocation, "currentLocation",
+ "()Lcom/fasterxml/jackson/core/JsonLocation;");
+ if (_m_JsonParser__currentLocation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_,
+ _m_JsonParser__currentLocation);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__currentTokenLocation = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__currentTokenLocation(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__currentTokenLocation,
+ "currentTokenLocation",
+ "()Lcom/fasterxml/jackson/core/JsonLocation;");
+ if (_m_JsonParser__currentTokenLocation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__currentTokenLocation);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getCurrentLocation = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getCurrentLocation(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getCurrentLocation,
+ "getCurrentLocation",
+ "()Lcom/fasterxml/jackson/core/JsonLocation;");
+ if (_m_JsonParser__getCurrentLocation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__getCurrentLocation);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getTokenLocation = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getTokenLocation(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getTokenLocation,
+ "getTokenLocation",
+ "()Lcom/fasterxml/jackson/core/JsonLocation;");
+ if (_m_JsonParser__getTokenLocation == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__getTokenLocation);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__currentValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__currentValue(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__currentValue, "currentValue",
+ "()Ljava/lang/Object;");
+ if (_m_JsonParser__currentValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__currentValue);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__assignCurrentValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__assignCurrentValue(jobject self_, jobject v) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__assignCurrentValue,
+ "assignCurrentValue", "(Ljava/lang/Object;)V");
+ if (_m_JsonParser__assignCurrentValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_JsonParser__assignCurrentValue,
+ v);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getCurrentValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getCurrentValue(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getCurrentValue, "getCurrentValue",
+ "()Ljava/lang/Object;");
+ if (_m_JsonParser__getCurrentValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_,
+ _m_JsonParser__getCurrentValue);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__setCurrentValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__setCurrentValue(jobject self_, jobject v) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__setCurrentValue, "setCurrentValue",
+ "(Ljava/lang/Object;)V");
+ if (_m_JsonParser__setCurrentValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_JsonParser__setCurrentValue, v);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__releaseBuffered = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__releaseBuffered(jobject self_, jobject out) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__releaseBuffered, "releaseBuffered",
+ "(Ljava/io/OutputStream;)I");
+ if (_m_JsonParser__releaseBuffered == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(
+ jniEnv, self_, _m_JsonParser__releaseBuffered, out);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__releaseBuffered1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__releaseBuffered1(jobject self_, jobject w) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__releaseBuffered1,
+ "releaseBuffered", "(Ljava/io/Writer;)I");
+ if (_m_JsonParser__releaseBuffered1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(
+ jniEnv, self_, _m_JsonParser__releaseBuffered1, w);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__enable = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__enable(jobject self_, jobject f) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__enable, "enable",
+ "(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Lcom/fasterxml/"
+ "jackson/core/JsonParser;");
+ if (_m_JsonParser__enable == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__enable, f);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__disable = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__disable(jobject self_, jobject f) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__disable, "disable",
+ "(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Lcom/fasterxml/"
+ "jackson/core/JsonParser;");
+ if (_m_JsonParser__disable == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__disable, f);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__configure = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__configure(jobject self_, jobject f, uint8_t state) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__configure, "configure",
+ "(Lcom/fasterxml/jackson/core/JsonParser$Feature;Z)Lcom/"
+ "fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonParser__configure == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__configure, f, state);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__isEnabled = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__isEnabled(jobject self_, jobject f) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__isEnabled, "isEnabled",
+ "(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Z");
+ if (_m_JsonParser__isEnabled == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result =
+ (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_JsonParser__isEnabled, f);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__isEnabled1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__isEnabled1(jobject self_, jobject f) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__isEnabled1, "isEnabled",
+ "(Lcom/fasterxml/jackson/core/StreamReadFeature;)Z");
+ if (_m_JsonParser__isEnabled1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result =
+ (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_JsonParser__isEnabled1, f);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getFeatureMask = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getFeatureMask(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getFeatureMask, "getFeatureMask",
+ "()I");
+ if (_m_JsonParser__getFeatureMask == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_JsonParser__getFeatureMask);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__setFeatureMask = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__setFeatureMask(jobject self_, int32_t mask) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__setFeatureMask, "setFeatureMask",
+ "(I)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonParser__setFeatureMask == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__setFeatureMask, mask);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__overrideStdFeatures = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__overrideStdFeatures(jobject self_,
+ int32_t values,
+ int32_t mask) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__overrideStdFeatures,
+ "overrideStdFeatures",
+ "(II)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonParser__overrideStdFeatures == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__overrideStdFeatures, values, mask);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getFormatFeatures = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getFormatFeatures(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getFormatFeatures,
+ "getFormatFeatures", "()I");
+ if (_m_JsonParser__getFormatFeatures == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_JsonParser__getFormatFeatures);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__overrideFormatFeatures = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__overrideFormatFeatures(jobject self_,
+ int32_t values,
+ int32_t mask) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__overrideFormatFeatures,
+ "overrideFormatFeatures",
+ "(II)Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonParser__overrideFormatFeatures == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__overrideFormatFeatures, values, mask);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__nextToken = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__nextToken(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__nextToken, "nextToken",
+ "()Lcom/fasterxml/jackson/core/JsonToken;");
+ if (_m_JsonParser__nextToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__nextToken);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__nextValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__nextValue(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__nextValue, "nextValue",
+ "()Lcom/fasterxml/jackson/core/JsonToken;");
+ if (_m_JsonParser__nextValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__nextValue);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__nextFieldName = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__nextFieldName(jobject self_, jobject str) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__nextFieldName, "nextFieldName",
+ "(Lcom/fasterxml/jackson/core/SerializableString;)Z");
+ if (_m_JsonParser__nextFieldName == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonParser__nextFieldName, str);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__nextFieldName1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__nextFieldName1(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__nextFieldName1, "nextFieldName",
+ "()Ljava/lang/String;");
+ if (_m_JsonParser__nextFieldName1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__nextFieldName1);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__nextTextValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__nextTextValue(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__nextTextValue, "nextTextValue",
+ "()Ljava/lang/String;");
+ if (_m_JsonParser__nextTextValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__nextTextValue);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__nextIntValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__nextIntValue(jobject self_, int32_t defaultValue) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__nextIntValue, "nextIntValue",
+ "(I)I");
+ if (_m_JsonParser__nextIntValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(
+ jniEnv, self_, _m_JsonParser__nextIntValue, defaultValue);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__nextLongValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__nextLongValue(jobject self_, int64_t defaultValue) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__nextLongValue, "nextLongValue",
+ "(J)J");
+ if (_m_JsonParser__nextLongValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int64_t _result = (*jniEnv)->CallLongMethod(
+ jniEnv, self_, _m_JsonParser__nextLongValue, defaultValue);
+ return (JniResult){.value = {.j = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__nextBooleanValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__nextBooleanValue(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__nextBooleanValue,
+ "nextBooleanValue", "()Ljava/lang/Boolean;");
+ if (_m_JsonParser__nextBooleanValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__nextBooleanValue);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__skipChildren = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__skipChildren(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__skipChildren, "skipChildren",
+ "()Lcom/fasterxml/jackson/core/JsonParser;");
+ if (_m_JsonParser__skipChildren == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__skipChildren);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__finishToken = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__finishToken(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__finishToken, "finishToken", "()V");
+ if (_m_JsonParser__finishToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_JsonParser__finishToken);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__currentToken = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__currentToken(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__currentToken, "currentToken",
+ "()Lcom/fasterxml/jackson/core/JsonToken;");
+ if (_m_JsonParser__currentToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__currentToken);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__currentTokenId = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__currentTokenId(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__currentTokenId, "currentTokenId",
+ "()I");
+ if (_m_JsonParser__currentTokenId == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_JsonParser__currentTokenId);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getCurrentToken = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getCurrentToken(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getCurrentToken, "getCurrentToken",
+ "()Lcom/fasterxml/jackson/core/JsonToken;");
+ if (_m_JsonParser__getCurrentToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_,
+ _m_JsonParser__getCurrentToken);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getCurrentTokenId = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getCurrentTokenId(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getCurrentTokenId,
+ "getCurrentTokenId", "()I");
+ if (_m_JsonParser__getCurrentTokenId == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_JsonParser__getCurrentTokenId);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__hasCurrentToken = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__hasCurrentToken(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__hasCurrentToken, "hasCurrentToken",
+ "()Z");
+ if (_m_JsonParser__hasCurrentToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonParser__hasCurrentToken);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__hasTokenId = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__hasTokenId(jobject self_, int32_t id) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__hasTokenId, "hasTokenId", "(I)Z");
+ if (_m_JsonParser__hasTokenId == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(jniEnv, self_,
+ _m_JsonParser__hasTokenId, id);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__hasToken = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__hasToken(jobject self_, jobject t) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__hasToken, "hasToken",
+ "(Lcom/fasterxml/jackson/core/JsonToken;)Z");
+ if (_m_JsonParser__hasToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result =
+ (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_JsonParser__hasToken, t);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__isExpectedStartArrayToken = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__isExpectedStartArrayToken(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__isExpectedStartArrayToken,
+ "isExpectedStartArrayToken", "()Z");
+ if (_m_JsonParser__isExpectedStartArrayToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonParser__isExpectedStartArrayToken);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__isExpectedStartObjectToken = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__isExpectedStartObjectToken(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__isExpectedStartObjectToken,
+ "isExpectedStartObjectToken", "()Z");
+ if (_m_JsonParser__isExpectedStartObjectToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonParser__isExpectedStartObjectToken);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__isExpectedNumberIntToken = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__isExpectedNumberIntToken(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__isExpectedNumberIntToken,
+ "isExpectedNumberIntToken", "()Z");
+ if (_m_JsonParser__isExpectedNumberIntToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonParser__isExpectedNumberIntToken);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__isNaN = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__isNaN(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__isNaN, "isNaN", "()Z");
+ if (_m_JsonParser__isNaN == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result =
+ (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_JsonParser__isNaN);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__clearCurrentToken = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__clearCurrentToken(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__clearCurrentToken,
+ "clearCurrentToken", "()V");
+ if (_m_JsonParser__clearCurrentToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_JsonParser__clearCurrentToken);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getLastClearedToken = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getLastClearedToken(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getLastClearedToken,
+ "getLastClearedToken",
+ "()Lcom/fasterxml/jackson/core/JsonToken;");
+ if (_m_JsonParser__getLastClearedToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__getLastClearedToken);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__overrideCurrentName = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__overrideCurrentName(jobject self_, jobject name) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__overrideCurrentName,
+ "overrideCurrentName", "(Ljava/lang/String;)V");
+ if (_m_JsonParser__overrideCurrentName == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_JsonParser__overrideCurrentName,
+ name);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getCurrentName = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getCurrentName(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getCurrentName, "getCurrentName",
+ "()Ljava/lang/String;");
+ if (_m_JsonParser__getCurrentName == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__getCurrentName);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__currentName = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__currentName(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__currentName, "currentName",
+ "()Ljava/lang/String;");
+ if (_m_JsonParser__currentName == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__currentName);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getText = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getText(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getText, "getText",
+ "()Ljava/lang/String;");
+ if (_m_JsonParser__getText == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__getText);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getText1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getText1(jobject self_, jobject writer) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getText1, "getText",
+ "(Ljava/io/Writer;)I");
+ if (_m_JsonParser__getText1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_JsonParser__getText1, writer);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getTextCharacters = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getTextCharacters(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getTextCharacters,
+ "getTextCharacters", "()[C");
+ if (_m_JsonParser__getTextCharacters == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__getTextCharacters);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getTextLength = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getTextLength(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getTextLength, "getTextLength",
+ "()I");
+ if (_m_JsonParser__getTextLength == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_JsonParser__getTextLength);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getTextOffset = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getTextOffset(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getTextOffset, "getTextOffset",
+ "()I");
+ if (_m_JsonParser__getTextOffset == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_JsonParser__getTextOffset);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__hasTextCharacters = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__hasTextCharacters(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__hasTextCharacters,
+ "hasTextCharacters", "()Z");
+ if (_m_JsonParser__hasTextCharacters == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonParser__hasTextCharacters);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getNumberValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getNumberValue(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getNumberValue, "getNumberValue",
+ "()Ljava/lang/Number;");
+ if (_m_JsonParser__getNumberValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__getNumberValue);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getNumberValueExact = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getNumberValueExact(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getNumberValueExact,
+ "getNumberValueExact", "()Ljava/lang/Number;");
+ if (_m_JsonParser__getNumberValueExact == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__getNumberValueExact);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getNumberType = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getNumberType(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getNumberType, "getNumberType",
+ "()Lcom/fasterxml/jackson/core/JsonParser$NumberType;");
+ if (_m_JsonParser__getNumberType == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__getNumberType);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getByteValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getByteValue(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getByteValue, "getByteValue",
+ "()B");
+ if (_m_JsonParser__getByteValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int8_t _result =
+ (*jniEnv)->CallByteMethod(jniEnv, self_, _m_JsonParser__getByteValue);
+ return (JniResult){.value = {.b = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getShortValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getShortValue(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getShortValue, "getShortValue",
+ "()S");
+ if (_m_JsonParser__getShortValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int16_t _result =
+ (*jniEnv)->CallShortMethod(jniEnv, self_, _m_JsonParser__getShortValue);
+ return (JniResult){.value = {.s = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getIntValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getIntValue(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getIntValue, "getIntValue", "()I");
+ if (_m_JsonParser__getIntValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_JsonParser__getIntValue);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getLongValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getLongValue(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getLongValue, "getLongValue",
+ "()J");
+ if (_m_JsonParser__getLongValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int64_t _result =
+ (*jniEnv)->CallLongMethod(jniEnv, self_, _m_JsonParser__getLongValue);
+ return (JniResult){.value = {.j = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getBigIntegerValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getBigIntegerValue(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getBigIntegerValue,
+ "getBigIntegerValue", "()Ljava/math/BigInteger;");
+ if (_m_JsonParser__getBigIntegerValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__getBigIntegerValue);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getFloatValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getFloatValue(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getFloatValue, "getFloatValue",
+ "()F");
+ if (_m_JsonParser__getFloatValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ float _result =
+ (*jniEnv)->CallFloatMethod(jniEnv, self_, _m_JsonParser__getFloatValue);
+ return (JniResult){.value = {.f = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getDoubleValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getDoubleValue(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getDoubleValue, "getDoubleValue",
+ "()D");
+ if (_m_JsonParser__getDoubleValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ double _result =
+ (*jniEnv)->CallDoubleMethod(jniEnv, self_, _m_JsonParser__getDoubleValue);
+ return (JniResult){.value = {.d = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getDecimalValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getDecimalValue(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getDecimalValue, "getDecimalValue",
+ "()Ljava/math/BigDecimal;");
+ if (_m_JsonParser__getDecimalValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_,
+ _m_JsonParser__getDecimalValue);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getBooleanValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getBooleanValue(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getBooleanValue, "getBooleanValue",
+ "()Z");
+ if (_m_JsonParser__getBooleanValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonParser__getBooleanValue);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getEmbeddedObject = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getEmbeddedObject(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getEmbeddedObject,
+ "getEmbeddedObject", "()Ljava/lang/Object;");
+ if (_m_JsonParser__getEmbeddedObject == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__getEmbeddedObject);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getBinaryValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getBinaryValue(jobject self_, jobject bv) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getBinaryValue, "getBinaryValue",
+ "(Lcom/fasterxml/jackson/core/Base64Variant;)[B");
+ if (_m_JsonParser__getBinaryValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__getBinaryValue, bv);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getBinaryValue1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getBinaryValue1(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getBinaryValue1, "getBinaryValue",
+ "()[B");
+ if (_m_JsonParser__getBinaryValue1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_,
+ _m_JsonParser__getBinaryValue1);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__readBinaryValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__readBinaryValue(jobject self_, jobject out) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__readBinaryValue, "readBinaryValue",
+ "(Ljava/io/OutputStream;)I");
+ if (_m_JsonParser__readBinaryValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(
+ jniEnv, self_, _m_JsonParser__readBinaryValue, out);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__readBinaryValue1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__readBinaryValue1(jobject self_, jobject bv, jobject out) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_JsonParser, &_m_JsonParser__readBinaryValue1, "readBinaryValue",
+ "(Lcom/fasterxml/jackson/core/Base64Variant;Ljava/io/OutputStream;)I");
+ if (_m_JsonParser__readBinaryValue1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(
+ jniEnv, self_, _m_JsonParser__readBinaryValue1, bv, out);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getValueAsInt = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getValueAsInt(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getValueAsInt, "getValueAsInt",
+ "()I");
+ if (_m_JsonParser__getValueAsInt == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_JsonParser__getValueAsInt);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getValueAsInt1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getValueAsInt1(jobject self_, int32_t def) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getValueAsInt1, "getValueAsInt",
+ "(I)I");
+ if (_m_JsonParser__getValueAsInt1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(
+ jniEnv, self_, _m_JsonParser__getValueAsInt1, def);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getValueAsLong = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getValueAsLong(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getValueAsLong, "getValueAsLong",
+ "()J");
+ if (_m_JsonParser__getValueAsLong == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int64_t _result =
+ (*jniEnv)->CallLongMethod(jniEnv, self_, _m_JsonParser__getValueAsLong);
+ return (JniResult){.value = {.j = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getValueAsLong1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getValueAsLong1(jobject self_, int64_t def) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getValueAsLong1, "getValueAsLong",
+ "(J)J");
+ if (_m_JsonParser__getValueAsLong1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int64_t _result = (*jniEnv)->CallLongMethod(
+ jniEnv, self_, _m_JsonParser__getValueAsLong1, def);
+ return (JniResult){.value = {.j = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getValueAsDouble = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getValueAsDouble(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getValueAsDouble,
+ "getValueAsDouble", "()D");
+ if (_m_JsonParser__getValueAsDouble == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ double _result = (*jniEnv)->CallDoubleMethod(jniEnv, self_,
+ _m_JsonParser__getValueAsDouble);
+ return (JniResult){.value = {.d = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getValueAsDouble1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getValueAsDouble1(jobject self_, double def) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getValueAsDouble1,
+ "getValueAsDouble", "(D)D");
+ if (_m_JsonParser__getValueAsDouble1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ double _result = (*jniEnv)->CallDoubleMethod(
+ jniEnv, self_, _m_JsonParser__getValueAsDouble1, def);
+ return (JniResult){.value = {.d = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getValueAsBoolean = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getValueAsBoolean(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getValueAsBoolean,
+ "getValueAsBoolean", "()Z");
+ if (_m_JsonParser__getValueAsBoolean == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonParser__getValueAsBoolean);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getValueAsBoolean1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getValueAsBoolean1(jobject self_, uint8_t def) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getValueAsBoolean1,
+ "getValueAsBoolean", "(Z)Z");
+ if (_m_JsonParser__getValueAsBoolean1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonParser__getValueAsBoolean1, def);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getValueAsString = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getValueAsString(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getValueAsString,
+ "getValueAsString", "()Ljava/lang/String;");
+ if (_m_JsonParser__getValueAsString == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__getValueAsString);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getValueAsString1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getValueAsString1(jobject self_, jobject def) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getValueAsString1,
+ "getValueAsString", "(Ljava/lang/String;)Ljava/lang/String;");
+ if (_m_JsonParser__getValueAsString1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__getValueAsString1, def);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__canReadObjectId = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__canReadObjectId(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__canReadObjectId, "canReadObjectId",
+ "()Z");
+ if (_m_JsonParser__canReadObjectId == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonParser__canReadObjectId);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__canReadTypeId = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__canReadTypeId(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__canReadTypeId, "canReadTypeId",
+ "()Z");
+ if (_m_JsonParser__canReadTypeId == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result =
+ (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_JsonParser__canReadTypeId);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser__getObjectId = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getObjectId(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getObjectId, "getObjectId",
+ "()Ljava/lang/Object;");
+ if (_m_JsonParser__getObjectId == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__getObjectId);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__getTypeId = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__getTypeId(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__getTypeId, "getTypeId",
+ "()Ljava/lang/Object;");
+ if (_m_JsonParser__getTypeId == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonParser__getTypeId);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__readValueAs = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__readValueAs(jobject self_, jobject valueType) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__readValueAs, "readValueAs",
+ "(Ljava/lang/Class;)Ljava/lang/Object;");
+ if (_m_JsonParser__readValueAs == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__readValueAs, valueType);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__readValueAs1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__readValueAs1(jobject self_, jobject valueTypeRef) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_JsonParser, &_m_JsonParser__readValueAs1, "readValueAs",
+ "(Lcom/fasterxml/jackson/core/type/TypeReference;)Ljava/lang/Object;");
+ if (_m_JsonParser__readValueAs1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__readValueAs1, valueTypeRef);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__readValuesAs = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__readValuesAs(jobject self_, jobject valueType) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__readValuesAs, "readValuesAs",
+ "(Ljava/lang/Class;)Ljava/util/Iterator;");
+ if (_m_JsonParser__readValuesAs == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__readValuesAs, valueType);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__readValuesAs1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__readValuesAs1(jobject self_, jobject valueTypeRef) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_JsonParser, &_m_JsonParser__readValuesAs1, "readValuesAs",
+ "(Lcom/fasterxml/jackson/core/type/TypeReference;)Ljava/util/Iterator;");
+ if (_m_JsonParser__readValuesAs1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_JsonParser__readValuesAs1, valueTypeRef);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser__readValueAsTree = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser__readValueAsTree(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser, &_m_JsonParser__readValueAsTree, "readValueAsTree",
+ "()Lcom/fasterxml/jackson/core/TreeNode;");
+ if (_m_JsonParser__readValueAsTree == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_,
+ _m_JsonParser__readValueAsTree);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_JsonParser__DEFAULT_READ_CAPABILITIES = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_JsonParser__DEFAULT_READ_CAPABILITIES() {
+ load_env();
+ load_class_global_ref(&_c_JsonParser,
+ "com/fasterxml/jackson/core/JsonParser");
+ if (_c_JsonParser == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_JsonParser, &_f_JsonParser__DEFAULT_READ_CAPABILITIES,
+ "DEFAULT_READ_CAPABILITIES",
+ "Lcom/fasterxml/jackson/core/util/JacksonFeatureSet;");
+ jobject _result = (*jniEnv)->GetStaticObjectField(
+ jniEnv, _c_JsonParser, _f_JsonParser__DEFAULT_READ_CAPABILITIES);
+ return to_global_ref_result(_result);
+}
+
+// com.fasterxml.jackson.core.JsonParser$Feature
+jclass _c_JsonParser_Feature = NULL;
+
+jmethodID _m_JsonParser_Feature__values = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser_Feature__values() {
+ load_env();
+ load_class_global_ref(&_c_JsonParser_Feature,
+ "com/fasterxml/jackson/core/JsonParser$Feature");
+ if (_c_JsonParser_Feature == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_JsonParser_Feature, &_m_JsonParser_Feature__values,
+ "values",
+ "()[Lcom/fasterxml/jackson/core/JsonParser$Feature;");
+ if (_m_JsonParser_Feature__values == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_JsonParser_Feature, _m_JsonParser_Feature__values);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser_Feature__valueOf = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser_Feature__valueOf(jobject name) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser_Feature,
+ "com/fasterxml/jackson/core/JsonParser$Feature");
+ if (_c_JsonParser_Feature == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_JsonParser_Feature, &_m_JsonParser_Feature__valueOf, "valueOf",
+ "(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonParser$Feature;");
+ if (_m_JsonParser_Feature__valueOf == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_JsonParser_Feature, _m_JsonParser_Feature__valueOf, name);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser_Feature__collectDefaults = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser_Feature__collectDefaults() {
+ load_env();
+ load_class_global_ref(&_c_JsonParser_Feature,
+ "com/fasterxml/jackson/core/JsonParser$Feature");
+ if (_c_JsonParser_Feature == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_JsonParser_Feature,
+ &_m_JsonParser_Feature__collectDefaults, "collectDefaults",
+ "()I");
+ if (_m_JsonParser_Feature__collectDefaults == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallStaticIntMethod(
+ jniEnv, _c_JsonParser_Feature, _m_JsonParser_Feature__collectDefaults);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser_Feature__enabledByDefault = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser_Feature__enabledByDefault(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser_Feature,
+ "com/fasterxml/jackson/core/JsonParser$Feature");
+ if (_c_JsonParser_Feature == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser_Feature, &_m_JsonParser_Feature__enabledByDefault,
+ "enabledByDefault", "()Z");
+ if (_m_JsonParser_Feature__enabledByDefault == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonParser_Feature__enabledByDefault);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser_Feature__enabledIn = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser_Feature__enabledIn(jobject self_, int32_t flags) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser_Feature,
+ "com/fasterxml/jackson/core/JsonParser$Feature");
+ if (_c_JsonParser_Feature == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser_Feature, &_m_JsonParser_Feature__enabledIn,
+ "enabledIn", "(I)Z");
+ if (_m_JsonParser_Feature__enabledIn == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result = (*jniEnv)->CallBooleanMethod(
+ jniEnv, self_, _m_JsonParser_Feature__enabledIn, flags);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonParser_Feature__getMask = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser_Feature__getMask(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser_Feature,
+ "com/fasterxml/jackson/core/JsonParser$Feature");
+ if (_c_JsonParser_Feature == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonParser_Feature, &_m_JsonParser_Feature__getMask, "getMask",
+ "()I");
+ if (_m_JsonParser_Feature__getMask == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_JsonParser_Feature__getMask);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+// com.fasterxml.jackson.core.JsonParser$NumberType
+jclass _c_JsonParser_NumberType = NULL;
+
+jmethodID _m_JsonParser_NumberType__values = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser_NumberType__values() {
+ load_env();
+ load_class_global_ref(&_c_JsonParser_NumberType,
+ "com/fasterxml/jackson/core/JsonParser$NumberType");
+ if (_c_JsonParser_NumberType == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_JsonParser_NumberType,
+ &_m_JsonParser_NumberType__values, "values",
+ "()[Lcom/fasterxml/jackson/core/JsonParser$NumberType;");
+ if (_m_JsonParser_NumberType__values == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_JsonParser_NumberType, _m_JsonParser_NumberType__values);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonParser_NumberType__valueOf = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonParser_NumberType__valueOf(jobject name) {
+ load_env();
+ load_class_global_ref(&_c_JsonParser_NumberType,
+ "com/fasterxml/jackson/core/JsonParser$NumberType");
+ if (_c_JsonParser_NumberType == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_JsonParser_NumberType, &_m_JsonParser_NumberType__valueOf, "valueOf",
+ "(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonParser$NumberType;");
+ if (_m_JsonParser_NumberType__valueOf == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_JsonParser_NumberType, _m_JsonParser_NumberType__valueOf,
+ name);
+ return to_global_ref_result(_result);
+}
+
+// com.fasterxml.jackson.core.JsonToken
+jclass _c_JsonToken = NULL;
+
+jmethodID _m_JsonToken__values = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonToken__values() {
+ load_env();
+ load_class_global_ref(&_c_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+ if (_c_JsonToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_JsonToken, &_m_JsonToken__values, "values",
+ "()[Lcom/fasterxml/jackson/core/JsonToken;");
+ if (_m_JsonToken__values == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_JsonToken,
+ _m_JsonToken__values);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonToken__valueOf = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonToken__valueOf(jobject name) {
+ load_env();
+ load_class_global_ref(&_c_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+ if (_c_JsonToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_JsonToken, &_m_JsonToken__valueOf, "valueOf",
+ "(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonToken;");
+ if (_m_JsonToken__valueOf == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_JsonToken, _m_JsonToken__valueOf, name);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonToken__id = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonToken__id(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+ if (_c_JsonToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonToken, &_m_JsonToken__id, "id", "()I");
+ if (_m_JsonToken__id == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_JsonToken__id);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonToken__asString = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonToken__asString(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+ if (_c_JsonToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonToken, &_m_JsonToken__asString, "asString",
+ "()Ljava/lang/String;");
+ if (_m_JsonToken__asString == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonToken__asString);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonToken__asCharArray = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonToken__asCharArray(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+ if (_c_JsonToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonToken, &_m_JsonToken__asCharArray, "asCharArray", "()[C");
+ if (_m_JsonToken__asCharArray == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonToken__asCharArray);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonToken__asByteArray = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonToken__asByteArray(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+ if (_c_JsonToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonToken, &_m_JsonToken__asByteArray, "asByteArray", "()[B");
+ if (_m_JsonToken__asByteArray == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_JsonToken__asByteArray);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonToken__isNumeric = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonToken__isNumeric(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+ if (_c_JsonToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonToken, &_m_JsonToken__isNumeric, "isNumeric", "()Z");
+ if (_m_JsonToken__isNumeric == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result =
+ (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_JsonToken__isNumeric);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonToken__isStructStart = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonToken__isStructStart(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+ if (_c_JsonToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonToken, &_m_JsonToken__isStructStart, "isStructStart",
+ "()Z");
+ if (_m_JsonToken__isStructStart == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result =
+ (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_JsonToken__isStructStart);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonToken__isStructEnd = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonToken__isStructEnd(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+ if (_c_JsonToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonToken, &_m_JsonToken__isStructEnd, "isStructEnd", "()Z");
+ if (_m_JsonToken__isStructEnd == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result =
+ (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_JsonToken__isStructEnd);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonToken__isScalarValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonToken__isScalarValue(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+ if (_c_JsonToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonToken, &_m_JsonToken__isScalarValue, "isScalarValue",
+ "()Z");
+ if (_m_JsonToken__isScalarValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result =
+ (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_JsonToken__isScalarValue);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_JsonToken__isBoolean = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonToken__isBoolean(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_JsonToken, "com/fasterxml/jackson/core/JsonToken");
+ if (_c_JsonToken == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_JsonToken, &_m_JsonToken__isBoolean, "isBoolean", "()Z");
+ if (_m_JsonToken__isBoolean == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result =
+ (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_JsonToken__isBoolean);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/_init.dart b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/_init.dart
new file mode 100644
index 0000000..8018e7d
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/_init.dart
@@ -0,0 +1,24 @@
+// Generated from jackson-core which is licensed under the Apache License 2.0.
+// The following copyright from the original authors applies.
+// See https://github.com/FasterXML/jackson-core/blob/2.14/LICENSE
+//
+// Copyright (c) 2007 - The Jackson Project Authors
+// Licensed under the Apache License, Version 2.0 (the "License")
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+
+// Auto-generated initialization code.
+
+final ffi.Pointer<T> Function<T extends ffi.NativeType>(String sym) jniLookup =
+ ProtectedJniExtensions.initGeneratedLibrary("jackson_core");
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonFactory.dart b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonFactory.dart
new file mode 100644
index 0000000..822a052
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonFactory.dart
@@ -0,0 +1,1997 @@
+// Generated from jackson-core which is licensed under the Apache License 2.0.
+// The following copyright from the original authors applies.
+// See https://github.com/FasterXML/jackson-core/blob/2.14/LICENSE
+//
+// Copyright (c) 2007 - The Jackson Project Authors
+// Licensed under the Apache License, Version 2.0 (the "License")
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+// ignore_for_file: annotate_overrides
+// ignore_for_file: camel_case_extensions
+// ignore_for_file: camel_case_types
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: doc_directive_unknown
+// ignore_for_file: file_names
+// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: overridden_fields
+// ignore_for_file: unnecessary_cast
+// ignore_for_file: unused_element
+// ignore_for_file: unused_field
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: unused_shown_name
+
+import "dart:isolate" show ReceivePort;
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+import "package:jni/jni.dart" as jni;
+
+import "JsonParser.dart" as jsonparser_;
+import "../../../../_init.dart";
+
+/// from: com.fasterxml.jackson.core.JsonFactory
+///
+/// The main factory class of Jackson package, used to configure and
+/// construct reader (aka parser, JsonParser)
+/// and writer (aka generator, JsonGenerator)
+/// instances.
+///
+/// Factory instances are thread-safe and reusable after configuration
+/// (if any). Typically applications and services use only a single
+/// globally shared factory instance, unless they need differently
+/// configured factories. Factory reuse is important if efficiency matters;
+/// most recycling of expensive construct is done on per-factory basis.
+///
+/// Creation of a factory instance is a light-weight operation,
+/// and since there is no need for pluggable alternative implementations
+/// (as there is no "standard" JSON processor API to implement),
+/// the default constructor is used for constructing factory
+/// instances.
+///@author Tatu Saloranta
+class JsonFactory extends jni.JObject {
+ @override
+ late final jni.JObjType<JsonFactory> $type = type;
+
+ JsonFactory.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $JsonFactoryType();
+
+ /// from: static public final java.lang.String FORMAT_NAME_JSON
+ ///
+ /// Name used to identify JSON format
+ /// (and returned by \#getFormatName()
+ static const FORMAT_NAME_JSON = r"""JSON""";
+
+ static final _get_DEFAULT_FACTORY_FEATURE_FLAGS =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_JsonFactory__DEFAULT_FACTORY_FEATURE_FLAGS")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static protected final int DEFAULT_FACTORY_FEATURE_FLAGS
+ ///
+ /// Bitfield (set of flags) of all factory features that are enabled by default.
+ static int get DEFAULT_FACTORY_FEATURE_FLAGS =>
+ _get_DEFAULT_FACTORY_FEATURE_FLAGS().integer;
+
+ static final _get_DEFAULT_PARSER_FEATURE_FLAGS =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_JsonFactory__DEFAULT_PARSER_FEATURE_FLAGS")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static protected final int DEFAULT_PARSER_FEATURE_FLAGS
+ ///
+ /// Bitfield (set of flags) of all parser features that are enabled
+ /// by default.
+ static int get DEFAULT_PARSER_FEATURE_FLAGS =>
+ _get_DEFAULT_PARSER_FEATURE_FLAGS().integer;
+
+ static final _get_DEFAULT_GENERATOR_FEATURE_FLAGS =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_JsonFactory__DEFAULT_GENERATOR_FEATURE_FLAGS")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static protected final int DEFAULT_GENERATOR_FEATURE_FLAGS
+ ///
+ /// Bitfield (set of flags) of all generator features that are enabled
+ /// by default.
+ static int get DEFAULT_GENERATOR_FEATURE_FLAGS =>
+ _get_DEFAULT_GENERATOR_FEATURE_FLAGS().integer;
+
+ static final _get_DEFAULT_ROOT_VALUE_SEPARATOR =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_JsonFactory__DEFAULT_ROOT_VALUE_SEPARATOR")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final com.fasterxml.jackson.core.SerializableString DEFAULT_ROOT_VALUE_SEPARATOR
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JObject get DEFAULT_ROOT_VALUE_SEPARATOR => const jni.JObjectType()
+ .fromRef(_get_DEFAULT_ROOT_VALUE_SEPARATOR().object);
+
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "JsonFactory__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Default constructor used to create factory instances.
+ /// Creation of a factory instance is a light-weight operation,
+ /// but it is still a good idea to reuse limited number of
+ /// factory instances (and quite often just a single instance):
+ /// factories are used as context for storing some reused
+ /// processing objects (such as symbol tables parsers use)
+ /// and this reuse only works within context of a single
+ /// factory instance.
+ factory JsonFactory() {
+ return JsonFactory.fromRef(_new0().object);
+ }
+
+ static final _new1 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__new1")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(com.fasterxml.jackson.core.ObjectCodec oc)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory JsonFactory.new1(
+ jni.JObject oc,
+ ) {
+ return JsonFactory.fromRef(_new1(oc.reference).object);
+ }
+
+ static final _new2 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__new2")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void <init>(com.fasterxml.jackson.core.JsonFactory src, com.fasterxml.jackson.core.ObjectCodec codec)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Constructor used when copy()ing a factory instance.
+ ///@param src Original factory to copy settings from
+ ///@param codec Databinding-level codec to use, if any
+ ///@since 2.2.1
+ factory JsonFactory.new2(
+ JsonFactory src,
+ jni.JObject codec,
+ ) {
+ return JsonFactory.fromRef(_new2(src.reference, codec.reference).object);
+ }
+
+ static final _new3 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__new3")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(com.fasterxml.jackson.core.JsonFactoryBuilder b)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Constructor used by JsonFactoryBuilder for instantiation.
+ ///@param b Builder that contains settings to use
+ ///@since 2.10
+ factory JsonFactory.new3(
+ jni.JObject b,
+ ) {
+ return JsonFactory.fromRef(_new3(b.reference).object);
+ }
+
+ static final _new4 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Uint8)>>("JsonFactory__new4")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: protected void <init>(com.fasterxml.jackson.core.TSFBuilder<?,?> b, boolean bogus)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Constructor for subtypes; needed to work around the fact that before 3.0,
+ /// this factory has cumbersome dual role as generic type as well as actual
+ /// implementation for json.
+ ///@param b Builder that contains settings to use
+ ///@param bogus Argument only needed to separate constructor signature; ignored
+ factory JsonFactory.new4(
+ jni.JObject b,
+ bool bogus,
+ ) {
+ return JsonFactory.fromRef(_new4(b.reference, bogus ? 1 : 0).object);
+ }
+
+ static final _rebuild = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__rebuild")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.TSFBuilder<?,?> rebuild()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that allows construction of differently configured factory, starting
+ /// with settings of this factory.
+ ///@return Builder instance to use
+ ///@since 2.10
+ jni.JObject rebuild() {
+ return const jni.JObjectType().fromRef(_rebuild(reference).object);
+ }
+
+ static final _builder =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "JsonFactory__builder")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public com.fasterxml.jackson.core.TSFBuilder<?,?> builder()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Main factory method to use for constructing JsonFactory instances with
+ /// different configuration: creates and returns a builder for collecting configuration
+ /// settings; instance created by calling {@code build()} after all configuration
+ /// set.
+ ///
+ /// NOTE: signature unfortunately does not expose true implementation type; this
+ /// will be fixed in 3.0.
+ ///@return Builder instance to use
+ static jni.JObject builder() {
+ return const jni.JObjectType().fromRef(_builder().object);
+ }
+
+ static final _copy = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__copy")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory copy()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing a new JsonFactory that has
+ /// the same settings as this instance, but is otherwise
+ /// independent (i.e. nothing is actually shared, symbol tables
+ /// are separate).
+ /// Note that ObjectCodec reference is not copied but is
+ /// set to null; caller typically needs to set it after calling
+ /// this method. Reason for this is that the codec is used for
+ /// callbacks, and assumption is that there is strict 1-to-1
+ /// mapping between codec, factory. Caller has to, then, explicitly
+ /// set codec after making the copy.
+ ///@return Copy of this factory instance
+ ///@since 2.1
+ JsonFactory copy() {
+ return const $JsonFactoryType().fromRef(_copy(reference).object);
+ }
+
+ static final _readResolve = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__readResolve")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected java.lang.Object readResolve()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that we need to override to actually make restoration go
+ /// through constructors etc: needed to allow JDK serializability of
+ /// factory instances.
+ ///
+ /// Note: must be overridden by sub-classes as well.
+ ///@return Newly constructed instance
+ jni.JObject readResolve() {
+ return const jni.JObjectType().fromRef(_readResolve(reference).object);
+ }
+
+ static final _requiresPropertyOrdering = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__requiresPropertyOrdering")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean requiresPropertyOrdering()
+ ///
+ /// Introspection method that higher-level functionality may call
+ /// to see whether underlying data format requires a stable ordering
+ /// of object properties or not.
+ /// This is usually used for determining
+ /// whether to force a stable ordering (like alphabetic ordering by name)
+ /// if no ordering if explicitly specified.
+ ///
+ /// Default implementation returns <code>false</code> as JSON does NOT
+ /// require stable ordering. Formats that require ordering include positional
+ /// textual formats like <code>CSV</code>, and schema-based binary formats
+ /// like <code>Avro</code>.
+ ///@return Whether format supported by this factory
+ /// requires Object properties to be ordered.
+ ///@since 2.3
+ bool requiresPropertyOrdering() {
+ return _requiresPropertyOrdering(reference).boolean;
+ }
+
+ static final _canHandleBinaryNatively = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__canHandleBinaryNatively")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean canHandleBinaryNatively()
+ ///
+ /// Introspection method that higher-level functionality may call
+ /// to see whether underlying data format can read and write binary
+ /// data natively; that is, embeded it as-is without using encodings
+ /// such as Base64.
+ ///
+ /// Default implementation returns <code>false</code> as JSON does not
+ /// support native access: all binary content must use Base64 encoding.
+ /// Most binary formats (like Smile and Avro) support native binary content.
+ ///@return Whether format supported by this factory
+ /// supports native binary content
+ ///@since 2.3
+ bool canHandleBinaryNatively() {
+ return _canHandleBinaryNatively(reference).boolean;
+ }
+
+ static final _canUseCharArrays = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__canUseCharArrays")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean canUseCharArrays()
+ ///
+ /// Introspection method that can be used by base factory to check
+ /// whether access using <code>char[]</code> is something that actual
+ /// parser implementations can take advantage of, over having to
+ /// use java.io.Reader. Sub-types are expected to override
+ /// definition; default implementation (suitable for JSON) alleges
+ /// that optimization are possible; and thereby is likely to try
+ /// to access java.lang.String content by first copying it into
+ /// recyclable intermediate buffer.
+ ///@return Whether access to decoded textual content can be efficiently
+ /// accessed using parser method {@code getTextCharacters()}.
+ ///@since 2.4
+ bool canUseCharArrays() {
+ return _canUseCharArrays(reference).boolean;
+ }
+
+ static final _canParseAsync = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__canParseAsync")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean canParseAsync()
+ ///
+ /// Introspection method that can be used to check whether this
+ /// factory can create non-blocking parsers: parsers that do not
+ /// use blocking I/O abstractions but instead use a
+ /// com.fasterxml.jackson.core.async.NonBlockingInputFeeder.
+ ///@return Whether this factory supports non-blocking ("async") parsing or
+ /// not (and consequently whether {@code createNonBlockingXxx()} method(s) work)
+ ///@since 2.9
+ bool canParseAsync() {
+ return _canParseAsync(reference).boolean;
+ }
+
+ static final _getFormatReadFeatureType = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__getFormatReadFeatureType")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.Class<? extends com.fasterxml.jackson.core.FormatFeature> getFormatReadFeatureType()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject getFormatReadFeatureType() {
+ return const jni.JObjectType()
+ .fromRef(_getFormatReadFeatureType(reference).object);
+ }
+
+ static final _getFormatWriteFeatureType = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__getFormatWriteFeatureType")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.Class<? extends com.fasterxml.jackson.core.FormatFeature> getFormatWriteFeatureType()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject getFormatWriteFeatureType() {
+ return const jni.JObjectType()
+ .fromRef(_getFormatWriteFeatureType(reference).object);
+ }
+
+ static final _canUseSchema = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__canUseSchema")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean canUseSchema(com.fasterxml.jackson.core.FormatSchema schema)
+ ///
+ /// Method that can be used to quickly check whether given schema
+ /// is something that parsers and/or generators constructed by this
+ /// factory could use. Note that this means possible use, at the level
+ /// of data format (i.e. schema is for same data format as parsers and
+ /// generators this factory constructs); individual schema instances
+ /// may have further usage restrictions.
+ ///@param schema Schema instance to check
+ ///@return Whether parsers and generators constructed by this factory
+ /// can use specified format schema instance
+ bool canUseSchema(
+ jni.JObject schema,
+ ) {
+ return _canUseSchema(reference, schema.reference).boolean;
+ }
+
+ static final _getFormatName = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__getFormatName")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getFormatName()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that returns short textual id identifying format
+ /// this factory supports.
+ ///
+ /// Note: sub-classes should override this method; default
+ /// implementation will return null for all sub-classes
+ ///@return Name of the format handled by parsers, generators this factory creates
+ jni.JString getFormatName() {
+ return const jni.JStringType().fromRef(_getFormatName(reference).object);
+ }
+
+ static final _hasFormat = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__hasFormat")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.format.MatchStrength hasFormat(com.fasterxml.jackson.core.format.InputAccessor acc)
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject hasFormat(
+ jni.JObject acc,
+ ) {
+ return const jni.JObjectType()
+ .fromRef(_hasFormat(reference, acc.reference).object);
+ }
+
+ static final _requiresCustomCodec = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__requiresCustomCodec")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean requiresCustomCodec()
+ ///
+ /// Method that can be called to determine if a custom
+ /// ObjectCodec is needed for binding data parsed
+ /// using JsonParser constructed by this factory
+ /// (which typically also implies the same for serialization
+ /// with JsonGenerator).
+ ///@return True if custom codec is needed with parsers and
+ /// generators created by this factory; false if a general
+ /// ObjectCodec is enough
+ ///@since 2.1
+ bool requiresCustomCodec() {
+ return _requiresCustomCodec(reference).boolean;
+ }
+
+ static final _hasJSONFormat = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__hasJSONFormat")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected com.fasterxml.jackson.core.format.MatchStrength hasJSONFormat(com.fasterxml.jackson.core.format.InputAccessor acc)
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject hasJSONFormat(
+ jni.JObject acc,
+ ) {
+ return const jni.JObjectType()
+ .fromRef(_hasJSONFormat(reference, acc.reference).object);
+ }
+
+ static final _version = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__version")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.Version version()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject version() {
+ return const jni.JObjectType().fromRef(_version(reference).object);
+ }
+
+ static final _configure = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Uint8)>>("JsonFactory__configure")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public final com.fasterxml.jackson.core.JsonFactory configure(com.fasterxml.jackson.core.JsonFactory.Feature f, boolean state)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for enabling or disabling specified parser feature
+ /// (check JsonParser.Feature for list of features)
+ ///@param f Feature to enable/disable
+ ///@param state Whether to enable or disable the feature
+ ///@return This factory instance (to allow call chaining)
+ ///@deprecated since 2.10 use JsonFactoryBuilder\#configure(JsonFactory.Feature, boolean) instead
+ JsonFactory configure(
+ JsonFactory_Feature f,
+ bool state,
+ ) {
+ return const $JsonFactoryType()
+ .fromRef(_configure(reference, f.reference, state ? 1 : 0).object);
+ }
+
+ static final _enable = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__enable")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory enable(com.fasterxml.jackson.core.JsonFactory.Feature f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for enabling specified parser feature
+ /// (check JsonFactory.Feature for list of features)
+ ///@param f Feature to enable
+ ///@return This factory instance (to allow call chaining)
+ ///@deprecated since 2.10 use JsonFactoryBuilder\#configure(JsonFactory.Feature, boolean) instead
+ JsonFactory enable(
+ JsonFactory_Feature f,
+ ) {
+ return const $JsonFactoryType()
+ .fromRef(_enable(reference, f.reference).object);
+ }
+
+ static final _disable = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__disable")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory disable(com.fasterxml.jackson.core.JsonFactory.Feature f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for disabling specified parser features
+ /// (check JsonFactory.Feature for list of features)
+ ///@param f Feature to disable
+ ///@return This factory instance (to allow call chaining)
+ ///@deprecated since 2.10 use JsonFactoryBuilder\#configure(JsonFactory.Feature, boolean) instead
+ JsonFactory disable(
+ JsonFactory_Feature f,
+ ) {
+ return const $JsonFactoryType()
+ .fromRef(_disable(reference, f.reference).object);
+ }
+
+ static final _isEnabled = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__isEnabled")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final boolean isEnabled(com.fasterxml.jackson.core.JsonFactory.Feature f)
+ ///
+ /// Checked whether specified parser feature is enabled.
+ ///@param f Feature to check
+ ///@return True if the specified feature is enabled
+ bool isEnabled(
+ JsonFactory_Feature f,
+ ) {
+ return _isEnabled(reference, f.reference).boolean;
+ }
+
+ static final _getParserFeatures = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__getParserFeatures")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final int getParserFeatures()
+ int getParserFeatures() {
+ return _getParserFeatures(reference).integer;
+ }
+
+ static final _getGeneratorFeatures = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__getGeneratorFeatures")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final int getGeneratorFeatures()
+ int getGeneratorFeatures() {
+ return _getGeneratorFeatures(reference).integer;
+ }
+
+ static final _getFormatParserFeatures = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__getFormatParserFeatures")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int getFormatParserFeatures()
+ int getFormatParserFeatures() {
+ return _getFormatParserFeatures(reference).integer;
+ }
+
+ static final _getFormatGeneratorFeatures = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__getFormatGeneratorFeatures")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int getFormatGeneratorFeatures()
+ int getFormatGeneratorFeatures() {
+ return _getFormatGeneratorFeatures(reference).integer;
+ }
+
+ static final _configure1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Uint8)>>("JsonFactory__configure1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public final com.fasterxml.jackson.core.JsonFactory configure(com.fasterxml.jackson.core.JsonParser.Feature f, boolean state)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for enabling or disabling specified parser feature
+ /// (check JsonParser.Feature for list of features)
+ ///@param f Feature to enable/disable
+ ///@param state Whether to enable or disable the feature
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory configure1(
+ jsonparser_.JsonParser_Feature f,
+ bool state,
+ ) {
+ return const $JsonFactoryType()
+ .fromRef(_configure1(reference, f.reference, state ? 1 : 0).object);
+ }
+
+ static final _enable1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__enable1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory enable(com.fasterxml.jackson.core.JsonParser.Feature f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for enabling specified parser feature
+ /// (check JsonParser.Feature for list of features)
+ ///@param f Feature to enable
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory enable1(
+ jsonparser_.JsonParser_Feature f,
+ ) {
+ return const $JsonFactoryType()
+ .fromRef(_enable1(reference, f.reference).object);
+ }
+
+ static final _disable1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__disable1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory disable(com.fasterxml.jackson.core.JsonParser.Feature f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for disabling specified parser features
+ /// (check JsonParser.Feature for list of features)
+ ///@param f Feature to disable
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory disable1(
+ jsonparser_.JsonParser_Feature f,
+ ) {
+ return const $JsonFactoryType()
+ .fromRef(_disable1(reference, f.reference).object);
+ }
+
+ static final _isEnabled1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__isEnabled1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final boolean isEnabled(com.fasterxml.jackson.core.JsonParser.Feature f)
+ ///
+ /// Method for checking if the specified parser feature is enabled.
+ ///@param f Feature to check
+ ///@return True if specified feature is enabled
+ bool isEnabled1(
+ jsonparser_.JsonParser_Feature f,
+ ) {
+ return _isEnabled1(reference, f.reference).boolean;
+ }
+
+ static final _isEnabled2 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__isEnabled2")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final boolean isEnabled(com.fasterxml.jackson.core.StreamReadFeature f)
+ ///
+ /// Method for checking if the specified stream read feature is enabled.
+ ///@param f Feature to check
+ ///@return True if specified feature is enabled
+ ///@since 2.10
+ bool isEnabled2(
+ jni.JObject f,
+ ) {
+ return _isEnabled2(reference, f.reference).boolean;
+ }
+
+ static final _getInputDecorator = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__getInputDecorator")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.io.InputDecorator getInputDecorator()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for getting currently configured input decorator (if any;
+ /// there is no default decorator).
+ ///@return InputDecorator configured, if any
+ jni.JObject getInputDecorator() {
+ return const jni.JObjectType()
+ .fromRef(_getInputDecorator(reference).object);
+ }
+
+ static final _setInputDecorator = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__setInputDecorator")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory setInputDecorator(com.fasterxml.jackson.core.io.InputDecorator d)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for overriding currently configured input decorator
+ ///@param d Decorator to configure for this factory, if any ({@code null} if none)
+ ///@return This factory instance (to allow call chaining)
+ ///@deprecated Since 2.10 use JsonFactoryBuilder\#inputDecorator(InputDecorator) instead
+ JsonFactory setInputDecorator(
+ jni.JObject d,
+ ) {
+ return const $JsonFactoryType()
+ .fromRef(_setInputDecorator(reference, d.reference).object);
+ }
+
+ static final _configure2 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Uint8)>>("JsonFactory__configure2")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public final com.fasterxml.jackson.core.JsonFactory configure(com.fasterxml.jackson.core.JsonGenerator.Feature f, boolean state)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for enabling or disabling specified generator feature
+ /// (check JsonGenerator.Feature for list of features)
+ ///@param f Feature to enable/disable
+ ///@param state Whether to enable or disable the feature
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory configure2(
+ jni.JObject f,
+ bool state,
+ ) {
+ return const $JsonFactoryType()
+ .fromRef(_configure2(reference, f.reference, state ? 1 : 0).object);
+ }
+
+ static final _enable2 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__enable2")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory enable(com.fasterxml.jackson.core.JsonGenerator.Feature f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for enabling specified generator features
+ /// (check JsonGenerator.Feature for list of features)
+ ///@param f Feature to enable
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory enable2(
+ jni.JObject f,
+ ) {
+ return const $JsonFactoryType()
+ .fromRef(_enable2(reference, f.reference).object);
+ }
+
+ static final _disable2 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__disable2")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory disable(com.fasterxml.jackson.core.JsonGenerator.Feature f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for disabling specified generator feature
+ /// (check JsonGenerator.Feature for list of features)
+ ///@param f Feature to disable
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory disable2(
+ jni.JObject f,
+ ) {
+ return const $JsonFactoryType()
+ .fromRef(_disable2(reference, f.reference).object);
+ }
+
+ static final _isEnabled3 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__isEnabled3")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final boolean isEnabled(com.fasterxml.jackson.core.JsonGenerator.Feature f)
+ ///
+ /// Check whether specified generator feature is enabled.
+ ///@param f Feature to check
+ ///@return Whether specified feature is enabled
+ bool isEnabled3(
+ jni.JObject f,
+ ) {
+ return _isEnabled3(reference, f.reference).boolean;
+ }
+
+ static final _isEnabled4 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__isEnabled4")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final boolean isEnabled(com.fasterxml.jackson.core.StreamWriteFeature f)
+ ///
+ /// Check whether specified stream write feature is enabled.
+ ///@param f Feature to check
+ ///@return Whether specified feature is enabled
+ ///@since 2.10
+ bool isEnabled4(
+ jni.JObject f,
+ ) {
+ return _isEnabled4(reference, f.reference).boolean;
+ }
+
+ static final _getCharacterEscapes = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__getCharacterEscapes")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.io.CharacterEscapes getCharacterEscapes()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for accessing custom escapes factory uses for JsonGenerators
+ /// it creates.
+ ///@return Configured {@code CharacterEscapes}, if any; {@code null} if none
+ jni.JObject getCharacterEscapes() {
+ return const jni.JObjectType()
+ .fromRef(_getCharacterEscapes(reference).object);
+ }
+
+ static final _setCharacterEscapes = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__setCharacterEscapes")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory setCharacterEscapes(com.fasterxml.jackson.core.io.CharacterEscapes esc)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for defining custom escapes factory uses for JsonGenerators
+ /// it creates.
+ ///@param esc CharaterEscapes to set (or {@code null} for "none")
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory setCharacterEscapes(
+ jni.JObject esc,
+ ) {
+ return const $JsonFactoryType()
+ .fromRef(_setCharacterEscapes(reference, esc.reference).object);
+ }
+
+ static final _getOutputDecorator = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__getOutputDecorator")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.io.OutputDecorator getOutputDecorator()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for getting currently configured output decorator (if any;
+ /// there is no default decorator).
+ ///@return OutputDecorator configured for generators factory creates, if any;
+ /// {@code null} if none.
+ jni.JObject getOutputDecorator() {
+ return const jni.JObjectType()
+ .fromRef(_getOutputDecorator(reference).object);
+ }
+
+ static final _setOutputDecorator = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__setOutputDecorator")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory setOutputDecorator(com.fasterxml.jackson.core.io.OutputDecorator d)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for overriding currently configured output decorator
+ ///@return This factory instance (to allow call chaining)
+ ///@param d Output decorator to use, if any
+ ///@deprecated Since 2.10 use JsonFactoryBuilder\#outputDecorator(OutputDecorator) instead
+ JsonFactory setOutputDecorator(
+ jni.JObject d,
+ ) {
+ return const $JsonFactoryType()
+ .fromRef(_setOutputDecorator(reference, d.reference).object);
+ }
+
+ static final _setRootValueSeparator = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__setRootValueSeparator")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory setRootValueSeparator(java.lang.String sep)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that allows overriding String used for separating root-level
+ /// JSON values (default is single space character)
+ ///@param sep Separator to use, if any; null means that no separator is
+ /// automatically added
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory setRootValueSeparator(
+ jni.JString sep,
+ ) {
+ return const $JsonFactoryType()
+ .fromRef(_setRootValueSeparator(reference, sep.reference).object);
+ }
+
+ static final _getRootValueSeparator = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__getRootValueSeparator")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getRootValueSeparator()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// @return Root value separator configured, if any
+ jni.JString getRootValueSeparator() {
+ return const jni.JStringType()
+ .fromRef(_getRootValueSeparator(reference).object);
+ }
+
+ static final _setCodec = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__setCodec")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory setCodec(com.fasterxml.jackson.core.ObjectCodec oc)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for associating a ObjectCodec (typically
+ /// a <code>com.fasterxml.jackson.databind.ObjectMapper</code>)
+ /// with this factory (and more importantly, parsers and generators
+ /// it constructs). This is needed to use data-binding methods
+ /// of JsonParser and JsonGenerator instances.
+ ///@param oc Codec to use
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory setCodec(
+ jni.JObject oc,
+ ) {
+ return const $JsonFactoryType()
+ .fromRef(_setCodec(reference, oc.reference).object);
+ }
+
+ static final _getCodec = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__getCodec")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.ObjectCodec getCodec()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject getCodec() {
+ return const jni.JObjectType().fromRef(_getCodec(reference).object);
+ }
+
+ static final _createParser = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createParser")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.io.File f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON parser instance to parse
+ /// contents of specified file.
+ ///
+ ///
+ /// Encoding is auto-detected from contents according to JSON
+ /// specification recommended mechanism. Json specification
+ /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
+ /// so auto-detection implemented only for this charsets.
+ /// For other charsets use \#createParser(java.io.Reader).
+ ///
+ ///
+ /// Underlying input stream (needed for reading contents)
+ /// will be __owned__ (and managed, i.e. closed as need be) by
+ /// the parser, since caller has no access to it.
+ ///@param f File that contains JSON content to parse
+ ///@since 2.1
+ jsonparser_.JsonParser createParser(
+ jni.JObject f,
+ ) {
+ return const jsonparser_.$JsonParserType()
+ .fromRef(_createParser(reference, f.reference).object);
+ }
+
+ static final _createParser1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createParser1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.net.URL url)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON parser instance to parse
+ /// contents of resource reference by given URL.
+ ///
+ /// Encoding is auto-detected from contents according to JSON
+ /// specification recommended mechanism. Json specification
+ /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
+ /// so auto-detection implemented only for this charsets.
+ /// For other charsets use \#createParser(java.io.Reader).
+ ///
+ /// Underlying input stream (needed for reading contents)
+ /// will be __owned__ (and managed, i.e. closed as need be) by
+ /// the parser, since caller has no access to it.
+ ///@param url URL pointing to resource that contains JSON content to parse
+ ///@since 2.1
+ jsonparser_.JsonParser createParser1(
+ jni.JObject url,
+ ) {
+ return const jsonparser_.$JsonParserType()
+ .fromRef(_createParser1(reference, url.reference).object);
+ }
+
+ static final _createParser2 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createParser2")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.io.InputStream in)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON parser instance to parse
+ /// the contents accessed via specified input stream.
+ ///
+ /// The input stream will __not be owned__ by
+ /// the parser, it will still be managed (i.e. closed if
+ /// end-of-stream is reacher, or parser close method called)
+ /// if (and only if) com.fasterxml.jackson.core.StreamReadFeature\#AUTO_CLOSE_SOURCE
+ /// is enabled.
+ ///
+ ///
+ /// Note: no encoding argument is taken since it can always be
+ /// auto-detected as suggested by JSON RFC. Json specification
+ /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
+ /// so auto-detection implemented only for this charsets.
+ /// For other charsets use \#createParser(java.io.Reader).
+ ///@param in InputStream to use for reading JSON content to parse
+ ///@since 2.1
+ jsonparser_.JsonParser createParser2(
+ jni.JObject in0,
+ ) {
+ return const jsonparser_.$JsonParserType()
+ .fromRef(_createParser2(reference, in0.reference).object);
+ }
+
+ static final _createParser3 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createParser3")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.io.Reader r)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing
+ /// the contents accessed via specified Reader.
+ ///
+ /// The read stream will __not be owned__ by
+ /// the parser, it will still be managed (i.e. closed if
+ /// end-of-stream is reacher, or parser close method called)
+ /// if (and only if) com.fasterxml.jackson.core.StreamReadFeature\#AUTO_CLOSE_SOURCE
+ /// is enabled.
+ ///@param r Reader to use for reading JSON content to parse
+ ///@since 2.1
+ jsonparser_.JsonParser createParser3(
+ jni.JObject r,
+ ) {
+ return const jsonparser_.$JsonParserType()
+ .fromRef(_createParser3(reference, r.reference).object);
+ }
+
+ static final _createParser4 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createParser4")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(byte[] data)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing
+ /// the contents of given byte array.
+ ///@since 2.1
+ jsonparser_.JsonParser createParser4(
+ jni.JArray<jni.jbyte> data,
+ ) {
+ return const jsonparser_.$JsonParserType()
+ .fromRef(_createParser4(reference, data.reference).object);
+ }
+
+ static final _createParser5 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32,
+ ffi.Int32)>>("JsonFactory__createParser5")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int, int)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(byte[] data, int offset, int len)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing
+ /// the contents of given byte array.
+ ///@param data Buffer that contains data to parse
+ ///@param offset Offset of the first data byte within buffer
+ ///@param len Length of contents to parse within buffer
+ ///@since 2.1
+ jsonparser_.JsonParser createParser5(
+ jni.JArray<jni.jbyte> data,
+ int offset,
+ int len,
+ ) {
+ return const jsonparser_.$JsonParserType()
+ .fromRef(_createParser5(reference, data.reference, offset, len).object);
+ }
+
+ static final _createParser6 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createParser6")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.lang.String content)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing
+ /// contents of given String.
+ ///@since 2.1
+ jsonparser_.JsonParser createParser6(
+ jni.JString content,
+ ) {
+ return const jsonparser_.$JsonParserType()
+ .fromRef(_createParser6(reference, content.reference).object);
+ }
+
+ static final _createParser7 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createParser7")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(char[] content)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing
+ /// contents of given char array.
+ ///@since 2.4
+ jsonparser_.JsonParser createParser7(
+ jni.JArray<jni.jchar> content,
+ ) {
+ return const jsonparser_.$JsonParserType()
+ .fromRef(_createParser7(reference, content.reference).object);
+ }
+
+ static final _createParser8 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32,
+ ffi.Int32)>>("JsonFactory__createParser8")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int, int)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(char[] content, int offset, int len)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing contents of given char array.
+ ///@since 2.4
+ jsonparser_.JsonParser createParser8(
+ jni.JArray<jni.jchar> content,
+ int offset,
+ int len,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(
+ _createParser8(reference, content.reference, offset, len).object);
+ }
+
+ static final _createParser9 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createParser9")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.io.DataInput in)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Optional method for constructing parser for reading contents from specified DataInput
+ /// instance.
+ ///
+ /// If this factory does not support DataInput as source,
+ /// will throw UnsupportedOperationException
+ ///@since 2.8
+ jsonparser_.JsonParser createParser9(
+ jni.JObject in0,
+ ) {
+ return const jsonparser_.$JsonParserType()
+ .fromRef(_createParser9(reference, in0.reference).object);
+ }
+
+ static final _createNonBlockingByteArrayParser = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory__createNonBlockingByteArrayParser")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createNonBlockingByteArrayParser()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Optional method for constructing parser for non-blocking parsing
+ /// via com.fasterxml.jackson.core.async.ByteArrayFeeder
+ /// interface (accessed using JsonParser\#getNonBlockingInputFeeder()
+ /// from constructed instance).
+ ///
+ /// If this factory does not support non-blocking parsing (either at all,
+ /// or from byte array),
+ /// will throw UnsupportedOperationException.
+ ///
+ /// Note that JSON-backed factory only supports parsing of UTF-8 encoded JSON content
+ /// (and US-ASCII since it is proper subset); other encodings are not supported
+ /// at this point.
+ ///@since 2.9
+ jsonparser_.JsonParser createNonBlockingByteArrayParser() {
+ return const jsonparser_.$JsonParserType()
+ .fromRef(_createNonBlockingByteArrayParser(reference).object);
+ }
+
+ static final _createGenerator = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createGenerator")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.OutputStream out, com.fasterxml.jackson.core.JsonEncoding enc)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON generator for writing JSON content
+ /// using specified output stream.
+ /// Encoding to use must be specified, and needs to be one of available
+ /// types (as per JSON specification).
+ ///
+ /// Underlying stream __is NOT owned__ by the generator constructed,
+ /// so that generator will NOT close the output stream when
+ /// JsonGenerator\#close is called (unless auto-closing
+ /// feature,
+ /// com.fasterxml.jackson.core.JsonGenerator.Feature\#AUTO_CLOSE_TARGET
+ /// is enabled).
+ /// Using application needs to close it explicitly if this is the case.
+ ///
+ /// Note: there are formats that use fixed encoding (like most binary data formats)
+ /// and that ignore passed in encoding.
+ ///@param out OutputStream to use for writing JSON content
+ ///@param enc Character encoding to use
+ ///@since 2.1
+ jni.JObject createGenerator(
+ jni.JObject out,
+ jni.JObject enc,
+ ) {
+ return const jni.JObjectType().fromRef(
+ _createGenerator(reference, out.reference, enc.reference).object);
+ }
+
+ static final _createGenerator1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createGenerator1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.OutputStream out)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Convenience method for constructing generator that uses default
+ /// encoding of the format (UTF-8 for JSON and most other data formats).
+ ///
+ /// Note: there are formats that use fixed encoding (like most binary data formats).
+ ///@since 2.1
+ jni.JObject createGenerator1(
+ jni.JObject out,
+ ) {
+ return const jni.JObjectType()
+ .fromRef(_createGenerator1(reference, out.reference).object);
+ }
+
+ static final _createGenerator2 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createGenerator2")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.Writer w)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON generator for writing JSON content
+ /// using specified Writer.
+ ///
+ /// Underlying stream __is NOT owned__ by the generator constructed,
+ /// so that generator will NOT close the Reader when
+ /// JsonGenerator\#close is called (unless auto-closing
+ /// feature,
+ /// com.fasterxml.jackson.core.JsonGenerator.Feature\#AUTO_CLOSE_TARGET is enabled).
+ /// Using application needs to close it explicitly.
+ ///@since 2.1
+ ///@param w Writer to use for writing JSON content
+ jni.JObject createGenerator2(
+ jni.JObject w,
+ ) {
+ return const jni.JObjectType()
+ .fromRef(_createGenerator2(reference, w.reference).object);
+ }
+
+ static final _createGenerator3 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createGenerator3")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.File f, com.fasterxml.jackson.core.JsonEncoding enc)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON generator for writing JSON content
+ /// to specified file, overwriting contents it might have (or creating
+ /// it if such file does not yet exist).
+ /// Encoding to use must be specified, and needs to be one of available
+ /// types (as per JSON specification).
+ ///
+ /// Underlying stream __is owned__ by the generator constructed,
+ /// i.e. generator will handle closing of file when
+ /// JsonGenerator\#close is called.
+ ///@param f File to write contents to
+ ///@param enc Character encoding to use
+ ///@since 2.1
+ jni.JObject createGenerator3(
+ jni.JObject f,
+ jni.JObject enc,
+ ) {
+ return const jni.JObjectType().fromRef(
+ _createGenerator3(reference, f.reference, enc.reference).object);
+ }
+
+ static final _createGenerator4 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createGenerator4")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.DataOutput out, com.fasterxml.jackson.core.JsonEncoding enc)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing generator for writing content using specified
+ /// DataOutput instance.
+ ///@since 2.8
+ jni.JObject createGenerator4(
+ jni.JObject out,
+ jni.JObject enc,
+ ) {
+ return const jni.JObjectType().fromRef(
+ _createGenerator4(reference, out.reference, enc.reference).object);
+ }
+
+ static final _createGenerator5 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createGenerator5")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.DataOutput out)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Convenience method for constructing generator that uses default
+ /// encoding of the format (UTF-8 for JSON and most other data formats).
+ ///
+ /// Note: there are formats that use fixed encoding (like most binary data formats).
+ ///@since 2.8
+ jni.JObject createGenerator5(
+ jni.JObject out,
+ ) {
+ return const jni.JObjectType()
+ .fromRef(_createGenerator5(reference, out.reference).object);
+ }
+
+ static final _createJsonParser = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonParser")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(java.io.File f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON parser instance to parse
+ /// contents of specified file.
+ ///
+ /// Encoding is auto-detected from contents according to JSON
+ /// specification recommended mechanism. Json specification
+ /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
+ /// so auto-detection implemented only for this charsets.
+ /// For other charsets use \#createParser(java.io.Reader).
+ ///
+ ///
+ /// Underlying input stream (needed for reading contents)
+ /// will be __owned__ (and managed, i.e. closed as need be) by
+ /// the parser, since caller has no access to it.
+ ///@param f File that contains JSON content to parse
+ ///@return Parser constructed
+ ///@throws IOException if parser initialization fails due to I/O (read) problem
+ ///@throws JsonParseException if parser initialization fails due to content decoding problem
+ ///@deprecated Since 2.2, use \#createParser(File) instead.
+ jsonparser_.JsonParser createJsonParser(
+ jni.JObject f,
+ ) {
+ return const jsonparser_.$JsonParserType()
+ .fromRef(_createJsonParser(reference, f.reference).object);
+ }
+
+ static final _createJsonParser1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonParser1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(java.net.URL url)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON parser instance to parse
+ /// contents of resource reference by given URL.
+ ///
+ /// Encoding is auto-detected from contents according to JSON
+ /// specification recommended mechanism. Json specification
+ /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
+ /// so auto-detection implemented only for this charsets.
+ /// For other charsets use \#createParser(java.io.Reader).
+ ///
+ /// Underlying input stream (needed for reading contents)
+ /// will be __owned__ (and managed, i.e. closed as need be) by
+ /// the parser, since caller has no access to it.
+ ///@param url URL pointing to resource that contains JSON content to parse
+ ///@return Parser constructed
+ ///@throws IOException if parser initialization fails due to I/O (read) problem
+ ///@throws JsonParseException if parser initialization fails due to content decoding problem
+ ///@deprecated Since 2.2, use \#createParser(URL) instead.
+ jsonparser_.JsonParser createJsonParser1(
+ jni.JObject url,
+ ) {
+ return const jsonparser_.$JsonParserType()
+ .fromRef(_createJsonParser1(reference, url.reference).object);
+ }
+
+ static final _createJsonParser2 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonParser2")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(java.io.InputStream in)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON parser instance to parse
+ /// the contents accessed via specified input stream.
+ ///
+ /// The input stream will __not be owned__ by
+ /// the parser, it will still be managed (i.e. closed if
+ /// end-of-stream is reacher, or parser close method called)
+ /// if (and only if) com.fasterxml.jackson.core.JsonParser.Feature\#AUTO_CLOSE_SOURCE
+ /// is enabled.
+ ///
+ ///
+ /// Note: no encoding argument is taken since it can always be
+ /// auto-detected as suggested by JSON RFC. Json specification
+ /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
+ /// so auto-detection implemented only for this charsets.
+ /// For other charsets use \#createParser(java.io.Reader).
+ ///@param in InputStream to use for reading JSON content to parse
+ ///@return Parser constructed
+ ///@throws IOException if parser initialization fails due to I/O (read) problem
+ ///@throws JsonParseException if parser initialization fails due to content decoding problem
+ ///@deprecated Since 2.2, use \#createParser(InputStream) instead.
+ jsonparser_.JsonParser createJsonParser2(
+ jni.JObject in0,
+ ) {
+ return const jsonparser_.$JsonParserType()
+ .fromRef(_createJsonParser2(reference, in0.reference).object);
+ }
+
+ static final _createJsonParser3 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonParser3")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(java.io.Reader r)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing
+ /// the contents accessed via specified Reader.
+ ///
+ /// The read stream will __not be owned__ by
+ /// the parser, it will still be managed (i.e. closed if
+ /// end-of-stream is reacher, or parser close method called)
+ /// if (and only if) com.fasterxml.jackson.core.JsonParser.Feature\#AUTO_CLOSE_SOURCE
+ /// is enabled.
+ ///@param r Reader to use for reading JSON content to parse
+ ///@return Parser constructed
+ ///@throws IOException if parser initialization fails due to I/O (read) problem
+ ///@throws JsonParseException if parser initialization fails due to content decoding problem
+ ///@deprecated Since 2.2, use \#createParser(Reader) instead.
+ jsonparser_.JsonParser createJsonParser3(
+ jni.JObject r,
+ ) {
+ return const jsonparser_.$JsonParserType()
+ .fromRef(_createJsonParser3(reference, r.reference).object);
+ }
+
+ static final _createJsonParser4 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonParser4")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(byte[] data)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing the contents of given byte array.
+ ///@param data Input content to parse
+ ///@return Parser constructed
+ ///@throws IOException if parser initialization fails due to I/O (read) problem
+ ///@throws JsonParseException if parser initialization fails due to content decoding problem
+ ///@deprecated Since 2.2, use \#createParser(byte[]) instead.
+ jsonparser_.JsonParser createJsonParser4(
+ jni.JArray<jni.jbyte> data,
+ ) {
+ return const jsonparser_.$JsonParserType()
+ .fromRef(_createJsonParser4(reference, data.reference).object);
+ }
+
+ static final _createJsonParser5 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32,
+ ffi.Int32)>>("JsonFactory__createJsonParser5")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int, int)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(byte[] data, int offset, int len)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing
+ /// the contents of given byte array.
+ ///@param data Buffer that contains data to parse
+ ///@param offset Offset of the first data byte within buffer
+ ///@param len Length of contents to parse within buffer
+ ///@return Parser constructed
+ ///@throws IOException if parser initialization fails due to I/O (read) problem
+ ///@throws JsonParseException if parser initialization fails due to content decoding problem
+ ///@deprecated Since 2.2, use \#createParser(byte[],int,int) instead.
+ jsonparser_.JsonParser createJsonParser5(
+ jni.JArray<jni.jbyte> data,
+ int offset,
+ int len,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(
+ _createJsonParser5(reference, data.reference, offset, len).object);
+ }
+
+ static final _createJsonParser6 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonParser6")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(java.lang.String content)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing
+ /// contents of given String.
+ ///@param content Input content to parse
+ ///@return Parser constructed
+ ///@throws IOException if parser initialization fails due to I/O (read) problem
+ ///@throws JsonParseException if parser initialization fails due to content decoding problem
+ ///@deprecated Since 2.2, use \#createParser(String) instead.
+ jsonparser_.JsonParser createJsonParser6(
+ jni.JString content,
+ ) {
+ return const jsonparser_.$JsonParserType()
+ .fromRef(_createJsonParser6(reference, content.reference).object);
+ }
+
+ static final _createJsonGenerator = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonGenerator")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createJsonGenerator(java.io.OutputStream out, com.fasterxml.jackson.core.JsonEncoding enc)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON generator for writing JSON content
+ /// using specified output stream.
+ /// Encoding to use must be specified, and needs to be one of available
+ /// types (as per JSON specification).
+ ///
+ /// Underlying stream __is NOT owned__ by the generator constructed,
+ /// so that generator will NOT close the output stream when
+ /// JsonGenerator\#close is called (unless auto-closing
+ /// feature,
+ /// com.fasterxml.jackson.core.JsonGenerator.Feature\#AUTO_CLOSE_TARGET
+ /// is enabled).
+ /// Using application needs to close it explicitly if this is the case.
+ ///
+ /// Note: there are formats that use fixed encoding (like most binary data formats)
+ /// and that ignore passed in encoding.
+ ///@param out OutputStream to use for writing JSON content
+ ///@param enc Character encoding to use
+ ///@return Generator constructed
+ ///@throws IOException if parser initialization fails due to I/O (write) problem
+ ///@deprecated Since 2.2, use \#createGenerator(OutputStream, JsonEncoding) instead.
+ jni.JObject createJsonGenerator(
+ jni.JObject out,
+ jni.JObject enc,
+ ) {
+ return const jni.JObjectType().fromRef(
+ _createJsonGenerator(reference, out.reference, enc.reference).object);
+ }
+
+ static final _createJsonGenerator1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonGenerator1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createJsonGenerator(java.io.Writer out)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON generator for writing JSON content
+ /// using specified Writer.
+ ///
+ /// Underlying stream __is NOT owned__ by the generator constructed,
+ /// so that generator will NOT close the Reader when
+ /// JsonGenerator\#close is called (unless auto-closing
+ /// feature,
+ /// com.fasterxml.jackson.core.JsonGenerator.Feature\#AUTO_CLOSE_TARGET is enabled).
+ /// Using application needs to close it explicitly.
+ ///@param out Writer to use for writing JSON content
+ ///@return Generator constructed
+ ///@throws IOException if parser initialization fails due to I/O (write) problem
+ ///@deprecated Since 2.2, use \#createGenerator(Writer) instead.
+ jni.JObject createJsonGenerator1(
+ jni.JObject out,
+ ) {
+ return const jni.JObjectType()
+ .fromRef(_createJsonGenerator1(reference, out.reference).object);
+ }
+
+ static final _createJsonGenerator2 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonGenerator2")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createJsonGenerator(java.io.OutputStream out)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Convenience method for constructing generator that uses default
+ /// encoding of the format (UTF-8 for JSON and most other data formats).
+ ///
+ /// Note: there are formats that use fixed encoding (like most binary data formats).
+ ///@param out OutputStream to use for writing JSON content
+ ///@return Generator constructed
+ ///@throws IOException if parser initialization fails due to I/O (write) problem
+ ///@deprecated Since 2.2, use \#createGenerator(OutputStream) instead.
+ jni.JObject createJsonGenerator2(
+ jni.JObject out,
+ ) {
+ return const jni.JObjectType()
+ .fromRef(_createJsonGenerator2(reference, out.reference).object);
+ }
+}
+
+final class $JsonFactoryType extends jni.JObjType<JsonFactory> {
+ const $JsonFactoryType();
+
+ @override
+ String get signature => r"Lcom/fasterxml/jackson/core/JsonFactory;";
+
+ @override
+ JsonFactory fromRef(jni.JObjectPtr ref) => JsonFactory.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($JsonFactoryType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($JsonFactoryType) && other is $JsonFactoryType;
+ }
+}
+
+/// from: com.fasterxml.jackson.core.JsonFactory$Feature
+///
+/// Enumeration that defines all on/off features that can only be
+/// changed for JsonFactory.
+class JsonFactory_Feature extends jni.JObject {
+ @override
+ late final jni.JObjType<JsonFactory_Feature> $type = type;
+
+ JsonFactory_Feature.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $JsonFactory_FeatureType();
+ static final _values =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "JsonFactory_Feature__values")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public com.fasterxml.jackson.core.JsonFactory.Feature[] values()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<JsonFactory_Feature> values() {
+ return const jni.JArrayType($JsonFactory_FeatureType())
+ .fromRef(_values().object);
+ }
+
+ static final _valueOf = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory_Feature__valueOf")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public com.fasterxml.jackson.core.JsonFactory.Feature valueOf(java.lang.String name)
+ /// The returned object must be released after use, by calling the [release] method.
+ static JsonFactory_Feature valueOf(
+ jni.JString name,
+ ) {
+ return const $JsonFactory_FeatureType()
+ .fromRef(_valueOf(name.reference).object);
+ }
+
+ static final _collectDefaults =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "JsonFactory_Feature__collectDefaults")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public int collectDefaults()
+ ///
+ /// Method that calculates bit set (flags) of all features that
+ /// are enabled by default.
+ ///@return Bit field of features enabled by default
+ static int collectDefaults() {
+ return _collectDefaults().integer;
+ }
+
+ static final _enabledByDefault = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory_Feature__enabledByDefault")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean enabledByDefault()
+ bool enabledByDefault() {
+ return _enabledByDefault(reference).boolean;
+ }
+
+ static final _enabledIn = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Int32)>>("JsonFactory_Feature__enabledIn")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public boolean enabledIn(int flags)
+ bool enabledIn(
+ int flags,
+ ) {
+ return _enabledIn(reference, flags).boolean;
+ }
+
+ static final _getMask = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonFactory_Feature__getMask")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int getMask()
+ int getMask() {
+ return _getMask(reference).integer;
+ }
+}
+
+final class $JsonFactory_FeatureType extends jni.JObjType<JsonFactory_Feature> {
+ const $JsonFactory_FeatureType();
+
+ @override
+ String get signature => r"Lcom/fasterxml/jackson/core/JsonFactory$Feature;";
+
+ @override
+ JsonFactory_Feature fromRef(jni.JObjectPtr ref) =>
+ JsonFactory_Feature.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($JsonFactory_FeatureType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($JsonFactory_FeatureType) &&
+ other is $JsonFactory_FeatureType;
+ }
+}
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonParser.dart b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonParser.dart
new file mode 100644
index 0000000..4a1863d
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonParser.dart
@@ -0,0 +1,2847 @@
+// Generated from jackson-core which is licensed under the Apache License 2.0.
+// The following copyright from the original authors applies.
+// See https://github.com/FasterXML/jackson-core/blob/2.14/LICENSE
+//
+// Copyright (c) 2007 - The Jackson Project Authors
+// Licensed under the Apache License, Version 2.0 (the "License")
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+// ignore_for_file: annotate_overrides
+// ignore_for_file: camel_case_extensions
+// ignore_for_file: camel_case_types
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: doc_directive_unknown
+// ignore_for_file: file_names
+// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: overridden_fields
+// ignore_for_file: unnecessary_cast
+// ignore_for_file: unused_element
+// ignore_for_file: unused_field
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: unused_shown_name
+
+import "dart:isolate" show ReceivePort;
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+import "package:jni/jni.dart" as jni;
+
+import "JsonToken.dart" as jsontoken_;
+import "../../../../_init.dart";
+
+/// from: com.fasterxml.jackson.core.JsonParser
+///
+/// Base class that defines public API for reading JSON content.
+/// Instances are created using factory methods of
+/// a JsonFactory instance.
+///@author Tatu Saloranta
+class JsonParser extends jni.JObject {
+ @override
+ late final jni.JObjType<JsonParser> $type = type;
+
+ JsonParser.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $JsonParserType();
+ static final _get_DEFAULT_READ_CAPABILITIES =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_JsonParser__DEFAULT_READ_CAPABILITIES")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static protected final com.fasterxml.jackson.core.util.JacksonFeatureSet<com.fasterxml.jackson.core.StreamReadCapability> DEFAULT_READ_CAPABILITIES
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Default set of StreamReadCapabilityies that may be used as
+ /// basis for format-specific readers (or as bogus instance if non-null
+ /// set needs to be passed).
+ ///@since 2.12
+ static jni.JObject get DEFAULT_READ_CAPABILITIES =>
+ const jni.JObjectType().fromRef(_get_DEFAULT_READ_CAPABILITIES().object);
+
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "JsonParser__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: protected void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory JsonParser() {
+ return JsonParser.fromRef(_new0().object);
+ }
+
+ static final _new1 =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Int32)>>(
+ "JsonParser__new1")
+ .asFunction<jni.JniResult Function(int)>();
+
+ /// from: protected void <init>(int features)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory JsonParser.new1(
+ int features,
+ ) {
+ return JsonParser.fromRef(_new1(features).object);
+ }
+
+ static final _getCodec = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getCodec")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract com.fasterxml.jackson.core.ObjectCodec getCodec()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Accessor for ObjectCodec associated with this
+ /// parser, if any. Codec is used by \#readValueAs(Class)
+ /// method (and its variants).
+ ///@return Codec assigned to this parser, if any; {@code null} if none
+ jni.JObject getCodec() {
+ return const jni.JObjectType().fromRef(_getCodec(reference).object);
+ }
+
+ static final _setCodec = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__setCodec")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract void setCodec(com.fasterxml.jackson.core.ObjectCodec oc)
+ ///
+ /// Setter that allows defining ObjectCodec associated with this
+ /// parser, if any. Codec is used by \#readValueAs(Class)
+ /// method (and its variants).
+ ///@param oc Codec to assign, if any; {@code null} if none
+ void setCodec(
+ jni.JObject oc,
+ ) {
+ return _setCodec(reference, oc.reference).check();
+ }
+
+ static final _getInputSource = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getInputSource")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.Object getInputSource()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that can be used to get access to object that is used
+ /// to access input being parsed; this is usually either
+ /// InputStream or Reader, depending on what
+ /// parser was constructed with.
+ /// Note that returned value may be null in some cases; including
+ /// case where parser implementation does not want to exposed raw
+ /// source to caller.
+ /// In cases where input has been decorated, object returned here
+ /// is the decorated version; this allows some level of interaction
+ /// between users of parser and decorator object.
+ ///
+ /// In general use of this accessor should be considered as
+ /// "last effort", i.e. only used if no other mechanism is applicable.
+ ///@return Input source this parser was configured with
+ jni.JObject getInputSource() {
+ return const jni.JObjectType().fromRef(_getInputSource(reference).object);
+ }
+
+ static final _setRequestPayloadOnError = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__setRequestPayloadOnError")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setRequestPayloadOnError(com.fasterxml.jackson.core.util.RequestPayload payload)
+ ///
+ /// Sets the payload to be passed if JsonParseException is thrown.
+ ///@param payload Payload to pass
+ ///@since 2.8
+ void setRequestPayloadOnError(
+ jni.JObject payload,
+ ) {
+ return _setRequestPayloadOnError(reference, payload.reference).check();
+ }
+
+ static final _setRequestPayloadOnError1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__setRequestPayloadOnError1")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setRequestPayloadOnError(byte[] payload, java.lang.String charset)
+ ///
+ /// Sets the byte[] request payload and the charset
+ ///@param payload Payload to pass
+ ///@param charset Character encoding for (lazily) decoding payload
+ ///@since 2.8
+ void setRequestPayloadOnError1(
+ jni.JArray<jni.jbyte> payload,
+ jni.JString charset,
+ ) {
+ return _setRequestPayloadOnError1(
+ reference, payload.reference, charset.reference)
+ .check();
+ }
+
+ static final _setRequestPayloadOnError2 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__setRequestPayloadOnError2")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setRequestPayloadOnError(java.lang.String payload)
+ ///
+ /// Sets the String request payload
+ ///@param payload Payload to pass
+ ///@since 2.8
+ void setRequestPayloadOnError2(
+ jni.JString payload,
+ ) {
+ return _setRequestPayloadOnError2(reference, payload.reference).check();
+ }
+
+ static final _setSchema = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__setSchema")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setSchema(com.fasterxml.jackson.core.FormatSchema schema)
+ ///
+ /// Method to call to make this parser use specified schema. Method must
+ /// be called before trying to parse any content, right after parser instance
+ /// has been created.
+ /// Note that not all parsers support schemas; and those that do usually only
+ /// accept specific types of schemas: ones defined for data format parser can read.
+ ///
+ /// If parser does not support specified schema, UnsupportedOperationException
+ /// is thrown.
+ ///@param schema Schema to use
+ ///@throws UnsupportedOperationException if parser does not support schema
+ void setSchema(
+ jni.JObject schema,
+ ) {
+ return _setSchema(reference, schema.reference).check();
+ }
+
+ static final _getSchema = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getSchema")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.FormatSchema getSchema()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for accessing Schema that this parser uses, if any.
+ /// Default implementation returns null.
+ ///@return Schema in use by this parser, if any; {@code null} if none
+ ///@since 2.1
+ jni.JObject getSchema() {
+ return const jni.JObjectType().fromRef(_getSchema(reference).object);
+ }
+
+ static final _canUseSchema = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__canUseSchema")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean canUseSchema(com.fasterxml.jackson.core.FormatSchema schema)
+ ///
+ /// Method that can be used to verify that given schema can be used with
+ /// this parser (using \#setSchema).
+ ///@param schema Schema to check
+ ///@return True if this parser can use given schema; false if not
+ bool canUseSchema(
+ jni.JObject schema,
+ ) {
+ return _canUseSchema(reference, schema.reference).boolean;
+ }
+
+ static final _requiresCustomCodec = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__requiresCustomCodec")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean requiresCustomCodec()
+ ///
+ /// Method that can be called to determine if a custom
+ /// ObjectCodec is needed for binding data parsed
+ /// using JsonParser constructed by this factory
+ /// (which typically also implies the same for serialization
+ /// with JsonGenerator).
+ ///@return True if format-specific codec is needed with this parser; false if a general
+ /// ObjectCodec is enough
+ ///@since 2.1
+ bool requiresCustomCodec() {
+ return _requiresCustomCodec(reference).boolean;
+ }
+
+ static final _canParseAsync = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__canParseAsync")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean canParseAsync()
+ ///
+ /// Method that can be called to determine if this parser instance
+ /// uses non-blocking ("asynchronous") input access for decoding or not.
+ /// Access mode is determined by earlier calls via JsonFactory;
+ /// it may not be changed after construction.
+ ///
+ /// If non-blocking decoding is (@code true}, it is possible to call
+ /// \#getNonBlockingInputFeeder() to obtain object to use
+ /// for feeding input; otherwise (<code>false</code> returned)
+ /// input is read by blocking
+ ///@return True if this is a non-blocking ("asynchronous") parser
+ ///@since 2.9
+ bool canParseAsync() {
+ return _canParseAsync(reference).boolean;
+ }
+
+ static final _getNonBlockingInputFeeder = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getNonBlockingInputFeeder")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.async.NonBlockingInputFeeder getNonBlockingInputFeeder()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that will either return a feeder instance (if parser uses
+ /// non-blocking, aka asynchronous access); or <code>null</code> for
+ /// parsers that use blocking I/O.
+ ///@return Input feeder to use with non-blocking (async) parsing
+ ///@since 2.9
+ jni.JObject getNonBlockingInputFeeder() {
+ return const jni.JObjectType()
+ .fromRef(_getNonBlockingInputFeeder(reference).object);
+ }
+
+ static final _getReadCapabilities = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getReadCapabilities")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.util.JacksonFeatureSet<com.fasterxml.jackson.core.StreamReadCapability> getReadCapabilities()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Accessor for getting metadata on capabilities of this parser, based on
+ /// underlying data format being read (directly or indirectly).
+ ///@return Set of read capabilities for content to read via this parser
+ ///@since 2.12
+ jni.JObject getReadCapabilities() {
+ return const jni.JObjectType()
+ .fromRef(_getReadCapabilities(reference).object);
+ }
+
+ static final _version = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__version")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract com.fasterxml.jackson.core.Version version()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Accessor for getting version of the core package, given a parser instance.
+ /// Left for sub-classes to implement.
+ ///@return Version of this generator (derived from version declared for
+ /// {@code jackson-core} jar that contains the class
+ jni.JObject version() {
+ return const jni.JObjectType().fromRef(_version(reference).object);
+ }
+
+ static final _close = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__close")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract void close()
+ ///
+ /// Closes the parser so that no further iteration or data access
+ /// can be made; will also close the underlying input source
+ /// if parser either __owns__ the input source, or feature
+ /// Feature\#AUTO_CLOSE_SOURCE is enabled.
+ /// Whether parser owns the input source depends on factory
+ /// method that was used to construct instance (so check
+ /// com.fasterxml.jackson.core.JsonFactory for details,
+ /// but the general
+ /// idea is that if caller passes in closable resource (such
+ /// as InputStream or Reader) parser does NOT
+ /// own the source; but if it passes a reference (such as
+ /// java.io.File or java.net.URL and creates
+ /// stream or reader it does own them.
+ ///@throws IOException if there is either an underlying I/O problem
+ void close() {
+ return _close(reference).check();
+ }
+
+ static final _isClosed = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__isClosed")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract boolean isClosed()
+ ///
+ /// Method that can be called to determine whether this parser
+ /// is closed or not. If it is closed, no new tokens can be
+ /// retrieved by calling \#nextToken (and the underlying
+ /// stream may be closed). Closing may be due to an explicit
+ /// call to \#close or because parser has encountered
+ /// end of input.
+ ///@return {@code True} if this parser instance has been closed
+ bool isClosed() {
+ return _isClosed(reference).boolean;
+ }
+
+ static final _getParsingContext = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getParsingContext")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonStreamContext getParsingContext()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that can be used to access current parsing context reader
+ /// is in. There are 3 different types: root, array and object contexts,
+ /// with slightly different available information. Contexts are
+ /// hierarchically nested, and can be used for example for figuring
+ /// out part of the input document that correspond to specific
+ /// array or object (for highlighting purposes, or error reporting).
+ /// Contexts can also be used for simple xpath-like matching of
+ /// input, if so desired.
+ ///@return Stream input context (JsonStreamContext) associated with this parser
+ jni.JObject getParsingContext() {
+ return const jni.JObjectType()
+ .fromRef(_getParsingContext(reference).object);
+ }
+
+ static final _currentLocation = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__currentLocation")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonLocation currentLocation()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that returns location of the last processed input unit (character
+ /// or byte) from the input;
+ /// usually for error reporting purposes.
+ ///
+ /// Note that the location is not guaranteed to be accurate (although most
+ /// implementation will try their best): some implementations may only
+ /// report specific boundary locations (start or end locations of tokens)
+ /// and others only return JsonLocation\#NA due to not having access
+ /// to input location information (when delegating actual decoding work
+ /// to other library)
+ ///@return Location of the last processed input unit (byte or character)
+ ///@since 2.13
+ jni.JObject currentLocation() {
+ return const jni.JObjectType().fromRef(_currentLocation(reference).object);
+ }
+
+ static final _currentTokenLocation = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__currentTokenLocation")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonLocation currentTokenLocation()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that return the __starting__ location of the current
+ /// (most recently returned)
+ /// token; that is, the position of the first input unit (character or byte) from input
+ /// that starts the current token.
+ ///
+ /// Note that the location is not guaranteed to be accurate (although most
+ /// implementation will try their best): some implementations may only
+ /// return JsonLocation\#NA due to not having access
+ /// to input location information (when delegating actual decoding work
+ /// to other library)
+ ///@return Starting location of the token parser currently points to
+ ///@since 2.13 (will eventually replace \#getTokenLocation)
+ jni.JObject currentTokenLocation() {
+ return const jni.JObjectType()
+ .fromRef(_currentTokenLocation(reference).object);
+ }
+
+ static final _getCurrentLocation = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getCurrentLocation")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonLocation getCurrentLocation()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Alias for \#currentLocation(), to be deprecated in later
+ /// Jackson 2.x versions (and removed from Jackson 3.0).
+ ///@return Location of the last processed input unit (byte or character)
+ jni.JObject getCurrentLocation() {
+ return const jni.JObjectType()
+ .fromRef(_getCurrentLocation(reference).object);
+ }
+
+ static final _getTokenLocation = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getTokenLocation")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonLocation getTokenLocation()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Alias for \#currentTokenLocation(), to be deprecated in later
+ /// Jackson 2.x versions (and removed from Jackson 3.0).
+ ///@return Starting location of the token parser currently points to
+ jni.JObject getTokenLocation() {
+ return const jni.JObjectType().fromRef(_getTokenLocation(reference).object);
+ }
+
+ static final _currentValue = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__currentValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.Object currentValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Helper method, usually equivalent to:
+ ///<code>
+ /// getParsingContext().getCurrentValue();
+ ///</code>
+ ///
+ /// Note that "current value" is NOT populated (or used) by Streaming parser;
+ /// it is only used by higher-level data-binding functionality.
+ /// The reason it is included here is that it can be stored and accessed hierarchically,
+ /// and gets passed through data-binding.
+ ///@return "Current value" associated with the current input context (state) of this parser
+ ///@since 2.13 (added as replacement for older \#getCurrentValue()
+ jni.JObject currentValue() {
+ return const jni.JObjectType().fromRef(_currentValue(reference).object);
+ }
+
+ static final _assignCurrentValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__assignCurrentValue")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void assignCurrentValue(java.lang.Object v)
+ ///
+ /// Helper method, usually equivalent to:
+ ///<code>
+ /// getParsingContext().setCurrentValue(v);
+ ///</code>
+ ///@param v Current value to assign for the current input context of this parser
+ ///@since 2.13 (added as replacement for older \#setCurrentValue
+ void assignCurrentValue(
+ jni.JObject v,
+ ) {
+ return _assignCurrentValue(reference, v.reference).check();
+ }
+
+ static final _getCurrentValue = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getCurrentValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.Object getCurrentValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Alias for \#currentValue(), to be deprecated in later
+ /// Jackson 2.x versions (and removed from Jackson 3.0).
+ ///@return Location of the last processed input unit (byte or character)
+ jni.JObject getCurrentValue() {
+ return const jni.JObjectType().fromRef(_getCurrentValue(reference).object);
+ }
+
+ static final _setCurrentValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__setCurrentValue")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setCurrentValue(java.lang.Object v)
+ ///
+ /// Alias for \#assignCurrentValue, to be deprecated in later
+ /// Jackson 2.x versions (and removed from Jackson 3.0).
+ ///@param v Current value to assign for the current input context of this parser
+ void setCurrentValue(
+ jni.JObject v,
+ ) {
+ return _setCurrentValue(reference, v.reference).check();
+ }
+
+ static final _releaseBuffered = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__releaseBuffered")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int releaseBuffered(java.io.OutputStream out)
+ ///
+ /// Method that can be called to push back any content that
+ /// has been read but not consumed by the parser. This is usually
+ /// done after reading all content of interest using parser.
+ /// Content is released by writing it to given stream if possible;
+ /// if underlying input is byte-based it can released, if not (char-based)
+ /// it can not.
+ ///@param out OutputStream to which buffered, undecoded content is written to
+ ///@return -1 if the underlying content source is not byte based
+ /// (that is, input can not be sent to OutputStream;
+ /// otherwise number of bytes released (0 if there was nothing to release)
+ ///@throws IOException if write to stream threw exception
+ int releaseBuffered(
+ jni.JObject out,
+ ) {
+ return _releaseBuffered(reference, out.reference).integer;
+ }
+
+ static final _releaseBuffered1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__releaseBuffered1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int releaseBuffered(java.io.Writer w)
+ ///
+ /// Method that can be called to push back any content that
+ /// has been read but not consumed by the parser.
+ /// This is usually
+ /// done after reading all content of interest using parser.
+ /// Content is released by writing it to given writer if possible;
+ /// if underlying input is char-based it can released, if not (byte-based)
+ /// it can not.
+ ///@param w Writer to which buffered but unprocessed content is written to
+ ///@return -1 if the underlying content source is not char-based
+ /// (that is, input can not be sent to Writer;
+ /// otherwise number of chars released (0 if there was nothing to release)
+ ///@throws IOException if write using Writer threw exception
+ int releaseBuffered1(
+ jni.JObject w,
+ ) {
+ return _releaseBuffered1(reference, w.reference).integer;
+ }
+
+ static final _enable = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__enable")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser enable(com.fasterxml.jackson.core.JsonParser.Feature f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for enabling specified parser feature
+ /// (check Feature for list of features)
+ ///@param f Feature to enable
+ ///@return This parser, to allow call chaining
+ JsonParser enable(
+ JsonParser_Feature f,
+ ) {
+ return const $JsonParserType()
+ .fromRef(_enable(reference, f.reference).object);
+ }
+
+ static final _disable = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__disable")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser disable(com.fasterxml.jackson.core.JsonParser.Feature f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for disabling specified feature
+ /// (check Feature for list of features)
+ ///@param f Feature to disable
+ ///@return This parser, to allow call chaining
+ JsonParser disable(
+ JsonParser_Feature f,
+ ) {
+ return const $JsonParserType()
+ .fromRef(_disable(reference, f.reference).object);
+ }
+
+ static final _configure = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Uint8)>>("JsonParser__configure")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser configure(com.fasterxml.jackson.core.JsonParser.Feature f, boolean state)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for enabling or disabling specified feature
+ /// (check Feature for list of features)
+ ///@param f Feature to enable or disable
+ ///@param state Whether to enable feature ({@code true}) or disable ({@code false})
+ ///@return This parser, to allow call chaining
+ JsonParser configure(
+ JsonParser_Feature f,
+ bool state,
+ ) {
+ return const $JsonParserType()
+ .fromRef(_configure(reference, f.reference, state ? 1 : 0).object);
+ }
+
+ static final _isEnabled = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__isEnabled")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean isEnabled(com.fasterxml.jackson.core.JsonParser.Feature f)
+ ///
+ /// Method for checking whether specified Feature is enabled.
+ ///@param f Feature to check
+ ///@return {@code True} if feature is enabled; {@code false} otherwise
+ bool isEnabled(
+ JsonParser_Feature f,
+ ) {
+ return _isEnabled(reference, f.reference).boolean;
+ }
+
+ static final _isEnabled1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__isEnabled1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean isEnabled(com.fasterxml.jackson.core.StreamReadFeature f)
+ ///
+ /// Method for checking whether specified Feature is enabled.
+ ///@param f Feature to check
+ ///@return {@code True} if feature is enabled; {@code false} otherwise
+ ///@since 2.10
+ bool isEnabled1(
+ jni.JObject f,
+ ) {
+ return _isEnabled1(reference, f.reference).boolean;
+ }
+
+ static final _getFeatureMask = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getFeatureMask")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int getFeatureMask()
+ ///
+ /// Bulk access method for getting state of all standard Features.
+ ///@return Bit mask that defines current states of all standard Features.
+ ///@since 2.3
+ int getFeatureMask() {
+ return _getFeatureMask(reference).integer;
+ }
+
+ static final _setFeatureMask = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Int32)>>("JsonParser__setFeatureMask")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser setFeatureMask(int mask)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Bulk set method for (re)setting states of all standard Features
+ ///@param mask Bit mask that defines set of features to enable
+ ///@return This parser, to allow call chaining
+ ///@since 2.3
+ ///@deprecated Since 2.7, use \#overrideStdFeatures(int, int) instead
+ JsonParser setFeatureMask(
+ int mask,
+ ) {
+ return const $JsonParserType()
+ .fromRef(_setFeatureMask(reference, mask).object);
+ }
+
+ static final _overrideStdFeatures = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Int32,
+ ffi.Int32)>>("JsonParser__overrideStdFeatures")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int, int)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser overrideStdFeatures(int values, int mask)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Bulk set method for (re)setting states of features specified by <code>mask</code>.
+ /// Functionally equivalent to
+ ///<code>
+ /// int oldState = getFeatureMask();
+ /// int newState = (oldState & ~mask) | (values & mask);
+ /// setFeatureMask(newState);
+ ///</code>
+ /// but preferred as this lets caller more efficiently specify actual changes made.
+ ///@param values Bit mask of set/clear state for features to change
+ ///@param mask Bit mask of features to change
+ ///@return This parser, to allow call chaining
+ ///@since 2.6
+ JsonParser overrideStdFeatures(
+ int values,
+ int mask,
+ ) {
+ return const $JsonParserType()
+ .fromRef(_overrideStdFeatures(reference, values, mask).object);
+ }
+
+ static final _getFormatFeatures = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getFormatFeatures")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int getFormatFeatures()
+ ///
+ /// Bulk access method for getting state of all FormatFeatures, format-specific
+ /// on/off configuration settings.
+ ///@return Bit mask that defines current states of all standard FormatFeatures.
+ ///@since 2.6
+ int getFormatFeatures() {
+ return _getFormatFeatures(reference).integer;
+ }
+
+ static final _overrideFormatFeatures = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Int32,
+ ffi.Int32)>>("JsonParser__overrideFormatFeatures")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int, int)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonParser overrideFormatFeatures(int values, int mask)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Bulk set method for (re)setting states of FormatFeatures,
+ /// by specifying values (set / clear) along with a mask, to determine
+ /// which features to change, if any.
+ ///
+ /// Default implementation will simply throw an exception to indicate that
+ /// the parser implementation does not support any FormatFeatures.
+ ///@param values Bit mask of set/clear state for features to change
+ ///@param mask Bit mask of features to change
+ ///@return This parser, to allow call chaining
+ ///@since 2.6
+ JsonParser overrideFormatFeatures(
+ int values,
+ int mask,
+ ) {
+ return const $JsonParserType()
+ .fromRef(_overrideFormatFeatures(reference, values, mask).object);
+ }
+
+ static final _nextToken = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__nextToken")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonToken nextToken()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Main iteration method, which will advance stream enough
+ /// to determine type of the next token, if any. If none
+ /// remaining (stream has no content other than possible
+ /// white space before ending), null will be returned.
+ ///@return Next token from the stream, if any found, or null
+ /// to indicate end-of-input
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jsontoken_.JsonToken nextToken() {
+ return const jsontoken_.$JsonTokenType()
+ .fromRef(_nextToken(reference).object);
+ }
+
+ static final _nextValue = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__nextValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonToken nextValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Iteration method that will advance stream enough
+ /// to determine type of the next token that is a value type
+ /// (including JSON Array and Object start/end markers).
+ /// Or put another way, nextToken() will be called once,
+ /// and if JsonToken\#FIELD_NAME is returned, another
+ /// time to get the value for the field.
+ /// Method is most useful for iterating over value entries
+ /// of JSON objects; field name will still be available
+ /// by calling \#getCurrentName when parser points to
+ /// the value.
+ ///@return Next non-field-name token from the stream, if any found,
+ /// or null to indicate end-of-input (or, for non-blocking
+ /// parsers, JsonToken\#NOT_AVAILABLE if no tokens were
+ /// available yet)
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jsontoken_.JsonToken nextValue() {
+ return const jsontoken_.$JsonTokenType()
+ .fromRef(_nextValue(reference).object);
+ }
+
+ static final _nextFieldName = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__nextFieldName")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean nextFieldName(com.fasterxml.jackson.core.SerializableString str)
+ ///
+ /// Method that fetches next token (as if calling \#nextToken) and
+ /// verifies whether it is JsonToken\#FIELD_NAME with specified name
+ /// and returns result of that comparison.
+ /// It is functionally equivalent to:
+ ///<pre>
+ /// return (nextToken() == JsonToken.FIELD_NAME) && str.getValue().equals(getCurrentName());
+ ///</pre>
+ /// but may be faster for parser to verify, and can therefore be used if caller
+ /// expects to get such a property name from input next.
+ ///@param str Property name to compare next token to (if next token is
+ /// <code>JsonToken.FIELD_NAME</code>)
+ ///@return {@code True} if parser advanced to {@code JsonToken.FIELD_NAME} with
+ /// specified name; {@code false} otherwise (different token or non-matching name)
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ bool nextFieldName(
+ jni.JObject str,
+ ) {
+ return _nextFieldName(reference, str.reference).boolean;
+ }
+
+ static final _nextFieldName1 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__nextFieldName1")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String nextFieldName()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that fetches next token (as if calling \#nextToken) and
+ /// verifies whether it is JsonToken\#FIELD_NAME; if it is,
+ /// returns same as \#getCurrentName(), otherwise null.
+ ///@return Name of the the {@code JsonToken.FIELD_NAME} parser advanced to, if any;
+ /// {@code null} if next token is of some other type
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.5
+ jni.JString nextFieldName1() {
+ return const jni.JStringType().fromRef(_nextFieldName1(reference).object);
+ }
+
+ static final _nextTextValue = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__nextTextValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String nextTextValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that fetches next token (as if calling \#nextToken) and
+ /// if it is JsonToken\#VALUE_STRING returns contained String value;
+ /// otherwise returns null.
+ /// It is functionally equivalent to:
+ ///<pre>
+ /// return (nextToken() == JsonToken.VALUE_STRING) ? getText() : null;
+ ///</pre>
+ /// but may be faster for parser to process, and can therefore be used if caller
+ /// expects to get a String value next from input.
+ ///@return Text value of the {@code JsonToken.VALUE_STRING} token parser advanced
+ /// to; or {@code null} if next token is of some other type
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JString nextTextValue() {
+ return const jni.JStringType().fromRef(_nextTextValue(reference).object);
+ }
+
+ static final _nextIntValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Int32)>>("JsonParser__nextIntValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public int nextIntValue(int defaultValue)
+ ///
+ /// Method that fetches next token (as if calling \#nextToken) and
+ /// if it is JsonToken\#VALUE_NUMBER_INT returns 32-bit int value;
+ /// otherwise returns specified default value
+ /// It is functionally equivalent to:
+ ///<pre>
+ /// return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getIntValue() : defaultValue;
+ ///</pre>
+ /// but may be faster for parser to process, and can therefore be used if caller
+ /// expects to get an int value next from input.
+ ///
+ /// NOTE: value checks are performed similar to \#getIntValue()
+ ///@param defaultValue Value to return if next token is NOT of type {@code JsonToken.VALUE_NUMBER_INT}
+ ///@return Integer ({@code int}) value of the {@code JsonToken.VALUE_NUMBER_INT} token parser advanced
+ /// to; or {@code defaultValue} if next token is of some other type
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@throws InputCoercionException if integer number does not fit in Java {@code int}
+ int nextIntValue(
+ int defaultValue,
+ ) {
+ return _nextIntValue(reference, defaultValue).integer;
+ }
+
+ static final _nextLongValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Int64)>>("JsonParser__nextLongValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public long nextLongValue(long defaultValue)
+ ///
+ /// Method that fetches next token (as if calling \#nextToken) and
+ /// if it is JsonToken\#VALUE_NUMBER_INT returns 64-bit long value;
+ /// otherwise returns specified default value
+ /// It is functionally equivalent to:
+ ///<pre>
+ /// return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getLongValue() : defaultValue;
+ ///</pre>
+ /// but may be faster for parser to process, and can therefore be used if caller
+ /// expects to get a long value next from input.
+ ///
+ /// NOTE: value checks are performed similar to \#getLongValue()
+ ///@param defaultValue Value to return if next token is NOT of type {@code JsonToken.VALUE_NUMBER_INT}
+ ///@return {@code long} value of the {@code JsonToken.VALUE_NUMBER_INT} token parser advanced
+ /// to; or {@code defaultValue} if next token is of some other type
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@throws InputCoercionException if integer number does not fit in Java {@code long}
+ int nextLongValue(
+ int defaultValue,
+ ) {
+ return _nextLongValue(reference, defaultValue).long;
+ }
+
+ static final _nextBooleanValue = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__nextBooleanValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.Boolean nextBooleanValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that fetches next token (as if calling \#nextToken) and
+ /// if it is JsonToken\#VALUE_TRUE or JsonToken\#VALUE_FALSE
+ /// returns matching Boolean value; otherwise return null.
+ /// It is functionally equivalent to:
+ ///<pre>
+ /// JsonToken t = nextToken();
+ /// if (t == JsonToken.VALUE_TRUE) return Boolean.TRUE;
+ /// if (t == JsonToken.VALUE_FALSE) return Boolean.FALSE;
+ /// return null;
+ ///</pre>
+ /// but may be faster for parser to process, and can therefore be used if caller
+ /// expects to get a Boolean value next from input.
+ ///@return {@code Boolean} value of the {@code JsonToken.VALUE_TRUE} or {@code JsonToken.VALUE_FALSE}
+ /// token parser advanced to; or {@code null} if next token is of some other type
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JBoolean nextBooleanValue() {
+ return const jni.JBooleanType()
+ .fromRef(_nextBooleanValue(reference).object);
+ }
+
+ static final _skipChildren = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__skipChildren")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonParser skipChildren()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that will skip all child tokens of an array or
+ /// object token that the parser currently points to,
+ /// iff stream points to
+ /// JsonToken\#START_OBJECT or JsonToken\#START_ARRAY.
+ /// If not, it will do nothing.
+ /// After skipping, stream will point to __matching__
+ /// JsonToken\#END_OBJECT or JsonToken\#END_ARRAY
+ /// (possibly skipping nested pairs of START/END OBJECT/ARRAY tokens
+ /// as well as value tokens).
+ /// The idea is that after calling this method, application
+ /// will call \#nextToken to point to the next
+ /// available token, if any.
+ ///@return This parser, to allow call chaining
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ JsonParser skipChildren() {
+ return const $JsonParserType().fromRef(_skipChildren(reference).object);
+ }
+
+ static final _finishToken = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__finishToken")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void finishToken()
+ ///
+ /// Method that may be used to force full handling of the current token
+ /// so that even if lazy processing is enabled, the whole contents are
+ /// read for possible retrieval. This is usually used to ensure that
+ /// the token end location is available, as well as token contents
+ /// (similar to what calling, say \#getTextCharacters(), would
+ /// achieve).
+ ///
+ /// Note that for many dataformat implementations this method
+ /// will not do anything; this is the default implementation unless
+ /// overridden by sub-classes.
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.8
+ void finishToken() {
+ return _finishToken(reference).check();
+ }
+
+ static final _currentToken = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__currentToken")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.fasterxml.jackson.core.JsonToken currentToken()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Accessor to find which token parser currently points to, if any;
+ /// null will be returned if none.
+ /// If return value is non-null, data associated with the token
+ /// is available via other accessor methods.
+ ///@return Type of the token this parser currently points to,
+ /// if any: null before any tokens have been read, and
+ /// after end-of-input has been encountered, as well as
+ /// if the current token has been explicitly cleared.
+ ///@since 2.8
+ jsontoken_.JsonToken currentToken() {
+ return const jsontoken_.$JsonTokenType()
+ .fromRef(_currentToken(reference).object);
+ }
+
+ static final _currentTokenId = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__currentTokenId")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int currentTokenId()
+ ///
+ /// Method similar to \#getCurrentToken() but that returns an
+ /// <code>int</code> instead of JsonToken (enum value).
+ ///
+ /// Use of int directly is typically more efficient on switch statements,
+ /// so this method may be useful when building low-overhead codecs.
+ /// Note, however, that effect may not be big enough to matter: make sure
+ /// to profile performance before deciding to use this method.
+ ///@since 2.8
+ ///@return {@code int} matching one of constants from JsonTokenId.
+ int currentTokenId() {
+ return _currentTokenId(reference).integer;
+ }
+
+ static final _getCurrentToken = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getCurrentToken")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonToken getCurrentToken()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Alias for \#currentToken(), may be deprecated sometime after
+ /// Jackson 2.13 (will be removed from 3.0).
+ ///@return Type of the token this parser currently points to,
+ /// if any: null before any tokens have been read, and
+ jsontoken_.JsonToken getCurrentToken() {
+ return const jsontoken_.$JsonTokenType()
+ .fromRef(_getCurrentToken(reference).object);
+ }
+
+ static final _getCurrentTokenId = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getCurrentTokenId")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract int getCurrentTokenId()
+ ///
+ /// Deprecated alias for \#currentTokenId().
+ ///@return {@code int} matching one of constants from JsonTokenId.
+ ///@deprecated Since 2.12 use \#currentTokenId instead
+ int getCurrentTokenId() {
+ return _getCurrentTokenId(reference).integer;
+ }
+
+ static final _hasCurrentToken = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__hasCurrentToken")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract boolean hasCurrentToken()
+ ///
+ /// Method for checking whether parser currently points to
+ /// a token (and data for that token is available).
+ /// Equivalent to check for <code>parser.getCurrentToken() != null</code>.
+ ///@return True if the parser just returned a valid
+ /// token via \#nextToken; false otherwise (parser
+ /// was just constructed, encountered end-of-input
+ /// and returned null from \#nextToken, or the token
+ /// has been consumed)
+ bool hasCurrentToken() {
+ return _hasCurrentToken(reference).boolean;
+ }
+
+ static final _hasTokenId = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Int32)>>("JsonParser__hasTokenId")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public abstract boolean hasTokenId(int id)
+ ///
+ /// Method that is functionally equivalent to:
+ ///<code>
+ /// return currentTokenId() == id
+ ///</code>
+ /// but may be more efficiently implemented.
+ ///
+ /// Note that no traversal or conversion is performed; so in some
+ /// cases calling method like \#isExpectedStartArrayToken()
+ /// is necessary instead.
+ ///@param id Token id to match (from (@link JsonTokenId})
+ ///@return {@code True} if the parser current points to specified token
+ ///@since 2.5
+ bool hasTokenId(
+ int id,
+ ) {
+ return _hasTokenId(reference, id).boolean;
+ }
+
+ static final _hasToken = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__hasToken")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract boolean hasToken(com.fasterxml.jackson.core.JsonToken t)
+ ///
+ /// Method that is functionally equivalent to:
+ ///<code>
+ /// return currentToken() == t
+ ///</code>
+ /// but may be more efficiently implemented.
+ ///
+ /// Note that no traversal or conversion is performed; so in some
+ /// cases calling method like \#isExpectedStartArrayToken()
+ /// is necessary instead.
+ ///@param t Token to match
+ ///@return {@code True} if the parser current points to specified token
+ ///@since 2.6
+ bool hasToken(
+ jsontoken_.JsonToken t,
+ ) {
+ return _hasToken(reference, t.reference).boolean;
+ }
+
+ static final _isExpectedStartArrayToken = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__isExpectedStartArrayToken")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean isExpectedStartArrayToken()
+ ///
+ /// Specialized accessor that can be used to verify that the current
+ /// token indicates start array (usually meaning that current token
+ /// is JsonToken\#START_ARRAY) when start array is expected.
+ /// For some specialized parsers this can return true for other cases
+ /// as well; this is usually done to emulate arrays in cases underlying
+ /// format is ambiguous (XML, for example, has no format-level difference
+ /// between Objects and Arrays; it just has elements).
+ ///
+ /// Default implementation is equivalent to:
+ ///<pre>
+ /// currentToken() == JsonToken.START_ARRAY
+ ///</pre>
+ /// but may be overridden by custom parser implementations.
+ ///@return True if the current token can be considered as a
+ /// start-array marker (such JsonToken\#START_ARRAY);
+ /// {@code false} if not
+ bool isExpectedStartArrayToken() {
+ return _isExpectedStartArrayToken(reference).boolean;
+ }
+
+ static final _isExpectedStartObjectToken = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__isExpectedStartObjectToken")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean isExpectedStartObjectToken()
+ ///
+ /// Similar to \#isExpectedStartArrayToken(), but checks whether stream
+ /// currently points to JsonToken\#START_OBJECT.
+ ///@return True if the current token can be considered as a
+ /// start-array marker (such JsonToken\#START_OBJECT);
+ /// {@code false} if not
+ ///@since 2.5
+ bool isExpectedStartObjectToken() {
+ return _isExpectedStartObjectToken(reference).boolean;
+ }
+
+ static final _isExpectedNumberIntToken = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__isExpectedNumberIntToken")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean isExpectedNumberIntToken()
+ ///
+ /// Similar to \#isExpectedStartArrayToken(), but checks whether stream
+ /// currently points to JsonToken\#VALUE_NUMBER_INT.
+ ///
+ /// The initial use case is for XML backend to efficiently (attempt to) coerce
+ /// textual content into numbers.
+ ///@return True if the current token can be considered as a
+ /// start-array marker (such JsonToken\#VALUE_NUMBER_INT);
+ /// {@code false} if not
+ ///@since 2.12
+ bool isExpectedNumberIntToken() {
+ return _isExpectedNumberIntToken(reference).boolean;
+ }
+
+ static final _isNaN = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__isNaN")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean isNaN()
+ ///
+ /// Access for checking whether current token is a numeric value token, but
+ /// one that is of "not-a-number" (NaN) variety (including both "NaN" AND
+ /// positive/negative infinity!): not supported by all formats,
+ /// but often supported for JsonToken\#VALUE_NUMBER_FLOAT.
+ /// NOTE: roughly equivalent to calling <code>!Double.isFinite()</code>
+ /// on value you would get from calling \#getDoubleValue().
+ ///@return {@code True} if the current token is of type JsonToken\#VALUE_NUMBER_FLOAT
+ /// but represents a "Not a Number"; {@code false} for other tokens and regular
+ /// floating-point numbers
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.9
+ bool isNaN() {
+ return _isNaN(reference).boolean;
+ }
+
+ static final _clearCurrentToken = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__clearCurrentToken")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract void clearCurrentToken()
+ ///
+ /// Method called to "consume" the current token by effectively
+ /// removing it so that \#hasCurrentToken returns false, and
+ /// \#getCurrentToken null).
+ /// Cleared token value can still be accessed by calling
+ /// \#getLastClearedToken (if absolutely needed), but
+ /// usually isn't.
+ ///
+ /// Method was added to be used by the optional data binder, since
+ /// it has to be able to consume last token used for binding (so that
+ /// it will not be used again).
+ void clearCurrentToken() {
+ return _clearCurrentToken(reference).check();
+ }
+
+ static final _getLastClearedToken = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getLastClearedToken")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonToken getLastClearedToken()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that can be called to get the last token that was
+ /// cleared using \#clearCurrentToken. This is not necessarily
+ /// the latest token read.
+ /// Will return null if no tokens have been cleared,
+ /// or if parser has been closed.
+ ///@return Last cleared token, if any; {@code null} otherwise
+ jsontoken_.JsonToken getLastClearedToken() {
+ return const jsontoken_.$JsonTokenType()
+ .fromRef(_getLastClearedToken(reference).object);
+ }
+
+ static final _overrideCurrentName = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__overrideCurrentName")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract void overrideCurrentName(java.lang.String name)
+ ///
+ /// Method that can be used to change what is considered to be
+ /// the current (field) name.
+ /// May be needed to support non-JSON data formats or unusual binding
+ /// conventions; not needed for typical processing.
+ ///
+ /// Note that use of this method should only be done as sort of last
+ /// resort, as it is a work-around for regular operation.
+ ///@param name Name to use as the current name; may be null.
+ void overrideCurrentName(
+ jni.JString name,
+ ) {
+ return _overrideCurrentName(reference, name.reference).check();
+ }
+
+ static final _getCurrentName = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getCurrentName")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract java.lang.String getCurrentName()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Alias of \#currentName().
+ ///@return Name of the current field in the parsing context
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JString getCurrentName() {
+ return const jni.JStringType().fromRef(_getCurrentName(reference).object);
+ }
+
+ static final _currentName = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__currentName")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String currentName()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that can be called to get the name associated with
+ /// the current token: for JsonToken\#FIELD_NAMEs it will
+ /// be the same as what \#getText returns;
+ /// for field values it will be preceding field name;
+ /// and for others (array values, root-level values) null.
+ ///@return Name of the current field in the parsing context
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.10
+ jni.JString currentName() {
+ return const jni.JStringType().fromRef(_currentName(reference).object);
+ }
+
+ static final _getText = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getText")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract java.lang.String getText()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for accessing textual representation of the current token;
+ /// if no current token (before first call to \#nextToken, or
+ /// after encountering end-of-input), returns null.
+ /// Method can be called for any token type.
+ ///@return Textual value associated with the current token (one returned
+ /// by \#nextToken() or other iteration methods)
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JString getText() {
+ return const jni.JStringType().fromRef(_getText(reference).object);
+ }
+
+ static final _getText1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__getText1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int getText(java.io.Writer writer)
+ ///
+ /// Method to read the textual representation of the current token in chunks and
+ /// pass it to the given Writer.
+ /// Conceptually same as calling:
+ ///<pre>
+ /// writer.write(parser.getText());
+ ///</pre>
+ /// but should typically be more efficient as longer content does need to
+ /// be combined into a single <code>String</code> to return, and write
+ /// can occur directly from intermediate buffers Jackson uses.
+ ///@param writer Writer to write textual content to
+ ///@return The number of characters written to the Writer
+ ///@throws IOException for low-level read issues or writes using passed
+ /// {@code writer}, or
+ /// JsonParseException for decoding problems
+ ///@since 2.8
+ int getText1(
+ jni.JObject writer,
+ ) {
+ return _getText1(reference, writer.reference).integer;
+ }
+
+ static final _getTextCharacters = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getTextCharacters")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract char[] getTextCharacters()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method similar to \#getText, but that will return
+ /// underlying (unmodifiable) character array that contains
+ /// textual value, instead of constructing a String object
+ /// to contain this information.
+ /// Note, however, that:
+ ///<ul>
+ /// <li>Textual contents are not guaranteed to start at
+ /// index 0 (rather, call \#getTextOffset) to
+ /// know the actual offset
+ /// </li>
+ /// <li>Length of textual contents may be less than the
+ /// length of returned buffer: call \#getTextLength
+ /// for actual length of returned content.
+ /// </li>
+ /// </ul>
+ ///
+ /// Note that caller __MUST NOT__ modify the returned
+ /// character array in any way -- doing so may corrupt
+ /// current parser state and render parser instance useless.
+ ///
+ /// The only reason to call this method (over \#getText)
+ /// is to avoid construction of a String object (which
+ /// will make a copy of contents).
+ ///@return Buffer that contains the current textual value (but not necessarily
+ /// at offset 0, and not necessarily until the end of buffer)
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JArray<jni.jchar> getTextCharacters() {
+ return const jni.JArrayType(jni.jcharType())
+ .fromRef(_getTextCharacters(reference).object);
+ }
+
+ static final _getTextLength = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getTextLength")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract int getTextLength()
+ ///
+ /// Accessor used with \#getTextCharacters, to know length
+ /// of String stored in returned buffer.
+ ///@return Number of characters within buffer returned
+ /// by \#getTextCharacters that are part of
+ /// textual content of the current token.
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getTextLength() {
+ return _getTextLength(reference).integer;
+ }
+
+ static final _getTextOffset = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getTextOffset")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract int getTextOffset()
+ ///
+ /// Accessor used with \#getTextCharacters, to know offset
+ /// of the first text content character within buffer.
+ ///@return Offset of the first character within buffer returned
+ /// by \#getTextCharacters that is part of
+ /// textual content of the current token.
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getTextOffset() {
+ return _getTextOffset(reference).integer;
+ }
+
+ static final _hasTextCharacters = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__hasTextCharacters")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract boolean hasTextCharacters()
+ ///
+ /// Method that can be used to determine whether calling of
+ /// \#getTextCharacters would be the most efficient
+ /// way to access textual content for the event parser currently
+ /// points to.
+ ///
+ /// Default implementation simply returns false since only actual
+ /// implementation class has knowledge of its internal buffering
+ /// state.
+ /// Implementations are strongly encouraged to properly override
+ /// this method, to allow efficient copying of content by other
+ /// code.
+ ///@return True if parser currently has character array that can
+ /// be efficiently returned via \#getTextCharacters; false
+ /// means that it may or may not exist
+ bool hasTextCharacters() {
+ return _hasTextCharacters(reference).boolean;
+ }
+
+ static final _getNumberValue = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getNumberValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract java.lang.Number getNumberValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Generic number value accessor method that will work for
+ /// all kinds of numeric values. It will return the optimal
+ /// (simplest/smallest possible) wrapper object that can
+ /// express the numeric value just parsed.
+ ///@return Numeric value of the current token in its most optimal
+ /// representation
+ ///@throws IOException Problem with access: JsonParseException if
+ /// the current token is not numeric, or if decoding of the value fails
+ /// (invalid format for numbers); plain IOException if underlying
+ /// content read fails (possible if values are extracted lazily)
+ jni.JNumber getNumberValue() {
+ return const jni.JNumberType().fromRef(_getNumberValue(reference).object);
+ }
+
+ static final _getNumberValueExact = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getNumberValueExact")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.Number getNumberValueExact()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method similar to \#getNumberValue with the difference that
+ /// for floating-point numbers value returned may be BigDecimal
+ /// if the underlying format does not store floating-point numbers using
+ /// native representation: for example, textual formats represent numbers
+ /// as Strings (which are 10-based), and conversion to java.lang.Double
+ /// is potentially lossy operation.
+ ///
+ /// Default implementation simply returns \#getNumberValue()
+ ///@return Numeric value of the current token using most accurate representation
+ ///@throws IOException Problem with access: JsonParseException if
+ /// the current token is not numeric, or if decoding of the value fails
+ /// (invalid format for numbers); plain IOException if underlying
+ /// content read fails (possible if values are extracted lazily)
+ ///@since 2.12
+ jni.JNumber getNumberValueExact() {
+ return const jni.JNumberType()
+ .fromRef(_getNumberValueExact(reference).object);
+ }
+
+ static final _getNumberType = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getNumberType")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonParser.NumberType getNumberType()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// If current token is of type
+ /// JsonToken\#VALUE_NUMBER_INT or
+ /// JsonToken\#VALUE_NUMBER_FLOAT, returns
+ /// one of NumberType constants; otherwise returns null.
+ ///@return Type of current number, if parser points to numeric token; {@code null} otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ JsonParser_NumberType getNumberType() {
+ return const $JsonParser_NumberTypeType()
+ .fromRef(_getNumberType(reference).object);
+ }
+
+ static final _getByteValue = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getByteValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public byte getByteValue()
+ ///
+ /// Numeric accessor that can be called when the current
+ /// token is of type JsonToken\#VALUE_NUMBER_INT and
+ /// it can be expressed as a value of Java byte primitive type.
+ /// Note that in addition to "natural" input range of {@code [-128, 127]},
+ /// this also allows "unsigned 8-bit byte" values {@code [128, 255]}:
+ /// but for this range value will be translated by truncation, leading
+ /// to sign change.
+ ///
+ /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
+ /// if so, it is equivalent to calling \#getDoubleValue
+ /// and then casting; except for possible overflow/underflow
+ /// exception.
+ ///
+ /// Note: if the resulting integer value falls outside range of
+ /// {@code [-128, 255]},
+ /// a InputCoercionException
+ /// will be thrown to indicate numeric overflow/underflow.
+ ///@return Current number value as {@code byte} (if numeric token within
+ /// range of {@code [-128, 255]}); otherwise exception thrown
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getByteValue() {
+ return _getByteValue(reference).byte;
+ }
+
+ static final _getShortValue = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getShortValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public short getShortValue()
+ ///
+ /// Numeric accessor that can be called when the current
+ /// token is of type JsonToken\#VALUE_NUMBER_INT and
+ /// it can be expressed as a value of Java short primitive type.
+ /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
+ /// if so, it is equivalent to calling \#getDoubleValue
+ /// and then casting; except for possible overflow/underflow
+ /// exception.
+ ///
+ /// Note: if the resulting integer value falls outside range of
+ /// Java short, a InputCoercionException
+ /// will be thrown to indicate numeric overflow/underflow.
+ ///@return Current number value as {@code short} (if numeric token within
+ /// Java 16-bit signed {@code short} range); otherwise exception thrown
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getShortValue() {
+ return _getShortValue(reference).short;
+ }
+
+ static final _getIntValue = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getIntValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract int getIntValue()
+ ///
+ /// Numeric accessor that can be called when the current
+ /// token is of type JsonToken\#VALUE_NUMBER_INT and
+ /// it can be expressed as a value of Java int primitive type.
+ /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
+ /// if so, it is equivalent to calling \#getDoubleValue
+ /// and then casting; except for possible overflow/underflow
+ /// exception.
+ ///
+ /// Note: if the resulting integer value falls outside range of
+ /// Java {@code int}, a InputCoercionException
+ /// may be thrown to indicate numeric overflow/underflow.
+ ///@return Current number value as {@code int} (if numeric token within
+ /// Java 32-bit signed {@code int} range); otherwise exception thrown
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getIntValue() {
+ return _getIntValue(reference).integer;
+ }
+
+ static final _getLongValue = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getLongValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract long getLongValue()
+ ///
+ /// Numeric accessor that can be called when the current
+ /// token is of type JsonToken\#VALUE_NUMBER_INT and
+ /// it can be expressed as a Java long primitive type.
+ /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
+ /// if so, it is equivalent to calling \#getDoubleValue
+ /// and then casting to int; except for possible overflow/underflow
+ /// exception.
+ ///
+ /// Note: if the token is an integer, but its value falls
+ /// outside of range of Java long, a InputCoercionException
+ /// may be thrown to indicate numeric overflow/underflow.
+ ///@return Current number value as {@code long} (if numeric token within
+ /// Java 32-bit signed {@code long} range); otherwise exception thrown
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getLongValue() {
+ return _getLongValue(reference).long;
+ }
+
+ static final _getBigIntegerValue = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getBigIntegerValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract java.math.BigInteger getBigIntegerValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Numeric accessor that can be called when the current
+ /// token is of type JsonToken\#VALUE_NUMBER_INT and
+ /// it can not be used as a Java long primitive type due to its
+ /// magnitude.
+ /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
+ /// if so, it is equivalent to calling \#getDecimalValue
+ /// and then constructing a BigInteger from that value.
+ ///@return Current number value as BigInteger (if numeric token);
+ /// otherwise exception thrown
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JObject getBigIntegerValue() {
+ return const jni.JObjectType()
+ .fromRef(_getBigIntegerValue(reference).object);
+ }
+
+ static final _getFloatValue = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getFloatValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract float getFloatValue()
+ ///
+ /// Numeric accessor that can be called when the current
+ /// token is of type JsonToken\#VALUE_NUMBER_FLOAT and
+ /// it can be expressed as a Java float primitive type.
+ /// It can also be called for JsonToken\#VALUE_NUMBER_INT;
+ /// if so, it is equivalent to calling \#getLongValue
+ /// and then casting; except for possible overflow/underflow
+ /// exception.
+ ///
+ /// Note: if the value falls
+ /// outside of range of Java float, a InputCoercionException
+ /// will be thrown to indicate numeric overflow/underflow.
+ ///@return Current number value as {@code float} (if numeric token within
+ /// Java {@code float} range); otherwise exception thrown
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ double getFloatValue() {
+ return _getFloatValue(reference).float;
+ }
+
+ static final _getDoubleValue = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getDoubleValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract double getDoubleValue()
+ ///
+ /// Numeric accessor that can be called when the current
+ /// token is of type JsonToken\#VALUE_NUMBER_FLOAT and
+ /// it can be expressed as a Java double primitive type.
+ /// It can also be called for JsonToken\#VALUE_NUMBER_INT;
+ /// if so, it is equivalent to calling \#getLongValue
+ /// and then casting; except for possible overflow/underflow
+ /// exception.
+ ///
+ /// Note: if the value falls
+ /// outside of range of Java double, a InputCoercionException
+ /// will be thrown to indicate numeric overflow/underflow.
+ ///@return Current number value as {@code double} (if numeric token within
+ /// Java {@code double} range); otherwise exception thrown
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ double getDoubleValue() {
+ return _getDoubleValue(reference).doubleFloat;
+ }
+
+ static final _getDecimalValue = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getDecimalValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract java.math.BigDecimal getDecimalValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Numeric accessor that can be called when the current
+ /// token is of type JsonToken\#VALUE_NUMBER_FLOAT or
+ /// JsonToken\#VALUE_NUMBER_INT. No under/overflow exceptions
+ /// are ever thrown.
+ ///@return Current number value as BigDecimal (if numeric token);
+ /// otherwise exception thrown
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JObject getDecimalValue() {
+ return const jni.JObjectType().fromRef(_getDecimalValue(reference).object);
+ }
+
+ static final _getBooleanValue = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getBooleanValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean getBooleanValue()
+ ///
+ /// Convenience accessor that can be called when the current
+ /// token is JsonToken\#VALUE_TRUE or
+ /// JsonToken\#VALUE_FALSE, to return matching {@code boolean}
+ /// value.
+ /// If the current token is of some other type, JsonParseException
+ /// will be thrown
+ ///@return {@code True} if current token is {@code JsonToken.VALUE_TRUE},
+ /// {@code false} if current token is {@code JsonToken.VALUE_FALSE};
+ /// otherwise throws JsonParseException
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ bool getBooleanValue() {
+ return _getBooleanValue(reference).boolean;
+ }
+
+ static final _getEmbeddedObject = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getEmbeddedObject")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.Object getEmbeddedObject()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Accessor that can be called if (and only if) the current token
+ /// is JsonToken\#VALUE_EMBEDDED_OBJECT. For other token types,
+ /// null is returned.
+ ///
+ /// Note: only some specialized parser implementations support
+ /// embedding of objects (usually ones that are facades on top
+ /// of non-streaming sources, such as object trees). One exception
+ /// is access to binary content (whether via base64 encoding or not)
+ /// which typically is accessible using this method, as well as
+ /// \#getBinaryValue().
+ ///@return Embedded value (usually of "native" type supported by format)
+ /// for the current token, if any; {@code null otherwise}
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JObject getEmbeddedObject() {
+ return const jni.JObjectType()
+ .fromRef(_getEmbeddedObject(reference).object);
+ }
+
+ static final _getBinaryValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__getBinaryValue")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract byte[] getBinaryValue(com.fasterxml.jackson.core.Base64Variant bv)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that can be used to read (and consume -- results
+ /// may not be accessible using other methods after the call)
+ /// base64-encoded binary data
+ /// included in the current textual JSON value.
+ /// It works similar to getting String value via \#getText
+ /// and decoding result (except for decoding part),
+ /// but should be significantly more performant.
+ ///
+ /// Note that non-decoded textual contents of the current token
+ /// are not guaranteed to be accessible after this method
+ /// is called. Current implementation, for example, clears up
+ /// textual content during decoding.
+ /// Decoded binary content, however, will be retained until
+ /// parser is advanced to the next event.
+ ///@param bv Expected variant of base64 encoded
+ /// content (see Base64Variants for definitions
+ /// of "standard" variants).
+ ///@return Decoded binary data
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JArray<jni.jbyte> getBinaryValue(
+ jni.JObject bv,
+ ) {
+ return const jni.JArrayType(jni.jbyteType())
+ .fromRef(_getBinaryValue(reference, bv.reference).object);
+ }
+
+ static final _getBinaryValue1 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getBinaryValue1")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public byte[] getBinaryValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Convenience alternative to \#getBinaryValue(Base64Variant)
+ /// that defaults to using
+ /// Base64Variants\#getDefaultVariant as the default encoding.
+ ///@return Decoded binary data
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JArray<jni.jbyte> getBinaryValue1() {
+ return const jni.JArrayType(jni.jbyteType())
+ .fromRef(_getBinaryValue1(reference).object);
+ }
+
+ static final _readBinaryValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__readBinaryValue")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int readBinaryValue(java.io.OutputStream out)
+ ///
+ /// Method that can be used as an alternative to \#getBigIntegerValue(),
+ /// especially when value can be large. The main difference (beyond method
+ /// of returning content using OutputStream instead of as byte array)
+ /// is that content will NOT remain accessible after method returns: any content
+ /// processed will be consumed and is not buffered in any way. If caller needs
+ /// buffering, it has to implement it.
+ ///@param out Output stream to use for passing decoded binary data
+ ///@return Number of bytes that were decoded and written via OutputStream
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.1
+ int readBinaryValue(
+ jni.JObject out,
+ ) {
+ return _readBinaryValue(reference, out.reference).integer;
+ }
+
+ static final _readBinaryValue1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__readBinaryValue1")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int readBinaryValue(com.fasterxml.jackson.core.Base64Variant bv, java.io.OutputStream out)
+ ///
+ /// Similar to \#readBinaryValue(OutputStream) but allows explicitly
+ /// specifying base64 variant to use.
+ ///@param bv base64 variant to use
+ ///@param out Output stream to use for passing decoded binary data
+ ///@return Number of bytes that were decoded and written via OutputStream
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.1
+ int readBinaryValue1(
+ jni.JObject bv,
+ jni.JObject out,
+ ) {
+ return _readBinaryValue1(reference, bv.reference, out.reference).integer;
+ }
+
+ static final _getValueAsInt = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getValueAsInt")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int getValueAsInt()
+ ///
+ /// Method that will try to convert value of current token to a
+ /// Java {@code int} value.
+ /// Numbers are coerced using default Java rules; booleans convert to 0 (false)
+ /// and 1 (true), and Strings are parsed using default Java language integer
+ /// parsing rules.
+ ///
+ /// If representation can not be converted to an int (including structured type
+ /// markers like start/end Object/Array)
+ /// default value of __0__ will be returned; no exceptions are thrown.
+ ///@return {@code int} value current token is converted to, if possible; exception thrown
+ /// otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getValueAsInt() {
+ return _getValueAsInt(reference).integer;
+ }
+
+ static final _getValueAsInt1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Int32)>>("JsonParser__getValueAsInt1")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public int getValueAsInt(int def)
+ ///
+ /// Method that will try to convert value of current token to a
+ /// __int__.
+ /// Numbers are coerced using default Java rules; booleans convert to 0 (false)
+ /// and 1 (true), and Strings are parsed using default Java language integer
+ /// parsing rules.
+ ///
+ /// If representation can not be converted to an int (including structured type
+ /// markers like start/end Object/Array)
+ /// specified __def__ will be returned; no exceptions are thrown.
+ ///@param def Default value to return if conversion to {@code int} is not possible
+ ///@return {@code int} value current token is converted to, if possible; {@code def} otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getValueAsInt1(
+ int def,
+ ) {
+ return _getValueAsInt1(reference, def).integer;
+ }
+
+ static final _getValueAsLong = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getValueAsLong")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public long getValueAsLong()
+ ///
+ /// Method that will try to convert value of current token to a
+ /// __long__.
+ /// Numbers are coerced using default Java rules; booleans convert to 0 (false)
+ /// and 1 (true), and Strings are parsed using default Java language integer
+ /// parsing rules.
+ ///
+ /// If representation can not be converted to a long (including structured type
+ /// markers like start/end Object/Array)
+ /// default value of __0L__ will be returned; no exceptions are thrown.
+ ///@return {@code long} value current token is converted to, if possible; exception thrown
+ /// otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getValueAsLong() {
+ return _getValueAsLong(reference).long;
+ }
+
+ static final _getValueAsLong1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Int64)>>("JsonParser__getValueAsLong1")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public long getValueAsLong(long def)
+ ///
+ /// Method that will try to convert value of current token to a
+ /// __long__.
+ /// Numbers are coerced using default Java rules; booleans convert to 0 (false)
+ /// and 1 (true), and Strings are parsed using default Java language integer
+ /// parsing rules.
+ ///
+ /// If representation can not be converted to a long (including structured type
+ /// markers like start/end Object/Array)
+ /// specified __def__ will be returned; no exceptions are thrown.
+ ///@param def Default value to return if conversion to {@code long} is not possible
+ ///@return {@code long} value current token is converted to, if possible; {@code def} otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getValueAsLong1(
+ int def,
+ ) {
+ return _getValueAsLong1(reference, def).long;
+ }
+
+ static final _getValueAsDouble = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getValueAsDouble")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public double getValueAsDouble()
+ ///
+ /// Method that will try to convert value of current token to a Java
+ /// __double__.
+ /// Numbers are coerced using default Java rules; booleans convert to 0.0 (false)
+ /// and 1.0 (true), and Strings are parsed using default Java language floating
+ /// point parsing rules.
+ ///
+ /// If representation can not be converted to a double (including structured types
+ /// like Objects and Arrays),
+ /// default value of __0.0__ will be returned; no exceptions are thrown.
+ ///@return {@code double} value current token is converted to, if possible; exception thrown
+ /// otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ double getValueAsDouble() {
+ return _getValueAsDouble(reference).doubleFloat;
+ }
+
+ static final _getValueAsDouble1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Double)>>("JsonParser__getValueAsDouble1")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, double)>();
+
+ /// from: public double getValueAsDouble(double def)
+ ///
+ /// Method that will try to convert value of current token to a
+ /// Java __double__.
+ /// Numbers are coerced using default Java rules; booleans convert to 0.0 (false)
+ /// and 1.0 (true), and Strings are parsed using default Java language floating
+ /// point parsing rules.
+ ///
+ /// If representation can not be converted to a double (including structured types
+ /// like Objects and Arrays),
+ /// specified __def__ will be returned; no exceptions are thrown.
+ ///@param def Default value to return if conversion to {@code double} is not possible
+ ///@return {@code double} value current token is converted to, if possible; {@code def} otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ double getValueAsDouble1(
+ double def,
+ ) {
+ return _getValueAsDouble1(reference, def).doubleFloat;
+ }
+
+ static final _getValueAsBoolean = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getValueAsBoolean")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean getValueAsBoolean()
+ ///
+ /// Method that will try to convert value of current token to a
+ /// __boolean__.
+ /// JSON booleans map naturally; integer numbers other than 0 map to true, and
+ /// 0 maps to false
+ /// and Strings 'true' and 'false' map to corresponding values.
+ ///
+ /// If representation can not be converted to a boolean value (including structured types
+ /// like Objects and Arrays),
+ /// default value of __false__ will be returned; no exceptions are thrown.
+ ///@return {@code boolean} value current token is converted to, if possible; exception thrown
+ /// otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ bool getValueAsBoolean() {
+ return _getValueAsBoolean(reference).boolean;
+ }
+
+ static final _getValueAsBoolean1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Uint8)>>("JsonParser__getValueAsBoolean1")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public boolean getValueAsBoolean(boolean def)
+ ///
+ /// Method that will try to convert value of current token to a
+ /// __boolean__.
+ /// JSON booleans map naturally; integer numbers other than 0 map to true, and
+ /// 0 maps to false
+ /// and Strings 'true' and 'false' map to corresponding values.
+ ///
+ /// If representation can not be converted to a boolean value (including structured types
+ /// like Objects and Arrays),
+ /// specified __def__ will be returned; no exceptions are thrown.
+ ///@param def Default value to return if conversion to {@code boolean} is not possible
+ ///@return {@code boolean} value current token is converted to, if possible; {@code def} otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ bool getValueAsBoolean1(
+ bool def,
+ ) {
+ return _getValueAsBoolean1(reference, def ? 1 : 0).boolean;
+ }
+
+ static final _getValueAsString = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getValueAsString")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getValueAsString()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that will try to convert value of current token to a
+ /// java.lang.String.
+ /// JSON Strings map naturally; scalar values get converted to
+ /// their textual representation.
+ /// If representation can not be converted to a String value (including structured types
+ /// like Objects and Arrays and {@code null} token), default value of
+ /// __null__ will be returned; no exceptions are thrown.
+ ///@return String value current token is converted to, if possible; {@code null} otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.1
+ jni.JString getValueAsString() {
+ return const jni.JStringType().fromRef(_getValueAsString(reference).object);
+ }
+
+ static final _getValueAsString1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__getValueAsString1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract java.lang.String getValueAsString(java.lang.String def)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that will try to convert value of current token to a
+ /// java.lang.String.
+ /// JSON Strings map naturally; scalar values get converted to
+ /// their textual representation.
+ /// If representation can not be converted to a String value (including structured types
+ /// like Objects and Arrays and {@code null} token), specified default value
+ /// will be returned; no exceptions are thrown.
+ ///@param def Default value to return if conversion to {@code String} is not possible
+ ///@return String value current token is converted to, if possible; {@code def} otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.1
+ jni.JString getValueAsString1(
+ jni.JString def,
+ ) {
+ return const jni.JStringType()
+ .fromRef(_getValueAsString1(reference, def.reference).object);
+ }
+
+ static final _canReadObjectId = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__canReadObjectId")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean canReadObjectId()
+ ///
+ /// Introspection method that may be called to see if the underlying
+ /// data format supports some kind of Object Ids natively (many do not;
+ /// for example, JSON doesn't).
+ ///
+ /// Default implementation returns true; overridden by data formats
+ /// that do support native Object Ids. Caller is expected to either
+ /// use a non-native notation (explicit property or such), or fail,
+ /// in case it can not use native object ids.
+ ///@return {@code True} if the format being read supports native Object Ids;
+ /// {@code false} if not
+ ///@since 2.3
+ bool canReadObjectId() {
+ return _canReadObjectId(reference).boolean;
+ }
+
+ static final _canReadTypeId = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__canReadTypeId")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean canReadTypeId()
+ ///
+ /// Introspection method that may be called to see if the underlying
+ /// data format supports some kind of Type Ids natively (many do not;
+ /// for example, JSON doesn't).
+ ///
+ /// Default implementation returns true; overridden by data formats
+ /// that do support native Type Ids. Caller is expected to either
+ /// use a non-native notation (explicit property or such), or fail,
+ /// in case it can not use native type ids.
+ ///@return {@code True} if the format being read supports native Type Ids;
+ /// {@code false} if not
+ ///@since 2.3
+ bool canReadTypeId() {
+ return _canReadTypeId(reference).boolean;
+ }
+
+ static final _getObjectId = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getObjectId")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.Object getObjectId()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that can be called to check whether current token
+ /// (one that was just read) has an associated Object id, and if
+ /// so, return it.
+ /// Note that while typically caller should check with \#canReadObjectId
+ /// first, it is not illegal to call this method even if that method returns
+ /// true; but if so, it will return null. This may be used to simplify calling
+ /// code.
+ ///
+ /// Default implementation will simply return null.
+ ///@return Native Object id associated with the current token, if any; {@code null} if none
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.3
+ jni.JObject getObjectId() {
+ return const jni.JObjectType().fromRef(_getObjectId(reference).object);
+ }
+
+ static final _getTypeId = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__getTypeId")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.Object getTypeId()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that can be called to check whether current token
+ /// (one that was just read) has an associated type id, and if
+ /// so, return it.
+ /// Note that while typically caller should check with \#canReadTypeId
+ /// first, it is not illegal to call this method even if that method returns
+ /// true; but if so, it will return null. This may be used to simplify calling
+ /// code.
+ ///
+ /// Default implementation will simply return null.
+ ///@return Native Type Id associated with the current token, if any; {@code null} if none
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.3
+ jni.JObject getTypeId() {
+ return const jni.JObjectType().fromRef(_getTypeId(reference).object);
+ }
+
+ static final _readValueAs = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__readValueAs")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public T readValueAs(java.lang.Class<T> valueType)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method to deserialize JSON content into a non-container
+ /// type (it can be an array type, however): typically a bean, array
+ /// or a wrapper type (like java.lang.Boolean).
+ /// __Note__: method can only be called if the parser has
+ /// an object codec assigned; this is true for parsers constructed
+ /// by <code>MappingJsonFactory</code> (from "jackson-databind" jar)
+ /// but not for JsonFactory (unless its <code>setCodec</code>
+ /// method has been explicitly called).
+ ///
+ /// This method may advance the event stream, for structured types
+ /// the current token will be the closing end marker (END_ARRAY,
+ /// END_OBJECT) of the bound structure. For non-structured Json types
+ /// (and for JsonToken\#VALUE_EMBEDDED_OBJECT)
+ /// stream is not advanced.
+ ///
+ /// Note: this method should NOT be used if the result type is a
+ /// container (java.util.Collection or java.util.Map.
+ /// The reason is that due to type erasure, key and value types
+ /// can not be introspected when using this method.
+ ///@param <T> Nominal type parameter for value type
+ ///@param valueType Java type to read content as (passed to ObjectCodec that
+ /// deserializes content)
+ ///@return Java value read from content
+ ///@throws IOException if there is either an underlying I/O problem or decoding
+ /// issue at format layer
+ $T readValueAs<$T extends jni.JObject>(
+ jni.JObject valueType, {
+ required jni.JObjType<$T> T,
+ }) {
+ return T.fromRef(_readValueAs(reference, valueType.reference).object);
+ }
+
+ static final _readValueAs1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__readValueAs1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public T readValueAs(com.fasterxml.jackson.core.type.TypeReference<?> valueTypeRef)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method to deserialize JSON content into a Java type, reference
+ /// to which is passed as argument. Type is passed using so-called
+ /// "super type token"
+ /// and specifically needs to be used if the root type is a
+ /// parameterized (generic) container type.
+ /// __Note__: method can only be called if the parser has
+ /// an object codec assigned; this is true for parsers constructed
+ /// by <code>MappingJsonFactory</code> (defined in 'jackson-databind' bundle)
+ /// but not for JsonFactory (unless its <code>setCodec</code>
+ /// method has been explicitly called).
+ ///
+ /// This method may advance the event stream, for structured types
+ /// the current token will be the closing end marker (END_ARRAY,
+ /// END_OBJECT) of the bound structure. For non-structured Json types
+ /// (and for JsonToken\#VALUE_EMBEDDED_OBJECT)
+ /// stream is not advanced.
+ ///@param <T> Nominal type parameter for value type
+ ///@param valueTypeRef Java type to read content as (passed to ObjectCodec that
+ /// deserializes content)
+ ///@return Java value read from content
+ ///@throws IOException if there is either an underlying I/O problem or decoding
+ /// issue at format layer
+ $T readValueAs1<$T extends jni.JObject>(
+ jni.JObject valueTypeRef, {
+ required jni.JObjType<$T> T,
+ }) {
+ return T.fromRef(_readValueAs1(reference, valueTypeRef.reference).object);
+ }
+
+ static final _readValuesAs = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__readValuesAs")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.util.Iterator<T> readValuesAs(java.lang.Class<T> valueType)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for reading sequence of Objects from parser stream,
+ /// all with same specified value type.
+ ///@param <T> Nominal type parameter for value type
+ ///@param valueType Java type to read content as (passed to ObjectCodec that
+ /// deserializes content)
+ ///@return Iterator for reading multiple Java values from content
+ ///@throws IOException if there is either an underlying I/O problem or decoding
+ /// issue at format layer
+ jni.JIterator<$T> readValuesAs<$T extends jni.JObject>(
+ jni.JObject valueType, {
+ required jni.JObjType<$T> T,
+ }) {
+ return jni.JIteratorType(T)
+ .fromRef(_readValuesAs(reference, valueType.reference).object);
+ }
+
+ static final _readValuesAs1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("JsonParser__readValuesAs1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.util.Iterator<T> readValuesAs(com.fasterxml.jackson.core.type.TypeReference<T> valueTypeRef)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for reading sequence of Objects from parser stream,
+ /// all with same specified value type.
+ ///@param <T> Nominal type parameter for value type
+ ///@param valueTypeRef Java type to read content as (passed to ObjectCodec that
+ /// deserializes content)
+ ///@return Iterator for reading multiple Java values from content
+ ///@throws IOException if there is either an underlying I/O problem or decoding
+ /// issue at format layer
+ jni.JIterator<$T> readValuesAs1<$T extends jni.JObject>(
+ jni.JObject valueTypeRef, {
+ required jni.JObjType<$T> T,
+ }) {
+ return jni.JIteratorType(T)
+ .fromRef(_readValuesAs1(reference, valueTypeRef.reference).object);
+ }
+
+ static final _readValueAsTree = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser__readValueAsTree")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public T readValueAsTree()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method to deserialize JSON content into equivalent "tree model",
+ /// represented by root TreeNode of resulting model.
+ /// For JSON Arrays it will an array node (with child nodes),
+ /// for objects object node (with child nodes), and for other types
+ /// matching leaf node type. Empty or whitespace documents are null.
+ ///@param <T> Nominal type parameter for result node type (to reduce need for casting)
+ ///@return root of the document, or null if empty or whitespace.
+ ///@throws IOException if there is either an underlying I/O problem or decoding
+ /// issue at format layer
+ $T readValueAsTree<$T extends jni.JObject>({
+ required jni.JObjType<$T> T,
+ }) {
+ return T.fromRef(_readValueAsTree(reference).object);
+ }
+}
+
+final class $JsonParserType extends jni.JObjType<JsonParser> {
+ const $JsonParserType();
+
+ @override
+ String get signature => r"Lcom/fasterxml/jackson/core/JsonParser;";
+
+ @override
+ JsonParser fromRef(jni.JObjectPtr ref) => JsonParser.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($JsonParserType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($JsonParserType) && other is $JsonParserType;
+ }
+}
+
+/// from: com.fasterxml.jackson.core.JsonParser$Feature
+///
+/// Enumeration that defines all on/off features for parsers.
+class JsonParser_Feature extends jni.JObject {
+ @override
+ late final jni.JObjType<JsonParser_Feature> $type = type;
+
+ JsonParser_Feature.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $JsonParser_FeatureType();
+ static final _values =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "JsonParser_Feature__values")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public com.fasterxml.jackson.core.JsonParser.Feature[] values()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<JsonParser_Feature> values() {
+ return const jni.JArrayType($JsonParser_FeatureType())
+ .fromRef(_values().object);
+ }
+
+ static final _valueOf = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser_Feature__valueOf")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public com.fasterxml.jackson.core.JsonParser.Feature valueOf(java.lang.String name)
+ /// The returned object must be released after use, by calling the [release] method.
+ static JsonParser_Feature valueOf(
+ jni.JString name,
+ ) {
+ return const $JsonParser_FeatureType()
+ .fromRef(_valueOf(name.reference).object);
+ }
+
+ static final _collectDefaults =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "JsonParser_Feature__collectDefaults")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public int collectDefaults()
+ ///
+ /// Method that calculates bit set (flags) of all features that
+ /// are enabled by default.
+ ///@return Bit mask of all features that are enabled by default
+ static int collectDefaults() {
+ return _collectDefaults().integer;
+ }
+
+ static final _enabledByDefault = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser_Feature__enabledByDefault")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean enabledByDefault()
+ bool enabledByDefault() {
+ return _enabledByDefault(reference).boolean;
+ }
+
+ static final _enabledIn = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Int32)>>("JsonParser_Feature__enabledIn")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public boolean enabledIn(int flags)
+ bool enabledIn(
+ int flags,
+ ) {
+ return _enabledIn(reference, flags).boolean;
+ }
+
+ static final _getMask = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser_Feature__getMask")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int getMask()
+ int getMask() {
+ return _getMask(reference).integer;
+ }
+}
+
+final class $JsonParser_FeatureType extends jni.JObjType<JsonParser_Feature> {
+ const $JsonParser_FeatureType();
+
+ @override
+ String get signature => r"Lcom/fasterxml/jackson/core/JsonParser$Feature;";
+
+ @override
+ JsonParser_Feature fromRef(jni.JObjectPtr ref) =>
+ JsonParser_Feature.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($JsonParser_FeatureType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($JsonParser_FeatureType) &&
+ other is $JsonParser_FeatureType;
+ }
+}
+
+/// from: com.fasterxml.jackson.core.JsonParser$NumberType
+///
+/// Enumeration of possible "native" (optimal) types that can be
+/// used for numbers.
+class JsonParser_NumberType extends jni.JObject {
+ @override
+ late final jni.JObjType<JsonParser_NumberType> $type = type;
+
+ JsonParser_NumberType.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $JsonParser_NumberTypeType();
+ static final _values =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "JsonParser_NumberType__values")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public com.fasterxml.jackson.core.JsonParser.NumberType[] values()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<JsonParser_NumberType> values() {
+ return const jni.JArrayType($JsonParser_NumberTypeType())
+ .fromRef(_values().object);
+ }
+
+ static final _valueOf = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonParser_NumberType__valueOf")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public com.fasterxml.jackson.core.JsonParser.NumberType valueOf(java.lang.String name)
+ /// The returned object must be released after use, by calling the [release] method.
+ static JsonParser_NumberType valueOf(
+ jni.JString name,
+ ) {
+ return const $JsonParser_NumberTypeType()
+ .fromRef(_valueOf(name.reference).object);
+ }
+}
+
+final class $JsonParser_NumberTypeType
+ extends jni.JObjType<JsonParser_NumberType> {
+ const $JsonParser_NumberTypeType();
+
+ @override
+ String get signature => r"Lcom/fasterxml/jackson/core/JsonParser$NumberType;";
+
+ @override
+ JsonParser_NumberType fromRef(jni.JObjectPtr ref) =>
+ JsonParser_NumberType.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($JsonParser_NumberTypeType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($JsonParser_NumberTypeType) &&
+ other is $JsonParser_NumberTypeType;
+ }
+}
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonToken.dart b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonToken.dart
new file mode 100644
index 0000000..2d036c5
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/JsonToken.dart
@@ -0,0 +1,238 @@
+// Generated from jackson-core which is licensed under the Apache License 2.0.
+// The following copyright from the original authors applies.
+// See https://github.com/FasterXML/jackson-core/blob/2.14/LICENSE
+//
+// Copyright (c) 2007 - The Jackson Project Authors
+// Licensed under the Apache License, Version 2.0 (the "License")
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+// ignore_for_file: annotate_overrides
+// ignore_for_file: camel_case_extensions
+// ignore_for_file: camel_case_types
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: doc_directive_unknown
+// ignore_for_file: file_names
+// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: overridden_fields
+// ignore_for_file: unnecessary_cast
+// ignore_for_file: unused_element
+// ignore_for_file: unused_field
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: unused_shown_name
+
+import "dart:isolate" show ReceivePort;
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+import "package:jni/jni.dart" as jni;
+
+import "../../../../_init.dart";
+
+/// from: com.fasterxml.jackson.core.JsonToken
+///
+/// Enumeration for basic token types used for returning results
+/// of parsing JSON content.
+class JsonToken extends jni.JObject {
+ @override
+ late final jni.JObjType<JsonToken> $type = type;
+
+ JsonToken.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $JsonTokenType();
+ static final _values =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "JsonToken__values")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public com.fasterxml.jackson.core.JsonToken[] values()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<JsonToken> values() {
+ return const jni.JArrayType($JsonTokenType()).fromRef(_values().object);
+ }
+
+ static final _valueOf = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonToken__valueOf")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public com.fasterxml.jackson.core.JsonToken valueOf(java.lang.String name)
+ /// The returned object must be released after use, by calling the [release] method.
+ static JsonToken valueOf(
+ jni.JString name,
+ ) {
+ return const $JsonTokenType().fromRef(_valueOf(name.reference).object);
+ }
+
+ static final _id = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("JsonToken__id")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final int id()
+ int id() {
+ return _id(reference).integer;
+ }
+
+ static final _asString = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonToken__asString")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final java.lang.String asString()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JString asString() {
+ return const jni.JStringType().fromRef(_asString(reference).object);
+ }
+
+ static final _asCharArray = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonToken__asCharArray")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final char[] asCharArray()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JArray<jni.jchar> asCharArray() {
+ return const jni.JArrayType(jni.jcharType())
+ .fromRef(_asCharArray(reference).object);
+ }
+
+ static final _asByteArray = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonToken__asByteArray")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final byte[] asByteArray()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JArray<jni.jbyte> asByteArray() {
+ return const jni.JArrayType(jni.jbyteType())
+ .fromRef(_asByteArray(reference).object);
+ }
+
+ static final _isNumeric = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonToken__isNumeric")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final boolean isNumeric()
+ ///
+ /// @return {@code True} if this token is {@code VALUE_NUMBER_INT} or {@code VALUE_NUMBER_FLOAT},
+ /// {@code false} otherwise
+ bool isNumeric() {
+ return _isNumeric(reference).boolean;
+ }
+
+ static final _isStructStart = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonToken__isStructStart")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final boolean isStructStart()
+ ///
+ /// Accessor that is functionally equivalent to:
+ /// <code>
+ /// this == JsonToken.START_OBJECT || this == JsonToken.START_ARRAY
+ /// </code>
+ ///@return {@code True} if this token is {@code START_OBJECT} or {@code START_ARRAY},
+ /// {@code false} otherwise
+ ///@since 2.3
+ bool isStructStart() {
+ return _isStructStart(reference).boolean;
+ }
+
+ static final _isStructEnd = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonToken__isStructEnd")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final boolean isStructEnd()
+ ///
+ /// Accessor that is functionally equivalent to:
+ /// <code>
+ /// this == JsonToken.END_OBJECT || this == JsonToken.END_ARRAY
+ /// </code>
+ ///@return {@code True} if this token is {@code END_OBJECT} or {@code END_ARRAY},
+ /// {@code false} otherwise
+ ///@since 2.3
+ bool isStructEnd() {
+ return _isStructEnd(reference).boolean;
+ }
+
+ static final _isScalarValue = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonToken__isScalarValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final boolean isScalarValue()
+ ///
+ /// Method that can be used to check whether this token represents
+ /// a valid non-structured value. This means all {@code VALUE_xxx} tokens;
+ /// excluding {@code START_xxx} and {@code END_xxx} tokens as well
+ /// {@code FIELD_NAME}.
+ ///@return {@code True} if this token is a scalar value token (one of
+ /// {@code VALUE_xxx} tokens), {@code false} otherwise
+ bool isScalarValue() {
+ return _isScalarValue(reference).boolean;
+ }
+
+ static final _isBoolean = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonToken__isBoolean")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final boolean isBoolean()
+ ///
+ /// @return {@code True} if this token is {@code VALUE_TRUE} or {@code VALUE_FALSE},
+ /// {@code false} otherwise
+ bool isBoolean() {
+ return _isBoolean(reference).boolean;
+ }
+}
+
+final class $JsonTokenType extends jni.JObjType<JsonToken> {
+ const $JsonTokenType();
+
+ @override
+ String get signature => r"Lcom/fasterxml/jackson/core/JsonToken;";
+
+ @override
+ JsonToken fromRef(jni.JObjectPtr ref) => JsonToken.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($JsonTokenType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($JsonTokenType) && other is $JsonTokenType;
+ }
+}
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/_package.dart b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/_package.dart
new file mode 100644
index 0000000..cae2a52
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/c_based/dart_bindings/com/fasterxml/jackson/core/_package.dart
@@ -0,0 +1,3 @@
+export "JsonFactory.dart";
+export "JsonParser.dart";
+export "JsonToken.dart";
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonFactory.dart b/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonFactory.dart
new file mode 100644
index 0000000..5aab2d4
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonFactory.dart
@@ -0,0 +1,1896 @@
+// Generated from jackson-core which is licensed under the Apache License 2.0.
+// The following copyright from the original authors applies.
+// See https://github.com/FasterXML/jackson-core/blob/2.14/LICENSE
+//
+// Copyright (c) 2007 - The Jackson Project Authors
+// Licensed under the Apache License, Version 2.0 (the "License")
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+// ignore_for_file: annotate_overrides
+// ignore_for_file: camel_case_extensions
+// ignore_for_file: camel_case_types
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: doc_directive_unknown
+// ignore_for_file: file_names
+// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: overridden_fields
+// ignore_for_file: unnecessary_cast
+// ignore_for_file: unused_element
+// ignore_for_file: unused_field
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: unused_shown_name
+
+import "dart:isolate" show ReceivePort;
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+import "package:jni/jni.dart" as jni;
+
+import "JsonParser.dart" as jsonparser_;
+
+/// from: com.fasterxml.jackson.core.JsonFactory
+///
+/// The main factory class of Jackson package, used to configure and
+/// construct reader (aka parser, JsonParser)
+/// and writer (aka generator, JsonGenerator)
+/// instances.
+///
+/// Factory instances are thread-safe and reusable after configuration
+/// (if any). Typically applications and services use only a single
+/// globally shared factory instance, unless they need differently
+/// configured factories. Factory reuse is important if efficiency matters;
+/// most recycling of expensive construct is done on per-factory basis.
+///
+/// Creation of a factory instance is a light-weight operation,
+/// and since there is no need for pluggable alternative implementations
+/// (as there is no "standard" JSON processor API to implement),
+/// the default constructor is used for constructing factory
+/// instances.
+///@author Tatu Saloranta
+class JsonFactory extends jni.JObject {
+ @override
+ late final jni.JObjType<JsonFactory> $type = type;
+
+ JsonFactory.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/fasterxml/jackson/core/JsonFactory");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $JsonFactoryType();
+
+ /// from: static public final java.lang.String FORMAT_NAME_JSON
+ ///
+ /// Name used to identify JSON format
+ /// (and returned by \#getFormatName()
+ static const FORMAT_NAME_JSON = r"""JSON""";
+
+ static final _id_DEFAULT_FACTORY_FEATURE_FLAGS =
+ jni.Jni.accessors.getStaticFieldIDOf(
+ _class.reference,
+ r"DEFAULT_FACTORY_FEATURE_FLAGS",
+ r"I",
+ );
+
+ /// from: static protected final int DEFAULT_FACTORY_FEATURE_FLAGS
+ ///
+ /// Bitfield (set of flags) of all factory features that are enabled by default.
+ static int get DEFAULT_FACTORY_FEATURE_FLAGS => jni.Jni.accessors
+ .getStaticField(_class.reference, _id_DEFAULT_FACTORY_FEATURE_FLAGS,
+ jni.JniCallType.intType)
+ .integer;
+
+ static final _id_DEFAULT_PARSER_FEATURE_FLAGS =
+ jni.Jni.accessors.getStaticFieldIDOf(
+ _class.reference,
+ r"DEFAULT_PARSER_FEATURE_FLAGS",
+ r"I",
+ );
+
+ /// from: static protected final int DEFAULT_PARSER_FEATURE_FLAGS
+ ///
+ /// Bitfield (set of flags) of all parser features that are enabled
+ /// by default.
+ static int get DEFAULT_PARSER_FEATURE_FLAGS => jni.Jni.accessors
+ .getStaticField(_class.reference, _id_DEFAULT_PARSER_FEATURE_FLAGS,
+ jni.JniCallType.intType)
+ .integer;
+
+ static final _id_DEFAULT_GENERATOR_FEATURE_FLAGS =
+ jni.Jni.accessors.getStaticFieldIDOf(
+ _class.reference,
+ r"DEFAULT_GENERATOR_FEATURE_FLAGS",
+ r"I",
+ );
+
+ /// from: static protected final int DEFAULT_GENERATOR_FEATURE_FLAGS
+ ///
+ /// Bitfield (set of flags) of all generator features that are enabled
+ /// by default.
+ static int get DEFAULT_GENERATOR_FEATURE_FLAGS => jni.Jni.accessors
+ .getStaticField(_class.reference, _id_DEFAULT_GENERATOR_FEATURE_FLAGS,
+ jni.JniCallType.intType)
+ .integer;
+
+ static final _id_DEFAULT_ROOT_VALUE_SEPARATOR =
+ jni.Jni.accessors.getStaticFieldIDOf(
+ _class.reference,
+ r"DEFAULT_ROOT_VALUE_SEPARATOR",
+ r"Lcom/fasterxml/jackson/core/SerializableString;",
+ );
+
+ /// from: static public final com.fasterxml.jackson.core.SerializableString DEFAULT_ROOT_VALUE_SEPARATOR
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JObject get DEFAULT_ROOT_VALUE_SEPARATOR =>
+ const jni.JObjectType().fromRef(jni.Jni.accessors
+ .getStaticField(_class.reference, _id_DEFAULT_ROOT_VALUE_SEPARATOR,
+ jni.JniCallType.objectType)
+ .object);
+
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Default constructor used to create factory instances.
+ /// Creation of a factory instance is a light-weight operation,
+ /// but it is still a good idea to reuse limited number of
+ /// factory instances (and quite often just a single instance):
+ /// factories are used as context for storing some reused
+ /// processing objects (such as symbol tables parsers use)
+ /// and this reuse only works within context of a single
+ /// factory instance.
+ factory JsonFactory() {
+ return JsonFactory.fromRef(jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+
+ static final _id_new1 = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"<init>", r"(Lcom/fasterxml/jackson/core/ObjectCodec;)V");
+
+ /// from: public void <init>(com.fasterxml.jackson.core.ObjectCodec oc)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory JsonFactory.new1(
+ jni.JObject oc,
+ ) {
+ return JsonFactory.fromRef(jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new1, [oc.reference]).object);
+ }
+
+ static final _id_new2 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"<init>",
+ r"(Lcom/fasterxml/jackson/core/JsonFactory;Lcom/fasterxml/jackson/core/ObjectCodec;)V");
+
+ /// from: protected void <init>(com.fasterxml.jackson.core.JsonFactory src, com.fasterxml.jackson.core.ObjectCodec codec)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Constructor used when copy()ing a factory instance.
+ ///@param src Original factory to copy settings from
+ ///@param codec Databinding-level codec to use, if any
+ ///@since 2.2.1
+ factory JsonFactory.new2(
+ JsonFactory src,
+ jni.JObject codec,
+ ) {
+ return JsonFactory.fromRef(jni.Jni.accessors.newObjectWithArgs(
+ _class.reference, _id_new2, [src.reference, codec.reference]).object);
+ }
+
+ static final _id_new3 = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"<init>", r"(Lcom/fasterxml/jackson/core/JsonFactoryBuilder;)V");
+
+ /// from: public void <init>(com.fasterxml.jackson.core.JsonFactoryBuilder b)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Constructor used by JsonFactoryBuilder for instantiation.
+ ///@param b Builder that contains settings to use
+ ///@since 2.10
+ factory JsonFactory.new3(
+ jni.JObject b,
+ ) {
+ return JsonFactory.fromRef(jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new3, [b.reference]).object);
+ }
+
+ static final _id_new4 = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"<init>", r"(Lcom/fasterxml/jackson/core/TSFBuilder;Z)V");
+
+ /// from: protected void <init>(com.fasterxml.jackson.core.TSFBuilder<?,?> b, boolean bogus)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Constructor for subtypes; needed to work around the fact that before 3.0,
+ /// this factory has cumbersome dual role as generic type as well as actual
+ /// implementation for json.
+ ///@param b Builder that contains settings to use
+ ///@param bogus Argument only needed to separate constructor signature; ignored
+ factory JsonFactory.new4(
+ jni.JObject b,
+ bool bogus,
+ ) {
+ return JsonFactory.fromRef(jni.Jni.accessors.newObjectWithArgs(
+ _class.reference, _id_new4, [b.reference, bogus ? 1 : 0]).object);
+ }
+
+ static final _id_rebuild = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"rebuild", r"()Lcom/fasterxml/jackson/core/TSFBuilder;");
+
+ /// from: public com.fasterxml.jackson.core.TSFBuilder<?,?> rebuild()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that allows construction of differently configured factory, starting
+ /// with settings of this factory.
+ ///@return Builder instance to use
+ ///@since 2.10
+ jni.JObject rebuild() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_rebuild, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_builder = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"builder",
+ r"()Lcom/fasterxml/jackson/core/TSFBuilder;");
+
+ /// from: static public com.fasterxml.jackson.core.TSFBuilder<?,?> builder()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Main factory method to use for constructing JsonFactory instances with
+ /// different configuration: creates and returns a builder for collecting configuration
+ /// settings; instance created by calling {@code build()} after all configuration
+ /// set.
+ ///
+ /// NOTE: signature unfortunately does not expose true implementation type; this
+ /// will be fixed in 3.0.
+ ///@return Builder instance to use
+ static jni.JObject builder() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _id_builder,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_copy = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"copy", r"()Lcom/fasterxml/jackson/core/JsonFactory;");
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory copy()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing a new JsonFactory that has
+ /// the same settings as this instance, but is otherwise
+ /// independent (i.e. nothing is actually shared, symbol tables
+ /// are separate).
+ /// Note that ObjectCodec reference is not copied but is
+ /// set to null; caller typically needs to set it after calling
+ /// this method. Reason for this is that the codec is used for
+ /// callbacks, and assumption is that there is strict 1-to-1
+ /// mapping between codec, factory. Caller has to, then, explicitly
+ /// set codec after making the copy.
+ ///@return Copy of this factory instance
+ ///@since 2.1
+ JsonFactory copy() {
+ return const $JsonFactoryType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(
+ reference, _id_copy, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_readResolve = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"readResolve", r"()Ljava/lang/Object;");
+
+ /// from: protected java.lang.Object readResolve()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that we need to override to actually make restoration go
+ /// through constructors etc: needed to allow JDK serializability of
+ /// factory instances.
+ ///
+ /// Note: must be overridden by sub-classes as well.
+ ///@return Newly constructed instance
+ jni.JObject readResolve() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_readResolve, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_requiresPropertyOrdering = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"requiresPropertyOrdering", r"()Z");
+
+ /// from: public boolean requiresPropertyOrdering()
+ ///
+ /// Introspection method that higher-level functionality may call
+ /// to see whether underlying data format requires a stable ordering
+ /// of object properties or not.
+ /// This is usually used for determining
+ /// whether to force a stable ordering (like alphabetic ordering by name)
+ /// if no ordering if explicitly specified.
+ ///
+ /// Default implementation returns <code>false</code> as JSON does NOT
+ /// require stable ordering. Formats that require ordering include positional
+ /// textual formats like <code>CSV</code>, and schema-based binary formats
+ /// like <code>Avro</code>.
+ ///@return Whether format supported by this factory
+ /// requires Object properties to be ordered.
+ ///@since 2.3
+ bool requiresPropertyOrdering() {
+ return jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_requiresPropertyOrdering, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_canHandleBinaryNatively = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"canHandleBinaryNatively", r"()Z");
+
+ /// from: public boolean canHandleBinaryNatively()
+ ///
+ /// Introspection method that higher-level functionality may call
+ /// to see whether underlying data format can read and write binary
+ /// data natively; that is, embeded it as-is without using encodings
+ /// such as Base64.
+ ///
+ /// Default implementation returns <code>false</code> as JSON does not
+ /// support native access: all binary content must use Base64 encoding.
+ /// Most binary formats (like Smile and Avro) support native binary content.
+ ///@return Whether format supported by this factory
+ /// supports native binary content
+ ///@since 2.3
+ bool canHandleBinaryNatively() {
+ return jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_canHandleBinaryNatively, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_canUseCharArrays = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"canUseCharArrays", r"()Z");
+
+ /// from: public boolean canUseCharArrays()
+ ///
+ /// Introspection method that can be used by base factory to check
+ /// whether access using <code>char[]</code> is something that actual
+ /// parser implementations can take advantage of, over having to
+ /// use java.io.Reader. Sub-types are expected to override
+ /// definition; default implementation (suitable for JSON) alleges
+ /// that optimization are possible; and thereby is likely to try
+ /// to access java.lang.String content by first copying it into
+ /// recyclable intermediate buffer.
+ ///@return Whether access to decoded textual content can be efficiently
+ /// accessed using parser method {@code getTextCharacters()}.
+ ///@since 2.4
+ bool canUseCharArrays() {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_canUseCharArrays,
+ jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_canParseAsync = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"canParseAsync", r"()Z");
+
+ /// from: public boolean canParseAsync()
+ ///
+ /// Introspection method that can be used to check whether this
+ /// factory can create non-blocking parsers: parsers that do not
+ /// use blocking I/O abstractions but instead use a
+ /// com.fasterxml.jackson.core.async.NonBlockingInputFeeder.
+ ///@return Whether this factory supports non-blocking ("async") parsing or
+ /// not (and consequently whether {@code createNonBlockingXxx()} method(s) work)
+ ///@since 2.9
+ bool canParseAsync() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_canParseAsync, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_getFormatReadFeatureType = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"getFormatReadFeatureType", r"()Ljava/lang/Class;");
+
+ /// from: public java.lang.Class<? extends com.fasterxml.jackson.core.FormatFeature> getFormatReadFeatureType()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject getFormatReadFeatureType() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getFormatReadFeatureType,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_getFormatWriteFeatureType = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"getFormatWriteFeatureType", r"()Ljava/lang/Class;");
+
+ /// from: public java.lang.Class<? extends com.fasterxml.jackson.core.FormatFeature> getFormatWriteFeatureType()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject getFormatWriteFeatureType() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getFormatWriteFeatureType,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_canUseSchema = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"canUseSchema",
+ r"(Lcom/fasterxml/jackson/core/FormatSchema;)Z");
+
+ /// from: public boolean canUseSchema(com.fasterxml.jackson.core.FormatSchema schema)
+ ///
+ /// Method that can be used to quickly check whether given schema
+ /// is something that parsers and/or generators constructed by this
+ /// factory could use. Note that this means possible use, at the level
+ /// of data format (i.e. schema is for same data format as parsers and
+ /// generators this factory constructs); individual schema instances
+ /// may have further usage restrictions.
+ ///@param schema Schema instance to check
+ ///@return Whether parsers and generators constructed by this factory
+ /// can use specified format schema instance
+ bool canUseSchema(
+ jni.JObject schema,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_canUseSchema,
+ jni.JniCallType.booleanType, [schema.reference]).boolean;
+ }
+
+ static final _id_getFormatName = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"getFormatName", r"()Ljava/lang/String;");
+
+ /// from: public java.lang.String getFormatName()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that returns short textual id identifying format
+ /// this factory supports.
+ ///
+ /// Note: sub-classes should override this method; default
+ /// implementation will return null for all sub-classes
+ ///@return Name of the format handled by parsers, generators this factory creates
+ jni.JString getFormatName() {
+ return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getFormatName, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_hasFormat = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"hasFormat",
+ r"(Lcom/fasterxml/jackson/core/format/InputAccessor;)Lcom/fasterxml/jackson/core/format/MatchStrength;");
+
+ /// from: public com.fasterxml.jackson.core.format.MatchStrength hasFormat(com.fasterxml.jackson.core.format.InputAccessor acc)
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject hasFormat(
+ jni.JObject acc,
+ ) {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_hasFormat,
+ jni.JniCallType.objectType,
+ [acc.reference]).object);
+ }
+
+ static final _id_requiresCustomCodec = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"requiresCustomCodec", r"()Z");
+
+ /// from: public boolean requiresCustomCodec()
+ ///
+ /// Method that can be called to determine if a custom
+ /// ObjectCodec is needed for binding data parsed
+ /// using JsonParser constructed by this factory
+ /// (which typically also implies the same for serialization
+ /// with JsonGenerator).
+ ///@return True if custom codec is needed with parsers and
+ /// generators created by this factory; false if a general
+ /// ObjectCodec is enough
+ ///@since 2.1
+ bool requiresCustomCodec() {
+ return jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_requiresCustomCodec, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_hasJSONFormat = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"hasJSONFormat",
+ r"(Lcom/fasterxml/jackson/core/format/InputAccessor;)Lcom/fasterxml/jackson/core/format/MatchStrength;");
+
+ /// from: protected com.fasterxml.jackson.core.format.MatchStrength hasJSONFormat(com.fasterxml.jackson.core.format.InputAccessor acc)
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject hasJSONFormat(
+ jni.JObject acc,
+ ) {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_hasJSONFormat,
+ jni.JniCallType.objectType,
+ [acc.reference]).object);
+ }
+
+ static final _id_version = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"version", r"()Lcom/fasterxml/jackson/core/Version;");
+
+ /// from: public com.fasterxml.jackson.core.Version version()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject version() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_version, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_configure = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"configure",
+ r"(Lcom/fasterxml/jackson/core/JsonFactory$Feature;Z)Lcom/fasterxml/jackson/core/JsonFactory;");
+
+ /// from: public final com.fasterxml.jackson.core.JsonFactory configure(com.fasterxml.jackson.core.JsonFactory.Feature f, boolean state)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for enabling or disabling specified parser feature
+ /// (check JsonParser.Feature for list of features)
+ ///@param f Feature to enable/disable
+ ///@param state Whether to enable or disable the feature
+ ///@return This factory instance (to allow call chaining)
+ ///@deprecated since 2.10 use JsonFactoryBuilder\#configure(JsonFactory.Feature, boolean) instead
+ JsonFactory configure(
+ JsonFactory_Feature f,
+ bool state,
+ ) {
+ return const $JsonFactoryType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_configure,
+ jni.JniCallType.objectType, [f.reference, state ? 1 : 0]).object);
+ }
+
+ static final _id_enable = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"enable",
+ r"(Lcom/fasterxml/jackson/core/JsonFactory$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;");
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory enable(com.fasterxml.jackson.core.JsonFactory.Feature f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for enabling specified parser feature
+ /// (check JsonFactory.Feature for list of features)
+ ///@param f Feature to enable
+ ///@return This factory instance (to allow call chaining)
+ ///@deprecated since 2.10 use JsonFactoryBuilder\#configure(JsonFactory.Feature, boolean) instead
+ JsonFactory enable(
+ JsonFactory_Feature f,
+ ) {
+ return const $JsonFactoryType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_enable, jni.JniCallType.objectType,
+ [f.reference]).object);
+ }
+
+ static final _id_disable = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"disable",
+ r"(Lcom/fasterxml/jackson/core/JsonFactory$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;");
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory disable(com.fasterxml.jackson.core.JsonFactory.Feature f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for disabling specified parser features
+ /// (check JsonFactory.Feature for list of features)
+ ///@param f Feature to disable
+ ///@return This factory instance (to allow call chaining)
+ ///@deprecated since 2.10 use JsonFactoryBuilder\#configure(JsonFactory.Feature, boolean) instead
+ JsonFactory disable(
+ JsonFactory_Feature f,
+ ) {
+ return const $JsonFactoryType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_disable, jni.JniCallType.objectType,
+ [f.reference]).object);
+ }
+
+ static final _id_isEnabled = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"isEnabled", r"(Lcom/fasterxml/jackson/core/JsonFactory$Feature;)Z");
+
+ /// from: public final boolean isEnabled(com.fasterxml.jackson.core.JsonFactory.Feature f)
+ ///
+ /// Checked whether specified parser feature is enabled.
+ ///@param f Feature to check
+ ///@return True if the specified feature is enabled
+ bool isEnabled(
+ JsonFactory_Feature f,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_isEnabled,
+ jni.JniCallType.booleanType, [f.reference]).boolean;
+ }
+
+ static final _id_getParserFeatures = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getParserFeatures", r"()I");
+
+ /// from: public final int getParserFeatures()
+ int getParserFeatures() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getParserFeatures, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_getGeneratorFeatures = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getGeneratorFeatures", r"()I");
+
+ /// from: public final int getGeneratorFeatures()
+ int getGeneratorFeatures() {
+ return jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_getGeneratorFeatures, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_getFormatParserFeatures = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getFormatParserFeatures", r"()I");
+
+ /// from: public int getFormatParserFeatures()
+ int getFormatParserFeatures() {
+ return jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_getFormatParserFeatures, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_getFormatGeneratorFeatures = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getFormatGeneratorFeatures", r"()I");
+
+ /// from: public int getFormatGeneratorFeatures()
+ int getFormatGeneratorFeatures() {
+ return jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_getFormatGeneratorFeatures, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_configure1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"configure",
+ r"(Lcom/fasterxml/jackson/core/JsonParser$Feature;Z)Lcom/fasterxml/jackson/core/JsonFactory;");
+
+ /// from: public final com.fasterxml.jackson.core.JsonFactory configure(com.fasterxml.jackson.core.JsonParser.Feature f, boolean state)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for enabling or disabling specified parser feature
+ /// (check JsonParser.Feature for list of features)
+ ///@param f Feature to enable/disable
+ ///@param state Whether to enable or disable the feature
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory configure1(
+ jsonparser_.JsonParser_Feature f,
+ bool state,
+ ) {
+ return const $JsonFactoryType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_configure1,
+ jni.JniCallType.objectType, [f.reference, state ? 1 : 0]).object);
+ }
+
+ static final _id_enable1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"enable",
+ r"(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;");
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory enable(com.fasterxml.jackson.core.JsonParser.Feature f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for enabling specified parser feature
+ /// (check JsonParser.Feature for list of features)
+ ///@param f Feature to enable
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory enable1(
+ jsonparser_.JsonParser_Feature f,
+ ) {
+ return const $JsonFactoryType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_enable1, jni.JniCallType.objectType,
+ [f.reference]).object);
+ }
+
+ static final _id_disable1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"disable",
+ r"(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;");
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory disable(com.fasterxml.jackson.core.JsonParser.Feature f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for disabling specified parser features
+ /// (check JsonParser.Feature for list of features)
+ ///@param f Feature to disable
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory disable1(
+ jsonparser_.JsonParser_Feature f,
+ ) {
+ return const $JsonFactoryType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_disable1, jni.JniCallType.objectType,
+ [f.reference]).object);
+ }
+
+ static final _id_isEnabled1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"isEnabled",
+ r"(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Z");
+
+ /// from: public final boolean isEnabled(com.fasterxml.jackson.core.JsonParser.Feature f)
+ ///
+ /// Method for checking if the specified parser feature is enabled.
+ ///@param f Feature to check
+ ///@return True if specified feature is enabled
+ bool isEnabled1(
+ jsonparser_.JsonParser_Feature f,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_isEnabled1,
+ jni.JniCallType.booleanType, [f.reference]).boolean;
+ }
+
+ static final _id_isEnabled2 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"isEnabled",
+ r"(Lcom/fasterxml/jackson/core/StreamReadFeature;)Z");
+
+ /// from: public final boolean isEnabled(com.fasterxml.jackson.core.StreamReadFeature f)
+ ///
+ /// Method for checking if the specified stream read feature is enabled.
+ ///@param f Feature to check
+ ///@return True if specified feature is enabled
+ ///@since 2.10
+ bool isEnabled2(
+ jni.JObject f,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_isEnabled2,
+ jni.JniCallType.booleanType, [f.reference]).boolean;
+ }
+
+ static final _id_getInputDecorator = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"getInputDecorator",
+ r"()Lcom/fasterxml/jackson/core/io/InputDecorator;");
+
+ /// from: public com.fasterxml.jackson.core.io.InputDecorator getInputDecorator()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for getting currently configured input decorator (if any;
+ /// there is no default decorator).
+ ///@return InputDecorator configured, if any
+ jni.JObject getInputDecorator() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getInputDecorator,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_setInputDecorator = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"setInputDecorator",
+ r"(Lcom/fasterxml/jackson/core/io/InputDecorator;)Lcom/fasterxml/jackson/core/JsonFactory;");
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory setInputDecorator(com.fasterxml.jackson.core.io.InputDecorator d)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for overriding currently configured input decorator
+ ///@param d Decorator to configure for this factory, if any ({@code null} if none)
+ ///@return This factory instance (to allow call chaining)
+ ///@deprecated Since 2.10 use JsonFactoryBuilder\#inputDecorator(InputDecorator) instead
+ JsonFactory setInputDecorator(
+ jni.JObject d,
+ ) {
+ return const $JsonFactoryType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_setInputDecorator,
+ jni.JniCallType.objectType, [d.reference]).object);
+ }
+
+ static final _id_configure2 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"configure",
+ r"(Lcom/fasterxml/jackson/core/JsonGenerator$Feature;Z)Lcom/fasterxml/jackson/core/JsonFactory;");
+
+ /// from: public final com.fasterxml.jackson.core.JsonFactory configure(com.fasterxml.jackson.core.JsonGenerator.Feature f, boolean state)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for enabling or disabling specified generator feature
+ /// (check JsonGenerator.Feature for list of features)
+ ///@param f Feature to enable/disable
+ ///@param state Whether to enable or disable the feature
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory configure2(
+ jni.JObject f,
+ bool state,
+ ) {
+ return const $JsonFactoryType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_configure2,
+ jni.JniCallType.objectType, [f.reference, state ? 1 : 0]).object);
+ }
+
+ static final _id_enable2 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"enable",
+ r"(Lcom/fasterxml/jackson/core/JsonGenerator$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;");
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory enable(com.fasterxml.jackson.core.JsonGenerator.Feature f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for enabling specified generator features
+ /// (check JsonGenerator.Feature for list of features)
+ ///@param f Feature to enable
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory enable2(
+ jni.JObject f,
+ ) {
+ return const $JsonFactoryType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_enable2, jni.JniCallType.objectType,
+ [f.reference]).object);
+ }
+
+ static final _id_disable2 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"disable",
+ r"(Lcom/fasterxml/jackson/core/JsonGenerator$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;");
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory disable(com.fasterxml.jackson.core.JsonGenerator.Feature f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for disabling specified generator feature
+ /// (check JsonGenerator.Feature for list of features)
+ ///@param f Feature to disable
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory disable2(
+ jni.JObject f,
+ ) {
+ return const $JsonFactoryType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_disable2, jni.JniCallType.objectType,
+ [f.reference]).object);
+ }
+
+ static final _id_isEnabled3 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"isEnabled",
+ r"(Lcom/fasterxml/jackson/core/JsonGenerator$Feature;)Z");
+
+ /// from: public final boolean isEnabled(com.fasterxml.jackson.core.JsonGenerator.Feature f)
+ ///
+ /// Check whether specified generator feature is enabled.
+ ///@param f Feature to check
+ ///@return Whether specified feature is enabled
+ bool isEnabled3(
+ jni.JObject f,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_isEnabled3,
+ jni.JniCallType.booleanType, [f.reference]).boolean;
+ }
+
+ static final _id_isEnabled4 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"isEnabled",
+ r"(Lcom/fasterxml/jackson/core/StreamWriteFeature;)Z");
+
+ /// from: public final boolean isEnabled(com.fasterxml.jackson.core.StreamWriteFeature f)
+ ///
+ /// Check whether specified stream write feature is enabled.
+ ///@param f Feature to check
+ ///@return Whether specified feature is enabled
+ ///@since 2.10
+ bool isEnabled4(
+ jni.JObject f,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_isEnabled4,
+ jni.JniCallType.booleanType, [f.reference]).boolean;
+ }
+
+ static final _id_getCharacterEscapes = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"getCharacterEscapes",
+ r"()Lcom/fasterxml/jackson/core/io/CharacterEscapes;");
+
+ /// from: public com.fasterxml.jackson.core.io.CharacterEscapes getCharacterEscapes()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for accessing custom escapes factory uses for JsonGenerators
+ /// it creates.
+ ///@return Configured {@code CharacterEscapes}, if any; {@code null} if none
+ jni.JObject getCharacterEscapes() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getCharacterEscapes,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_setCharacterEscapes = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"setCharacterEscapes",
+ r"(Lcom/fasterxml/jackson/core/io/CharacterEscapes;)Lcom/fasterxml/jackson/core/JsonFactory;");
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory setCharacterEscapes(com.fasterxml.jackson.core.io.CharacterEscapes esc)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for defining custom escapes factory uses for JsonGenerators
+ /// it creates.
+ ///@param esc CharaterEscapes to set (or {@code null} for "none")
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory setCharacterEscapes(
+ jni.JObject esc,
+ ) {
+ return const $JsonFactoryType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_setCharacterEscapes,
+ jni.JniCallType.objectType, [esc.reference]).object);
+ }
+
+ static final _id_getOutputDecorator = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"getOutputDecorator",
+ r"()Lcom/fasterxml/jackson/core/io/OutputDecorator;");
+
+ /// from: public com.fasterxml.jackson.core.io.OutputDecorator getOutputDecorator()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for getting currently configured output decorator (if any;
+ /// there is no default decorator).
+ ///@return OutputDecorator configured for generators factory creates, if any;
+ /// {@code null} if none.
+ jni.JObject getOutputDecorator() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getOutputDecorator,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_setOutputDecorator = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"setOutputDecorator",
+ r"(Lcom/fasterxml/jackson/core/io/OutputDecorator;)Lcom/fasterxml/jackson/core/JsonFactory;");
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory setOutputDecorator(com.fasterxml.jackson.core.io.OutputDecorator d)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for overriding currently configured output decorator
+ ///@return This factory instance (to allow call chaining)
+ ///@param d Output decorator to use, if any
+ ///@deprecated Since 2.10 use JsonFactoryBuilder\#outputDecorator(OutputDecorator) instead
+ JsonFactory setOutputDecorator(
+ jni.JObject d,
+ ) {
+ return const $JsonFactoryType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_setOutputDecorator,
+ jni.JniCallType.objectType, [d.reference]).object);
+ }
+
+ static final _id_setRootValueSeparator = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"setRootValueSeparator",
+ r"(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonFactory;");
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory setRootValueSeparator(java.lang.String sep)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that allows overriding String used for separating root-level
+ /// JSON values (default is single space character)
+ ///@param sep Separator to use, if any; null means that no separator is
+ /// automatically added
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory setRootValueSeparator(
+ jni.JString sep,
+ ) {
+ return const $JsonFactoryType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_setRootValueSeparator,
+ jni.JniCallType.objectType, [sep.reference]).object);
+ }
+
+ static final _id_getRootValueSeparator = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"getRootValueSeparator", r"()Ljava/lang/String;");
+
+ /// from: public java.lang.String getRootValueSeparator()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// @return Root value separator configured, if any
+ jni.JString getRootValueSeparator() {
+ return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getRootValueSeparator,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_setCodec = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"setCodec",
+ r"(Lcom/fasterxml/jackson/core/ObjectCodec;)Lcom/fasterxml/jackson/core/JsonFactory;");
+
+ /// from: public com.fasterxml.jackson.core.JsonFactory setCodec(com.fasterxml.jackson.core.ObjectCodec oc)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for associating a ObjectCodec (typically
+ /// a <code>com.fasterxml.jackson.databind.ObjectMapper</code>)
+ /// with this factory (and more importantly, parsers and generators
+ /// it constructs). This is needed to use data-binding methods
+ /// of JsonParser and JsonGenerator instances.
+ ///@param oc Codec to use
+ ///@return This factory instance (to allow call chaining)
+ JsonFactory setCodec(
+ jni.JObject oc,
+ ) {
+ return const $JsonFactoryType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_setCodec, jni.JniCallType.objectType,
+ [oc.reference]).object);
+ }
+
+ static final _id_getCodec = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"getCodec", r"()Lcom/fasterxml/jackson/core/ObjectCodec;");
+
+ /// from: public com.fasterxml.jackson.core.ObjectCodec getCodec()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject getCodec() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getCodec, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_createParser = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createParser",
+ r"(Ljava/io/File;)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.io.File f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON parser instance to parse
+ /// contents of specified file.
+ ///
+ ///
+ /// Encoding is auto-detected from contents according to JSON
+ /// specification recommended mechanism. Json specification
+ /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
+ /// so auto-detection implemented only for this charsets.
+ /// For other charsets use \#createParser(java.io.Reader).
+ ///
+ ///
+ /// Underlying input stream (needed for reading contents)
+ /// will be __owned__ (and managed, i.e. closed as need be) by
+ /// the parser, since caller has no access to it.
+ ///@param f File that contains JSON content to parse
+ ///@since 2.1
+ jsonparser_.JsonParser createParser(
+ jni.JObject f,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_createParser,
+ jni.JniCallType.objectType, [f.reference]).object);
+ }
+
+ static final _id_createParser1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createParser",
+ r"(Ljava/net/URL;)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.net.URL url)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON parser instance to parse
+ /// contents of resource reference by given URL.
+ ///
+ /// Encoding is auto-detected from contents according to JSON
+ /// specification recommended mechanism. Json specification
+ /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
+ /// so auto-detection implemented only for this charsets.
+ /// For other charsets use \#createParser(java.io.Reader).
+ ///
+ /// Underlying input stream (needed for reading contents)
+ /// will be __owned__ (and managed, i.e. closed as need be) by
+ /// the parser, since caller has no access to it.
+ ///@param url URL pointing to resource that contains JSON content to parse
+ ///@since 2.1
+ jsonparser_.JsonParser createParser1(
+ jni.JObject url,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_createParser1,
+ jni.JniCallType.objectType, [url.reference]).object);
+ }
+
+ static final _id_createParser2 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createParser",
+ r"(Ljava/io/InputStream;)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.io.InputStream in)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON parser instance to parse
+ /// the contents accessed via specified input stream.
+ ///
+ /// The input stream will __not be owned__ by
+ /// the parser, it will still be managed (i.e. closed if
+ /// end-of-stream is reacher, or parser close method called)
+ /// if (and only if) com.fasterxml.jackson.core.StreamReadFeature\#AUTO_CLOSE_SOURCE
+ /// is enabled.
+ ///
+ ///
+ /// Note: no encoding argument is taken since it can always be
+ /// auto-detected as suggested by JSON RFC. Json specification
+ /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
+ /// so auto-detection implemented only for this charsets.
+ /// For other charsets use \#createParser(java.io.Reader).
+ ///@param in InputStream to use for reading JSON content to parse
+ ///@since 2.1
+ jsonparser_.JsonParser createParser2(
+ jni.JObject in0,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_createParser2,
+ jni.JniCallType.objectType, [in0.reference]).object);
+ }
+
+ static final _id_createParser3 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createParser",
+ r"(Ljava/io/Reader;)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.io.Reader r)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing
+ /// the contents accessed via specified Reader.
+ ///
+ /// The read stream will __not be owned__ by
+ /// the parser, it will still be managed (i.e. closed if
+ /// end-of-stream is reacher, or parser close method called)
+ /// if (and only if) com.fasterxml.jackson.core.StreamReadFeature\#AUTO_CLOSE_SOURCE
+ /// is enabled.
+ ///@param r Reader to use for reading JSON content to parse
+ ///@since 2.1
+ jsonparser_.JsonParser createParser3(
+ jni.JObject r,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_createParser3,
+ jni.JniCallType.objectType, [r.reference]).object);
+ }
+
+ static final _id_createParser4 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createParser",
+ r"([B)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(byte[] data)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing
+ /// the contents of given byte array.
+ ///@since 2.1
+ jsonparser_.JsonParser createParser4(
+ jni.JArray<jni.jbyte> data,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_createParser4,
+ jni.JniCallType.objectType, [data.reference]).object);
+ }
+
+ static final _id_createParser5 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createParser",
+ r"([BII)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(byte[] data, int offset, int len)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing
+ /// the contents of given byte array.
+ ///@param data Buffer that contains data to parse
+ ///@param offset Offset of the first data byte within buffer
+ ///@param len Length of contents to parse within buffer
+ ///@since 2.1
+ jsonparser_.JsonParser createParser5(
+ jni.JArray<jni.jbyte> data,
+ int offset,
+ int len,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(
+ reference, _id_createParser5, jni.JniCallType.objectType, [
+ data.reference,
+ jni.JValueInt(offset),
+ jni.JValueInt(len)
+ ]).object);
+ }
+
+ static final _id_createParser6 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createParser",
+ r"(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.lang.String content)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing
+ /// contents of given String.
+ ///@since 2.1
+ jsonparser_.JsonParser createParser6(
+ jni.JString content,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_createParser6,
+ jni.JniCallType.objectType, [content.reference]).object);
+ }
+
+ static final _id_createParser7 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createParser",
+ r"([C)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(char[] content)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing
+ /// contents of given char array.
+ ///@since 2.4
+ jsonparser_.JsonParser createParser7(
+ jni.JArray<jni.jchar> content,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_createParser7,
+ jni.JniCallType.objectType, [content.reference]).object);
+ }
+
+ static final _id_createParser8 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createParser",
+ r"([CII)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(char[] content, int offset, int len)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing contents of given char array.
+ ///@since 2.4
+ jsonparser_.JsonParser createParser8(
+ jni.JArray<jni.jchar> content,
+ int offset,
+ int len,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(
+ reference, _id_createParser8, jni.JniCallType.objectType, [
+ content.reference,
+ jni.JValueInt(offset),
+ jni.JValueInt(len)
+ ]).object);
+ }
+
+ static final _id_createParser9 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createParser",
+ r"(Ljava/io/DataInput;)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.io.DataInput in)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Optional method for constructing parser for reading contents from specified DataInput
+ /// instance.
+ ///
+ /// If this factory does not support DataInput as source,
+ /// will throw UnsupportedOperationException
+ ///@since 2.8
+ jsonparser_.JsonParser createParser9(
+ jni.JObject in0,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_createParser9,
+ jni.JniCallType.objectType, [in0.reference]).object);
+ }
+
+ static final _id_createNonBlockingByteArrayParser = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"createNonBlockingByteArrayParser",
+ r"()Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createNonBlockingByteArrayParser()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Optional method for constructing parser for non-blocking parsing
+ /// via com.fasterxml.jackson.core.async.ByteArrayFeeder
+ /// interface (accessed using JsonParser\#getNonBlockingInputFeeder()
+ /// from constructed instance).
+ ///
+ /// If this factory does not support non-blocking parsing (either at all,
+ /// or from byte array),
+ /// will throw UnsupportedOperationException.
+ ///
+ /// Note that JSON-backed factory only supports parsing of UTF-8 encoded JSON content
+ /// (and US-ASCII since it is proper subset); other encodings are not supported
+ /// at this point.
+ ///@since 2.9
+ jsonparser_.JsonParser createNonBlockingByteArrayParser() {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_createNonBlockingByteArrayParser,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_createGenerator = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createGenerator",
+ r"(Ljava/io/OutputStream;Lcom/fasterxml/jackson/core/JsonEncoding;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.OutputStream out, com.fasterxml.jackson.core.JsonEncoding enc)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON generator for writing JSON content
+ /// using specified output stream.
+ /// Encoding to use must be specified, and needs to be one of available
+ /// types (as per JSON specification).
+ ///
+ /// Underlying stream __is NOT owned__ by the generator constructed,
+ /// so that generator will NOT close the output stream when
+ /// JsonGenerator\#close is called (unless auto-closing
+ /// feature,
+ /// com.fasterxml.jackson.core.JsonGenerator.Feature\#AUTO_CLOSE_TARGET
+ /// is enabled).
+ /// Using application needs to close it explicitly if this is the case.
+ ///
+ /// Note: there are formats that use fixed encoding (like most binary data formats)
+ /// and that ignore passed in encoding.
+ ///@param out OutputStream to use for writing JSON content
+ ///@param enc Character encoding to use
+ ///@since 2.1
+ jni.JObject createGenerator(
+ jni.JObject out,
+ jni.JObject enc,
+ ) {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_createGenerator,
+ jni.JniCallType.objectType,
+ [out.reference, enc.reference]).object);
+ }
+
+ static final _id_createGenerator1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createGenerator",
+ r"(Ljava/io/OutputStream;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.OutputStream out)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Convenience method for constructing generator that uses default
+ /// encoding of the format (UTF-8 for JSON and most other data formats).
+ ///
+ /// Note: there are formats that use fixed encoding (like most binary data formats).
+ ///@since 2.1
+ jni.JObject createGenerator1(
+ jni.JObject out,
+ ) {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_createGenerator1,
+ jni.JniCallType.objectType,
+ [out.reference]).object);
+ }
+
+ static final _id_createGenerator2 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createGenerator",
+ r"(Ljava/io/Writer;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.Writer w)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON generator for writing JSON content
+ /// using specified Writer.
+ ///
+ /// Underlying stream __is NOT owned__ by the generator constructed,
+ /// so that generator will NOT close the Reader when
+ /// JsonGenerator\#close is called (unless auto-closing
+ /// feature,
+ /// com.fasterxml.jackson.core.JsonGenerator.Feature\#AUTO_CLOSE_TARGET is enabled).
+ /// Using application needs to close it explicitly.
+ ///@since 2.1
+ ///@param w Writer to use for writing JSON content
+ jni.JObject createGenerator2(
+ jni.JObject w,
+ ) {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_createGenerator2,
+ jni.JniCallType.objectType,
+ [w.reference]).object);
+ }
+
+ static final _id_createGenerator3 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createGenerator",
+ r"(Ljava/io/File;Lcom/fasterxml/jackson/core/JsonEncoding;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.File f, com.fasterxml.jackson.core.JsonEncoding enc)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON generator for writing JSON content
+ /// to specified file, overwriting contents it might have (or creating
+ /// it if such file does not yet exist).
+ /// Encoding to use must be specified, and needs to be one of available
+ /// types (as per JSON specification).
+ ///
+ /// Underlying stream __is owned__ by the generator constructed,
+ /// i.e. generator will handle closing of file when
+ /// JsonGenerator\#close is called.
+ ///@param f File to write contents to
+ ///@param enc Character encoding to use
+ ///@since 2.1
+ jni.JObject createGenerator3(
+ jni.JObject f,
+ jni.JObject enc,
+ ) {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_createGenerator3,
+ jni.JniCallType.objectType,
+ [f.reference, enc.reference]).object);
+ }
+
+ static final _id_createGenerator4 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createGenerator",
+ r"(Ljava/io/DataOutput;Lcom/fasterxml/jackson/core/JsonEncoding;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.DataOutput out, com.fasterxml.jackson.core.JsonEncoding enc)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing generator for writing content using specified
+ /// DataOutput instance.
+ ///@since 2.8
+ jni.JObject createGenerator4(
+ jni.JObject out,
+ jni.JObject enc,
+ ) {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_createGenerator4,
+ jni.JniCallType.objectType,
+ [out.reference, enc.reference]).object);
+ }
+
+ static final _id_createGenerator5 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createGenerator",
+ r"(Ljava/io/DataOutput;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.DataOutput out)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Convenience method for constructing generator that uses default
+ /// encoding of the format (UTF-8 for JSON and most other data formats).
+ ///
+ /// Note: there are formats that use fixed encoding (like most binary data formats).
+ ///@since 2.8
+ jni.JObject createGenerator5(
+ jni.JObject out,
+ ) {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_createGenerator5,
+ jni.JniCallType.objectType,
+ [out.reference]).object);
+ }
+
+ static final _id_createJsonParser = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createJsonParser",
+ r"(Ljava/io/File;)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(java.io.File f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON parser instance to parse
+ /// contents of specified file.
+ ///
+ /// Encoding is auto-detected from contents according to JSON
+ /// specification recommended mechanism. Json specification
+ /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
+ /// so auto-detection implemented only for this charsets.
+ /// For other charsets use \#createParser(java.io.Reader).
+ ///
+ ///
+ /// Underlying input stream (needed for reading contents)
+ /// will be __owned__ (and managed, i.e. closed as need be) by
+ /// the parser, since caller has no access to it.
+ ///@param f File that contains JSON content to parse
+ ///@return Parser constructed
+ ///@throws IOException if parser initialization fails due to I/O (read) problem
+ ///@throws JsonParseException if parser initialization fails due to content decoding problem
+ ///@deprecated Since 2.2, use \#createParser(File) instead.
+ jsonparser_.JsonParser createJsonParser(
+ jni.JObject f,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_createJsonParser,
+ jni.JniCallType.objectType, [f.reference]).object);
+ }
+
+ static final _id_createJsonParser1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createJsonParser",
+ r"(Ljava/net/URL;)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(java.net.URL url)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON parser instance to parse
+ /// contents of resource reference by given URL.
+ ///
+ /// Encoding is auto-detected from contents according to JSON
+ /// specification recommended mechanism. Json specification
+ /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
+ /// so auto-detection implemented only for this charsets.
+ /// For other charsets use \#createParser(java.io.Reader).
+ ///
+ /// Underlying input stream (needed for reading contents)
+ /// will be __owned__ (and managed, i.e. closed as need be) by
+ /// the parser, since caller has no access to it.
+ ///@param url URL pointing to resource that contains JSON content to parse
+ ///@return Parser constructed
+ ///@throws IOException if parser initialization fails due to I/O (read) problem
+ ///@throws JsonParseException if parser initialization fails due to content decoding problem
+ ///@deprecated Since 2.2, use \#createParser(URL) instead.
+ jsonparser_.JsonParser createJsonParser1(
+ jni.JObject url,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_createJsonParser1,
+ jni.JniCallType.objectType, [url.reference]).object);
+ }
+
+ static final _id_createJsonParser2 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createJsonParser",
+ r"(Ljava/io/InputStream;)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(java.io.InputStream in)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON parser instance to parse
+ /// the contents accessed via specified input stream.
+ ///
+ /// The input stream will __not be owned__ by
+ /// the parser, it will still be managed (i.e. closed if
+ /// end-of-stream is reacher, or parser close method called)
+ /// if (and only if) com.fasterxml.jackson.core.JsonParser.Feature\#AUTO_CLOSE_SOURCE
+ /// is enabled.
+ ///
+ ///
+ /// Note: no encoding argument is taken since it can always be
+ /// auto-detected as suggested by JSON RFC. Json specification
+ /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
+ /// so auto-detection implemented only for this charsets.
+ /// For other charsets use \#createParser(java.io.Reader).
+ ///@param in InputStream to use for reading JSON content to parse
+ ///@return Parser constructed
+ ///@throws IOException if parser initialization fails due to I/O (read) problem
+ ///@throws JsonParseException if parser initialization fails due to content decoding problem
+ ///@deprecated Since 2.2, use \#createParser(InputStream) instead.
+ jsonparser_.JsonParser createJsonParser2(
+ jni.JObject in0,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_createJsonParser2,
+ jni.JniCallType.objectType, [in0.reference]).object);
+ }
+
+ static final _id_createJsonParser3 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createJsonParser",
+ r"(Ljava/io/Reader;)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(java.io.Reader r)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing
+ /// the contents accessed via specified Reader.
+ ///
+ /// The read stream will __not be owned__ by
+ /// the parser, it will still be managed (i.e. closed if
+ /// end-of-stream is reacher, or parser close method called)
+ /// if (and only if) com.fasterxml.jackson.core.JsonParser.Feature\#AUTO_CLOSE_SOURCE
+ /// is enabled.
+ ///@param r Reader to use for reading JSON content to parse
+ ///@return Parser constructed
+ ///@throws IOException if parser initialization fails due to I/O (read) problem
+ ///@throws JsonParseException if parser initialization fails due to content decoding problem
+ ///@deprecated Since 2.2, use \#createParser(Reader) instead.
+ jsonparser_.JsonParser createJsonParser3(
+ jni.JObject r,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_createJsonParser3,
+ jni.JniCallType.objectType, [r.reference]).object);
+ }
+
+ static final _id_createJsonParser4 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createJsonParser",
+ r"([B)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(byte[] data)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing the contents of given byte array.
+ ///@param data Input content to parse
+ ///@return Parser constructed
+ ///@throws IOException if parser initialization fails due to I/O (read) problem
+ ///@throws JsonParseException if parser initialization fails due to content decoding problem
+ ///@deprecated Since 2.2, use \#createParser(byte[]) instead.
+ jsonparser_.JsonParser createJsonParser4(
+ jni.JArray<jni.jbyte> data,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_createJsonParser4,
+ jni.JniCallType.objectType, [data.reference]).object);
+ }
+
+ static final _id_createJsonParser5 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createJsonParser",
+ r"([BII)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(byte[] data, int offset, int len)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing
+ /// the contents of given byte array.
+ ///@param data Buffer that contains data to parse
+ ///@param offset Offset of the first data byte within buffer
+ ///@param len Length of contents to parse within buffer
+ ///@return Parser constructed
+ ///@throws IOException if parser initialization fails due to I/O (read) problem
+ ///@throws JsonParseException if parser initialization fails due to content decoding problem
+ ///@deprecated Since 2.2, use \#createParser(byte[],int,int) instead.
+ jsonparser_.JsonParser createJsonParser5(
+ jni.JArray<jni.jbyte> data,
+ int offset,
+ int len,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(
+ reference, _id_createJsonParser5, jni.JniCallType.objectType, [
+ data.reference,
+ jni.JValueInt(offset),
+ jni.JValueInt(len)
+ ]).object);
+ }
+
+ static final _id_createJsonParser6 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createJsonParser",
+ r"(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(java.lang.String content)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing parser for parsing
+ /// contents of given String.
+ ///@param content Input content to parse
+ ///@return Parser constructed
+ ///@throws IOException if parser initialization fails due to I/O (read) problem
+ ///@throws JsonParseException if parser initialization fails due to content decoding problem
+ ///@deprecated Since 2.2, use \#createParser(String) instead.
+ jsonparser_.JsonParser createJsonParser6(
+ jni.JString content,
+ ) {
+ return const jsonparser_.$JsonParserType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_createJsonParser6,
+ jni.JniCallType.objectType, [content.reference]).object);
+ }
+
+ static final _id_createJsonGenerator = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createJsonGenerator",
+ r"(Ljava/io/OutputStream;Lcom/fasterxml/jackson/core/JsonEncoding;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createJsonGenerator(java.io.OutputStream out, com.fasterxml.jackson.core.JsonEncoding enc)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON generator for writing JSON content
+ /// using specified output stream.
+ /// Encoding to use must be specified, and needs to be one of available
+ /// types (as per JSON specification).
+ ///
+ /// Underlying stream __is NOT owned__ by the generator constructed,
+ /// so that generator will NOT close the output stream when
+ /// JsonGenerator\#close is called (unless auto-closing
+ /// feature,
+ /// com.fasterxml.jackson.core.JsonGenerator.Feature\#AUTO_CLOSE_TARGET
+ /// is enabled).
+ /// Using application needs to close it explicitly if this is the case.
+ ///
+ /// Note: there are formats that use fixed encoding (like most binary data formats)
+ /// and that ignore passed in encoding.
+ ///@param out OutputStream to use for writing JSON content
+ ///@param enc Character encoding to use
+ ///@return Generator constructed
+ ///@throws IOException if parser initialization fails due to I/O (write) problem
+ ///@deprecated Since 2.2, use \#createGenerator(OutputStream, JsonEncoding) instead.
+ jni.JObject createJsonGenerator(
+ jni.JObject out,
+ jni.JObject enc,
+ ) {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_createJsonGenerator,
+ jni.JniCallType.objectType,
+ [out.reference, enc.reference]).object);
+ }
+
+ static final _id_createJsonGenerator1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createJsonGenerator",
+ r"(Ljava/io/Writer;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createJsonGenerator(java.io.Writer out)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for constructing JSON generator for writing JSON content
+ /// using specified Writer.
+ ///
+ /// Underlying stream __is NOT owned__ by the generator constructed,
+ /// so that generator will NOT close the Reader when
+ /// JsonGenerator\#close is called (unless auto-closing
+ /// feature,
+ /// com.fasterxml.jackson.core.JsonGenerator.Feature\#AUTO_CLOSE_TARGET is enabled).
+ /// Using application needs to close it explicitly.
+ ///@param out Writer to use for writing JSON content
+ ///@return Generator constructed
+ ///@throws IOException if parser initialization fails due to I/O (write) problem
+ ///@deprecated Since 2.2, use \#createGenerator(Writer) instead.
+ jni.JObject createJsonGenerator1(
+ jni.JObject out,
+ ) {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_createJsonGenerator1,
+ jni.JniCallType.objectType,
+ [out.reference]).object);
+ }
+
+ static final _id_createJsonGenerator2 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"createJsonGenerator",
+ r"(Ljava/io/OutputStream;)Lcom/fasterxml/jackson/core/JsonGenerator;");
+
+ /// from: public com.fasterxml.jackson.core.JsonGenerator createJsonGenerator(java.io.OutputStream out)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Convenience method for constructing generator that uses default
+ /// encoding of the format (UTF-8 for JSON and most other data formats).
+ ///
+ /// Note: there are formats that use fixed encoding (like most binary data formats).
+ ///@param out OutputStream to use for writing JSON content
+ ///@return Generator constructed
+ ///@throws IOException if parser initialization fails due to I/O (write) problem
+ ///@deprecated Since 2.2, use \#createGenerator(OutputStream) instead.
+ jni.JObject createJsonGenerator2(
+ jni.JObject out,
+ ) {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_createJsonGenerator2,
+ jni.JniCallType.objectType,
+ [out.reference]).object);
+ }
+}
+
+final class $JsonFactoryType extends jni.JObjType<JsonFactory> {
+ const $JsonFactoryType();
+
+ @override
+ String get signature => r"Lcom/fasterxml/jackson/core/JsonFactory;";
+
+ @override
+ JsonFactory fromRef(jni.JObjectPtr ref) => JsonFactory.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($JsonFactoryType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($JsonFactoryType) && other is $JsonFactoryType;
+ }
+}
+
+/// from: com.fasterxml.jackson.core.JsonFactory$Feature
+///
+/// Enumeration that defines all on/off features that can only be
+/// changed for JsonFactory.
+class JsonFactory_Feature extends jni.JObject {
+ @override
+ late final jni.JObjType<JsonFactory_Feature> $type = type;
+
+ JsonFactory_Feature.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/fasterxml/jackson/core/JsonFactory$Feature");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $JsonFactory_FeatureType();
+ static final _id_values = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"values",
+ r"()[Lcom/fasterxml/jackson/core/JsonFactory$Feature;");
+
+ /// from: static public com.fasterxml.jackson.core.JsonFactory.Feature[] values()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<JsonFactory_Feature> values() {
+ return const jni.JArrayType($JsonFactory_FeatureType()).fromRef(
+ jni.Jni.accessors.callStaticMethodWithArgs(_class.reference, _id_values,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_valueOf = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"valueOf",
+ r"(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonFactory$Feature;");
+
+ /// from: static public com.fasterxml.jackson.core.JsonFactory.Feature valueOf(java.lang.String name)
+ /// The returned object must be released after use, by calling the [release] method.
+ static JsonFactory_Feature valueOf(
+ jni.JString name,
+ ) {
+ return const $JsonFactory_FeatureType().fromRef(jni.Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _id_valueOf,
+ jni.JniCallType.objectType, [name.reference]).object);
+ }
+
+ static final _id_collectDefaults = jni.Jni.accessors
+ .getStaticMethodIDOf(_class.reference, r"collectDefaults", r"()I");
+
+ /// from: static public int collectDefaults()
+ ///
+ /// Method that calculates bit set (flags) of all features that
+ /// are enabled by default.
+ ///@return Bit field of features enabled by default
+ static int collectDefaults() {
+ return jni.Jni.accessors.callStaticMethodWithArgs(_class.reference,
+ _id_collectDefaults, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_enabledByDefault = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"enabledByDefault", r"()Z");
+
+ /// from: public boolean enabledByDefault()
+ bool enabledByDefault() {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_enabledByDefault,
+ jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_enabledIn =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"enabledIn", r"(I)Z");
+
+ /// from: public boolean enabledIn(int flags)
+ bool enabledIn(
+ int flags,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_enabledIn,
+ jni.JniCallType.booleanType, [jni.JValueInt(flags)]).boolean;
+ }
+
+ static final _id_getMask =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"getMask", r"()I");
+
+ /// from: public int getMask()
+ int getMask() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getMask, jni.JniCallType.intType, []).integer;
+ }
+}
+
+final class $JsonFactory_FeatureType extends jni.JObjType<JsonFactory_Feature> {
+ const $JsonFactory_FeatureType();
+
+ @override
+ String get signature => r"Lcom/fasterxml/jackson/core/JsonFactory$Feature;";
+
+ @override
+ JsonFactory_Feature fromRef(jni.JObjectPtr ref) =>
+ JsonFactory_Feature.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($JsonFactory_FeatureType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($JsonFactory_FeatureType) &&
+ other is $JsonFactory_FeatureType;
+ }
+}
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonParser.dart b/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonParser.dart
new file mode 100644
index 0000000..2c27ecc
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonParser.dart
@@ -0,0 +1,2701 @@
+// Generated from jackson-core which is licensed under the Apache License 2.0.
+// The following copyright from the original authors applies.
+// See https://github.com/FasterXML/jackson-core/blob/2.14/LICENSE
+//
+// Copyright (c) 2007 - The Jackson Project Authors
+// Licensed under the Apache License, Version 2.0 (the "License")
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+// ignore_for_file: annotate_overrides
+// ignore_for_file: camel_case_extensions
+// ignore_for_file: camel_case_types
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: doc_directive_unknown
+// ignore_for_file: file_names
+// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: overridden_fields
+// ignore_for_file: unnecessary_cast
+// ignore_for_file: unused_element
+// ignore_for_file: unused_field
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: unused_shown_name
+
+import "dart:isolate" show ReceivePort;
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+import "package:jni/jni.dart" as jni;
+
+import "JsonToken.dart" as jsontoken_;
+
+/// from: com.fasterxml.jackson.core.JsonParser
+///
+/// Base class that defines public API for reading JSON content.
+/// Instances are created using factory methods of
+/// a JsonFactory instance.
+///@author Tatu Saloranta
+class JsonParser extends jni.JObject {
+ @override
+ late final jni.JObjType<JsonParser> $type = type;
+
+ JsonParser.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/fasterxml/jackson/core/JsonParser");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $JsonParserType();
+ static final _id_DEFAULT_READ_CAPABILITIES =
+ jni.Jni.accessors.getStaticFieldIDOf(
+ _class.reference,
+ r"DEFAULT_READ_CAPABILITIES",
+ r"Lcom/fasterxml/jackson/core/util/JacksonFeatureSet;",
+ );
+
+ /// from: static protected final com.fasterxml.jackson.core.util.JacksonFeatureSet<com.fasterxml.jackson.core.StreamReadCapability> DEFAULT_READ_CAPABILITIES
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Default set of StreamReadCapabilityies that may be used as
+ /// basis for format-specific readers (or as bogus instance if non-null
+ /// set needs to be passed).
+ ///@since 2.12
+ static jni.JObject get DEFAULT_READ_CAPABILITIES =>
+ const jni.JObjectType().fromRef(jni.Jni.accessors
+ .getStaticField(_class.reference, _id_DEFAULT_READ_CAPABILITIES,
+ jni.JniCallType.objectType)
+ .object);
+
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: protected void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory JsonParser() {
+ return JsonParser.fromRef(jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+
+ static final _id_new1 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"(I)V");
+
+ /// from: protected void <init>(int features)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory JsonParser.new1(
+ int features,
+ ) {
+ return JsonParser.fromRef(jni.Jni.accessors.newObjectWithArgs(
+ _class.reference, _id_new1, [jni.JValueInt(features)]).object);
+ }
+
+ static final _id_getCodec = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"getCodec", r"()Lcom/fasterxml/jackson/core/ObjectCodec;");
+
+ /// from: public abstract com.fasterxml.jackson.core.ObjectCodec getCodec()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Accessor for ObjectCodec associated with this
+ /// parser, if any. Codec is used by \#readValueAs(Class)
+ /// method (and its variants).
+ ///@return Codec assigned to this parser, if any; {@code null} if none
+ jni.JObject getCodec() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getCodec, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_setCodec = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"setCodec", r"(Lcom/fasterxml/jackson/core/ObjectCodec;)V");
+
+ /// from: public abstract void setCodec(com.fasterxml.jackson.core.ObjectCodec oc)
+ ///
+ /// Setter that allows defining ObjectCodec associated with this
+ /// parser, if any. Codec is used by \#readValueAs(Class)
+ /// method (and its variants).
+ ///@param oc Codec to assign, if any; {@code null} if none
+ void setCodec(
+ jni.JObject oc,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_setCodec,
+ jni.JniCallType.voidType, [oc.reference]).check();
+ }
+
+ static final _id_getInputSource = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"getInputSource", r"()Ljava/lang/Object;");
+
+ /// from: public java.lang.Object getInputSource()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that can be used to get access to object that is used
+ /// to access input being parsed; this is usually either
+ /// InputStream or Reader, depending on what
+ /// parser was constructed with.
+ /// Note that returned value may be null in some cases; including
+ /// case where parser implementation does not want to exposed raw
+ /// source to caller.
+ /// In cases where input has been decorated, object returned here
+ /// is the decorated version; this allows some level of interaction
+ /// between users of parser and decorator object.
+ ///
+ /// In general use of this accessor should be considered as
+ /// "last effort", i.e. only used if no other mechanism is applicable.
+ ///@return Input source this parser was configured with
+ jni.JObject getInputSource() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getInputSource, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_setRequestPayloadOnError = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"setRequestPayloadOnError",
+ r"(Lcom/fasterxml/jackson/core/util/RequestPayload;)V");
+
+ /// from: public void setRequestPayloadOnError(com.fasterxml.jackson.core.util.RequestPayload payload)
+ ///
+ /// Sets the payload to be passed if JsonParseException is thrown.
+ ///@param payload Payload to pass
+ ///@since 2.8
+ void setRequestPayloadOnError(
+ jni.JObject payload,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_setRequestPayloadOnError,
+ jni.JniCallType.voidType,
+ [payload.reference]).check();
+ }
+
+ static final _id_setRequestPayloadOnError1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"setRequestPayloadOnError",
+ r"([BLjava/lang/String;)V");
+
+ /// from: public void setRequestPayloadOnError(byte[] payload, java.lang.String charset)
+ ///
+ /// Sets the byte[] request payload and the charset
+ ///@param payload Payload to pass
+ ///@param charset Character encoding for (lazily) decoding payload
+ ///@since 2.8
+ void setRequestPayloadOnError1(
+ jni.JArray<jni.jbyte> payload,
+ jni.JString charset,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_setRequestPayloadOnError1,
+ jni.JniCallType.voidType,
+ [payload.reference, charset.reference]).check();
+ }
+
+ static final _id_setRequestPayloadOnError2 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"setRequestPayloadOnError", r"(Ljava/lang/String;)V");
+
+ /// from: public void setRequestPayloadOnError(java.lang.String payload)
+ ///
+ /// Sets the String request payload
+ ///@param payload Payload to pass
+ ///@since 2.8
+ void setRequestPayloadOnError2(
+ jni.JString payload,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_setRequestPayloadOnError2,
+ jni.JniCallType.voidType,
+ [payload.reference]).check();
+ }
+
+ static final _id_setSchema = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"setSchema", r"(Lcom/fasterxml/jackson/core/FormatSchema;)V");
+
+ /// from: public void setSchema(com.fasterxml.jackson.core.FormatSchema schema)
+ ///
+ /// Method to call to make this parser use specified schema. Method must
+ /// be called before trying to parse any content, right after parser instance
+ /// has been created.
+ /// Note that not all parsers support schemas; and those that do usually only
+ /// accept specific types of schemas: ones defined for data format parser can read.
+ ///
+ /// If parser does not support specified schema, UnsupportedOperationException
+ /// is thrown.
+ ///@param schema Schema to use
+ ///@throws UnsupportedOperationException if parser does not support schema
+ void setSchema(
+ jni.JObject schema,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_setSchema,
+ jni.JniCallType.voidType, [schema.reference]).check();
+ }
+
+ static final _id_getSchema = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"getSchema", r"()Lcom/fasterxml/jackson/core/FormatSchema;");
+
+ /// from: public com.fasterxml.jackson.core.FormatSchema getSchema()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for accessing Schema that this parser uses, if any.
+ /// Default implementation returns null.
+ ///@return Schema in use by this parser, if any; {@code null} if none
+ ///@since 2.1
+ jni.JObject getSchema() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getSchema, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_canUseSchema = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"canUseSchema",
+ r"(Lcom/fasterxml/jackson/core/FormatSchema;)Z");
+
+ /// from: public boolean canUseSchema(com.fasterxml.jackson.core.FormatSchema schema)
+ ///
+ /// Method that can be used to verify that given schema can be used with
+ /// this parser (using \#setSchema).
+ ///@param schema Schema to check
+ ///@return True if this parser can use given schema; false if not
+ bool canUseSchema(
+ jni.JObject schema,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_canUseSchema,
+ jni.JniCallType.booleanType, [schema.reference]).boolean;
+ }
+
+ static final _id_requiresCustomCodec = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"requiresCustomCodec", r"()Z");
+
+ /// from: public boolean requiresCustomCodec()
+ ///
+ /// Method that can be called to determine if a custom
+ /// ObjectCodec is needed for binding data parsed
+ /// using JsonParser constructed by this factory
+ /// (which typically also implies the same for serialization
+ /// with JsonGenerator).
+ ///@return True if format-specific codec is needed with this parser; false if a general
+ /// ObjectCodec is enough
+ ///@since 2.1
+ bool requiresCustomCodec() {
+ return jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_requiresCustomCodec, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_canParseAsync = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"canParseAsync", r"()Z");
+
+ /// from: public boolean canParseAsync()
+ ///
+ /// Method that can be called to determine if this parser instance
+ /// uses non-blocking ("asynchronous") input access for decoding or not.
+ /// Access mode is determined by earlier calls via JsonFactory;
+ /// it may not be changed after construction.
+ ///
+ /// If non-blocking decoding is (@code true}, it is possible to call
+ /// \#getNonBlockingInputFeeder() to obtain object to use
+ /// for feeding input; otherwise (<code>false</code> returned)
+ /// input is read by blocking
+ ///@return True if this is a non-blocking ("asynchronous") parser
+ ///@since 2.9
+ bool canParseAsync() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_canParseAsync, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_getNonBlockingInputFeeder = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"getNonBlockingInputFeeder",
+ r"()Lcom/fasterxml/jackson/core/async/NonBlockingInputFeeder;");
+
+ /// from: public com.fasterxml.jackson.core.async.NonBlockingInputFeeder getNonBlockingInputFeeder()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that will either return a feeder instance (if parser uses
+ /// non-blocking, aka asynchronous access); or <code>null</code> for
+ /// parsers that use blocking I/O.
+ ///@return Input feeder to use with non-blocking (async) parsing
+ ///@since 2.9
+ jni.JObject getNonBlockingInputFeeder() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getNonBlockingInputFeeder,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_getReadCapabilities = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"getReadCapabilities",
+ r"()Lcom/fasterxml/jackson/core/util/JacksonFeatureSet;");
+
+ /// from: public com.fasterxml.jackson.core.util.JacksonFeatureSet<com.fasterxml.jackson.core.StreamReadCapability> getReadCapabilities()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Accessor for getting metadata on capabilities of this parser, based on
+ /// underlying data format being read (directly or indirectly).
+ ///@return Set of read capabilities for content to read via this parser
+ ///@since 2.12
+ jni.JObject getReadCapabilities() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getReadCapabilities,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_version = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"version", r"()Lcom/fasterxml/jackson/core/Version;");
+
+ /// from: public abstract com.fasterxml.jackson.core.Version version()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Accessor for getting version of the core package, given a parser instance.
+ /// Left for sub-classes to implement.
+ ///@return Version of this generator (derived from version declared for
+ /// {@code jackson-core} jar that contains the class
+ jni.JObject version() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_version, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_close =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"close", r"()V");
+
+ /// from: public abstract void close()
+ ///
+ /// Closes the parser so that no further iteration or data access
+ /// can be made; will also close the underlying input source
+ /// if parser either __owns__ the input source, or feature
+ /// Feature\#AUTO_CLOSE_SOURCE is enabled.
+ /// Whether parser owns the input source depends on factory
+ /// method that was used to construct instance (so check
+ /// com.fasterxml.jackson.core.JsonFactory for details,
+ /// but the general
+ /// idea is that if caller passes in closable resource (such
+ /// as InputStream or Reader) parser does NOT
+ /// own the source; but if it passes a reference (such as
+ /// java.io.File or java.net.URL and creates
+ /// stream or reader it does own them.
+ ///@throws IOException if there is either an underlying I/O problem
+ void close() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_close, jni.JniCallType.voidType, []).check();
+ }
+
+ static final _id_isClosed =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"isClosed", r"()Z");
+
+ /// from: public abstract boolean isClosed()
+ ///
+ /// Method that can be called to determine whether this parser
+ /// is closed or not. If it is closed, no new tokens can be
+ /// retrieved by calling \#nextToken (and the underlying
+ /// stream may be closed). Closing may be due to an explicit
+ /// call to \#close or because parser has encountered
+ /// end of input.
+ ///@return {@code True} if this parser instance has been closed
+ bool isClosed() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_isClosed, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_getParsingContext = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"getParsingContext",
+ r"()Lcom/fasterxml/jackson/core/JsonStreamContext;");
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonStreamContext getParsingContext()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that can be used to access current parsing context reader
+ /// is in. There are 3 different types: root, array and object contexts,
+ /// with slightly different available information. Contexts are
+ /// hierarchically nested, and can be used for example for figuring
+ /// out part of the input document that correspond to specific
+ /// array or object (for highlighting purposes, or error reporting).
+ /// Contexts can also be used for simple xpath-like matching of
+ /// input, if so desired.
+ ///@return Stream input context (JsonStreamContext) associated with this parser
+ jni.JObject getParsingContext() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getParsingContext,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_currentLocation = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"currentLocation",
+ r"()Lcom/fasterxml/jackson/core/JsonLocation;");
+
+ /// from: public com.fasterxml.jackson.core.JsonLocation currentLocation()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that returns location of the last processed input unit (character
+ /// or byte) from the input;
+ /// usually for error reporting purposes.
+ ///
+ /// Note that the location is not guaranteed to be accurate (although most
+ /// implementation will try their best): some implementations may only
+ /// report specific boundary locations (start or end locations of tokens)
+ /// and others only return JsonLocation\#NA due to not having access
+ /// to input location information (when delegating actual decoding work
+ /// to other library)
+ ///@return Location of the last processed input unit (byte or character)
+ ///@since 2.13
+ jni.JObject currentLocation() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_currentLocation, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_currentTokenLocation = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"currentTokenLocation",
+ r"()Lcom/fasterxml/jackson/core/JsonLocation;");
+
+ /// from: public com.fasterxml.jackson.core.JsonLocation currentTokenLocation()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that return the __starting__ location of the current
+ /// (most recently returned)
+ /// token; that is, the position of the first input unit (character or byte) from input
+ /// that starts the current token.
+ ///
+ /// Note that the location is not guaranteed to be accurate (although most
+ /// implementation will try their best): some implementations may only
+ /// return JsonLocation\#NA due to not having access
+ /// to input location information (when delegating actual decoding work
+ /// to other library)
+ ///@return Starting location of the token parser currently points to
+ ///@since 2.13 (will eventually replace \#getTokenLocation)
+ jni.JObject currentTokenLocation() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_currentTokenLocation,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_getCurrentLocation = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"getCurrentLocation",
+ r"()Lcom/fasterxml/jackson/core/JsonLocation;");
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonLocation getCurrentLocation()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Alias for \#currentLocation(), to be deprecated in later
+ /// Jackson 2.x versions (and removed from Jackson 3.0).
+ ///@return Location of the last processed input unit (byte or character)
+ jni.JObject getCurrentLocation() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getCurrentLocation,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_getTokenLocation = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"getTokenLocation",
+ r"()Lcom/fasterxml/jackson/core/JsonLocation;");
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonLocation getTokenLocation()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Alias for \#currentTokenLocation(), to be deprecated in later
+ /// Jackson 2.x versions (and removed from Jackson 3.0).
+ ///@return Starting location of the token parser currently points to
+ jni.JObject getTokenLocation() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getTokenLocation,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_currentValue = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"currentValue", r"()Ljava/lang/Object;");
+
+ /// from: public java.lang.Object currentValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Helper method, usually equivalent to:
+ ///<code>
+ /// getParsingContext().getCurrentValue();
+ ///</code>
+ ///
+ /// Note that "current value" is NOT populated (or used) by Streaming parser;
+ /// it is only used by higher-level data-binding functionality.
+ /// The reason it is included here is that it can be stored and accessed hierarchically,
+ /// and gets passed through data-binding.
+ ///@return "Current value" associated with the current input context (state) of this parser
+ ///@since 2.13 (added as replacement for older \#getCurrentValue()
+ jni.JObject currentValue() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_currentValue, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_assignCurrentValue = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"assignCurrentValue", r"(Ljava/lang/Object;)V");
+
+ /// from: public void assignCurrentValue(java.lang.Object v)
+ ///
+ /// Helper method, usually equivalent to:
+ ///<code>
+ /// getParsingContext().setCurrentValue(v);
+ ///</code>
+ ///@param v Current value to assign for the current input context of this parser
+ ///@since 2.13 (added as replacement for older \#setCurrentValue
+ void assignCurrentValue(
+ jni.JObject v,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_assignCurrentValue,
+ jni.JniCallType.voidType,
+ [v.reference]).check();
+ }
+
+ static final _id_getCurrentValue = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"getCurrentValue", r"()Ljava/lang/Object;");
+
+ /// from: public java.lang.Object getCurrentValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Alias for \#currentValue(), to be deprecated in later
+ /// Jackson 2.x versions (and removed from Jackson 3.0).
+ ///@return Location of the last processed input unit (byte or character)
+ jni.JObject getCurrentValue() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getCurrentValue, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_setCurrentValue = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"setCurrentValue", r"(Ljava/lang/Object;)V");
+
+ /// from: public void setCurrentValue(java.lang.Object v)
+ ///
+ /// Alias for \#assignCurrentValue, to be deprecated in later
+ /// Jackson 2.x versions (and removed from Jackson 3.0).
+ ///@param v Current value to assign for the current input context of this parser
+ void setCurrentValue(
+ jni.JObject v,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_setCurrentValue,
+ jni.JniCallType.voidType, [v.reference]).check();
+ }
+
+ static final _id_releaseBuffered = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"releaseBuffered", r"(Ljava/io/OutputStream;)I");
+
+ /// from: public int releaseBuffered(java.io.OutputStream out)
+ ///
+ /// Method that can be called to push back any content that
+ /// has been read but not consumed by the parser. This is usually
+ /// done after reading all content of interest using parser.
+ /// Content is released by writing it to given stream if possible;
+ /// if underlying input is byte-based it can released, if not (char-based)
+ /// it can not.
+ ///@param out OutputStream to which buffered, undecoded content is written to
+ ///@return -1 if the underlying content source is not byte based
+ /// (that is, input can not be sent to OutputStream;
+ /// otherwise number of bytes released (0 if there was nothing to release)
+ ///@throws IOException if write to stream threw exception
+ int releaseBuffered(
+ jni.JObject out,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_releaseBuffered,
+ jni.JniCallType.intType, [out.reference]).integer;
+ }
+
+ static final _id_releaseBuffered1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"releaseBuffered", r"(Ljava/io/Writer;)I");
+
+ /// from: public int releaseBuffered(java.io.Writer w)
+ ///
+ /// Method that can be called to push back any content that
+ /// has been read but not consumed by the parser.
+ /// This is usually
+ /// done after reading all content of interest using parser.
+ /// Content is released by writing it to given writer if possible;
+ /// if underlying input is char-based it can released, if not (byte-based)
+ /// it can not.
+ ///@param w Writer to which buffered but unprocessed content is written to
+ ///@return -1 if the underlying content source is not char-based
+ /// (that is, input can not be sent to Writer;
+ /// otherwise number of chars released (0 if there was nothing to release)
+ ///@throws IOException if write using Writer threw exception
+ int releaseBuffered1(
+ jni.JObject w,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_releaseBuffered1,
+ jni.JniCallType.intType, [w.reference]).integer;
+ }
+
+ static final _id_enable = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"enable",
+ r"(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser enable(com.fasterxml.jackson.core.JsonParser.Feature f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for enabling specified parser feature
+ /// (check Feature for list of features)
+ ///@param f Feature to enable
+ ///@return This parser, to allow call chaining
+ JsonParser enable(
+ JsonParser_Feature f,
+ ) {
+ return const $JsonParserType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_enable,
+ jni.JniCallType.objectType,
+ [f.reference]).object);
+ }
+
+ static final _id_disable = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"disable",
+ r"(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser disable(com.fasterxml.jackson.core.JsonParser.Feature f)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for disabling specified feature
+ /// (check Feature for list of features)
+ ///@param f Feature to disable
+ ///@return This parser, to allow call chaining
+ JsonParser disable(
+ JsonParser_Feature f,
+ ) {
+ return const $JsonParserType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_disable,
+ jni.JniCallType.objectType,
+ [f.reference]).object);
+ }
+
+ static final _id_configure = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"configure",
+ r"(Lcom/fasterxml/jackson/core/JsonParser$Feature;Z)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser configure(com.fasterxml.jackson.core.JsonParser.Feature f, boolean state)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for enabling or disabling specified feature
+ /// (check Feature for list of features)
+ ///@param f Feature to enable or disable
+ ///@param state Whether to enable feature ({@code true}) or disable ({@code false})
+ ///@return This parser, to allow call chaining
+ JsonParser configure(
+ JsonParser_Feature f,
+ bool state,
+ ) {
+ return const $JsonParserType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_configure,
+ jni.JniCallType.objectType,
+ [f.reference, state ? 1 : 0]).object);
+ }
+
+ static final _id_isEnabled = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"isEnabled", r"(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Z");
+
+ /// from: public boolean isEnabled(com.fasterxml.jackson.core.JsonParser.Feature f)
+ ///
+ /// Method for checking whether specified Feature is enabled.
+ ///@param f Feature to check
+ ///@return {@code True} if feature is enabled; {@code false} otherwise
+ bool isEnabled(
+ JsonParser_Feature f,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_isEnabled,
+ jni.JniCallType.booleanType, [f.reference]).boolean;
+ }
+
+ static final _id_isEnabled1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"isEnabled",
+ r"(Lcom/fasterxml/jackson/core/StreamReadFeature;)Z");
+
+ /// from: public boolean isEnabled(com.fasterxml.jackson.core.StreamReadFeature f)
+ ///
+ /// Method for checking whether specified Feature is enabled.
+ ///@param f Feature to check
+ ///@return {@code True} if feature is enabled; {@code false} otherwise
+ ///@since 2.10
+ bool isEnabled1(
+ jni.JObject f,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_isEnabled1,
+ jni.JniCallType.booleanType, [f.reference]).boolean;
+ }
+
+ static final _id_getFeatureMask = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getFeatureMask", r"()I");
+
+ /// from: public int getFeatureMask()
+ ///
+ /// Bulk access method for getting state of all standard Features.
+ ///@return Bit mask that defines current states of all standard Features.
+ ///@since 2.3
+ int getFeatureMask() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getFeatureMask, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_setFeatureMask = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"setFeatureMask",
+ r"(I)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser setFeatureMask(int mask)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Bulk set method for (re)setting states of all standard Features
+ ///@param mask Bit mask that defines set of features to enable
+ ///@return This parser, to allow call chaining
+ ///@since 2.3
+ ///@deprecated Since 2.7, use \#overrideStdFeatures(int, int) instead
+ JsonParser setFeatureMask(
+ int mask,
+ ) {
+ return const $JsonParserType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_setFeatureMask,
+ jni.JniCallType.objectType,
+ [jni.JValueInt(mask)]).object);
+ }
+
+ static final _id_overrideStdFeatures = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"overrideStdFeatures",
+ r"(II)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser overrideStdFeatures(int values, int mask)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Bulk set method for (re)setting states of features specified by <code>mask</code>.
+ /// Functionally equivalent to
+ ///<code>
+ /// int oldState = getFeatureMask();
+ /// int newState = (oldState & ~mask) | (values & mask);
+ /// setFeatureMask(newState);
+ ///</code>
+ /// but preferred as this lets caller more efficiently specify actual changes made.
+ ///@param values Bit mask of set/clear state for features to change
+ ///@param mask Bit mask of features to change
+ ///@return This parser, to allow call chaining
+ ///@since 2.6
+ JsonParser overrideStdFeatures(
+ int values,
+ int mask,
+ ) {
+ return const $JsonParserType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_overrideStdFeatures,
+ jni.JniCallType.objectType,
+ [jni.JValueInt(values), jni.JValueInt(mask)]).object);
+ }
+
+ static final _id_getFormatFeatures = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getFormatFeatures", r"()I");
+
+ /// from: public int getFormatFeatures()
+ ///
+ /// Bulk access method for getting state of all FormatFeatures, format-specific
+ /// on/off configuration settings.
+ ///@return Bit mask that defines current states of all standard FormatFeatures.
+ ///@since 2.6
+ int getFormatFeatures() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getFormatFeatures, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_overrideFormatFeatures = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"overrideFormatFeatures",
+ r"(II)Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public com.fasterxml.jackson.core.JsonParser overrideFormatFeatures(int values, int mask)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Bulk set method for (re)setting states of FormatFeatures,
+ /// by specifying values (set / clear) along with a mask, to determine
+ /// which features to change, if any.
+ ///
+ /// Default implementation will simply throw an exception to indicate that
+ /// the parser implementation does not support any FormatFeatures.
+ ///@param values Bit mask of set/clear state for features to change
+ ///@param mask Bit mask of features to change
+ ///@return This parser, to allow call chaining
+ ///@since 2.6
+ JsonParser overrideFormatFeatures(
+ int values,
+ int mask,
+ ) {
+ return const $JsonParserType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_overrideFormatFeatures,
+ jni.JniCallType.objectType,
+ [jni.JValueInt(values), jni.JValueInt(mask)]).object);
+ }
+
+ static final _id_nextToken = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"nextToken", r"()Lcom/fasterxml/jackson/core/JsonToken;");
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonToken nextToken()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Main iteration method, which will advance stream enough
+ /// to determine type of the next token, if any. If none
+ /// remaining (stream has no content other than possible
+ /// white space before ending), null will be returned.
+ ///@return Next token from the stream, if any found, or null
+ /// to indicate end-of-input
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jsontoken_.JsonToken nextToken() {
+ return const jsontoken_.$JsonTokenType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(
+ reference, _id_nextToken, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_nextValue = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"nextValue", r"()Lcom/fasterxml/jackson/core/JsonToken;");
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonToken nextValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Iteration method that will advance stream enough
+ /// to determine type of the next token that is a value type
+ /// (including JSON Array and Object start/end markers).
+ /// Or put another way, nextToken() will be called once,
+ /// and if JsonToken\#FIELD_NAME is returned, another
+ /// time to get the value for the field.
+ /// Method is most useful for iterating over value entries
+ /// of JSON objects; field name will still be available
+ /// by calling \#getCurrentName when parser points to
+ /// the value.
+ ///@return Next non-field-name token from the stream, if any found,
+ /// or null to indicate end-of-input (or, for non-blocking
+ /// parsers, JsonToken\#NOT_AVAILABLE if no tokens were
+ /// available yet)
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jsontoken_.JsonToken nextValue() {
+ return const jsontoken_.$JsonTokenType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(
+ reference, _id_nextValue, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_nextFieldName = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"nextFieldName",
+ r"(Lcom/fasterxml/jackson/core/SerializableString;)Z");
+
+ /// from: public boolean nextFieldName(com.fasterxml.jackson.core.SerializableString str)
+ ///
+ /// Method that fetches next token (as if calling \#nextToken) and
+ /// verifies whether it is JsonToken\#FIELD_NAME with specified name
+ /// and returns result of that comparison.
+ /// It is functionally equivalent to:
+ ///<pre>
+ /// return (nextToken() == JsonToken.FIELD_NAME) && str.getValue().equals(getCurrentName());
+ ///</pre>
+ /// but may be faster for parser to verify, and can therefore be used if caller
+ /// expects to get such a property name from input next.
+ ///@param str Property name to compare next token to (if next token is
+ /// <code>JsonToken.FIELD_NAME</code>)
+ ///@return {@code True} if parser advanced to {@code JsonToken.FIELD_NAME} with
+ /// specified name; {@code false} otherwise (different token or non-matching name)
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ bool nextFieldName(
+ jni.JObject str,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_nextFieldName,
+ jni.JniCallType.booleanType, [str.reference]).boolean;
+ }
+
+ static final _id_nextFieldName1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"nextFieldName", r"()Ljava/lang/String;");
+
+ /// from: public java.lang.String nextFieldName()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that fetches next token (as if calling \#nextToken) and
+ /// verifies whether it is JsonToken\#FIELD_NAME; if it is,
+ /// returns same as \#getCurrentName(), otherwise null.
+ ///@return Name of the the {@code JsonToken.FIELD_NAME} parser advanced to, if any;
+ /// {@code null} if next token is of some other type
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.5
+ jni.JString nextFieldName1() {
+ return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_nextFieldName1, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_nextTextValue = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"nextTextValue", r"()Ljava/lang/String;");
+
+ /// from: public java.lang.String nextTextValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that fetches next token (as if calling \#nextToken) and
+ /// if it is JsonToken\#VALUE_STRING returns contained String value;
+ /// otherwise returns null.
+ /// It is functionally equivalent to:
+ ///<pre>
+ /// return (nextToken() == JsonToken.VALUE_STRING) ? getText() : null;
+ ///</pre>
+ /// but may be faster for parser to process, and can therefore be used if caller
+ /// expects to get a String value next from input.
+ ///@return Text value of the {@code JsonToken.VALUE_STRING} token parser advanced
+ /// to; or {@code null} if next token is of some other type
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JString nextTextValue() {
+ return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_nextTextValue, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_nextIntValue = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"nextIntValue", r"(I)I");
+
+ /// from: public int nextIntValue(int defaultValue)
+ ///
+ /// Method that fetches next token (as if calling \#nextToken) and
+ /// if it is JsonToken\#VALUE_NUMBER_INT returns 32-bit int value;
+ /// otherwise returns specified default value
+ /// It is functionally equivalent to:
+ ///<pre>
+ /// return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getIntValue() : defaultValue;
+ ///</pre>
+ /// but may be faster for parser to process, and can therefore be used if caller
+ /// expects to get an int value next from input.
+ ///
+ /// NOTE: value checks are performed similar to \#getIntValue()
+ ///@param defaultValue Value to return if next token is NOT of type {@code JsonToken.VALUE_NUMBER_INT}
+ ///@return Integer ({@code int}) value of the {@code JsonToken.VALUE_NUMBER_INT} token parser advanced
+ /// to; or {@code defaultValue} if next token is of some other type
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@throws InputCoercionException if integer number does not fit in Java {@code int}
+ int nextIntValue(
+ int defaultValue,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_nextIntValue,
+ jni.JniCallType.intType, [jni.JValueInt(defaultValue)]).integer;
+ }
+
+ static final _id_nextLongValue = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"nextLongValue", r"(J)J");
+
+ /// from: public long nextLongValue(long defaultValue)
+ ///
+ /// Method that fetches next token (as if calling \#nextToken) and
+ /// if it is JsonToken\#VALUE_NUMBER_INT returns 64-bit long value;
+ /// otherwise returns specified default value
+ /// It is functionally equivalent to:
+ ///<pre>
+ /// return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getLongValue() : defaultValue;
+ ///</pre>
+ /// but may be faster for parser to process, and can therefore be used if caller
+ /// expects to get a long value next from input.
+ ///
+ /// NOTE: value checks are performed similar to \#getLongValue()
+ ///@param defaultValue Value to return if next token is NOT of type {@code JsonToken.VALUE_NUMBER_INT}
+ ///@return {@code long} value of the {@code JsonToken.VALUE_NUMBER_INT} token parser advanced
+ /// to; or {@code defaultValue} if next token is of some other type
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@throws InputCoercionException if integer number does not fit in Java {@code long}
+ int nextLongValue(
+ int defaultValue,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_nextLongValue,
+ jni.JniCallType.longType, [defaultValue]).long;
+ }
+
+ static final _id_nextBooleanValue = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"nextBooleanValue", r"()Ljava/lang/Boolean;");
+
+ /// from: public java.lang.Boolean nextBooleanValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that fetches next token (as if calling \#nextToken) and
+ /// if it is JsonToken\#VALUE_TRUE or JsonToken\#VALUE_FALSE
+ /// returns matching Boolean value; otherwise return null.
+ /// It is functionally equivalent to:
+ ///<pre>
+ /// JsonToken t = nextToken();
+ /// if (t == JsonToken.VALUE_TRUE) return Boolean.TRUE;
+ /// if (t == JsonToken.VALUE_FALSE) return Boolean.FALSE;
+ /// return null;
+ ///</pre>
+ /// but may be faster for parser to process, and can therefore be used if caller
+ /// expects to get a Boolean value next from input.
+ ///@return {@code Boolean} value of the {@code JsonToken.VALUE_TRUE} or {@code JsonToken.VALUE_FALSE}
+ /// token parser advanced to; or {@code null} if next token is of some other type
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JBoolean nextBooleanValue() {
+ return const jni.JBooleanType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_nextBooleanValue,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_skipChildren = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"skipChildren",
+ r"()Lcom/fasterxml/jackson/core/JsonParser;");
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonParser skipChildren()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that will skip all child tokens of an array or
+ /// object token that the parser currently points to,
+ /// iff stream points to
+ /// JsonToken\#START_OBJECT or JsonToken\#START_ARRAY.
+ /// If not, it will do nothing.
+ /// After skipping, stream will point to __matching__
+ /// JsonToken\#END_OBJECT or JsonToken\#END_ARRAY
+ /// (possibly skipping nested pairs of START/END OBJECT/ARRAY tokens
+ /// as well as value tokens).
+ /// The idea is that after calling this method, application
+ /// will call \#nextToken to point to the next
+ /// available token, if any.
+ ///@return This parser, to allow call chaining
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ JsonParser skipChildren() {
+ return const $JsonParserType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_skipChildren, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_finishToken =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"finishToken", r"()V");
+
+ /// from: public void finishToken()
+ ///
+ /// Method that may be used to force full handling of the current token
+ /// so that even if lazy processing is enabled, the whole contents are
+ /// read for possible retrieval. This is usually used to ensure that
+ /// the token end location is available, as well as token contents
+ /// (similar to what calling, say \#getTextCharacters(), would
+ /// achieve).
+ ///
+ /// Note that for many dataformat implementations this method
+ /// will not do anything; this is the default implementation unless
+ /// overridden by sub-classes.
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.8
+ void finishToken() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_finishToken, jni.JniCallType.voidType, []).check();
+ }
+
+ static final _id_currentToken = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"currentToken",
+ r"()Lcom/fasterxml/jackson/core/JsonToken;");
+
+ /// from: public com.fasterxml.jackson.core.JsonToken currentToken()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Accessor to find which token parser currently points to, if any;
+ /// null will be returned if none.
+ /// If return value is non-null, data associated with the token
+ /// is available via other accessor methods.
+ ///@return Type of the token this parser currently points to,
+ /// if any: null before any tokens have been read, and
+ /// after end-of-input has been encountered, as well as
+ /// if the current token has been explicitly cleared.
+ ///@since 2.8
+ jsontoken_.JsonToken currentToken() {
+ return const jsontoken_.$JsonTokenType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_currentToken,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_currentTokenId = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"currentTokenId", r"()I");
+
+ /// from: public int currentTokenId()
+ ///
+ /// Method similar to \#getCurrentToken() but that returns an
+ /// <code>int</code> instead of JsonToken (enum value).
+ ///
+ /// Use of int directly is typically more efficient on switch statements,
+ /// so this method may be useful when building low-overhead codecs.
+ /// Note, however, that effect may not be big enough to matter: make sure
+ /// to profile performance before deciding to use this method.
+ ///@since 2.8
+ ///@return {@code int} matching one of constants from JsonTokenId.
+ int currentTokenId() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_currentTokenId, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_getCurrentToken = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"getCurrentToken",
+ r"()Lcom/fasterxml/jackson/core/JsonToken;");
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonToken getCurrentToken()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Alias for \#currentToken(), may be deprecated sometime after
+ /// Jackson 2.13 (will be removed from 3.0).
+ ///@return Type of the token this parser currently points to,
+ /// if any: null before any tokens have been read, and
+ jsontoken_.JsonToken getCurrentToken() {
+ return const jsontoken_.$JsonTokenType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_getCurrentToken,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_getCurrentTokenId = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getCurrentTokenId", r"()I");
+
+ /// from: public abstract int getCurrentTokenId()
+ ///
+ /// Deprecated alias for \#currentTokenId().
+ ///@return {@code int} matching one of constants from JsonTokenId.
+ ///@deprecated Since 2.12 use \#currentTokenId instead
+ int getCurrentTokenId() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getCurrentTokenId, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_hasCurrentToken = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"hasCurrentToken", r"()Z");
+
+ /// from: public abstract boolean hasCurrentToken()
+ ///
+ /// Method for checking whether parser currently points to
+ /// a token (and data for that token is available).
+ /// Equivalent to check for <code>parser.getCurrentToken() != null</code>.
+ ///@return True if the parser just returned a valid
+ /// token via \#nextToken; false otherwise (parser
+ /// was just constructed, encountered end-of-input
+ /// and returned null from \#nextToken, or the token
+ /// has been consumed)
+ bool hasCurrentToken() {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_hasCurrentToken,
+ jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_hasTokenId =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"hasTokenId", r"(I)Z");
+
+ /// from: public abstract boolean hasTokenId(int id)
+ ///
+ /// Method that is functionally equivalent to:
+ ///<code>
+ /// return currentTokenId() == id
+ ///</code>
+ /// but may be more efficiently implemented.
+ ///
+ /// Note that no traversal or conversion is performed; so in some
+ /// cases calling method like \#isExpectedStartArrayToken()
+ /// is necessary instead.
+ ///@param id Token id to match (from (@link JsonTokenId})
+ ///@return {@code True} if the parser current points to specified token
+ ///@since 2.5
+ bool hasTokenId(
+ int id,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_hasTokenId,
+ jni.JniCallType.booleanType, [jni.JValueInt(id)]).boolean;
+ }
+
+ static final _id_hasToken = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"hasToken", r"(Lcom/fasterxml/jackson/core/JsonToken;)Z");
+
+ /// from: public abstract boolean hasToken(com.fasterxml.jackson.core.JsonToken t)
+ ///
+ /// Method that is functionally equivalent to:
+ ///<code>
+ /// return currentToken() == t
+ ///</code>
+ /// but may be more efficiently implemented.
+ ///
+ /// Note that no traversal or conversion is performed; so in some
+ /// cases calling method like \#isExpectedStartArrayToken()
+ /// is necessary instead.
+ ///@param t Token to match
+ ///@return {@code True} if the parser current points to specified token
+ ///@since 2.6
+ bool hasToken(
+ jsontoken_.JsonToken t,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_hasToken,
+ jni.JniCallType.booleanType, [t.reference]).boolean;
+ }
+
+ static final _id_isExpectedStartArrayToken = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"isExpectedStartArrayToken", r"()Z");
+
+ /// from: public boolean isExpectedStartArrayToken()
+ ///
+ /// Specialized accessor that can be used to verify that the current
+ /// token indicates start array (usually meaning that current token
+ /// is JsonToken\#START_ARRAY) when start array is expected.
+ /// For some specialized parsers this can return true for other cases
+ /// as well; this is usually done to emulate arrays in cases underlying
+ /// format is ambiguous (XML, for example, has no format-level difference
+ /// between Objects and Arrays; it just has elements).
+ ///
+ /// Default implementation is equivalent to:
+ ///<pre>
+ /// currentToken() == JsonToken.START_ARRAY
+ ///</pre>
+ /// but may be overridden by custom parser implementations.
+ ///@return True if the current token can be considered as a
+ /// start-array marker (such JsonToken\#START_ARRAY);
+ /// {@code false} if not
+ bool isExpectedStartArrayToken() {
+ return jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_isExpectedStartArrayToken, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_isExpectedStartObjectToken = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"isExpectedStartObjectToken", r"()Z");
+
+ /// from: public boolean isExpectedStartObjectToken()
+ ///
+ /// Similar to \#isExpectedStartArrayToken(), but checks whether stream
+ /// currently points to JsonToken\#START_OBJECT.
+ ///@return True if the current token can be considered as a
+ /// start-array marker (such JsonToken\#START_OBJECT);
+ /// {@code false} if not
+ ///@since 2.5
+ bool isExpectedStartObjectToken() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_isExpectedStartObjectToken,
+ jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_isExpectedNumberIntToken = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"isExpectedNumberIntToken", r"()Z");
+
+ /// from: public boolean isExpectedNumberIntToken()
+ ///
+ /// Similar to \#isExpectedStartArrayToken(), but checks whether stream
+ /// currently points to JsonToken\#VALUE_NUMBER_INT.
+ ///
+ /// The initial use case is for XML backend to efficiently (attempt to) coerce
+ /// textual content into numbers.
+ ///@return True if the current token can be considered as a
+ /// start-array marker (such JsonToken\#VALUE_NUMBER_INT);
+ /// {@code false} if not
+ ///@since 2.12
+ bool isExpectedNumberIntToken() {
+ return jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_isExpectedNumberIntToken, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_isNaN =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"isNaN", r"()Z");
+
+ /// from: public boolean isNaN()
+ ///
+ /// Access for checking whether current token is a numeric value token, but
+ /// one that is of "not-a-number" (NaN) variety (including both "NaN" AND
+ /// positive/negative infinity!): not supported by all formats,
+ /// but often supported for JsonToken\#VALUE_NUMBER_FLOAT.
+ /// NOTE: roughly equivalent to calling <code>!Double.isFinite()</code>
+ /// on value you would get from calling \#getDoubleValue().
+ ///@return {@code True} if the current token is of type JsonToken\#VALUE_NUMBER_FLOAT
+ /// but represents a "Not a Number"; {@code false} for other tokens and regular
+ /// floating-point numbers
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.9
+ bool isNaN() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_isNaN, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_clearCurrentToken = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"clearCurrentToken", r"()V");
+
+ /// from: public abstract void clearCurrentToken()
+ ///
+ /// Method called to "consume" the current token by effectively
+ /// removing it so that \#hasCurrentToken returns false, and
+ /// \#getCurrentToken null).
+ /// Cleared token value can still be accessed by calling
+ /// \#getLastClearedToken (if absolutely needed), but
+ /// usually isn't.
+ ///
+ /// Method was added to be used by the optional data binder, since
+ /// it has to be able to consume last token used for binding (so that
+ /// it will not be used again).
+ void clearCurrentToken() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_clearCurrentToken, jni.JniCallType.voidType, []).check();
+ }
+
+ static final _id_getLastClearedToken = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"getLastClearedToken",
+ r"()Lcom/fasterxml/jackson/core/JsonToken;");
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonToken getLastClearedToken()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that can be called to get the last token that was
+ /// cleared using \#clearCurrentToken. This is not necessarily
+ /// the latest token read.
+ /// Will return null if no tokens have been cleared,
+ /// or if parser has been closed.
+ ///@return Last cleared token, if any; {@code null} otherwise
+ jsontoken_.JsonToken getLastClearedToken() {
+ return const jsontoken_.$JsonTokenType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_getLastClearedToken,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_overrideCurrentName = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"overrideCurrentName", r"(Ljava/lang/String;)V");
+
+ /// from: public abstract void overrideCurrentName(java.lang.String name)
+ ///
+ /// Method that can be used to change what is considered to be
+ /// the current (field) name.
+ /// May be needed to support non-JSON data formats or unusual binding
+ /// conventions; not needed for typical processing.
+ ///
+ /// Note that use of this method should only be done as sort of last
+ /// resort, as it is a work-around for regular operation.
+ ///@param name Name to use as the current name; may be null.
+ void overrideCurrentName(
+ jni.JString name,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_overrideCurrentName,
+ jni.JniCallType.voidType,
+ [name.reference]).check();
+ }
+
+ static final _id_getCurrentName = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"getCurrentName", r"()Ljava/lang/String;");
+
+ /// from: public abstract java.lang.String getCurrentName()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Alias of \#currentName().
+ ///@return Name of the current field in the parsing context
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JString getCurrentName() {
+ return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getCurrentName, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_currentName = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"currentName", r"()Ljava/lang/String;");
+
+ /// from: public java.lang.String currentName()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that can be called to get the name associated with
+ /// the current token: for JsonToken\#FIELD_NAMEs it will
+ /// be the same as what \#getText returns;
+ /// for field values it will be preceding field name;
+ /// and for others (array values, root-level values) null.
+ ///@return Name of the current field in the parsing context
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.10
+ jni.JString currentName() {
+ return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_currentName, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_getText = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getText", r"()Ljava/lang/String;");
+
+ /// from: public abstract java.lang.String getText()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for accessing textual representation of the current token;
+ /// if no current token (before first call to \#nextToken, or
+ /// after encountering end-of-input), returns null.
+ /// Method can be called for any token type.
+ ///@return Textual value associated with the current token (one returned
+ /// by \#nextToken() or other iteration methods)
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JString getText() {
+ return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getText, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_getText1 = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getText", r"(Ljava/io/Writer;)I");
+
+ /// from: public int getText(java.io.Writer writer)
+ ///
+ /// Method to read the textual representation of the current token in chunks and
+ /// pass it to the given Writer.
+ /// Conceptually same as calling:
+ ///<pre>
+ /// writer.write(parser.getText());
+ ///</pre>
+ /// but should typically be more efficient as longer content does need to
+ /// be combined into a single <code>String</code> to return, and write
+ /// can occur directly from intermediate buffers Jackson uses.
+ ///@param writer Writer to write textual content to
+ ///@return The number of characters written to the Writer
+ ///@throws IOException for low-level read issues or writes using passed
+ /// {@code writer}, or
+ /// JsonParseException for decoding problems
+ ///@since 2.8
+ int getText1(
+ jni.JObject writer,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_getText1,
+ jni.JniCallType.intType, [writer.reference]).integer;
+ }
+
+ static final _id_getTextCharacters = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getTextCharacters", r"()[C");
+
+ /// from: public abstract char[] getTextCharacters()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method similar to \#getText, but that will return
+ /// underlying (unmodifiable) character array that contains
+ /// textual value, instead of constructing a String object
+ /// to contain this information.
+ /// Note, however, that:
+ ///<ul>
+ /// <li>Textual contents are not guaranteed to start at
+ /// index 0 (rather, call \#getTextOffset) to
+ /// know the actual offset
+ /// </li>
+ /// <li>Length of textual contents may be less than the
+ /// length of returned buffer: call \#getTextLength
+ /// for actual length of returned content.
+ /// </li>
+ /// </ul>
+ ///
+ /// Note that caller __MUST NOT__ modify the returned
+ /// character array in any way -- doing so may corrupt
+ /// current parser state and render parser instance useless.
+ ///
+ /// The only reason to call this method (over \#getText)
+ /// is to avoid construction of a String object (which
+ /// will make a copy of contents).
+ ///@return Buffer that contains the current textual value (but not necessarily
+ /// at offset 0, and not necessarily until the end of buffer)
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JArray<jni.jchar> getTextCharacters() {
+ return const jni.JArrayType(jni.jcharType()).fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_getTextCharacters,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_getTextLength = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getTextLength", r"()I");
+
+ /// from: public abstract int getTextLength()
+ ///
+ /// Accessor used with \#getTextCharacters, to know length
+ /// of String stored in returned buffer.
+ ///@return Number of characters within buffer returned
+ /// by \#getTextCharacters that are part of
+ /// textual content of the current token.
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getTextLength() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getTextLength, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_getTextOffset = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getTextOffset", r"()I");
+
+ /// from: public abstract int getTextOffset()
+ ///
+ /// Accessor used with \#getTextCharacters, to know offset
+ /// of the first text content character within buffer.
+ ///@return Offset of the first character within buffer returned
+ /// by \#getTextCharacters that is part of
+ /// textual content of the current token.
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getTextOffset() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getTextOffset, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_hasTextCharacters = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"hasTextCharacters", r"()Z");
+
+ /// from: public abstract boolean hasTextCharacters()
+ ///
+ /// Method that can be used to determine whether calling of
+ /// \#getTextCharacters would be the most efficient
+ /// way to access textual content for the event parser currently
+ /// points to.
+ ///
+ /// Default implementation simply returns false since only actual
+ /// implementation class has knowledge of its internal buffering
+ /// state.
+ /// Implementations are strongly encouraged to properly override
+ /// this method, to allow efficient copying of content by other
+ /// code.
+ ///@return True if parser currently has character array that can
+ /// be efficiently returned via \#getTextCharacters; false
+ /// means that it may or may not exist
+ bool hasTextCharacters() {
+ return jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_hasTextCharacters, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_getNumberValue = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"getNumberValue", r"()Ljava/lang/Number;");
+
+ /// from: public abstract java.lang.Number getNumberValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Generic number value accessor method that will work for
+ /// all kinds of numeric values. It will return the optimal
+ /// (simplest/smallest possible) wrapper object that can
+ /// express the numeric value just parsed.
+ ///@return Numeric value of the current token in its most optimal
+ /// representation
+ ///@throws IOException Problem with access: JsonParseException if
+ /// the current token is not numeric, or if decoding of the value fails
+ /// (invalid format for numbers); plain IOException if underlying
+ /// content read fails (possible if values are extracted lazily)
+ jni.JNumber getNumberValue() {
+ return const jni.JNumberType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getNumberValue, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_getNumberValueExact = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"getNumberValueExact", r"()Ljava/lang/Number;");
+
+ /// from: public java.lang.Number getNumberValueExact()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method similar to \#getNumberValue with the difference that
+ /// for floating-point numbers value returned may be BigDecimal
+ /// if the underlying format does not store floating-point numbers using
+ /// native representation: for example, textual formats represent numbers
+ /// as Strings (which are 10-based), and conversion to java.lang.Double
+ /// is potentially lossy operation.
+ ///
+ /// Default implementation simply returns \#getNumberValue()
+ ///@return Numeric value of the current token using most accurate representation
+ ///@throws IOException Problem with access: JsonParseException if
+ /// the current token is not numeric, or if decoding of the value fails
+ /// (invalid format for numbers); plain IOException if underlying
+ /// content read fails (possible if values are extracted lazily)
+ ///@since 2.12
+ jni.JNumber getNumberValueExact() {
+ return const jni.JNumberType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getNumberValueExact,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_getNumberType = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"getNumberType",
+ r"()Lcom/fasterxml/jackson/core/JsonParser$NumberType;");
+
+ /// from: public abstract com.fasterxml.jackson.core.JsonParser.NumberType getNumberType()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// If current token is of type
+ /// JsonToken\#VALUE_NUMBER_INT or
+ /// JsonToken\#VALUE_NUMBER_FLOAT, returns
+ /// one of NumberType constants; otherwise returns null.
+ ///@return Type of current number, if parser points to numeric token; {@code null} otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ JsonParser_NumberType getNumberType() {
+ return const $JsonParser_NumberTypeType().fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_getNumberType,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_getByteValue = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getByteValue", r"()B");
+
+ /// from: public byte getByteValue()
+ ///
+ /// Numeric accessor that can be called when the current
+ /// token is of type JsonToken\#VALUE_NUMBER_INT and
+ /// it can be expressed as a value of Java byte primitive type.
+ /// Note that in addition to "natural" input range of {@code [-128, 127]},
+ /// this also allows "unsigned 8-bit byte" values {@code [128, 255]}:
+ /// but for this range value will be translated by truncation, leading
+ /// to sign change.
+ ///
+ /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
+ /// if so, it is equivalent to calling \#getDoubleValue
+ /// and then casting; except for possible overflow/underflow
+ /// exception.
+ ///
+ /// Note: if the resulting integer value falls outside range of
+ /// {@code [-128, 255]},
+ /// a InputCoercionException
+ /// will be thrown to indicate numeric overflow/underflow.
+ ///@return Current number value as {@code byte} (if numeric token within
+ /// range of {@code [-128, 255]}); otherwise exception thrown
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getByteValue() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getByteValue, jni.JniCallType.byteType, []).byte;
+ }
+
+ static final _id_getShortValue = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getShortValue", r"()S");
+
+ /// from: public short getShortValue()
+ ///
+ /// Numeric accessor that can be called when the current
+ /// token is of type JsonToken\#VALUE_NUMBER_INT and
+ /// it can be expressed as a value of Java short primitive type.
+ /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
+ /// if so, it is equivalent to calling \#getDoubleValue
+ /// and then casting; except for possible overflow/underflow
+ /// exception.
+ ///
+ /// Note: if the resulting integer value falls outside range of
+ /// Java short, a InputCoercionException
+ /// will be thrown to indicate numeric overflow/underflow.
+ ///@return Current number value as {@code short} (if numeric token within
+ /// Java 16-bit signed {@code short} range); otherwise exception thrown
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getShortValue() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getShortValue, jni.JniCallType.shortType, []).short;
+ }
+
+ static final _id_getIntValue =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"getIntValue", r"()I");
+
+ /// from: public abstract int getIntValue()
+ ///
+ /// Numeric accessor that can be called when the current
+ /// token is of type JsonToken\#VALUE_NUMBER_INT and
+ /// it can be expressed as a value of Java int primitive type.
+ /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
+ /// if so, it is equivalent to calling \#getDoubleValue
+ /// and then casting; except for possible overflow/underflow
+ /// exception.
+ ///
+ /// Note: if the resulting integer value falls outside range of
+ /// Java {@code int}, a InputCoercionException
+ /// may be thrown to indicate numeric overflow/underflow.
+ ///@return Current number value as {@code int} (if numeric token within
+ /// Java 32-bit signed {@code int} range); otherwise exception thrown
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getIntValue() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getIntValue, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_getLongValue = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getLongValue", r"()J");
+
+ /// from: public abstract long getLongValue()
+ ///
+ /// Numeric accessor that can be called when the current
+ /// token is of type JsonToken\#VALUE_NUMBER_INT and
+ /// it can be expressed as a Java long primitive type.
+ /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
+ /// if so, it is equivalent to calling \#getDoubleValue
+ /// and then casting to int; except for possible overflow/underflow
+ /// exception.
+ ///
+ /// Note: if the token is an integer, but its value falls
+ /// outside of range of Java long, a InputCoercionException
+ /// may be thrown to indicate numeric overflow/underflow.
+ ///@return Current number value as {@code long} (if numeric token within
+ /// Java 32-bit signed {@code long} range); otherwise exception thrown
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getLongValue() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getLongValue, jni.JniCallType.longType, []).long;
+ }
+
+ static final _id_getBigIntegerValue = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"getBigIntegerValue", r"()Ljava/math/BigInteger;");
+
+ /// from: public abstract java.math.BigInteger getBigIntegerValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Numeric accessor that can be called when the current
+ /// token is of type JsonToken\#VALUE_NUMBER_INT and
+ /// it can not be used as a Java long primitive type due to its
+ /// magnitude.
+ /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
+ /// if so, it is equivalent to calling \#getDecimalValue
+ /// and then constructing a BigInteger from that value.
+ ///@return Current number value as BigInteger (if numeric token);
+ /// otherwise exception thrown
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JObject getBigIntegerValue() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getBigIntegerValue,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_getFloatValue = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getFloatValue", r"()F");
+
+ /// from: public abstract float getFloatValue()
+ ///
+ /// Numeric accessor that can be called when the current
+ /// token is of type JsonToken\#VALUE_NUMBER_FLOAT and
+ /// it can be expressed as a Java float primitive type.
+ /// It can also be called for JsonToken\#VALUE_NUMBER_INT;
+ /// if so, it is equivalent to calling \#getLongValue
+ /// and then casting; except for possible overflow/underflow
+ /// exception.
+ ///
+ /// Note: if the value falls
+ /// outside of range of Java float, a InputCoercionException
+ /// will be thrown to indicate numeric overflow/underflow.
+ ///@return Current number value as {@code float} (if numeric token within
+ /// Java {@code float} range); otherwise exception thrown
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ double getFloatValue() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getFloatValue, jni.JniCallType.floatType, []).float;
+ }
+
+ static final _id_getDoubleValue = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getDoubleValue", r"()D");
+
+ /// from: public abstract double getDoubleValue()
+ ///
+ /// Numeric accessor that can be called when the current
+ /// token is of type JsonToken\#VALUE_NUMBER_FLOAT and
+ /// it can be expressed as a Java double primitive type.
+ /// It can also be called for JsonToken\#VALUE_NUMBER_INT;
+ /// if so, it is equivalent to calling \#getLongValue
+ /// and then casting; except for possible overflow/underflow
+ /// exception.
+ ///
+ /// Note: if the value falls
+ /// outside of range of Java double, a InputCoercionException
+ /// will be thrown to indicate numeric overflow/underflow.
+ ///@return Current number value as {@code double} (if numeric token within
+ /// Java {@code double} range); otherwise exception thrown
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ double getDoubleValue() {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_getDoubleValue,
+ jni.JniCallType.doubleType, []).doubleFloat;
+ }
+
+ static final _id_getDecimalValue = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"getDecimalValue", r"()Ljava/math/BigDecimal;");
+
+ /// from: public abstract java.math.BigDecimal getDecimalValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Numeric accessor that can be called when the current
+ /// token is of type JsonToken\#VALUE_NUMBER_FLOAT or
+ /// JsonToken\#VALUE_NUMBER_INT. No under/overflow exceptions
+ /// are ever thrown.
+ ///@return Current number value as BigDecimal (if numeric token);
+ /// otherwise exception thrown
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JObject getDecimalValue() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getDecimalValue, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_getBooleanValue = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getBooleanValue", r"()Z");
+
+ /// from: public boolean getBooleanValue()
+ ///
+ /// Convenience accessor that can be called when the current
+ /// token is JsonToken\#VALUE_TRUE or
+ /// JsonToken\#VALUE_FALSE, to return matching {@code boolean}
+ /// value.
+ /// If the current token is of some other type, JsonParseException
+ /// will be thrown
+ ///@return {@code True} if current token is {@code JsonToken.VALUE_TRUE},
+ /// {@code false} if current token is {@code JsonToken.VALUE_FALSE};
+ /// otherwise throws JsonParseException
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ bool getBooleanValue() {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_getBooleanValue,
+ jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_getEmbeddedObject = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"getEmbeddedObject", r"()Ljava/lang/Object;");
+
+ /// from: public java.lang.Object getEmbeddedObject()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Accessor that can be called if (and only if) the current token
+ /// is JsonToken\#VALUE_EMBEDDED_OBJECT. For other token types,
+ /// null is returned.
+ ///
+ /// Note: only some specialized parser implementations support
+ /// embedding of objects (usually ones that are facades on top
+ /// of non-streaming sources, such as object trees). One exception
+ /// is access to binary content (whether via base64 encoding or not)
+ /// which typically is accessible using this method, as well as
+ /// \#getBinaryValue().
+ ///@return Embedded value (usually of "native" type supported by format)
+ /// for the current token, if any; {@code null otherwise}
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JObject getEmbeddedObject() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getEmbeddedObject,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_getBinaryValue = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"getBinaryValue",
+ r"(Lcom/fasterxml/jackson/core/Base64Variant;)[B");
+
+ /// from: public abstract byte[] getBinaryValue(com.fasterxml.jackson.core.Base64Variant bv)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that can be used to read (and consume -- results
+ /// may not be accessible using other methods after the call)
+ /// base64-encoded binary data
+ /// included in the current textual JSON value.
+ /// It works similar to getting String value via \#getText
+ /// and decoding result (except for decoding part),
+ /// but should be significantly more performant.
+ ///
+ /// Note that non-decoded textual contents of the current token
+ /// are not guaranteed to be accessible after this method
+ /// is called. Current implementation, for example, clears up
+ /// textual content during decoding.
+ /// Decoded binary content, however, will be retained until
+ /// parser is advanced to the next event.
+ ///@param bv Expected variant of base64 encoded
+ /// content (see Base64Variants for definitions
+ /// of "standard" variants).
+ ///@return Decoded binary data
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JArray<jni.jbyte> getBinaryValue(
+ jni.JObject bv,
+ ) {
+ return const jni.JArrayType(jni.jbyteType()).fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_getBinaryValue,
+ jni.JniCallType.objectType, [bv.reference]).object);
+ }
+
+ static final _id_getBinaryValue1 = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getBinaryValue", r"()[B");
+
+ /// from: public byte[] getBinaryValue()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Convenience alternative to \#getBinaryValue(Base64Variant)
+ /// that defaults to using
+ /// Base64Variants\#getDefaultVariant as the default encoding.
+ ///@return Decoded binary data
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ jni.JArray<jni.jbyte> getBinaryValue1() {
+ return const jni.JArrayType(jni.jbyteType()).fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_getBinaryValue1,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_readBinaryValue = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"readBinaryValue", r"(Ljava/io/OutputStream;)I");
+
+ /// from: public int readBinaryValue(java.io.OutputStream out)
+ ///
+ /// Method that can be used as an alternative to \#getBigIntegerValue(),
+ /// especially when value can be large. The main difference (beyond method
+ /// of returning content using OutputStream instead of as byte array)
+ /// is that content will NOT remain accessible after method returns: any content
+ /// processed will be consumed and is not buffered in any way. If caller needs
+ /// buffering, it has to implement it.
+ ///@param out Output stream to use for passing decoded binary data
+ ///@return Number of bytes that were decoded and written via OutputStream
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.1
+ int readBinaryValue(
+ jni.JObject out,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_readBinaryValue,
+ jni.JniCallType.intType, [out.reference]).integer;
+ }
+
+ static final _id_readBinaryValue1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"readBinaryValue",
+ r"(Lcom/fasterxml/jackson/core/Base64Variant;Ljava/io/OutputStream;)I");
+
+ /// from: public int readBinaryValue(com.fasterxml.jackson.core.Base64Variant bv, java.io.OutputStream out)
+ ///
+ /// Similar to \#readBinaryValue(OutputStream) but allows explicitly
+ /// specifying base64 variant to use.
+ ///@param bv base64 variant to use
+ ///@param out Output stream to use for passing decoded binary data
+ ///@return Number of bytes that were decoded and written via OutputStream
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.1
+ int readBinaryValue1(
+ jni.JObject bv,
+ jni.JObject out,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_readBinaryValue1,
+ jni.JniCallType.intType, [bv.reference, out.reference]).integer;
+ }
+
+ static final _id_getValueAsInt = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getValueAsInt", r"()I");
+
+ /// from: public int getValueAsInt()
+ ///
+ /// Method that will try to convert value of current token to a
+ /// Java {@code int} value.
+ /// Numbers are coerced using default Java rules; booleans convert to 0 (false)
+ /// and 1 (true), and Strings are parsed using default Java language integer
+ /// parsing rules.
+ ///
+ /// If representation can not be converted to an int (including structured type
+ /// markers like start/end Object/Array)
+ /// default value of __0__ will be returned; no exceptions are thrown.
+ ///@return {@code int} value current token is converted to, if possible; exception thrown
+ /// otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getValueAsInt() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getValueAsInt, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_getValueAsInt1 = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getValueAsInt", r"(I)I");
+
+ /// from: public int getValueAsInt(int def)
+ ///
+ /// Method that will try to convert value of current token to a
+ /// __int__.
+ /// Numbers are coerced using default Java rules; booleans convert to 0 (false)
+ /// and 1 (true), and Strings are parsed using default Java language integer
+ /// parsing rules.
+ ///
+ /// If representation can not be converted to an int (including structured type
+ /// markers like start/end Object/Array)
+ /// specified __def__ will be returned; no exceptions are thrown.
+ ///@param def Default value to return if conversion to {@code int} is not possible
+ ///@return {@code int} value current token is converted to, if possible; {@code def} otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getValueAsInt1(
+ int def,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_getValueAsInt1,
+ jni.JniCallType.intType, [jni.JValueInt(def)]).integer;
+ }
+
+ static final _id_getValueAsLong = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getValueAsLong", r"()J");
+
+ /// from: public long getValueAsLong()
+ ///
+ /// Method that will try to convert value of current token to a
+ /// __long__.
+ /// Numbers are coerced using default Java rules; booleans convert to 0 (false)
+ /// and 1 (true), and Strings are parsed using default Java language integer
+ /// parsing rules.
+ ///
+ /// If representation can not be converted to a long (including structured type
+ /// markers like start/end Object/Array)
+ /// default value of __0L__ will be returned; no exceptions are thrown.
+ ///@return {@code long} value current token is converted to, if possible; exception thrown
+ /// otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getValueAsLong() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getValueAsLong, jni.JniCallType.longType, []).long;
+ }
+
+ static final _id_getValueAsLong1 = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getValueAsLong", r"(J)J");
+
+ /// from: public long getValueAsLong(long def)
+ ///
+ /// Method that will try to convert value of current token to a
+ /// __long__.
+ /// Numbers are coerced using default Java rules; booleans convert to 0 (false)
+ /// and 1 (true), and Strings are parsed using default Java language integer
+ /// parsing rules.
+ ///
+ /// If representation can not be converted to a long (including structured type
+ /// markers like start/end Object/Array)
+ /// specified __def__ will be returned; no exceptions are thrown.
+ ///@param def Default value to return if conversion to {@code long} is not possible
+ ///@return {@code long} value current token is converted to, if possible; {@code def} otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ int getValueAsLong1(
+ int def,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getValueAsLong1, jni.JniCallType.longType, [def]).long;
+ }
+
+ static final _id_getValueAsDouble = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getValueAsDouble", r"()D");
+
+ /// from: public double getValueAsDouble()
+ ///
+ /// Method that will try to convert value of current token to a Java
+ /// __double__.
+ /// Numbers are coerced using default Java rules; booleans convert to 0.0 (false)
+ /// and 1.0 (true), and Strings are parsed using default Java language floating
+ /// point parsing rules.
+ ///
+ /// If representation can not be converted to a double (including structured types
+ /// like Objects and Arrays),
+ /// default value of __0.0__ will be returned; no exceptions are thrown.
+ ///@return {@code double} value current token is converted to, if possible; exception thrown
+ /// otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ double getValueAsDouble() {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_getValueAsDouble,
+ jni.JniCallType.doubleType, []).doubleFloat;
+ }
+
+ static final _id_getValueAsDouble1 = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getValueAsDouble", r"(D)D");
+
+ /// from: public double getValueAsDouble(double def)
+ ///
+ /// Method that will try to convert value of current token to a
+ /// Java __double__.
+ /// Numbers are coerced using default Java rules; booleans convert to 0.0 (false)
+ /// and 1.0 (true), and Strings are parsed using default Java language floating
+ /// point parsing rules.
+ ///
+ /// If representation can not be converted to a double (including structured types
+ /// like Objects and Arrays),
+ /// specified __def__ will be returned; no exceptions are thrown.
+ ///@param def Default value to return if conversion to {@code double} is not possible
+ ///@return {@code double} value current token is converted to, if possible; {@code def} otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ double getValueAsDouble1(
+ double def,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_getValueAsDouble1, jni.JniCallType.doubleType, [def]).doubleFloat;
+ }
+
+ static final _id_getValueAsBoolean = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getValueAsBoolean", r"()Z");
+
+ /// from: public boolean getValueAsBoolean()
+ ///
+ /// Method that will try to convert value of current token to a
+ /// __boolean__.
+ /// JSON booleans map naturally; integer numbers other than 0 map to true, and
+ /// 0 maps to false
+ /// and Strings 'true' and 'false' map to corresponding values.
+ ///
+ /// If representation can not be converted to a boolean value (including structured types
+ /// like Objects and Arrays),
+ /// default value of __false__ will be returned; no exceptions are thrown.
+ ///@return {@code boolean} value current token is converted to, if possible; exception thrown
+ /// otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ bool getValueAsBoolean() {
+ return jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_getValueAsBoolean, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_getValueAsBoolean1 = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getValueAsBoolean", r"(Z)Z");
+
+ /// from: public boolean getValueAsBoolean(boolean def)
+ ///
+ /// Method that will try to convert value of current token to a
+ /// __boolean__.
+ /// JSON booleans map naturally; integer numbers other than 0 map to true, and
+ /// 0 maps to false
+ /// and Strings 'true' and 'false' map to corresponding values.
+ ///
+ /// If representation can not be converted to a boolean value (including structured types
+ /// like Objects and Arrays),
+ /// specified __def__ will be returned; no exceptions are thrown.
+ ///@param def Default value to return if conversion to {@code boolean} is not possible
+ ///@return {@code boolean} value current token is converted to, if possible; {@code def} otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ bool getValueAsBoolean1(
+ bool def,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getValueAsBoolean1,
+ jni.JniCallType.booleanType,
+ [def ? 1 : 0]).boolean;
+ }
+
+ static final _id_getValueAsString = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"getValueAsString", r"()Ljava/lang/String;");
+
+ /// from: public java.lang.String getValueAsString()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that will try to convert value of current token to a
+ /// java.lang.String.
+ /// JSON Strings map naturally; scalar values get converted to
+ /// their textual representation.
+ /// If representation can not be converted to a String value (including structured types
+ /// like Objects and Arrays and {@code null} token), default value of
+ /// __null__ will be returned; no exceptions are thrown.
+ ///@return String value current token is converted to, if possible; {@code null} otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.1
+ jni.JString getValueAsString() {
+ return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getValueAsString,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_getValueAsString1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"getValueAsString",
+ r"(Ljava/lang/String;)Ljava/lang/String;");
+
+ /// from: public abstract java.lang.String getValueAsString(java.lang.String def)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that will try to convert value of current token to a
+ /// java.lang.String.
+ /// JSON Strings map naturally; scalar values get converted to
+ /// their textual representation.
+ /// If representation can not be converted to a String value (including structured types
+ /// like Objects and Arrays and {@code null} token), specified default value
+ /// will be returned; no exceptions are thrown.
+ ///@param def Default value to return if conversion to {@code String} is not possible
+ ///@return String value current token is converted to, if possible; {@code def} otherwise
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.1
+ jni.JString getValueAsString1(
+ jni.JString def,
+ ) {
+ return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getValueAsString1,
+ jni.JniCallType.objectType,
+ [def.reference]).object);
+ }
+
+ static final _id_canReadObjectId = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"canReadObjectId", r"()Z");
+
+ /// from: public boolean canReadObjectId()
+ ///
+ /// Introspection method that may be called to see if the underlying
+ /// data format supports some kind of Object Ids natively (many do not;
+ /// for example, JSON doesn't).
+ ///
+ /// Default implementation returns true; overridden by data formats
+ /// that do support native Object Ids. Caller is expected to either
+ /// use a non-native notation (explicit property or such), or fail,
+ /// in case it can not use native object ids.
+ ///@return {@code True} if the format being read supports native Object Ids;
+ /// {@code false} if not
+ ///@since 2.3
+ bool canReadObjectId() {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_canReadObjectId,
+ jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_canReadTypeId = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"canReadTypeId", r"()Z");
+
+ /// from: public boolean canReadTypeId()
+ ///
+ /// Introspection method that may be called to see if the underlying
+ /// data format supports some kind of Type Ids natively (many do not;
+ /// for example, JSON doesn't).
+ ///
+ /// Default implementation returns true; overridden by data formats
+ /// that do support native Type Ids. Caller is expected to either
+ /// use a non-native notation (explicit property or such), or fail,
+ /// in case it can not use native type ids.
+ ///@return {@code True} if the format being read supports native Type Ids;
+ /// {@code false} if not
+ ///@since 2.3
+ bool canReadTypeId() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_canReadTypeId, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_getObjectId = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getObjectId", r"()Ljava/lang/Object;");
+
+ /// from: public java.lang.Object getObjectId()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that can be called to check whether current token
+ /// (one that was just read) has an associated Object id, and if
+ /// so, return it.
+ /// Note that while typically caller should check with \#canReadObjectId
+ /// first, it is not illegal to call this method even if that method returns
+ /// true; but if so, it will return null. This may be used to simplify calling
+ /// code.
+ ///
+ /// Default implementation will simply return null.
+ ///@return Native Object id associated with the current token, if any; {@code null} if none
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.3
+ jni.JObject getObjectId() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getObjectId, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_getTypeId = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getTypeId", r"()Ljava/lang/Object;");
+
+ /// from: public java.lang.Object getTypeId()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method that can be called to check whether current token
+ /// (one that was just read) has an associated type id, and if
+ /// so, return it.
+ /// Note that while typically caller should check with \#canReadTypeId
+ /// first, it is not illegal to call this method even if that method returns
+ /// true; but if so, it will return null. This may be used to simplify calling
+ /// code.
+ ///
+ /// Default implementation will simply return null.
+ ///@return Native Type Id associated with the current token, if any; {@code null} if none
+ ///@throws IOException for low-level read issues, or
+ /// JsonParseException for decoding problems
+ ///@since 2.3
+ jni.JObject getTypeId() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getTypeId, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_readValueAs = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"readValueAs",
+ r"(Ljava/lang/Class;)Ljava/lang/Object;");
+
+ /// from: public T readValueAs(java.lang.Class<T> valueType)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method to deserialize JSON content into a non-container
+ /// type (it can be an array type, however): typically a bean, array
+ /// or a wrapper type (like java.lang.Boolean).
+ /// __Note__: method can only be called if the parser has
+ /// an object codec assigned; this is true for parsers constructed
+ /// by <code>MappingJsonFactory</code> (from "jackson-databind" jar)
+ /// but not for JsonFactory (unless its <code>setCodec</code>
+ /// method has been explicitly called).
+ ///
+ /// This method may advance the event stream, for structured types
+ /// the current token will be the closing end marker (END_ARRAY,
+ /// END_OBJECT) of the bound structure. For non-structured Json types
+ /// (and for JsonToken\#VALUE_EMBEDDED_OBJECT)
+ /// stream is not advanced.
+ ///
+ /// Note: this method should NOT be used if the result type is a
+ /// container (java.util.Collection or java.util.Map.
+ /// The reason is that due to type erasure, key and value types
+ /// can not be introspected when using this method.
+ ///@param <T> Nominal type parameter for value type
+ ///@param valueType Java type to read content as (passed to ObjectCodec that
+ /// deserializes content)
+ ///@return Java value read from content
+ ///@throws IOException if there is either an underlying I/O problem or decoding
+ /// issue at format layer
+ $T readValueAs<$T extends jni.JObject>(
+ jni.JObject valueType, {
+ required jni.JObjType<$T> T,
+ }) {
+ return T.fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_readValueAs,
+ jni.JniCallType.objectType,
+ [valueType.reference]).object);
+ }
+
+ static final _id_readValueAs1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"readValueAs",
+ r"(Lcom/fasterxml/jackson/core/type/TypeReference;)Ljava/lang/Object;");
+
+ /// from: public T readValueAs(com.fasterxml.jackson.core.type.TypeReference<?> valueTypeRef)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method to deserialize JSON content into a Java type, reference
+ /// to which is passed as argument. Type is passed using so-called
+ /// "super type token"
+ /// and specifically needs to be used if the root type is a
+ /// parameterized (generic) container type.
+ /// __Note__: method can only be called if the parser has
+ /// an object codec assigned; this is true for parsers constructed
+ /// by <code>MappingJsonFactory</code> (defined in 'jackson-databind' bundle)
+ /// but not for JsonFactory (unless its <code>setCodec</code>
+ /// method has been explicitly called).
+ ///
+ /// This method may advance the event stream, for structured types
+ /// the current token will be the closing end marker (END_ARRAY,
+ /// END_OBJECT) of the bound structure. For non-structured Json types
+ /// (and for JsonToken\#VALUE_EMBEDDED_OBJECT)
+ /// stream is not advanced.
+ ///@param <T> Nominal type parameter for value type
+ ///@param valueTypeRef Java type to read content as (passed to ObjectCodec that
+ /// deserializes content)
+ ///@return Java value read from content
+ ///@throws IOException if there is either an underlying I/O problem or decoding
+ /// issue at format layer
+ $T readValueAs1<$T extends jni.JObject>(
+ jni.JObject valueTypeRef, {
+ required jni.JObjType<$T> T,
+ }) {
+ return T.fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_readValueAs1,
+ jni.JniCallType.objectType,
+ [valueTypeRef.reference]).object);
+ }
+
+ static final _id_readValuesAs = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"readValuesAs",
+ r"(Ljava/lang/Class;)Ljava/util/Iterator;");
+
+ /// from: public java.util.Iterator<T> readValuesAs(java.lang.Class<T> valueType)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for reading sequence of Objects from parser stream,
+ /// all with same specified value type.
+ ///@param <T> Nominal type parameter for value type
+ ///@param valueType Java type to read content as (passed to ObjectCodec that
+ /// deserializes content)
+ ///@return Iterator for reading multiple Java values from content
+ ///@throws IOException if there is either an underlying I/O problem or decoding
+ /// issue at format layer
+ jni.JIterator<$T> readValuesAs<$T extends jni.JObject>(
+ jni.JObject valueType, {
+ required jni.JObjType<$T> T,
+ }) {
+ return jni.JIteratorType(T).fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_readValuesAs,
+ jni.JniCallType.objectType,
+ [valueType.reference]).object);
+ }
+
+ static final _id_readValuesAs1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"readValuesAs",
+ r"(Lcom/fasterxml/jackson/core/type/TypeReference;)Ljava/util/Iterator;");
+
+ /// from: public java.util.Iterator<T> readValuesAs(com.fasterxml.jackson.core.type.TypeReference<T> valueTypeRef)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method for reading sequence of Objects from parser stream,
+ /// all with same specified value type.
+ ///@param <T> Nominal type parameter for value type
+ ///@param valueTypeRef Java type to read content as (passed to ObjectCodec that
+ /// deserializes content)
+ ///@return Iterator for reading multiple Java values from content
+ ///@throws IOException if there is either an underlying I/O problem or decoding
+ /// issue at format layer
+ jni.JIterator<$T> readValuesAs1<$T extends jni.JObject>(
+ jni.JObject valueTypeRef, {
+ required jni.JObjType<$T> T,
+ }) {
+ return jni.JIteratorType(T).fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_readValuesAs1,
+ jni.JniCallType.objectType,
+ [valueTypeRef.reference]).object);
+ }
+
+ static final _id_readValueAsTree = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"readValueAsTree",
+ r"()Lcom/fasterxml/jackson/core/TreeNode;");
+
+ /// from: public T readValueAsTree()
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Method to deserialize JSON content into equivalent "tree model",
+ /// represented by root TreeNode of resulting model.
+ /// For JSON Arrays it will an array node (with child nodes),
+ /// for objects object node (with child nodes), and for other types
+ /// matching leaf node type. Empty or whitespace documents are null.
+ ///@param <T> Nominal type parameter for result node type (to reduce need for casting)
+ ///@return root of the document, or null if empty or whitespace.
+ ///@throws IOException if there is either an underlying I/O problem or decoding
+ /// issue at format layer
+ $T readValueAsTree<$T extends jni.JObject>({
+ required jni.JObjType<$T> T,
+ }) {
+ return T.fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_readValueAsTree, jni.JniCallType.objectType, []).object);
+ }
+}
+
+final class $JsonParserType extends jni.JObjType<JsonParser> {
+ const $JsonParserType();
+
+ @override
+ String get signature => r"Lcom/fasterxml/jackson/core/JsonParser;";
+
+ @override
+ JsonParser fromRef(jni.JObjectPtr ref) => JsonParser.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($JsonParserType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($JsonParserType) && other is $JsonParserType;
+ }
+}
+
+/// from: com.fasterxml.jackson.core.JsonParser$Feature
+///
+/// Enumeration that defines all on/off features for parsers.
+class JsonParser_Feature extends jni.JObject {
+ @override
+ late final jni.JObjType<JsonParser_Feature> $type = type;
+
+ JsonParser_Feature.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/fasterxml/jackson/core/JsonParser$Feature");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $JsonParser_FeatureType();
+ static final _id_values = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"values",
+ r"()[Lcom/fasterxml/jackson/core/JsonParser$Feature;");
+
+ /// from: static public com.fasterxml.jackson.core.JsonParser.Feature[] values()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<JsonParser_Feature> values() {
+ return const jni.JArrayType($JsonParser_FeatureType()).fromRef(
+ jni.Jni.accessors.callStaticMethodWithArgs(_class.reference, _id_values,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_valueOf = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"valueOf",
+ r"(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonParser$Feature;");
+
+ /// from: static public com.fasterxml.jackson.core.JsonParser.Feature valueOf(java.lang.String name)
+ /// The returned object must be released after use, by calling the [release] method.
+ static JsonParser_Feature valueOf(
+ jni.JString name,
+ ) {
+ return const $JsonParser_FeatureType().fromRef(jni.Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _id_valueOf,
+ jni.JniCallType.objectType, [name.reference]).object);
+ }
+
+ static final _id_collectDefaults = jni.Jni.accessors
+ .getStaticMethodIDOf(_class.reference, r"collectDefaults", r"()I");
+
+ /// from: static public int collectDefaults()
+ ///
+ /// Method that calculates bit set (flags) of all features that
+ /// are enabled by default.
+ ///@return Bit mask of all features that are enabled by default
+ static int collectDefaults() {
+ return jni.Jni.accessors.callStaticMethodWithArgs(_class.reference,
+ _id_collectDefaults, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_enabledByDefault = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"enabledByDefault", r"()Z");
+
+ /// from: public boolean enabledByDefault()
+ bool enabledByDefault() {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_enabledByDefault,
+ jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_enabledIn =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"enabledIn", r"(I)Z");
+
+ /// from: public boolean enabledIn(int flags)
+ bool enabledIn(
+ int flags,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_enabledIn,
+ jni.JniCallType.booleanType, [jni.JValueInt(flags)]).boolean;
+ }
+
+ static final _id_getMask =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"getMask", r"()I");
+
+ /// from: public int getMask()
+ int getMask() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getMask, jni.JniCallType.intType, []).integer;
+ }
+}
+
+final class $JsonParser_FeatureType extends jni.JObjType<JsonParser_Feature> {
+ const $JsonParser_FeatureType();
+
+ @override
+ String get signature => r"Lcom/fasterxml/jackson/core/JsonParser$Feature;";
+
+ @override
+ JsonParser_Feature fromRef(jni.JObjectPtr ref) =>
+ JsonParser_Feature.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($JsonParser_FeatureType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($JsonParser_FeatureType) &&
+ other is $JsonParser_FeatureType;
+ }
+}
+
+/// from: com.fasterxml.jackson.core.JsonParser$NumberType
+///
+/// Enumeration of possible "native" (optimal) types that can be
+/// used for numbers.
+class JsonParser_NumberType extends jni.JObject {
+ @override
+ late final jni.JObjType<JsonParser_NumberType> $type = type;
+
+ JsonParser_NumberType.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/fasterxml/jackson/core/JsonParser$NumberType");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $JsonParser_NumberTypeType();
+ static final _id_values = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"values",
+ r"()[Lcom/fasterxml/jackson/core/JsonParser$NumberType;");
+
+ /// from: static public com.fasterxml.jackson.core.JsonParser.NumberType[] values()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<JsonParser_NumberType> values() {
+ return const jni.JArrayType($JsonParser_NumberTypeType()).fromRef(
+ jni.Jni.accessors.callStaticMethodWithArgs(_class.reference, _id_values,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_valueOf = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"valueOf",
+ r"(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonParser$NumberType;");
+
+ /// from: static public com.fasterxml.jackson.core.JsonParser.NumberType valueOf(java.lang.String name)
+ /// The returned object must be released after use, by calling the [release] method.
+ static JsonParser_NumberType valueOf(
+ jni.JString name,
+ ) {
+ return const $JsonParser_NumberTypeType().fromRef(jni.Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _id_valueOf,
+ jni.JniCallType.objectType, [name.reference]).object);
+ }
+}
+
+final class $JsonParser_NumberTypeType
+ extends jni.JObjType<JsonParser_NumberType> {
+ const $JsonParser_NumberTypeType();
+
+ @override
+ String get signature => r"Lcom/fasterxml/jackson/core/JsonParser$NumberType;";
+
+ @override
+ JsonParser_NumberType fromRef(jni.JObjectPtr ref) =>
+ JsonParser_NumberType.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($JsonParser_NumberTypeType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($JsonParser_NumberTypeType) &&
+ other is $JsonParser_NumberTypeType;
+ }
+}
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonToken.dart b/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonToken.dart
new file mode 100644
index 0000000..4e67a2d
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/JsonToken.dart
@@ -0,0 +1,225 @@
+// Generated from jackson-core which is licensed under the Apache License 2.0.
+// The following copyright from the original authors applies.
+// See https://github.com/FasterXML/jackson-core/blob/2.14/LICENSE
+//
+// Copyright (c) 2007 - The Jackson Project Authors
+// Licensed under the Apache License, Version 2.0 (the "License")
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+// ignore_for_file: annotate_overrides
+// ignore_for_file: camel_case_extensions
+// ignore_for_file: camel_case_types
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: doc_directive_unknown
+// ignore_for_file: file_names
+// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: overridden_fields
+// ignore_for_file: unnecessary_cast
+// ignore_for_file: unused_element
+// ignore_for_file: unused_field
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: unused_shown_name
+
+import "dart:isolate" show ReceivePort;
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+import "package:jni/jni.dart" as jni;
+
+/// from: com.fasterxml.jackson.core.JsonToken
+///
+/// Enumeration for basic token types used for returning results
+/// of parsing JSON content.
+class JsonToken extends jni.JObject {
+ @override
+ late final jni.JObjType<JsonToken> $type = type;
+
+ JsonToken.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/fasterxml/jackson/core/JsonToken");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $JsonTokenType();
+ static final _id_values = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"values",
+ r"()[Lcom/fasterxml/jackson/core/JsonToken;");
+
+ /// from: static public com.fasterxml.jackson.core.JsonToken[] values()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<JsonToken> values() {
+ return const jni.JArrayType($JsonTokenType()).fromRef(jni.Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _id_values,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_valueOf = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"valueOf",
+ r"(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonToken;");
+
+ /// from: static public com.fasterxml.jackson.core.JsonToken valueOf(java.lang.String name)
+ /// The returned object must be released after use, by calling the [release] method.
+ static JsonToken valueOf(
+ jni.JString name,
+ ) {
+ return const $JsonTokenType().fromRef(jni.Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _id_valueOf,
+ jni.JniCallType.objectType, [name.reference]).object);
+ }
+
+ static final _id_id =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"id", r"()I");
+
+ /// from: public final int id()
+ int id() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_id, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_asString = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"asString", r"()Ljava/lang/String;");
+
+ /// from: public final java.lang.String asString()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JString asString() {
+ return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_asString, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_asCharArray = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"asCharArray", r"()[C");
+
+ /// from: public final char[] asCharArray()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JArray<jni.jchar> asCharArray() {
+ return const jni.JArrayType(jni.jcharType()).fromRef(jni.Jni.accessors
+ .callMethodWithArgs(
+ reference, _id_asCharArray, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_asByteArray = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"asByteArray", r"()[B");
+
+ /// from: public final byte[] asByteArray()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JArray<jni.jbyte> asByteArray() {
+ return const jni.JArrayType(jni.jbyteType()).fromRef(jni.Jni.accessors
+ .callMethodWithArgs(
+ reference, _id_asByteArray, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_isNumeric =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"isNumeric", r"()Z");
+
+ /// from: public final boolean isNumeric()
+ ///
+ /// @return {@code True} if this token is {@code VALUE_NUMBER_INT} or {@code VALUE_NUMBER_FLOAT},
+ /// {@code false} otherwise
+ bool isNumeric() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_isNumeric, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_isStructStart = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"isStructStart", r"()Z");
+
+ /// from: public final boolean isStructStart()
+ ///
+ /// Accessor that is functionally equivalent to:
+ /// <code>
+ /// this == JsonToken.START_OBJECT || this == JsonToken.START_ARRAY
+ /// </code>
+ ///@return {@code True} if this token is {@code START_OBJECT} or {@code START_ARRAY},
+ /// {@code false} otherwise
+ ///@since 2.3
+ bool isStructStart() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_isStructStart, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_isStructEnd =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"isStructEnd", r"()Z");
+
+ /// from: public final boolean isStructEnd()
+ ///
+ /// Accessor that is functionally equivalent to:
+ /// <code>
+ /// this == JsonToken.END_OBJECT || this == JsonToken.END_ARRAY
+ /// </code>
+ ///@return {@code True} if this token is {@code END_OBJECT} or {@code END_ARRAY},
+ /// {@code false} otherwise
+ ///@since 2.3
+ bool isStructEnd() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_isStructEnd, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_isScalarValue = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"isScalarValue", r"()Z");
+
+ /// from: public final boolean isScalarValue()
+ ///
+ /// Method that can be used to check whether this token represents
+ /// a valid non-structured value. This means all {@code VALUE_xxx} tokens;
+ /// excluding {@code START_xxx} and {@code END_xxx} tokens as well
+ /// {@code FIELD_NAME}.
+ ///@return {@code True} if this token is a scalar value token (one of
+ /// {@code VALUE_xxx} tokens), {@code false} otherwise
+ bool isScalarValue() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_isScalarValue, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_isBoolean =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"isBoolean", r"()Z");
+
+ /// from: public final boolean isBoolean()
+ ///
+ /// @return {@code True} if this token is {@code VALUE_TRUE} or {@code VALUE_FALSE},
+ /// {@code false} otherwise
+ bool isBoolean() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_isBoolean, jni.JniCallType.booleanType, []).boolean;
+ }
+}
+
+final class $JsonTokenType extends jni.JObjType<JsonToken> {
+ const $JsonTokenType();
+
+ @override
+ String get signature => r"Lcom/fasterxml/jackson/core/JsonToken;";
+
+ @override
+ JsonToken fromRef(jni.JObjectPtr ref) => JsonToken.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($JsonTokenType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($JsonTokenType) && other is $JsonTokenType;
+ }
+}
diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/_package.dart b/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/_package.dart
new file mode 100644
index 0000000..cae2a52
--- /dev/null
+++ b/pkgs/jnigen/test/jackson_core_test/third_party/dart_only/dart_bindings/com/fasterxml/jackson/core/_package.dart
@@ -0,0 +1,3 @@
+export "JsonFactory.dart";
+export "JsonParser.dart";
+export "JsonToken.dart";
diff --git a/pkgs/jnigen/test/kotlin_test/.gitignore b/pkgs/jnigen/test/kotlin_test/.gitignore
new file mode 100644
index 0000000..39de10f
--- /dev/null
+++ b/pkgs/jnigen/test/kotlin_test/.gitignore
@@ -0,0 +1,5 @@
+build/
+*.class
+test_lib/
+test_src/
+target/
diff --git a/pkgs/jnigen/test/kotlin_test/c_based/c_bindings/.clang-format b/pkgs/jnigen/test/kotlin_test/c_based/c_bindings/.clang-format
new file mode 100644
index 0000000..a256c2f
--- /dev/null
+++ b/pkgs/jnigen/test/kotlin_test/c_based/c_bindings/.clang-format
@@ -0,0 +1,15 @@
+# From dart SDK: https://github.com/dart-lang/sdk/blob/main/.clang-format
+
+# Defines the Chromium style for automatic reformatting.
+# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
+BasedOnStyle: Chromium
+
+# clang-format doesn't seem to do a good job of this for longer comments.
+ReflowComments: 'false'
+
+# We have lots of these. Though we need to put them all in curly braces,
+# clang-format can't do that.
+AllowShortIfStatementsOnASingleLine: 'true'
+
+# Put escaped newlines into the rightmost column.
+AlignEscapedNewlinesLeft: false
diff --git a/pkgs/jnigen/test/kotlin_test/c_based/c_bindings/CMakeLists.txt b/pkgs/jnigen/test/kotlin_test/c_based/c_bindings/CMakeLists.txt
new file mode 100644
index 0000000..3889f54
--- /dev/null
+++ b/pkgs/jnigen/test/kotlin_test/c_based/c_bindings/CMakeLists.txt
@@ -0,0 +1,32 @@
+# jni_native_build (Build with jni:setup. Do not delete this line.)
+
+# 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)
+
+project(kotlin VERSION 0.0.1 LANGUAGES C)
+
+add_library(kotlin SHARED
+ "./kotlin.c"
+)
+
+set_target_properties(kotlin PROPERTIES
+ OUTPUT_NAME "kotlin"
+)
+
+target_compile_definitions(kotlin PUBLIC DART_SHARED_LIB)
+
+if(WIN32)
+ set_target_properties(${TARGET_NAME} PROPERTIES
+ LINK_FLAGS "/DELAYLOAD:jvm.dll")
+endif()
+
+if (ANDROID)
+ target_link_libraries(kotlin log)
+else()
+ find_package(Java REQUIRED)
+ find_package(JNI REQUIRED)
+ include_directories(${JNI_INCLUDE_DIRS})
+ target_link_libraries(kotlin ${JNI_LIBRARIES})
+endif()
diff --git a/pkgs/jnigen/test/kotlin_test/c_based/c_bindings/dartjni.h b/pkgs/jnigen/test/kotlin_test/c_based/c_bindings/dartjni.h
new file mode 100644
index 0000000..8f1dc74
--- /dev/null
+++ b/pkgs/jnigen/test/kotlin_test/c_based/c_bindings/dartjni.h
@@ -0,0 +1,424 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#pragma once
+
+// Note: include appropriate system jni.h as found by CMake, not third_party/jni.h.
+#include <jni.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if _WIN32
+#include <windows.h>
+#else
+#include <pthread.h>
+#include <unistd.h>
+#endif
+
+#if _WIN32
+#define FFI_PLUGIN_EXPORT __declspec(dllexport)
+#else
+#define FFI_PLUGIN_EXPORT
+#endif
+
+#if defined _WIN32
+#define thread_local __declspec(thread)
+#else
+#define thread_local __thread
+#endif
+
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
+
+#ifdef __ANDROID__
+#define __ENVP_CAST (JNIEnv**)
+#else
+#define __ENVP_CAST (void**)
+#endif
+
+/// Locking functions for windows and pthread.
+
+#if defined _WIN32
+#include <windows.h>
+
+typedef CRITICAL_SECTION MutexLock;
+typedef CONDITION_VARIABLE ConditionVariable;
+
+static inline void init_lock(MutexLock* lock) {
+ InitializeCriticalSection(lock);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+ EnterCriticalSection(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+ LeaveCriticalSection(lock);
+}
+
+static inline void destroy_lock(MutexLock* lock) {
+ DeleteCriticalSection(lock);
+}
+
+static inline void init_cond(ConditionVariable* cond) {
+ InitializeConditionVariable(cond);
+}
+
+static inline void signal_cond(ConditionVariable* cond) {
+ WakeConditionVariable(cond);
+}
+
+static inline void wait_for(ConditionVariable* cond, MutexLock* lock) {
+ SleepConditionVariableCS(cond, lock, INFINITE);
+}
+
+static inline void destroy_cond(ConditionVariable* cond) {
+ // Not available.
+}
+
+#elif defined __APPLE__ || defined __LINUX__ || defined __ANDROID__ || \
+ defined __GNUC__
+#include <pthread.h>
+
+typedef pthread_mutex_t MutexLock;
+typedef pthread_cond_t ConditionVariable;
+
+static inline void init_lock(MutexLock* lock) {
+ pthread_mutex_init(lock, NULL);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+ pthread_mutex_lock(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+ pthread_mutex_unlock(lock);
+}
+
+static inline void destroy_lock(MutexLock* lock) {
+ pthread_mutex_destroy(lock);
+}
+
+static inline void init_cond(ConditionVariable* cond) {
+ pthread_cond_init(cond, NULL);
+}
+
+static inline void signal_cond(ConditionVariable* cond) {
+ pthread_cond_signal(cond);
+}
+
+static inline void wait_for(ConditionVariable* cond, MutexLock* lock) {
+ pthread_cond_wait(cond, lock);
+}
+
+static inline void destroy_cond(ConditionVariable* cond) {
+ pthread_cond_destroy(cond);
+}
+
+#else
+
+#error "No locking/condition variable support; Possibly unsupported platform"
+
+#endif
+
+typedef struct CallbackResult {
+ MutexLock lock;
+ ConditionVariable cond;
+ int ready;
+ jobject object;
+} CallbackResult;
+
+typedef struct JniLocks {
+ MutexLock classLoadingLock;
+ MutexLock methodLoadingLock;
+ MutexLock fieldLoadingLock;
+} JniLocks;
+
+/// Represents the error when dart-jni layer has already spawned singleton VM.
+#define DART_JNI_SINGLETON_EXISTS (-99);
+
+/// Stores the global state of the JNI.
+typedef struct JniContext {
+ JavaVM* jvm;
+ jobject classLoader;
+ jmethodID loadClassMethod;
+ jobject currentActivity;
+ jobject appContext;
+ JniLocks locks;
+} JniContext;
+
+// jniEnv for this thread, used by inline functions in this header,
+// therefore declared as extern.
+extern thread_local JNIEnv* jniEnv;
+
+extern JniContext* jni;
+
+/// Types used by JNI API to distinguish between primitive types.
+enum JniType {
+ booleanType = 0,
+ byteType = 1,
+ shortType = 2,
+ charType = 3,
+ intType = 4,
+ longType = 5,
+ floatType = 6,
+ doubleType = 7,
+ objectType = 8,
+ voidType = 9,
+};
+
+/// Result type for use by JNI.
+///
+/// If [exception] is null, it means the result is valid.
+/// It's assumed that the caller knows the expected type in [result].
+typedef struct JniResult {
+ jvalue value;
+ jthrowable exception;
+} JniResult;
+
+/// Similar to [JniResult] but for class lookups.
+typedef struct JniClassLookupResult {
+ jclass value;
+ jthrowable exception;
+} JniClassLookupResult;
+
+/// Similar to [JniResult] but for method/field ID lookups.
+typedef struct JniPointerResult {
+ const void* value;
+ jthrowable exception;
+} JniPointerResult;
+
+/// JniExceptionDetails holds 2 jstring objects, one is the result of
+/// calling `toString` on exception object, other is stack trace;
+typedef struct JniExceptionDetails {
+ jstring message;
+ jstring stacktrace;
+} JniExceptionDetails;
+
+/// This struct contains functions which wrap method call / field access conveniently along with
+/// exception checking.
+///
+/// Flutter embedding checks for pending JNI exceptions before an FFI transition, which requires us
+/// to check for and clear the exception before returning to dart code, which requires these functions
+/// to return result types.
+typedef struct JniAccessorsStruct {
+ JniClassLookupResult (*getClass)(char* internalName);
+ JniPointerResult (*getFieldID)(jclass cls, char* fieldName, char* signature);
+ JniPointerResult (*getStaticFieldID)(jclass cls,
+ char* fieldName,
+ char* signature);
+ JniPointerResult (*getMethodID)(jclass cls,
+ char* methodName,
+ char* signature);
+ JniPointerResult (*getStaticMethodID)(jclass cls,
+ char* methodName,
+ char* signature);
+ JniResult (*newObject)(jclass cls, jmethodID ctor, jvalue* args);
+ JniResult (*newPrimitiveArray)(jsize length, int type);
+ JniResult (*newObjectArray)(jsize length,
+ jclass elementClass,
+ jobject initialElement);
+ JniResult (*getArrayElement)(jarray array, int index, int type);
+ JniResult (*callMethod)(jobject obj,
+ jmethodID methodID,
+ int callType,
+ jvalue* args);
+ JniResult (*callStaticMethod)(jclass cls,
+ jmethodID methodID,
+ int callType,
+ jvalue* args);
+ JniResult (*getField)(jobject obj, jfieldID fieldID, int callType);
+ JniResult (*getStaticField)(jclass cls, jfieldID fieldID, int callType);
+ JniExceptionDetails (*getExceptionDetails)(jthrowable exception);
+} JniAccessorsStruct;
+
+FFI_PLUGIN_EXPORT JniAccessorsStruct* GetAccessors();
+
+FFI_PLUGIN_EXPORT JavaVM* GetJavaVM(void);
+
+FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv(void);
+
+/// Spawn a JVM with given arguments.
+///
+/// Returns JNI_OK on success, and one of the documented JNI error codes on
+/// failure. It returns DART_JNI_SINGLETON_EXISTS if an attempt to spawn multiple
+/// JVMs is made, even if the underlying API potentially supports multiple VMs.
+FFI_PLUGIN_EXPORT int SpawnJvm(JavaVMInitArgs* args);
+
+/// Load class through platform-specific mechanism.
+///
+/// Currently uses application classloader on android,
+/// and JNIEnv->FindClass on other platforms.
+FFI_PLUGIN_EXPORT jclass FindClass(const char* name);
+
+/// Returns Application classLoader (on Android),
+/// which can be used to load application and platform classes.
+///
+/// On other platforms, NULL is returned.
+FFI_PLUGIN_EXPORT jobject GetClassLoader(void);
+
+/// Returns application context on Android.
+///
+/// On other platforms, NULL is returned.
+FFI_PLUGIN_EXPORT jobject GetApplicationContext(void);
+
+/// Returns current activity of the app on Android.
+FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
+
+static inline void attach_thread() {
+ if (jniEnv == NULL) {
+ (*jni->jvm)->AttachCurrentThread(jni->jvm, __ENVP_CAST & jniEnv, NULL);
+ }
+}
+
+/// Load class into [cls] using platform specific mechanism
+static inline void load_class_platform(jclass* cls, const char* name) {
+#ifdef __ANDROID__
+ jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
+ *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni->classLoader,
+ jni->loadClassMethod, className);
+ (*jniEnv)->DeleteLocalRef(jniEnv, className);
+#else
+ *cls = (*jniEnv)->FindClass(jniEnv, name);
+#endif
+}
+
+static inline void load_class_local_ref(jclass* cls, const char* name) {
+ if (*cls == NULL) {
+ acquire_lock(&jni->locks.classLoadingLock);
+ if (*cls == NULL) {
+ load_class_platform(cls, name);
+ }
+ release_lock(&jni->locks.classLoadingLock);
+ }
+}
+
+static inline void load_class_global_ref(jclass* cls, const char* name) {
+ if (*cls == NULL) {
+ jclass tmp = NULL;
+ acquire_lock(&jni->locks.classLoadingLock);
+ if (*cls == NULL) {
+ load_class_platform(&tmp, name);
+ if (!(*jniEnv)->ExceptionCheck(jniEnv)) {
+ *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
+ (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
+ }
+ }
+ release_lock(&jni->locks.classLoadingLock);
+ }
+}
+
+static inline void load_method(jclass cls,
+ jmethodID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.methodLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.methodLoadingLock);
+ }
+}
+
+static inline void load_static_method(jclass cls,
+ jmethodID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.methodLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.methodLoadingLock);
+ }
+}
+
+static inline void load_field(jclass cls,
+ jfieldID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.fieldLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.fieldLoadingLock);
+ }
+}
+
+static inline void load_static_field(jclass cls,
+ jfieldID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.fieldLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.fieldLoadingLock);
+ }
+}
+
+static inline jobject to_global_ref(jobject ref) {
+ jobject g = (*jniEnv)->NewGlobalRef(jniEnv, ref);
+ (*jniEnv)->DeleteLocalRef(jniEnv, ref);
+ return g;
+}
+
+// These functions are useful for C+Dart bindings, and not required for pure dart bindings.
+
+FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr();
+
+/// For use by jni_gen's generated code
+/// don't use these.
+
+// these 2 fn ptr vars will be defined by generated code library
+extern JniContext* (*context_getter)(void);
+extern JNIEnv* (*env_getter)(void);
+
+// this function will be exported by generated code library
+// it will set above 2 variables.
+FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext* (*cg)(void),
+ JNIEnv* (*eg)(void));
+
+static inline void load_env() {
+ if (jniEnv == NULL) {
+ jni = context_getter();
+ jniEnv = env_getter();
+ }
+}
+
+static inline jthrowable check_exception() {
+ jthrowable exception = (*jniEnv)->ExceptionOccurred(jniEnv);
+ if (exception != NULL) (*jniEnv)->ExceptionClear(jniEnv);
+ if (exception == NULL) return NULL;
+ return to_global_ref(exception);
+}
+
+static inline JniResult to_global_ref_result(jobject ref) {
+ JniResult result;
+ result.exception = check_exception();
+ if (result.exception == NULL) {
+ result.value.l = to_global_ref(ref);
+ }
+ return result;
+}
+
+FFI_PLUGIN_EXPORT intptr_t InitDartApiDL(void* data);
+
+FFI_PLUGIN_EXPORT
+JniResult DartException__ctor(jstring message);
+
+FFI_PLUGIN_EXPORT
+JniResult PortContinuation__ctor(int64_t j);
+
+FFI_PLUGIN_EXPORT
+JniResult PortProxy__newInstance(jobject binaryName,
+ int64_t port,
+ int64_t functionPtr);
+
+FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
diff --git a/pkgs/jnigen/test/kotlin_test/c_based/c_bindings/kotlin.c b/pkgs/jnigen/test/kotlin_test/c_based/c_bindings/kotlin.c
new file mode 100644
index 0000000..e3c227e
--- /dev/null
+++ b/pkgs/jnigen/test/kotlin_test/c_based/c_bindings/kotlin.c
@@ -0,0 +1,76 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+#include <stdint.h>
+#include "dartjni.h"
+#include "jni.h"
+
+thread_local JNIEnv* jniEnv;
+JniContext* jni;
+
+JniContext* (*context_getter)(void);
+JNIEnv* (*env_getter)(void);
+
+void setJniGetters(JniContext* (*cg)(void), JNIEnv* (*eg)(void)) {
+ context_getter = cg;
+ env_getter = eg;
+}
+
+// com.github.dart_lang.jnigen.SuspendFun
+jclass _c_SuspendFun = NULL;
+
+jmethodID _m_SuspendFun__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult SuspendFun__new0() {
+ load_env();
+ load_class_global_ref(&_c_SuspendFun,
+ "com/github/dart_lang/jnigen/SuspendFun");
+ if (_c_SuspendFun == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_SuspendFun, &_m_SuspendFun__new0, "<init>", "()V");
+ if (_m_SuspendFun__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_SuspendFun, _m_SuspendFun__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_SuspendFun__sayHello = NULL;
+FFI_PLUGIN_EXPORT
+JniResult SuspendFun__sayHello(jobject self_, jobject continuation) {
+ load_env();
+ load_class_global_ref(&_c_SuspendFun,
+ "com/github/dart_lang/jnigen/SuspendFun");
+ if (_c_SuspendFun == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_SuspendFun, &_m_SuspendFun__sayHello, "sayHello",
+ "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;");
+ if (_m_SuspendFun__sayHello == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_SuspendFun__sayHello, continuation);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_SuspendFun__sayHello1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult SuspendFun__sayHello1(jobject self_,
+ jobject string,
+ jobject continuation) {
+ load_env();
+ load_class_global_ref(&_c_SuspendFun,
+ "com/github/dart_lang/jnigen/SuspendFun");
+ if (_c_SuspendFun == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_SuspendFun, &_m_SuspendFun__sayHello1, "sayHello",
+ "(Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;");
+ if (_m_SuspendFun__sayHello1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_SuspendFun__sayHello1, string, continuation);
+ return to_global_ref_result(_result);
+}
diff --git a/pkgs/jnigen/test/kotlin_test/c_based/dart_bindings/kotlin.dart b/pkgs/jnigen/test/kotlin_test/c_based/dart_bindings/kotlin.dart
new file mode 100644
index 0000000..e96d08c
--- /dev/null
+++ b/pkgs/jnigen/test/kotlin_test/c_based/dart_bindings/kotlin.dart
@@ -0,0 +1,128 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+// ignore_for_file: annotate_overrides
+// ignore_for_file: camel_case_extensions
+// ignore_for_file: camel_case_types
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: doc_directive_unknown
+// ignore_for_file: file_names
+// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: overridden_fields
+// ignore_for_file: unnecessary_cast
+// ignore_for_file: unused_element
+// ignore_for_file: unused_field
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: unused_shown_name
+
+import "dart:isolate" show ReceivePort;
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+import "package:jni/jni.dart" as jni;
+
+// Auto-generated initialization code.
+
+final ffi.Pointer<T> Function<T extends ffi.NativeType>(String sym) jniLookup =
+ ProtectedJniExtensions.initGeneratedLibrary("kotlin");
+
+/// from: com.github.dart_lang.jnigen.SuspendFun
+class SuspendFun extends jni.JObject {
+ @override
+ late final jni.JObjType<SuspendFun> $type = type;
+
+ SuspendFun.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $SuspendFunType();
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "SuspendFun__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory SuspendFun() {
+ return SuspendFun.fromRef(_new0().object);
+ }
+
+ static final _sayHello = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("SuspendFun__sayHello")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final java.lang.Object sayHello(kotlin.coroutines.Continuation continuation)
+ /// The returned object must be released after use, by calling the [release] method.
+ Future<jni.JString> sayHello() async {
+ final $p = ReceivePort();
+ final $c =
+ jni.JObject.fromRef(ProtectedJniExtensions.newPortContinuation($p));
+ _sayHello(reference, $c.reference).object;
+ final $o = jni.JObjectPtr.fromAddress(await $p.first);
+ final $k = const jni.JStringType().getClass().reference;
+ if (!jni.Jni.env.IsInstanceOf($o, $k)) {
+ throw "Failed";
+ }
+ return const jni.JStringType().fromRef($o);
+ }
+
+ static final _sayHello1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("SuspendFun__sayHello1")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final java.lang.Object sayHello(java.lang.String string, kotlin.coroutines.Continuation continuation)
+ /// The returned object must be released after use, by calling the [release] method.
+ Future<jni.JString> sayHello1(
+ jni.JString string,
+ ) async {
+ final $p = ReceivePort();
+ final $c =
+ jni.JObject.fromRef(ProtectedJniExtensions.newPortContinuation($p));
+ _sayHello1(reference, string.reference, $c.reference).object;
+ final $o = jni.JObjectPtr.fromAddress(await $p.first);
+ final $k = const jni.JStringType().getClass().reference;
+ if (!jni.Jni.env.IsInstanceOf($o, $k)) {
+ throw "Failed";
+ }
+ return const jni.JStringType().fromRef($o);
+ }
+}
+
+final class $SuspendFunType extends jni.JObjType<SuspendFun> {
+ const $SuspendFunType();
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/SuspendFun;";
+
+ @override
+ SuspendFun fromRef(jni.JObjectPtr ref) => SuspendFun.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($SuspendFunType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($SuspendFunType) && other is $SuspendFunType;
+ }
+}
diff --git a/pkgs/jnigen/test/kotlin_test/dart_only/dart_bindings/kotlin.dart b/pkgs/jnigen/test/kotlin_test/dart_only/dart_bindings/kotlin.dart
new file mode 100644
index 0000000..b3a1985
--- /dev/null
+++ b/pkgs/jnigen/test/kotlin_test/dart_only/dart_bindings/kotlin.dart
@@ -0,0 +1,118 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+// ignore_for_file: annotate_overrides
+// ignore_for_file: camel_case_extensions
+// ignore_for_file: camel_case_types
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: doc_directive_unknown
+// ignore_for_file: file_names
+// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: overridden_fields
+// ignore_for_file: unnecessary_cast
+// ignore_for_file: unused_element
+// ignore_for_file: unused_field
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: unused_shown_name
+
+import "dart:isolate" show ReceivePort;
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+import "package:jni/jni.dart" as jni;
+
+/// from: com.github.dart_lang.jnigen.SuspendFun
+class SuspendFun extends jni.JObject {
+ @override
+ late final jni.JObjType<SuspendFun> $type = type;
+
+ SuspendFun.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/github/dart_lang/jnigen/SuspendFun");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $SuspendFunType();
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory SuspendFun() {
+ return SuspendFun.fromRef(jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+
+ static final _id_sayHello = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"sayHello", r"(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;");
+
+ /// from: public final java.lang.Object sayHello(kotlin.coroutines.Continuation continuation)
+ /// The returned object must be released after use, by calling the [release] method.
+ Future<jni.JString> sayHello() async {
+ final $p = ReceivePort();
+ final $c =
+ jni.JObject.fromRef(ProtectedJniExtensions.newPortContinuation($p));
+ jni.Jni.accessors.callMethodWithArgs(reference, _id_sayHello,
+ jni.JniCallType.objectType, [$c.reference]).object;
+ final $o = jni.JObjectPtr.fromAddress(await $p.first);
+ final $k = const jni.JStringType().getClass().reference;
+ if (!jni.Jni.env.IsInstanceOf($o, $k)) {
+ throw "Failed";
+ }
+ return const jni.JStringType().fromRef($o);
+ }
+
+ static final _id_sayHello1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"sayHello",
+ r"(Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;");
+
+ /// from: public final java.lang.Object sayHello(java.lang.String string, kotlin.coroutines.Continuation continuation)
+ /// The returned object must be released after use, by calling the [release] method.
+ Future<jni.JString> sayHello1(
+ jni.JString string,
+ ) async {
+ final $p = ReceivePort();
+ final $c =
+ jni.JObject.fromRef(ProtectedJniExtensions.newPortContinuation($p));
+ jni.Jni.accessors.callMethodWithArgs(reference, _id_sayHello1,
+ jni.JniCallType.objectType, [string.reference, $c.reference]).object;
+ final $o = jni.JObjectPtr.fromAddress(await $p.first);
+ final $k = const jni.JStringType().getClass().reference;
+ if (!jni.Jni.env.IsInstanceOf($o, $k)) {
+ throw "Failed";
+ }
+ return const jni.JStringType().fromRef($o);
+ }
+}
+
+final class $SuspendFunType extends jni.JObjType<SuspendFun> {
+ const $SuspendFunType();
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/SuspendFun;";
+
+ @override
+ SuspendFun fromRef(jni.JObjectPtr ref) => SuspendFun.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($SuspendFunType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($SuspendFunType) && other is $SuspendFunType;
+ }
+}
diff --git a/pkgs/jnigen/test/kotlin_test/generate.dart b/pkgs/jnigen/test/kotlin_test/generate.dart
new file mode 100644
index 0000000..6168667
--- /dev/null
+++ b/pkgs/jnigen/test/kotlin_test/generate.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:logging/logging.dart';
+import 'package:path/path.dart';
+import 'package:jnigen/jnigen.dart';
+
+const testName = 'kotlin_test';
+const jarFile = '$testName.jar';
+
+final testRoot = join('test', testName);
+final kotlinPath = join(testRoot, 'kotlin');
+final jarPath = join(kotlinPath, 'target', jarFile);
+
+const preamble = '''
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+''';
+
+void compileKotlinSources(String workingDir) async {
+ final procRes = Process.runSync(
+ 'mvn',
+ ['package'],
+ workingDirectory: workingDir,
+ runInShell: true,
+ );
+ if (procRes.exitCode != 0) {
+ throw "mvn exited with ${procRes.exitCode}\n"
+ "${procRes.stderr}";
+ }
+}
+
+Config getConfig([BindingsType bindingsType = BindingsType.cBased]) {
+ compileKotlinSources(kotlinPath);
+ final typeDir = bindingsType.getConfigString();
+ final cWrapperDir = Uri.directory(join(testRoot, typeDir, "c_bindings"));
+ final dartWrappersRoot = Uri.directory(
+ join(testRoot, typeDir, "dart_bindings"),
+ );
+ final config = Config(
+ classPath: [Uri.file(jarPath)],
+ classes: [
+ // Generating the entire library.
+ //
+ // This makes sure that no private class generated by Kotlin can make its
+ // way to the generated code.
+ 'com.github.dart_lang.jnigen',
+ ],
+ logLevel: Level.ALL,
+ outputConfig: OutputConfig(
+ bindingsType: bindingsType,
+ cConfig: CCodeOutputConfig(
+ path: cWrapperDir,
+ libraryName: 'kotlin',
+ ),
+ dartConfig: DartCodeOutputConfig(
+ path: dartWrappersRoot.resolve('kotlin.dart'),
+ structure: OutputStructure.singleFile,
+ ),
+ ),
+ summarizerOptions: SummarizerOptions(backend: SummarizerBackend.asm),
+ preamble: preamble,
+ );
+ return config;
+}
+
+void main() async {
+ await generateJniBindings(getConfig(BindingsType.cBased));
+ await generateJniBindings(getConfig(BindingsType.dartOnly));
+}
diff --git a/pkgs/jnigen/test/kotlin_test/generated_files_test.dart b/pkgs/jnigen/test/kotlin_test/generated_files_test.dart
new file mode 100644
index 0000000..b96c643
--- /dev/null
+++ b/pkgs/jnigen/test/kotlin_test/generated_files_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:jnigen/jnigen.dart';
+import 'package:test/test.dart';
+
+import 'generate.dart';
+import '../test_util/test_util.dart';
+
+void main() async {
+ // This is not run in setupAll, because we want to exit with one line of
+ // error message, not throw a long exception.
+ await checkLocallyBuiltDependencies();
+ generateAndCompareBothModes(
+ 'Generate and compare bindings for kotlin_test',
+ getConfig(BindingsType.cBased),
+ getConfig(BindingsType.dartOnly),
+ );
+ test(
+ "Generate and analyze bindings for kotlin_test - pure dart",
+ () async {
+ await generateAndAnalyzeBindings(
+ getConfig(BindingsType.dartOnly),
+ );
+ },
+ timeout: const Timeout.factor(1.5),
+ tags: largeTestTag,
+ );
+}
diff --git a/pkgs/jnigen/test/kotlin_test/kotlin/pom.xml b/pkgs/jnigen/test/kotlin_test/kotlin/pom.xml
new file mode 100644
index 0000000..b32d4ed
--- /dev/null
+++ b/pkgs/jnigen/test/kotlin_test/kotlin/pom.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>kotlin</artifactId>
+ <groupId>com.github.dart_lang.jnigen</groupId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+ <name>consoleApp</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <kotlin.code.style>official</kotlin.code.style>
+ <main.class>com.github.dart_lang.jnigen.SuspendFun</main.class>
+ <kotlin.compiler.jvmTarget>1.8</kotlin.compiler.jvmTarget>
+ </properties>
+
+ <repositories>
+ <repository>
+ <id>mavenCentral</id>
+ <url>https://repo1.maven.org/maven2/</url>
+ </repository>
+ </repositories>
+
+ <build>
+ <finalName>kotlin_test</finalName>
+ <sourceDirectory>src/main/kotlin</sourceDirectory>
+ <testSourceDirectory>src/test/kotlin</testSourceDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-maven-plugin</artifactId>
+ <version>1.7.20</version>
+ <executions>
+ <execution>
+ <id>compile</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>test-compile</id>
+ <phase>test-compile</phase>
+ <goals>
+ <goal>test-compile</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.22.2</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <version>2.22.2</version>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.6.0</version>
+ <configuration>
+ <mainClass>MainKt</mainClass>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals> <goal>single</goal> </goals>
+ <configuration>
+ <archive>
+ <manifest>
+ <mainClass>${main.class}</mainClass>
+ </manifest>
+ </archive>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-test-junit5</artifactId>
+ <version>1.7.20</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlinx</groupId>
+ <artifactId>kotlinx-coroutines-core</artifactId>
+ <version>1.6.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ <version>5.8.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-stdlib-jdk8</artifactId>
+ <version>1.7.20</version>
+ </dependency>
+ </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/pkgs/jnigen/test/kotlin_test/kotlin/src/main/kotlin/com/github/dart_lang/jnigen/SuspendFun.kt b/pkgs/jnigen/test/kotlin_test/kotlin/src/main/kotlin/com/github/dart_lang/jnigen/SuspendFun.kt
new file mode 100644
index 0000000..ffd4376
--- /dev/null
+++ b/pkgs/jnigen/test/kotlin_test/kotlin/src/main/kotlin/com/github/dart_lang/jnigen/SuspendFun.kt
@@ -0,0 +1,21 @@
+/* Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+ * for details. All rights reserved. Use of this source code is governed by a
+ * BSD-style license that can be found in the LICENSE file.
+ */
+
+package com.github.dart_lang.jnigen
+
+import kotlinx.coroutines.delay
+import kotlin.coroutines.Continuation
+
+public class SuspendFun {
+ suspend fun sayHello(): String {
+ delay(100L)
+ return "Hello!"
+ }
+
+ suspend fun sayHello(name: String): String {
+ delay(100L)
+ return "Hello $name!"
+ }
+}
\ No newline at end of file
diff --git a/pkgs/jnigen/test/kotlin_test/runtime_test_registrant.dart b/pkgs/jnigen/test/kotlin_test/runtime_test_registrant.dart
new file mode 100644
index 0000000..6a9696b
--- /dev/null
+++ b/pkgs/jnigen/test/kotlin_test/runtime_test_registrant.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+import 'package:jni/jni.dart';
+
+import '../test_util/callback_types.dart';
+
+import 'c_based/dart_bindings/kotlin.dart';
+
+void registerTests(String groupName, TestRunnerCallback test) {
+ group(groupName, () {
+ test('Suspend functions', () async {
+ await using((arena) async {
+ final suspendFun = SuspendFun()..releasedBy(arena);
+ final hello = await suspendFun.sayHello();
+ expect(hello.toDartString(releaseOriginal: true), "Hello!");
+ const name = "Bob";
+ final helloBob =
+ await suspendFun.sayHello1(name.toJString()..releasedBy(arena));
+ expect(helloBob.toDartString(releaseOriginal: true), "Hello $name!");
+ });
+ });
+ });
+}
diff --git a/pkgs/jnigen/test/package_resolver_test.dart b/pkgs/jnigen/test/package_resolver_test.dart
new file mode 100644
index 0000000..a29e043
--- /dev/null
+++ b/pkgs/jnigen/test/package_resolver_test.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:jnigen/src/bindings/resolver.dart';
+import 'package:jnigen/src/elements/elements.dart';
+import 'package:test/test.dart';
+
+import 'test_util/test_util.dart';
+
+class ResolverTest {
+ ResolverTest(this.binaryName, this.expectedImport, this.expectedName);
+ String binaryName;
+ String expectedImport;
+ String expectedName;
+}
+
+void main() async {
+ await checkLocallyBuiltDependencies();
+ final resolver = Resolver(
+ importedClasses: {
+ 'org.apache.pdfbox.pdmodel.PDDocument': ClassDecl(
+ declKind: DeclKind.classKind,
+ binaryName: 'org.apache.pdfbox.pdmodel.PDDocument',
+ )..path = 'package:pdfbox/pdfbox.dart',
+ 'android.os.Process': ClassDecl(
+ declKind: DeclKind.classKind,
+ binaryName: 'android.os.Process',
+ )..path = 'package:android/os.dart',
+ },
+ currentClass: 'a.b.N',
+ inputClassNames: {
+ 'a.b.C',
+ 'a.b.c.D',
+ 'a.b.c.d.E',
+ 'a.X',
+ 'e.f.G',
+ 'e.F',
+ 'a.g.Y',
+ 'a.m.n.P'
+ },
+ );
+
+ final tests = [
+ // Absolute imports resolved using import map
+ ResolverTest('android.os.Process', 'package:android/os.dart', 'process_.'),
+ ResolverTest('org.apache.pdfbox.pdmodel.PDDocument',
+ 'package:pdfbox/pdfbox.dart', 'pddocument_.'),
+ // Relative imports
+ // inner package
+ ResolverTest('a.b.c.D', 'c/D.dart', 'd_.'),
+ // inner package, deeper
+ ResolverTest('a.b.c.d.E', 'c/d/E.dart', 'e_.'),
+ // parent package
+ ResolverTest('a.X', '../X.dart', 'x_.'),
+ // unrelated package in same translation unit
+ ResolverTest('e.f.G', '../../e/f/G.dart', 'g_.'),
+ ResolverTest('e.F', '../../e/F.dart', 'f_.'),
+ // neighbour package
+ ResolverTest('a.g.Y', '../g/Y.dart', 'y_.'),
+ // inner package of a neighbour package
+ ResolverTest('a.m.n.P', '../m/n/P.dart', 'p_.'),
+ ];
+
+ for (var testCase in tests) {
+ final binaryName = testCase.binaryName;
+ final packageName = Resolver.getFileClassName(binaryName);
+ test(
+ 'getImport $binaryName',
+ () => expect(resolver.getImport(packageName, binaryName),
+ equals(testCase.expectedImport)));
+ test(
+ 'resolve $binaryName',
+ () => expect(
+ resolver.resolvePrefix(ClassDecl(
+ declKind: DeclKind.classKind,
+ binaryName: binaryName,
+ )..path = ''),
+ equals(testCase.expectedName)));
+ }
+}
diff --git a/pkgs/jnigen/test/regenerate_examples_test.dart b/pkgs/jnigen/test/regenerate_examples_test.dart
new file mode 100644
index 0000000..35ab2e0
--- /dev/null
+++ b/pkgs/jnigen/test/regenerate_examples_test.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:test/test.dart';
+import 'package:path/path.dart' hide equals;
+
+import 'package:jnigen/jnigen.dart';
+import 'package:jnigen/tools.dart';
+
+import 'test_util/test_util.dart';
+
+final inAppJava = join('example', 'in_app_java');
+final inAppJavaYaml = join(inAppJava, 'jnigen.yaml');
+final notificationPlugin = join('example', 'notification_plugin');
+final notificationPluginYaml = join(notificationPlugin, 'jnigen.yaml');
+final kotlinPlugin = join('example', 'kotlin_plugin');
+final kotlinPluginYaml = join(kotlinPlugin, 'jnigen.yaml');
+
+/// Generates bindings using jnigen config in [exampleName] and compares
+/// them to provided reference outputs.
+///
+/// [dartOutput] and [cOutput] are relative paths from example project dir.
+///
+/// Pass [isLargeTest] as true if the test will take considerable time.
+void testExample(String exampleName, String dartOutput, String? cOutput,
+ {bool isLargeTest = false}) {
+ test(
+ 'Generate and compare bindings for $exampleName',
+ timeout: const Timeout.factor(3),
+ () async {
+ final examplePath = join('example', exampleName);
+ final configPath = join(examplePath, 'jnigen.yaml');
+
+ final config = Config.parseArgs(['--config', configPath]);
+ try {
+ await generateAndCompareBindings(config);
+ } on GradleException catch (_) {
+ stderr.writeln('Skip: $exampleName');
+ }
+ },
+ tags: isLargeTest ? largeTestTag : null,
+ );
+}
+
+void main() async {
+ await checkLocallyBuiltDependencies();
+ testExample(
+ 'in_app_java',
+ join('lib', 'android_utils.dart'),
+ join('src', 'android_utils'),
+ isLargeTest: true,
+ );
+ testExample(
+ 'pdfbox_plugin',
+ join('lib', 'src', 'third_party'),
+ 'src',
+ isLargeTest: false,
+ );
+ testExample(
+ 'notification_plugin',
+ join('lib', 'notifications.dart'),
+ 'src',
+ isLargeTest: true,
+ );
+ testExample(
+ 'kotlin_plugin',
+ join('lib', 'kotlin_bindings.dart'),
+ 'src',
+ isLargeTest: true,
+ );
+}
diff --git a/pkgs/jnigen/test/simple_package_test/.gitignore b/pkgs/jnigen/test/simple_package_test/.gitignore
new file mode 100644
index 0000000..1db9cf8
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/.gitignore
@@ -0,0 +1,6 @@
+build/
+*.class
+test_lib/
+test_src/
+*_dartonly_generated.dart ## Generated test replicas
+generated_runtime_test.dart
\ No newline at end of file
diff --git a/pkgs/jnigen/test/simple_package_test/c_based/c_bindings/.clang-format b/pkgs/jnigen/test/simple_package_test/c_based/c_bindings/.clang-format
new file mode 100644
index 0000000..a256c2f
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/c_based/c_bindings/.clang-format
@@ -0,0 +1,15 @@
+# From dart SDK: https://github.com/dart-lang/sdk/blob/main/.clang-format
+
+# Defines the Chromium style for automatic reformatting.
+# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
+BasedOnStyle: Chromium
+
+# clang-format doesn't seem to do a good job of this for longer comments.
+ReflowComments: 'false'
+
+# We have lots of these. Though we need to put them all in curly braces,
+# clang-format can't do that.
+AllowShortIfStatementsOnASingleLine: 'true'
+
+# Put escaped newlines into the rightmost column.
+AlignEscapedNewlinesLeft: false
diff --git a/pkgs/jnigen/test/simple_package_test/c_based/c_bindings/CMakeLists.txt b/pkgs/jnigen/test/simple_package_test/c_based/c_bindings/CMakeLists.txt
new file mode 100644
index 0000000..eeb352d
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/c_based/c_bindings/CMakeLists.txt
@@ -0,0 +1,32 @@
+# jni_native_build (Build with jni:setup. Do not delete this line.)
+
+# 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)
+
+project(simple_package VERSION 0.0.1 LANGUAGES C)
+
+add_library(simple_package SHARED
+ "./simple_package.c"
+)
+
+set_target_properties(simple_package PROPERTIES
+ OUTPUT_NAME "simple_package"
+)
+
+target_compile_definitions(simple_package PUBLIC DART_SHARED_LIB)
+
+if(WIN32)
+ set_target_properties(${TARGET_NAME} PROPERTIES
+ LINK_FLAGS "/DELAYLOAD:jvm.dll")
+endif()
+
+if (ANDROID)
+ target_link_libraries(simple_package log)
+else()
+ find_package(Java REQUIRED)
+ find_package(JNI REQUIRED)
+ include_directories(${JNI_INCLUDE_DIRS})
+ target_link_libraries(simple_package ${JNI_LIBRARIES})
+endif()
diff --git a/pkgs/jnigen/test/simple_package_test/c_based/c_bindings/dartjni.h b/pkgs/jnigen/test/simple_package_test/c_based/c_bindings/dartjni.h
new file mode 100644
index 0000000..8f1dc74
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/c_based/c_bindings/dartjni.h
@@ -0,0 +1,424 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#pragma once
+
+// Note: include appropriate system jni.h as found by CMake, not third_party/jni.h.
+#include <jni.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if _WIN32
+#include <windows.h>
+#else
+#include <pthread.h>
+#include <unistd.h>
+#endif
+
+#if _WIN32
+#define FFI_PLUGIN_EXPORT __declspec(dllexport)
+#else
+#define FFI_PLUGIN_EXPORT
+#endif
+
+#if defined _WIN32
+#define thread_local __declspec(thread)
+#else
+#define thread_local __thread
+#endif
+
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
+
+#ifdef __ANDROID__
+#define __ENVP_CAST (JNIEnv**)
+#else
+#define __ENVP_CAST (void**)
+#endif
+
+/// Locking functions for windows and pthread.
+
+#if defined _WIN32
+#include <windows.h>
+
+typedef CRITICAL_SECTION MutexLock;
+typedef CONDITION_VARIABLE ConditionVariable;
+
+static inline void init_lock(MutexLock* lock) {
+ InitializeCriticalSection(lock);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+ EnterCriticalSection(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+ LeaveCriticalSection(lock);
+}
+
+static inline void destroy_lock(MutexLock* lock) {
+ DeleteCriticalSection(lock);
+}
+
+static inline void init_cond(ConditionVariable* cond) {
+ InitializeConditionVariable(cond);
+}
+
+static inline void signal_cond(ConditionVariable* cond) {
+ WakeConditionVariable(cond);
+}
+
+static inline void wait_for(ConditionVariable* cond, MutexLock* lock) {
+ SleepConditionVariableCS(cond, lock, INFINITE);
+}
+
+static inline void destroy_cond(ConditionVariable* cond) {
+ // Not available.
+}
+
+#elif defined __APPLE__ || defined __LINUX__ || defined __ANDROID__ || \
+ defined __GNUC__
+#include <pthread.h>
+
+typedef pthread_mutex_t MutexLock;
+typedef pthread_cond_t ConditionVariable;
+
+static inline void init_lock(MutexLock* lock) {
+ pthread_mutex_init(lock, NULL);
+}
+
+static inline void acquire_lock(MutexLock* lock) {
+ pthread_mutex_lock(lock);
+}
+
+static inline void release_lock(MutexLock* lock) {
+ pthread_mutex_unlock(lock);
+}
+
+static inline void destroy_lock(MutexLock* lock) {
+ pthread_mutex_destroy(lock);
+}
+
+static inline void init_cond(ConditionVariable* cond) {
+ pthread_cond_init(cond, NULL);
+}
+
+static inline void signal_cond(ConditionVariable* cond) {
+ pthread_cond_signal(cond);
+}
+
+static inline void wait_for(ConditionVariable* cond, MutexLock* lock) {
+ pthread_cond_wait(cond, lock);
+}
+
+static inline void destroy_cond(ConditionVariable* cond) {
+ pthread_cond_destroy(cond);
+}
+
+#else
+
+#error "No locking/condition variable support; Possibly unsupported platform"
+
+#endif
+
+typedef struct CallbackResult {
+ MutexLock lock;
+ ConditionVariable cond;
+ int ready;
+ jobject object;
+} CallbackResult;
+
+typedef struct JniLocks {
+ MutexLock classLoadingLock;
+ MutexLock methodLoadingLock;
+ MutexLock fieldLoadingLock;
+} JniLocks;
+
+/// Represents the error when dart-jni layer has already spawned singleton VM.
+#define DART_JNI_SINGLETON_EXISTS (-99);
+
+/// Stores the global state of the JNI.
+typedef struct JniContext {
+ JavaVM* jvm;
+ jobject classLoader;
+ jmethodID loadClassMethod;
+ jobject currentActivity;
+ jobject appContext;
+ JniLocks locks;
+} JniContext;
+
+// jniEnv for this thread, used by inline functions in this header,
+// therefore declared as extern.
+extern thread_local JNIEnv* jniEnv;
+
+extern JniContext* jni;
+
+/// Types used by JNI API to distinguish between primitive types.
+enum JniType {
+ booleanType = 0,
+ byteType = 1,
+ shortType = 2,
+ charType = 3,
+ intType = 4,
+ longType = 5,
+ floatType = 6,
+ doubleType = 7,
+ objectType = 8,
+ voidType = 9,
+};
+
+/// Result type for use by JNI.
+///
+/// If [exception] is null, it means the result is valid.
+/// It's assumed that the caller knows the expected type in [result].
+typedef struct JniResult {
+ jvalue value;
+ jthrowable exception;
+} JniResult;
+
+/// Similar to [JniResult] but for class lookups.
+typedef struct JniClassLookupResult {
+ jclass value;
+ jthrowable exception;
+} JniClassLookupResult;
+
+/// Similar to [JniResult] but for method/field ID lookups.
+typedef struct JniPointerResult {
+ const void* value;
+ jthrowable exception;
+} JniPointerResult;
+
+/// JniExceptionDetails holds 2 jstring objects, one is the result of
+/// calling `toString` on exception object, other is stack trace;
+typedef struct JniExceptionDetails {
+ jstring message;
+ jstring stacktrace;
+} JniExceptionDetails;
+
+/// This struct contains functions which wrap method call / field access conveniently along with
+/// exception checking.
+///
+/// Flutter embedding checks for pending JNI exceptions before an FFI transition, which requires us
+/// to check for and clear the exception before returning to dart code, which requires these functions
+/// to return result types.
+typedef struct JniAccessorsStruct {
+ JniClassLookupResult (*getClass)(char* internalName);
+ JniPointerResult (*getFieldID)(jclass cls, char* fieldName, char* signature);
+ JniPointerResult (*getStaticFieldID)(jclass cls,
+ char* fieldName,
+ char* signature);
+ JniPointerResult (*getMethodID)(jclass cls,
+ char* methodName,
+ char* signature);
+ JniPointerResult (*getStaticMethodID)(jclass cls,
+ char* methodName,
+ char* signature);
+ JniResult (*newObject)(jclass cls, jmethodID ctor, jvalue* args);
+ JniResult (*newPrimitiveArray)(jsize length, int type);
+ JniResult (*newObjectArray)(jsize length,
+ jclass elementClass,
+ jobject initialElement);
+ JniResult (*getArrayElement)(jarray array, int index, int type);
+ JniResult (*callMethod)(jobject obj,
+ jmethodID methodID,
+ int callType,
+ jvalue* args);
+ JniResult (*callStaticMethod)(jclass cls,
+ jmethodID methodID,
+ int callType,
+ jvalue* args);
+ JniResult (*getField)(jobject obj, jfieldID fieldID, int callType);
+ JniResult (*getStaticField)(jclass cls, jfieldID fieldID, int callType);
+ JniExceptionDetails (*getExceptionDetails)(jthrowable exception);
+} JniAccessorsStruct;
+
+FFI_PLUGIN_EXPORT JniAccessorsStruct* GetAccessors();
+
+FFI_PLUGIN_EXPORT JavaVM* GetJavaVM(void);
+
+FFI_PLUGIN_EXPORT JNIEnv* GetJniEnv(void);
+
+/// Spawn a JVM with given arguments.
+///
+/// Returns JNI_OK on success, and one of the documented JNI error codes on
+/// failure. It returns DART_JNI_SINGLETON_EXISTS if an attempt to spawn multiple
+/// JVMs is made, even if the underlying API potentially supports multiple VMs.
+FFI_PLUGIN_EXPORT int SpawnJvm(JavaVMInitArgs* args);
+
+/// Load class through platform-specific mechanism.
+///
+/// Currently uses application classloader on android,
+/// and JNIEnv->FindClass on other platforms.
+FFI_PLUGIN_EXPORT jclass FindClass(const char* name);
+
+/// Returns Application classLoader (on Android),
+/// which can be used to load application and platform classes.
+///
+/// On other platforms, NULL is returned.
+FFI_PLUGIN_EXPORT jobject GetClassLoader(void);
+
+/// Returns application context on Android.
+///
+/// On other platforms, NULL is returned.
+FFI_PLUGIN_EXPORT jobject GetApplicationContext(void);
+
+/// Returns current activity of the app on Android.
+FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void);
+
+static inline void attach_thread() {
+ if (jniEnv == NULL) {
+ (*jni->jvm)->AttachCurrentThread(jni->jvm, __ENVP_CAST & jniEnv, NULL);
+ }
+}
+
+/// Load class into [cls] using platform specific mechanism
+static inline void load_class_platform(jclass* cls, const char* name) {
+#ifdef __ANDROID__
+ jstring className = (*jniEnv)->NewStringUTF(jniEnv, name);
+ *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni->classLoader,
+ jni->loadClassMethod, className);
+ (*jniEnv)->DeleteLocalRef(jniEnv, className);
+#else
+ *cls = (*jniEnv)->FindClass(jniEnv, name);
+#endif
+}
+
+static inline void load_class_local_ref(jclass* cls, const char* name) {
+ if (*cls == NULL) {
+ acquire_lock(&jni->locks.classLoadingLock);
+ if (*cls == NULL) {
+ load_class_platform(cls, name);
+ }
+ release_lock(&jni->locks.classLoadingLock);
+ }
+}
+
+static inline void load_class_global_ref(jclass* cls, const char* name) {
+ if (*cls == NULL) {
+ jclass tmp = NULL;
+ acquire_lock(&jni->locks.classLoadingLock);
+ if (*cls == NULL) {
+ load_class_platform(&tmp, name);
+ if (!(*jniEnv)->ExceptionCheck(jniEnv)) {
+ *cls = (*jniEnv)->NewGlobalRef(jniEnv, tmp);
+ (*jniEnv)->DeleteLocalRef(jniEnv, tmp);
+ }
+ }
+ release_lock(&jni->locks.classLoadingLock);
+ }
+}
+
+static inline void load_method(jclass cls,
+ jmethodID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.methodLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetMethodID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.methodLoadingLock);
+ }
+}
+
+static inline void load_static_method(jclass cls,
+ jmethodID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.methodLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetStaticMethodID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.methodLoadingLock);
+ }
+}
+
+static inline void load_field(jclass cls,
+ jfieldID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.fieldLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetFieldID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.fieldLoadingLock);
+ }
+}
+
+static inline void load_static_field(jclass cls,
+ jfieldID* res,
+ const char* name,
+ const char* sig) {
+ if (*res == NULL) {
+ acquire_lock(&jni->locks.fieldLoadingLock);
+ if (*res == NULL) {
+ *res = (*jniEnv)->GetStaticFieldID(jniEnv, cls, name, sig);
+ }
+ release_lock(&jni->locks.fieldLoadingLock);
+ }
+}
+
+static inline jobject to_global_ref(jobject ref) {
+ jobject g = (*jniEnv)->NewGlobalRef(jniEnv, ref);
+ (*jniEnv)->DeleteLocalRef(jniEnv, ref);
+ return g;
+}
+
+// These functions are useful for C+Dart bindings, and not required for pure dart bindings.
+
+FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr();
+
+/// For use by jni_gen's generated code
+/// don't use these.
+
+// these 2 fn ptr vars will be defined by generated code library
+extern JniContext* (*context_getter)(void);
+extern JNIEnv* (*env_getter)(void);
+
+// this function will be exported by generated code library
+// it will set above 2 variables.
+FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext* (*cg)(void),
+ JNIEnv* (*eg)(void));
+
+static inline void load_env() {
+ if (jniEnv == NULL) {
+ jni = context_getter();
+ jniEnv = env_getter();
+ }
+}
+
+static inline jthrowable check_exception() {
+ jthrowable exception = (*jniEnv)->ExceptionOccurred(jniEnv);
+ if (exception != NULL) (*jniEnv)->ExceptionClear(jniEnv);
+ if (exception == NULL) return NULL;
+ return to_global_ref(exception);
+}
+
+static inline JniResult to_global_ref_result(jobject ref) {
+ JniResult result;
+ result.exception = check_exception();
+ if (result.exception == NULL) {
+ result.value.l = to_global_ref(ref);
+ }
+ return result;
+}
+
+FFI_PLUGIN_EXPORT intptr_t InitDartApiDL(void* data);
+
+FFI_PLUGIN_EXPORT
+JniResult DartException__ctor(jstring message);
+
+FFI_PLUGIN_EXPORT
+JniResult PortContinuation__ctor(int64_t j);
+
+FFI_PLUGIN_EXPORT
+JniResult PortProxy__newInstance(jobject binaryName,
+ int64_t port,
+ int64_t functionPtr);
+
+FFI_PLUGIN_EXPORT void resultFor(CallbackResult* result, jobject object);
diff --git a/pkgs/jnigen/test/simple_package_test/c_based/c_bindings/simple_package.c b/pkgs/jnigen/test/simple_package_test/c_based/c_bindings/simple_package.c
new file mode 100644
index 0000000..20c7e7e
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/c_based/c_bindings/simple_package.c
@@ -0,0 +1,2954 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+#include <stdint.h>
+#include "dartjni.h"
+#include "jni.h"
+
+thread_local JNIEnv* jniEnv;
+JniContext* jni;
+
+JniContext* (*context_getter)(void);
+JNIEnv* (*env_getter)(void);
+
+void setJniGetters(JniContext* (*cg)(void), JNIEnv* (*eg)(void)) {
+ context_getter = cg;
+ env_getter = eg;
+}
+
+// com.github.dart_lang.jnigen.simple_package.Color
+jclass _c_Color = NULL;
+
+jmethodID _m_Color__values = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Color__values() {
+ load_env();
+ load_class_global_ref(&_c_Color,
+ "com/github/dart_lang/jnigen/simple_package/Color");
+ if (_c_Color == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Color, &_m_Color__values, "values",
+ "()[Lcom/github/dart_lang/jnigen/simple_package/Color;");
+ if (_m_Color__values == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_Color, _m_Color__values);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Color__valueOf = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Color__valueOf(jobject name) {
+ load_env();
+ load_class_global_ref(&_c_Color,
+ "com/github/dart_lang/jnigen/simple_package/Color");
+ if (_c_Color == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_Color, &_m_Color__valueOf, "valueOf",
+ "(Ljava/lang/String;)Lcom/github/dart_lang/jnigen/simple_package/Color;");
+ if (_m_Color__valueOf == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_Color,
+ _m_Color__valueOf, name);
+ return to_global_ref_result(_result);
+}
+
+// com.github.dart_lang.jnigen.simple_package.Example
+jclass _c_Example = NULL;
+
+jmethodID _m_Example__getAmount = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__getAmount() {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Example, &_m_Example__getAmount, "getAmount", "()I");
+ if (_m_Example__getAmount == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallStaticIntMethod(jniEnv, _c_Example, _m_Example__getAmount);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__getPi = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__getPi() {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Example, &_m_Example__getPi, "getPi", "()D");
+ if (_m_Example__getPi == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ double _result =
+ (*jniEnv)->CallStaticDoubleMethod(jniEnv, _c_Example, _m_Example__getPi);
+ return (JniResult){.value = {.d = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__getAsterisk = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__getAsterisk() {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Example, &_m_Example__getAsterisk, "getAsterisk",
+ "()C");
+ if (_m_Example__getAsterisk == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint16_t _result = (*jniEnv)->CallStaticCharMethod(jniEnv, _c_Example,
+ _m_Example__getAsterisk);
+ return (JniResult){.value = {.c = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__getName = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__getName() {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Example, &_m_Example__getName, "getName",
+ "()Ljava/lang/String;");
+ if (_m_Example__getName == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_Example,
+ _m_Example__getName);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Example__getNestedInstance = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__getNestedInstance() {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_Example, &_m_Example__getNestedInstance, "getNestedInstance",
+ "()Lcom/github/dart_lang/jnigen/simple_package/Example$Nested;");
+ if (_m_Example__getNestedInstance == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_Example, _m_Example__getNestedInstance);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Example__setAmount = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__setAmount(int32_t newAmount) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Example, &_m_Example__setAmount, "setAmount", "(I)V");
+ if (_m_Example__setAmount == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallStaticVoidMethod(jniEnv, _c_Example, _m_Example__setAmount,
+ newAmount);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__setName = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__setName(jobject newName) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Example, &_m_Example__setName, "setName",
+ "(Ljava/lang/String;)V");
+ if (_m_Example__setName == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallStaticVoidMethod(jniEnv, _c_Example, _m_Example__setName,
+ newName);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__setNestedInstance = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__setNestedInstance(jobject newNested) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_Example, &_m_Example__setNestedInstance, "setNestedInstance",
+ "(Lcom/github/dart_lang/jnigen/simple_package/Example$Nested;)V");
+ if (_m_Example__setNestedInstance == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallStaticVoidMethod(jniEnv, _c_Example,
+ _m_Example__setNestedInstance, newNested);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__max4 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__max4(int32_t a, int32_t b, int32_t c, int32_t d) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Example, &_m_Example__max4, "max4", "(IIII)I");
+ if (_m_Example__max4 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallStaticIntMethod(
+ jniEnv, _c_Example, _m_Example__max4, a, b, c, d);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__max8 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__max8(int32_t a,
+ int32_t b,
+ int32_t c,
+ int32_t d,
+ int32_t e,
+ int32_t f,
+ int32_t g,
+ int32_t h) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Example, &_m_Example__max8, "max8", "(IIIIIIII)I");
+ if (_m_Example__max8 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallStaticIntMethod(
+ jniEnv, _c_Example, _m_Example__max8, a, b, c, d, e, f, g, h);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__getNumber = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__getNumber(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__getNumber, "getNumber", "()I");
+ if (_m_Example__getNumber == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_Example__getNumber);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__setNumber = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__setNumber(jobject self_, int32_t number) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__setNumber, "setNumber", "(I)V");
+ if (_m_Example__setNumber == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_Example__setNumber, number);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__getIsUp = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__getIsUp(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__getIsUp, "getIsUp", "()Z");
+ if (_m_Example__getIsUp == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result =
+ (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_Example__getIsUp);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__setUp = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__setUp(jobject self_, uint8_t isUp) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__setUp, "setUp", "(Z)V");
+ if (_m_Example__setUp == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_Example__setUp, isUp);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__getCodename = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__getCodename(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__getCodename, "getCodename",
+ "()Ljava/lang/String;");
+ if (_m_Example__getCodename == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_Example__getCodename);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Example__setCodename = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__setCodename(jobject self_, jobject codename) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__setCodename, "setCodename",
+ "(Ljava/lang/String;)V");
+ if (_m_Example__setCodename == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_Example__setCodename, codename);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__getRandom = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__getRandom(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__getRandom, "getRandom",
+ "()Ljava/util/Random;");
+ if (_m_Example__getRandom == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_Example__getRandom);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Example__setRandom = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__setRandom(jobject self_, jobject random) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__setRandom, "setRandom",
+ "(Ljava/util/Random;)V");
+ if (_m_Example__setRandom == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_Example__setRandom, random);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__getRandomLong = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__getRandomLong(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__getRandomLong, "getRandomLong", "()J");
+ if (_m_Example__getRandomLong == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int64_t _result =
+ (*jniEnv)->CallLongMethod(jniEnv, self_, _m_Example__getRandomLong);
+ return (JniResult){.value = {.j = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__add4Longs = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__add4Longs(jobject self_,
+ int64_t a,
+ int64_t b,
+ int64_t c,
+ int64_t d) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__add4Longs, "add4Longs", "(JJJJ)J");
+ if (_m_Example__add4Longs == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int64_t _result = (*jniEnv)->CallLongMethod(
+ jniEnv, self_, _m_Example__add4Longs, a, b, c, d);
+ return (JniResult){.value = {.j = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__add8Longs = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__add8Longs(jobject self_,
+ int64_t a,
+ int64_t b,
+ int64_t c,
+ int64_t d,
+ int64_t e,
+ int64_t f,
+ int64_t g,
+ int64_t h) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__add8Longs, "add8Longs", "(JJJJJJJJ)J");
+ if (_m_Example__add8Longs == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int64_t _result = (*jniEnv)->CallLongMethod(
+ jniEnv, self_, _m_Example__add8Longs, a, b, c, d, e, f, g, h);
+ return (JniResult){.value = {.j = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__getRandomNumericString = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__getRandomNumericString(jobject self_, jobject random) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__getRandomNumericString,
+ "getRandomNumericString",
+ "(Ljava/util/Random;)Ljava/lang/String;");
+ if (_m_Example__getRandomNumericString == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_Example__getRandomNumericString, random);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Example__protectedMethod = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__protectedMethod(jobject self_, jobject a, jobject b) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__protectedMethod, "protectedMethod",
+ "(Ljava/lang/String;Ljava/lang/String;)V");
+ if (_m_Example__protectedMethod == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_Example__protectedMethod, a, b);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__finalMethod = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__finalMethod(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__finalMethod, "finalMethod", "()V");
+ if (_m_Example__finalMethod == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_Example__finalMethod);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__getList = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__getList(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__getList, "getList",
+ "()Ljava/util/List;");
+ if (_m_Example__getList == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_Example__getList);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Example__joinStrings = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__joinStrings(jobject self_, jobject values, jobject delim) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__joinStrings, "joinStrings",
+ "(Ljava/util/List;Ljava/lang/String;)Ljava/lang/String;");
+ if (_m_Example__joinStrings == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_Example__joinStrings, values, delim);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Example__methodWithSeveralParams = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__methodWithSeveralParams(jobject self_,
+ uint16_t ch,
+ jobject s,
+ jobject a,
+ jobject t,
+ jobject lt,
+ jobject wm) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__methodWithSeveralParams,
+ "methodWithSeveralParams",
+ "(CLjava/lang/String;[ILjava/lang/CharSequence;Ljava/util/"
+ "List;Ljava/util/Map;)V");
+ if (_m_Example__methodWithSeveralParams == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_Example__methodWithSeveralParams,
+ ch, s, a, t, lt, wm);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__new0() {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__new0, "<init>", "()V");
+ if (_m_Example__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_Example, _m_Example__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Example__new1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__new1(int32_t number) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__new1, "<init>", "(I)V");
+ if (_m_Example__new1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_Example, _m_Example__new1, number);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Example__new2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__new2(int32_t number, uint8_t isUp) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__new2, "<init>", "(IZ)V");
+ if (_m_Example__new2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_Example, _m_Example__new2, number, isUp);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Example__new3 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__new3(int32_t number, uint8_t isUp, jobject codename) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__new3, "<init>",
+ "(IZLjava/lang/String;)V");
+ if (_m_Example__new3 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_Example, _m_Example__new3,
+ number, isUp, codename);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Example__new4 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__new4(int32_t a,
+ int32_t b,
+ int32_t c,
+ int32_t d,
+ int32_t e,
+ int32_t f,
+ int32_t g,
+ int32_t h) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__new4, "<init>", "(IIIIIIII)V");
+ if (_m_Example__new4 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_Example, _m_Example__new4,
+ a, b, c, d, e, f, g, h);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Example__whichExample = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__whichExample(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__whichExample, "whichExample", "()I");
+ if (_m_Example__whichExample == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_Example__whichExample);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__addInts = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__addInts(int32_t a, int32_t b) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Example, &_m_Example__addInts, "addInts", "(II)I");
+ if (_m_Example__addInts == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallStaticIntMethod(jniEnv, _c_Example,
+ _m_Example__addInts, a, b);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__getArr = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__getArr() {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Example, &_m_Example__getArr, "getArr", "()[I");
+ if (_m_Example__getArr == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_Example, _m_Example__getArr);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Example__addAll = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__addAll(jobject arr) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Example, &_m_Example__addAll, "addAll", "([I)I");
+ if (_m_Example__addAll == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallStaticIntMethod(jniEnv, _c_Example,
+ _m_Example__addAll, arr);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__getSelf = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__getSelf(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__getSelf, "getSelf",
+ "()Lcom/github/dart_lang/jnigen/simple_package/Example;");
+ if (_m_Example__getSelf == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_Example__getSelf);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Example__throwException = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__throwException() {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Example, &_m_Example__throwException, "throwException",
+ "()V");
+ if (_m_Example__throwException == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallStaticVoidMethod(jniEnv, _c_Example,
+ _m_Example__throwException);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__overloaded = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__overloaded(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__overloaded, "overloaded", "()V");
+ if (_m_Example__overloaded == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_Example__overloaded);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__overloaded1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__overloaded1(jobject self_, int32_t a, jobject b) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__overloaded1, "overloaded",
+ "(ILjava/lang/String;)V");
+ if (_m_Example__overloaded1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_Example__overloaded1, a, b);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__overloaded2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__overloaded2(jobject self_, int32_t a) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__overloaded2, "overloaded", "(I)V");
+ if (_m_Example__overloaded2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_Example__overloaded2, a);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__overloaded3 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__overloaded3(jobject self_, jobject a, jobject b) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__overloaded3, "overloaded",
+ "(Ljava/util/List;Ljava/lang/String;)V");
+ if (_m_Example__overloaded3 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_Example__overloaded3, a, b);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_Example__overloaded4 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example__overloaded4(jobject self_, jobject a) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example, &_m_Example__overloaded4, "overloaded",
+ "(Ljava/util/List;)V");
+ if (_m_Example__overloaded4 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_Example__overloaded4, a);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_Example__unusedRandom = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Example__unusedRandom() {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Example, &_f_Example__unusedRandom, "unusedRandom",
+ "Ljava/util/Random;");
+ jobject _result = (*jniEnv)->GetStaticObjectField(jniEnv, _c_Example,
+ _f_Example__unusedRandom);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Example__protectedField = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Example__protectedField(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_Example, &_f_Example__protectedField, "protectedField",
+ "Ljava/util/Random;");
+ jobject _result =
+ (*jniEnv)->GetObjectField(jniEnv, self_, _f_Example__protectedField);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_Example__protectedField(jobject self_, jobject value) {
+ load_env();
+ load_class_global_ref(&_c_Example,
+ "com/github/dart_lang/jnigen/simple_package/Example");
+ if (_c_Example == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_Example, &_f_Example__protectedField, "protectedField",
+ "Ljava/util/Random;");
+ (*jniEnv)->SetObjectField(jniEnv, self_, _f_Example__protectedField, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.simple_package.Example$Nested
+jclass _c_Example_Nested = NULL;
+
+jmethodID _m_Example_Nested__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example_Nested__new0(uint8_t value) {
+ load_env();
+ load_class_global_ref(
+ &_c_Example_Nested,
+ "com/github/dart_lang/jnigen/simple_package/Example$Nested");
+ if (_c_Example_Nested == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example_Nested, &_m_Example_Nested__new0, "<init>", "(Z)V");
+ if (_m_Example_Nested__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_Example_Nested,
+ _m_Example_Nested__new0, value);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Example_Nested__usesAnonymousInnerClass = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example_Nested__usesAnonymousInnerClass(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_Example_Nested,
+ "com/github/dart_lang/jnigen/simple_package/Example$Nested");
+ if (_c_Example_Nested == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example_Nested, &_m_Example_Nested__usesAnonymousInnerClass,
+ "usesAnonymousInnerClass", "()V");
+ if (_m_Example_Nested__usesAnonymousInnerClass == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_Example_Nested__usesAnonymousInnerClass);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_Example_Nested__getValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example_Nested__getValue(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_Example_Nested,
+ "com/github/dart_lang/jnigen/simple_package/Example$Nested");
+ if (_c_Example_Nested == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example_Nested, &_m_Example_Nested__getValue, "getValue",
+ "()Z");
+ if (_m_Example_Nested__getValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ uint8_t _result =
+ (*jniEnv)->CallBooleanMethod(jniEnv, self_, _m_Example_Nested__getValue);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Example_Nested__setValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example_Nested__setValue(jobject self_, uint8_t value) {
+ load_env();
+ load_class_global_ref(
+ &_c_Example_Nested,
+ "com/github/dart_lang/jnigen/simple_package/Example$Nested");
+ if (_c_Example_Nested == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example_Nested, &_m_Example_Nested__setValue, "setValue",
+ "(Z)V");
+ if (_m_Example_Nested__setValue == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_Example_Nested__setValue, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.simple_package.Example$Nested$NestedTwice
+jclass _c_Example_Nested_NestedTwice = NULL;
+
+jmethodID _m_Example_Nested_NestedTwice__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example_Nested_NestedTwice__new0() {
+ load_env();
+ load_class_global_ref(
+ &_c_Example_Nested_NestedTwice,
+ "com/github/dart_lang/jnigen/simple_package/Example$Nested$NestedTwice");
+ if (_c_Example_Nested_NestedTwice == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example_Nested_NestedTwice,
+ &_m_Example_Nested_NestedTwice__new0, "<init>", "()V");
+ if (_m_Example_Nested_NestedTwice__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_Example_Nested_NestedTwice,
+ _m_Example_Nested_NestedTwice__new0);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Example_Nested_NestedTwice__ZERO = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Example_Nested_NestedTwice__ZERO() {
+ load_env();
+ load_class_global_ref(
+ &_c_Example_Nested_NestedTwice,
+ "com/github/dart_lang/jnigen/simple_package/Example$Nested$NestedTwice");
+ if (_c_Example_Nested_NestedTwice == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Example_Nested_NestedTwice,
+ &_f_Example_Nested_NestedTwice__ZERO, "ZERO", "I");
+ int32_t _result =
+ (*jniEnv)->GetStaticIntField(jniEnv, _c_Example_Nested_NestedTwice,
+ _f_Example_Nested_NestedTwice__ZERO);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_Example_Nested_NestedTwice__ZERO(int32_t value) {
+ load_env();
+ load_class_global_ref(
+ &_c_Example_Nested_NestedTwice,
+ "com/github/dart_lang/jnigen/simple_package/Example$Nested$NestedTwice");
+ if (_c_Example_Nested_NestedTwice == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Example_Nested_NestedTwice,
+ &_f_Example_Nested_NestedTwice__ZERO, "ZERO", "I");
+ (*jniEnv)->SetStaticIntField(jniEnv, _c_Example_Nested_NestedTwice,
+ _f_Example_Nested_NestedTwice__ZERO, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.simple_package.Example$NonStaticNested
+jclass _c_Example_NonStaticNested = NULL;
+
+jmethodID _m_Example_NonStaticNested__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example_NonStaticNested__new0(jobject _parent) {
+ load_env();
+ load_class_global_ref(
+ &_c_Example_NonStaticNested,
+ "com/github/dart_lang/jnigen/simple_package/Example$NonStaticNested");
+ if (_c_Example_NonStaticNested == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example_NonStaticNested, &_m_Example_NonStaticNested__new0,
+ "<init>",
+ "(Lcom/github/dart_lang/jnigen/simple_package/Example;)V");
+ if (_m_Example_NonStaticNested__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_Example_NonStaticNested,
+ _m_Example_NonStaticNested__new0, _parent);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Example_NonStaticNested__ok = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Example_NonStaticNested__ok(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_Example_NonStaticNested,
+ "com/github/dart_lang/jnigen/simple_package/Example$NonStaticNested");
+ if (_c_Example_NonStaticNested == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_Example_NonStaticNested, &_f_Example_NonStaticNested__ok, "ok",
+ "Z");
+ uint8_t _result =
+ (*jniEnv)->GetBooleanField(jniEnv, self_, _f_Example_NonStaticNested__ok);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_Example_NonStaticNested__ok(jobject self_, uint8_t value) {
+ load_env();
+ load_class_global_ref(
+ &_c_Example_NonStaticNested,
+ "com/github/dart_lang/jnigen/simple_package/Example$NonStaticNested");
+ if (_c_Example_NonStaticNested == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_Example_NonStaticNested, &_f_Example_NonStaticNested__ok, "ok",
+ "Z");
+ (*jniEnv)->SetBooleanField(jniEnv, self_, _f_Example_NonStaticNested__ok,
+ value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.simple_package.Exceptions
+jclass _c_Exceptions = NULL;
+
+jmethodID _m_Exceptions__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Exceptions__new0() {
+ load_env();
+ load_class_global_ref(
+ &_c_Exceptions, "com/github/dart_lang/jnigen/simple_package/Exceptions");
+ if (_c_Exceptions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Exceptions, &_m_Exceptions__new0, "<init>", "()V");
+ if (_m_Exceptions__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_Exceptions, _m_Exceptions__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Exceptions__new1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Exceptions__new1(float x) {
+ load_env();
+ load_class_global_ref(
+ &_c_Exceptions, "com/github/dart_lang/jnigen/simple_package/Exceptions");
+ if (_c_Exceptions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Exceptions, &_m_Exceptions__new1, "<init>", "(F)V");
+ if (_m_Exceptions__new1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_Exceptions, _m_Exceptions__new1, x);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Exceptions__new2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Exceptions__new2(int32_t a,
+ int32_t b,
+ int32_t c,
+ int32_t d,
+ int32_t e,
+ int32_t f) {
+ load_env();
+ load_class_global_ref(
+ &_c_Exceptions, "com/github/dart_lang/jnigen/simple_package/Exceptions");
+ if (_c_Exceptions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Exceptions, &_m_Exceptions__new2, "<init>", "(IIIIII)V");
+ if (_m_Exceptions__new2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_Exceptions,
+ _m_Exceptions__new2, a, b, c, d, e, f);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Exceptions__staticObjectMethod = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Exceptions__staticObjectMethod() {
+ load_env();
+ load_class_global_ref(
+ &_c_Exceptions, "com/github/dart_lang/jnigen/simple_package/Exceptions");
+ if (_c_Exceptions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Exceptions, &_m_Exceptions__staticObjectMethod,
+ "staticObjectMethod", "()Ljava/lang/Object;");
+ if (_m_Exceptions__staticObjectMethod == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_Exceptions, _m_Exceptions__staticObjectMethod);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Exceptions__staticIntMethod = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Exceptions__staticIntMethod() {
+ load_env();
+ load_class_global_ref(
+ &_c_Exceptions, "com/github/dart_lang/jnigen/simple_package/Exceptions");
+ if (_c_Exceptions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Exceptions, &_m_Exceptions__staticIntMethod,
+ "staticIntMethod", "()I");
+ if (_m_Exceptions__staticIntMethod == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallStaticIntMethod(
+ jniEnv, _c_Exceptions, _m_Exceptions__staticIntMethod);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Exceptions__staticObjectArrayMethod = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Exceptions__staticObjectArrayMethod() {
+ load_env();
+ load_class_global_ref(
+ &_c_Exceptions, "com/github/dart_lang/jnigen/simple_package/Exceptions");
+ if (_c_Exceptions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Exceptions, &_m_Exceptions__staticObjectArrayMethod,
+ "staticObjectArrayMethod", "()[Ljava/lang/Object;");
+ if (_m_Exceptions__staticObjectArrayMethod == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_Exceptions, _m_Exceptions__staticObjectArrayMethod);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Exceptions__staticIntArrayMethod = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Exceptions__staticIntArrayMethod() {
+ load_env();
+ load_class_global_ref(
+ &_c_Exceptions, "com/github/dart_lang/jnigen/simple_package/Exceptions");
+ if (_c_Exceptions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Exceptions, &_m_Exceptions__staticIntArrayMethod,
+ "staticIntArrayMethod", "()[I");
+ if (_m_Exceptions__staticIntArrayMethod == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_Exceptions, _m_Exceptions__staticIntArrayMethod);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Exceptions__objectMethod = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Exceptions__objectMethod(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_Exceptions, "com/github/dart_lang/jnigen/simple_package/Exceptions");
+ if (_c_Exceptions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Exceptions, &_m_Exceptions__objectMethod, "objectMethod",
+ "()Ljava/lang/Object;");
+ if (_m_Exceptions__objectMethod == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_Exceptions__objectMethod);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Exceptions__intMethod = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Exceptions__intMethod(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_Exceptions, "com/github/dart_lang/jnigen/simple_package/Exceptions");
+ if (_c_Exceptions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Exceptions, &_m_Exceptions__intMethod, "intMethod", "()I");
+ if (_m_Exceptions__intMethod == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_Exceptions__intMethod);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Exceptions__objectArrayMethod = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Exceptions__objectArrayMethod(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_Exceptions, "com/github/dart_lang/jnigen/simple_package/Exceptions");
+ if (_c_Exceptions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Exceptions, &_m_Exceptions__objectArrayMethod,
+ "objectArrayMethod", "()[Ljava/lang/Object;");
+ if (_m_Exceptions__objectArrayMethod == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_Exceptions__objectArrayMethod);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Exceptions__intArrayMethod = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Exceptions__intArrayMethod(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_Exceptions, "com/github/dart_lang/jnigen/simple_package/Exceptions");
+ if (_c_Exceptions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Exceptions, &_m_Exceptions__intArrayMethod, "intArrayMethod",
+ "()[I");
+ if (_m_Exceptions__intArrayMethod == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_Exceptions__intArrayMethod);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Exceptions__throwNullPointerException = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Exceptions__throwNullPointerException(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_Exceptions, "com/github/dart_lang/jnigen/simple_package/Exceptions");
+ if (_c_Exceptions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Exceptions, &_m_Exceptions__throwNullPointerException,
+ "throwNullPointerException", "()I");
+ if (_m_Exceptions__throwNullPointerException == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(
+ jniEnv, self_, _m_Exceptions__throwNullPointerException);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Exceptions__throwFileNotFoundException = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Exceptions__throwFileNotFoundException(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_Exceptions, "com/github/dart_lang/jnigen/simple_package/Exceptions");
+ if (_c_Exceptions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Exceptions, &_m_Exceptions__throwFileNotFoundException,
+ "throwFileNotFoundException", "()Ljava/io/InputStream;");
+ if (_m_Exceptions__throwFileNotFoundException == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_Exceptions__throwFileNotFoundException);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Exceptions__throwClassCastException = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Exceptions__throwClassCastException(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_Exceptions, "com/github/dart_lang/jnigen/simple_package/Exceptions");
+ if (_c_Exceptions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Exceptions, &_m_Exceptions__throwClassCastException,
+ "throwClassCastException", "()Ljava/io/FileInputStream;");
+ if (_m_Exceptions__throwClassCastException == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_Exceptions__throwClassCastException);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Exceptions__throwArrayIndexException = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Exceptions__throwArrayIndexException(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_Exceptions, "com/github/dart_lang/jnigen/simple_package/Exceptions");
+ if (_c_Exceptions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Exceptions, &_m_Exceptions__throwArrayIndexException,
+ "throwArrayIndexException", "()I");
+ if (_m_Exceptions__throwArrayIndexException == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(
+ jniEnv, self_, _m_Exceptions__throwArrayIndexException);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Exceptions__throwArithmeticException = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Exceptions__throwArithmeticException(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_Exceptions, "com/github/dart_lang/jnigen/simple_package/Exceptions");
+ if (_c_Exceptions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Exceptions, &_m_Exceptions__throwArithmeticException,
+ "throwArithmeticException", "()I");
+ if (_m_Exceptions__throwArithmeticException == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(
+ jniEnv, self_, _m_Exceptions__throwArithmeticException);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+jmethodID _m_Exceptions__throwLoremIpsum = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Exceptions__throwLoremIpsum() {
+ load_env();
+ load_class_global_ref(
+ &_c_Exceptions, "com/github/dart_lang/jnigen/simple_package/Exceptions");
+ if (_c_Exceptions == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_Exceptions, &_m_Exceptions__throwLoremIpsum,
+ "throwLoremIpsum", "()V");
+ if (_m_Exceptions__throwLoremIpsum == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallStaticVoidMethod(jniEnv, _c_Exceptions,
+ _m_Exceptions__throwLoremIpsum);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.simple_package.Fields
+jclass _c_Fields = NULL;
+
+jmethodID _m_Fields__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Fields__new0() {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Fields, &_m_Fields__new0, "<init>", "()V");
+ if (_m_Fields__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_Fields, _m_Fields__new0);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Fields__amount = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Fields__amount() {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Fields, &_f_Fields__amount, "amount", "I");
+ int32_t _result =
+ (*jniEnv)->GetStaticIntField(jniEnv, _c_Fields, _f_Fields__amount);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_Fields__amount(int32_t value) {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Fields, &_f_Fields__amount, "amount", "I");
+ (*jniEnv)->SetStaticIntField(jniEnv, _c_Fields, _f_Fields__amount, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_Fields__pi = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Fields__pi() {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Fields, &_f_Fields__pi, "pi", "D");
+ double _result =
+ (*jniEnv)->GetStaticDoubleField(jniEnv, _c_Fields, _f_Fields__pi);
+ return (JniResult){.value = {.d = _result}, .exception = check_exception()};
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_Fields__pi(double value) {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Fields, &_f_Fields__pi, "pi", "D");
+ (*jniEnv)->SetStaticDoubleField(jniEnv, _c_Fields, _f_Fields__pi, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_Fields__asterisk = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Fields__asterisk() {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Fields, &_f_Fields__asterisk, "asterisk", "C");
+ uint16_t _result =
+ (*jniEnv)->GetStaticCharField(jniEnv, _c_Fields, _f_Fields__asterisk);
+ return (JniResult){.value = {.c = _result}, .exception = check_exception()};
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_Fields__asterisk(uint16_t value) {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Fields, &_f_Fields__asterisk, "asterisk", "C");
+ (*jniEnv)->SetStaticCharField(jniEnv, _c_Fields, _f_Fields__asterisk, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_Fields__name = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Fields__name() {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Fields, &_f_Fields__name, "name", "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetStaticObjectField(jniEnv, _c_Fields, _f_Fields__name);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_Fields__name(jobject value) {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Fields, &_f_Fields__name, "name", "Ljava/lang/String;");
+ (*jniEnv)->SetStaticObjectField(jniEnv, _c_Fields, _f_Fields__name, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_Fields__i = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Fields__i(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_Fields, &_f_Fields__i, "i", "Ljava/lang/Integer;");
+ jobject _result = (*jniEnv)->GetObjectField(jniEnv, self_, _f_Fields__i);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_Fields__i(jobject self_, jobject value) {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_Fields, &_f_Fields__i, "i", "Ljava/lang/Integer;");
+ (*jniEnv)->SetObjectField(jniEnv, self_, _f_Fields__i, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_Fields__trillion = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Fields__trillion(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_Fields, &_f_Fields__trillion, "trillion", "J");
+ int64_t _result = (*jniEnv)->GetLongField(jniEnv, self_, _f_Fields__trillion);
+ return (JniResult){.value = {.j = _result}, .exception = check_exception()};
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_Fields__trillion(jobject self_, int64_t value) {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_Fields, &_f_Fields__trillion, "trillion", "J");
+ (*jniEnv)->SetLongField(jniEnv, self_, _f_Fields__trillion, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_Fields__isAchillesDead = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Fields__isAchillesDead(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_Fields, &_f_Fields__isAchillesDead, "isAchillesDead", "Z");
+ uint8_t _result =
+ (*jniEnv)->GetBooleanField(jniEnv, self_, _f_Fields__isAchillesDead);
+ return (JniResult){.value = {.z = _result}, .exception = check_exception()};
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_Fields__isAchillesDead(jobject self_, uint8_t value) {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_Fields, &_f_Fields__isAchillesDead, "isAchillesDead", "Z");
+ (*jniEnv)->SetBooleanField(jniEnv, self_, _f_Fields__isAchillesDead, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_Fields__bestFighterInGreece = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Fields__bestFighterInGreece(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_Fields, &_f_Fields__bestFighterInGreece, "bestFighterInGreece",
+ "Ljava/lang/String;");
+ jobject _result =
+ (*jniEnv)->GetObjectField(jniEnv, self_, _f_Fields__bestFighterInGreece);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_Fields__bestFighterInGreece(jobject self_, jobject value) {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_Fields, &_f_Fields__bestFighterInGreece, "bestFighterInGreece",
+ "Ljava/lang/String;");
+ (*jniEnv)->SetObjectField(jniEnv, self_, _f_Fields__bestFighterInGreece,
+ value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_Fields__random = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Fields__random(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_Fields, &_f_Fields__random, "random", "Ljava/util/Random;");
+ jobject _result = (*jniEnv)->GetObjectField(jniEnv, self_, _f_Fields__random);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_Fields__random(jobject self_, jobject value) {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_Fields, &_f_Fields__random, "random", "Ljava/util/Random;");
+ (*jniEnv)->SetObjectField(jniEnv, self_, _f_Fields__random, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_Fields__euroSymbol = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Fields__euroSymbol() {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Fields, &_f_Fields__euroSymbol, "euroSymbol", "C");
+ uint16_t _result =
+ (*jniEnv)->GetStaticCharField(jniEnv, _c_Fields, _f_Fields__euroSymbol);
+ return (JniResult){.value = {.c = _result}, .exception = check_exception()};
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_Fields__euroSymbol(uint16_t value) {
+ load_env();
+ load_class_global_ref(&_c_Fields,
+ "com/github/dart_lang/jnigen/simple_package/Fields");
+ if (_c_Fields == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Fields, &_f_Fields__euroSymbol, "euroSymbol", "C");
+ (*jniEnv)->SetStaticCharField(jniEnv, _c_Fields, _f_Fields__euroSymbol,
+ value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.simple_package.Fields$Nested
+jclass _c_Fields_Nested = NULL;
+
+jmethodID _m_Fields_Nested__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Fields_Nested__new0() {
+ load_env();
+ load_class_global_ref(
+ &_c_Fields_Nested,
+ "com/github/dart_lang/jnigen/simple_package/Fields$Nested");
+ if (_c_Fields_Nested == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Fields_Nested, &_m_Fields_Nested__new0, "<init>", "()V");
+ if (_m_Fields_Nested__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_Fields_Nested, _m_Fields_Nested__new0);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_Fields_Nested__hundred = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Fields_Nested__hundred(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_Fields_Nested,
+ "com/github/dart_lang/jnigen/simple_package/Fields$Nested");
+ if (_c_Fields_Nested == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_Fields_Nested, &_f_Fields_Nested__hundred, "hundred", "J");
+ int64_t _result =
+ (*jniEnv)->GetLongField(jniEnv, self_, _f_Fields_Nested__hundred);
+ return (JniResult){.value = {.j = _result}, .exception = check_exception()};
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_Fields_Nested__hundred(jobject self_, int64_t value) {
+ load_env();
+ load_class_global_ref(
+ &_c_Fields_Nested,
+ "com/github/dart_lang/jnigen/simple_package/Fields$Nested");
+ if (_c_Fields_Nested == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_Fields_Nested, &_f_Fields_Nested__hundred, "hundred", "J");
+ (*jniEnv)->SetLongField(jniEnv, self_, _f_Fields_Nested__hundred, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_Fields_Nested__BEST_GOD = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_Fields_Nested__BEST_GOD() {
+ load_env();
+ load_class_global_ref(
+ &_c_Fields_Nested,
+ "com/github/dart_lang/jnigen/simple_package/Fields$Nested");
+ if (_c_Fields_Nested == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Fields_Nested, &_f_Fields_Nested__BEST_GOD, "BEST_GOD",
+ "Ljava/lang/String;");
+ jobject _result = (*jniEnv)->GetStaticObjectField(jniEnv, _c_Fields_Nested,
+ _f_Fields_Nested__BEST_GOD);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_Fields_Nested__BEST_GOD(jobject value) {
+ load_env();
+ load_class_global_ref(
+ &_c_Fields_Nested,
+ "com/github/dart_lang/jnigen/simple_package/Fields$Nested");
+ if (_c_Fields_Nested == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_Fields_Nested, &_f_Fields_Nested__BEST_GOD, "BEST_GOD",
+ "Ljava/lang/String;");
+ (*jniEnv)->SetStaticObjectField(jniEnv, _c_Fields_Nested,
+ _f_Fields_Nested__BEST_GOD, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.pkg2.C2
+jclass _c_C2 = NULL;
+
+jmethodID _m_C2__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult C2__new0() {
+ load_env();
+ load_class_global_ref(&_c_C2, "com/github/dart_lang/jnigen/pkg2/C2");
+ if (_c_C2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_C2, &_m_C2__new0, "<init>", "()V");
+ if (_m_C2__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_C2, _m_C2__new0);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_C2__CONSTANT = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_C2__CONSTANT() {
+ load_env();
+ load_class_global_ref(&_c_C2, "com/github/dart_lang/jnigen/pkg2/C2");
+ if (_c_C2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_C2, &_f_C2__CONSTANT, "CONSTANT", "I");
+ int32_t _result =
+ (*jniEnv)->GetStaticIntField(jniEnv, _c_C2, _f_C2__CONSTANT);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_C2__CONSTANT(int32_t value) {
+ load_env();
+ load_class_global_ref(&_c_C2, "com/github/dart_lang/jnigen/pkg2/C2");
+ if (_c_C2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_field(_c_C2, &_f_C2__CONSTANT, "CONSTANT", "I");
+ (*jniEnv)->SetStaticIntField(jniEnv, _c_C2, _f_C2__CONSTANT, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.pkg2.Example
+jclass _c_Example1 = NULL;
+
+jmethodID _m_Example1__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example1__new0() {
+ load_env();
+ load_class_global_ref(&_c_Example1,
+ "com/github/dart_lang/jnigen/pkg2/Example");
+ if (_c_Example1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example1, &_m_Example1__new0, "<init>", "()V");
+ if (_m_Example1__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_Example1, _m_Example1__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_Example1__whichExample = NULL;
+FFI_PLUGIN_EXPORT
+JniResult Example1__whichExample(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_Example1,
+ "com/github/dart_lang/jnigen/pkg2/Example");
+ if (_c_Example1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_Example1, &_m_Example1__whichExample, "whichExample", "()I");
+ if (_m_Example1__whichExample == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result =
+ (*jniEnv)->CallIntMethod(jniEnv, self_, _m_Example1__whichExample);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.generics.GenericTypeParams
+jclass _c_GenericTypeParams = NULL;
+
+jmethodID _m_GenericTypeParams__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult GenericTypeParams__new0() {
+ load_env();
+ load_class_global_ref(
+ &_c_GenericTypeParams,
+ "com/github/dart_lang/jnigen/generics/GenericTypeParams");
+ if (_c_GenericTypeParams == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_GenericTypeParams, &_m_GenericTypeParams__new0, "<init>",
+ "()V");
+ if (_m_GenericTypeParams__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_GenericTypeParams,
+ _m_GenericTypeParams__new0);
+ return to_global_ref_result(_result);
+}
+
+// com.github.dart_lang.jnigen.generics.GrandParent
+jclass _c_GrandParent = NULL;
+
+jmethodID _m_GrandParent__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult GrandParent__new0(jobject value) {
+ load_env();
+ load_class_global_ref(&_c_GrandParent,
+ "com/github/dart_lang/jnigen/generics/GrandParent");
+ if (_c_GrandParent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_GrandParent, &_m_GrandParent__new0, "<init>",
+ "(Ljava/lang/Object;)V");
+ if (_m_GrandParent__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_GrandParent, _m_GrandParent__new0, value);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_GrandParent__stringParent = NULL;
+FFI_PLUGIN_EXPORT
+JniResult GrandParent__stringParent(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_GrandParent,
+ "com/github/dart_lang/jnigen/generics/GrandParent");
+ if (_c_GrandParent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_GrandParent, &_m_GrandParent__stringParent, "stringParent",
+ "()Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent;");
+ if (_m_GrandParent__stringParent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_GrandParent__stringParent);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_GrandParent__varParent = NULL;
+FFI_PLUGIN_EXPORT
+JniResult GrandParent__varParent(jobject self_, jobject nestedValue) {
+ load_env();
+ load_class_global_ref(&_c_GrandParent,
+ "com/github/dart_lang/jnigen/generics/GrandParent");
+ if (_c_GrandParent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_GrandParent, &_m_GrandParent__varParent, "varParent",
+ "(Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/"
+ "GrandParent$Parent;");
+ if (_m_GrandParent__varParent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_GrandParent__varParent, nestedValue);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_GrandParent__stringStaticParent = NULL;
+FFI_PLUGIN_EXPORT
+JniResult GrandParent__stringStaticParent() {
+ load_env();
+ load_class_global_ref(&_c_GrandParent,
+ "com/github/dart_lang/jnigen/generics/GrandParent");
+ if (_c_GrandParent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_GrandParent, &_m_GrandParent__stringStaticParent, "stringStaticParent",
+ "()Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;");
+ if (_m_GrandParent__stringStaticParent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_GrandParent, _m_GrandParent__stringStaticParent);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_GrandParent__varStaticParent = NULL;
+FFI_PLUGIN_EXPORT
+JniResult GrandParent__varStaticParent(jobject value) {
+ load_env();
+ load_class_global_ref(&_c_GrandParent,
+ "com/github/dart_lang/jnigen/generics/GrandParent");
+ if (_c_GrandParent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_GrandParent, &_m_GrandParent__varStaticParent,
+ "varStaticParent",
+ "(Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/"
+ "generics/GrandParent$StaticParent;");
+ if (_m_GrandParent__varStaticParent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_GrandParent, _m_GrandParent__varStaticParent, value);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_GrandParent__staticParentWithSameType = NULL;
+FFI_PLUGIN_EXPORT
+JniResult GrandParent__staticParentWithSameType(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_GrandParent,
+ "com/github/dart_lang/jnigen/generics/GrandParent");
+ if (_c_GrandParent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_GrandParent, &_m_GrandParent__staticParentWithSameType,
+ "staticParentWithSameType",
+ "()Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;");
+ if (_m_GrandParent__staticParentWithSameType == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_GrandParent__staticParentWithSameType);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_GrandParent__value = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_GrandParent__value(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_GrandParent,
+ "com/github/dart_lang/jnigen/generics/GrandParent");
+ if (_c_GrandParent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent, &_f_GrandParent__value, "value",
+ "Ljava/lang/Object;");
+ jobject _result =
+ (*jniEnv)->GetObjectField(jniEnv, self_, _f_GrandParent__value);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_GrandParent__value(jobject self_, jobject value) {
+ load_env();
+ load_class_global_ref(&_c_GrandParent,
+ "com/github/dart_lang/jnigen/generics/GrandParent");
+ if (_c_GrandParent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent, &_f_GrandParent__value, "value",
+ "Ljava/lang/Object;");
+ (*jniEnv)->SetObjectField(jniEnv, self_, _f_GrandParent__value, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.generics.GrandParent$Parent
+jclass _c_GrandParent_Parent = NULL;
+
+jmethodID _m_GrandParent_Parent__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult GrandParent_Parent__new0(jobject _parent, jobject newValue) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_Parent,
+ "com/github/dart_lang/jnigen/generics/GrandParent$Parent");
+ if (_c_GrandParent_Parent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_GrandParent_Parent, &_m_GrandParent_Parent__new0, "<init>",
+ "(Lcom/github/dart_lang/jnigen/generics/GrandParent;Ljava/lang/"
+ "Object;)V");
+ if (_m_GrandParent_Parent__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_GrandParent_Parent,
+ _m_GrandParent_Parent__new0, _parent, newValue);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_GrandParent_Parent__parentValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_GrandParent_Parent__parentValue(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_Parent,
+ "com/github/dart_lang/jnigen/generics/GrandParent$Parent");
+ if (_c_GrandParent_Parent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent_Parent, &_f_GrandParent_Parent__parentValue,
+ "parentValue", "Ljava/lang/Object;");
+ jobject _result = (*jniEnv)->GetObjectField(
+ jniEnv, self_, _f_GrandParent_Parent__parentValue);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_GrandParent_Parent__parentValue(jobject self_, jobject value) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_Parent,
+ "com/github/dart_lang/jnigen/generics/GrandParent$Parent");
+ if (_c_GrandParent_Parent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent_Parent, &_f_GrandParent_Parent__parentValue,
+ "parentValue", "Ljava/lang/Object;");
+ (*jniEnv)->SetObjectField(jniEnv, self_, _f_GrandParent_Parent__parentValue,
+ value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_GrandParent_Parent__value = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_GrandParent_Parent__value(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_Parent,
+ "com/github/dart_lang/jnigen/generics/GrandParent$Parent");
+ if (_c_GrandParent_Parent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent_Parent, &_f_GrandParent_Parent__value, "value",
+ "Ljava/lang/Object;");
+ jobject _result =
+ (*jniEnv)->GetObjectField(jniEnv, self_, _f_GrandParent_Parent__value);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_GrandParent_Parent__value(jobject self_, jobject value) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_Parent,
+ "com/github/dart_lang/jnigen/generics/GrandParent$Parent");
+ if (_c_GrandParent_Parent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent_Parent, &_f_GrandParent_Parent__value, "value",
+ "Ljava/lang/Object;");
+ (*jniEnv)->SetObjectField(jniEnv, self_, _f_GrandParent_Parent__value, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.generics.GrandParent$Parent$Child
+jclass _c_GrandParent_Parent_Child = NULL;
+
+jmethodID _m_GrandParent_Parent_Child__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult GrandParent_Parent_Child__new0(jobject _parent, jobject newValue) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_Parent_Child,
+ "com/github/dart_lang/jnigen/generics/GrandParent$Parent$Child");
+ if (_c_GrandParent_Parent_Child == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_GrandParent_Parent_Child, &_m_GrandParent_Parent_Child__new0,
+ "<init>",
+ "(Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent;Ljava/"
+ "lang/Object;)V");
+ if (_m_GrandParent_Parent_Child__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_GrandParent_Parent_Child,
+ _m_GrandParent_Parent_Child__new0,
+ _parent, newValue);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_GrandParent_Parent_Child__grandParentValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_GrandParent_Parent_Child__grandParentValue(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_Parent_Child,
+ "com/github/dart_lang/jnigen/generics/GrandParent$Parent$Child");
+ if (_c_GrandParent_Parent_Child == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent_Parent_Child,
+ &_f_GrandParent_Parent_Child__grandParentValue, "grandParentValue",
+ "Ljava/lang/Object;");
+ jobject _result = (*jniEnv)->GetObjectField(
+ jniEnv, self_, _f_GrandParent_Parent_Child__grandParentValue);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_GrandParent_Parent_Child__grandParentValue(jobject self_,
+ jobject value) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_Parent_Child,
+ "com/github/dart_lang/jnigen/generics/GrandParent$Parent$Child");
+ if (_c_GrandParent_Parent_Child == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent_Parent_Child,
+ &_f_GrandParent_Parent_Child__grandParentValue, "grandParentValue",
+ "Ljava/lang/Object;");
+ (*jniEnv)->SetObjectField(
+ jniEnv, self_, _f_GrandParent_Parent_Child__grandParentValue, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_GrandParent_Parent_Child__parentValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_GrandParent_Parent_Child__parentValue(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_Parent_Child,
+ "com/github/dart_lang/jnigen/generics/GrandParent$Parent$Child");
+ if (_c_GrandParent_Parent_Child == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent_Parent_Child,
+ &_f_GrandParent_Parent_Child__parentValue, "parentValue",
+ "Ljava/lang/Object;");
+ jobject _result = (*jniEnv)->GetObjectField(
+ jniEnv, self_, _f_GrandParent_Parent_Child__parentValue);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_GrandParent_Parent_Child__parentValue(jobject self_,
+ jobject value) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_Parent_Child,
+ "com/github/dart_lang/jnigen/generics/GrandParent$Parent$Child");
+ if (_c_GrandParent_Parent_Child == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent_Parent_Child,
+ &_f_GrandParent_Parent_Child__parentValue, "parentValue",
+ "Ljava/lang/Object;");
+ (*jniEnv)->SetObjectField(jniEnv, self_,
+ _f_GrandParent_Parent_Child__parentValue, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_GrandParent_Parent_Child__value = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_GrandParent_Parent_Child__value(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_Parent_Child,
+ "com/github/dart_lang/jnigen/generics/GrandParent$Parent$Child");
+ if (_c_GrandParent_Parent_Child == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent_Parent_Child, &_f_GrandParent_Parent_Child__value,
+ "value", "Ljava/lang/Object;");
+ jobject _result = (*jniEnv)->GetObjectField(
+ jniEnv, self_, _f_GrandParent_Parent_Child__value);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_GrandParent_Parent_Child__value(jobject self_, jobject value) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_Parent_Child,
+ "com/github/dart_lang/jnigen/generics/GrandParent$Parent$Child");
+ if (_c_GrandParent_Parent_Child == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent_Parent_Child, &_f_GrandParent_Parent_Child__value,
+ "value", "Ljava/lang/Object;");
+ (*jniEnv)->SetObjectField(jniEnv, self_, _f_GrandParent_Parent_Child__value,
+ value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.generics.GrandParent$StaticParent
+jclass _c_GrandParent_StaticParent = NULL;
+
+jmethodID _m_GrandParent_StaticParent__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult GrandParent_StaticParent__new0(jobject value) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_StaticParent,
+ "com/github/dart_lang/jnigen/generics/GrandParent$StaticParent");
+ if (_c_GrandParent_StaticParent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_GrandParent_StaticParent, &_m_GrandParent_StaticParent__new0,
+ "<init>", "(Ljava/lang/Object;)V");
+ if (_m_GrandParent_StaticParent__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_GrandParent_StaticParent,
+ _m_GrandParent_StaticParent__new0, value);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_GrandParent_StaticParent__value = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_GrandParent_StaticParent__value(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_StaticParent,
+ "com/github/dart_lang/jnigen/generics/GrandParent$StaticParent");
+ if (_c_GrandParent_StaticParent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent_StaticParent, &_f_GrandParent_StaticParent__value,
+ "value", "Ljava/lang/Object;");
+ jobject _result = (*jniEnv)->GetObjectField(
+ jniEnv, self_, _f_GrandParent_StaticParent__value);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_GrandParent_StaticParent__value(jobject self_, jobject value) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_StaticParent,
+ "com/github/dart_lang/jnigen/generics/GrandParent$StaticParent");
+ if (_c_GrandParent_StaticParent == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent_StaticParent, &_f_GrandParent_StaticParent__value,
+ "value", "Ljava/lang/Object;");
+ (*jniEnv)->SetObjectField(jniEnv, self_, _f_GrandParent_StaticParent__value,
+ value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.generics.GrandParent$StaticParent$Child
+jclass _c_GrandParent_StaticParent_Child = NULL;
+
+jmethodID _m_GrandParent_StaticParent_Child__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult GrandParent_StaticParent_Child__new0(jobject _parent,
+ jobject parentValue,
+ jobject value) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_StaticParent_Child,
+ "com/github/dart_lang/jnigen/generics/GrandParent$StaticParent$Child");
+ if (_c_GrandParent_StaticParent_Child == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(
+ _c_GrandParent_StaticParent_Child,
+ &_m_GrandParent_StaticParent_Child__new0, "<init>",
+ "(Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;Ljava/"
+ "lang/Object;Ljava/lang/Object;)V");
+ if (_m_GrandParent_StaticParent_Child__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(
+ jniEnv, _c_GrandParent_StaticParent_Child,
+ _m_GrandParent_StaticParent_Child__new0, _parent, parentValue, value);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_GrandParent_StaticParent_Child__parentValue = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_GrandParent_StaticParent_Child__parentValue(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_StaticParent_Child,
+ "com/github/dart_lang/jnigen/generics/GrandParent$StaticParent$Child");
+ if (_c_GrandParent_StaticParent_Child == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent_StaticParent_Child,
+ &_f_GrandParent_StaticParent_Child__parentValue, "parentValue",
+ "Ljava/lang/Object;");
+ jobject _result = (*jniEnv)->GetObjectField(
+ jniEnv, self_, _f_GrandParent_StaticParent_Child__parentValue);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_GrandParent_StaticParent_Child__parentValue(jobject self_,
+ jobject value) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_StaticParent_Child,
+ "com/github/dart_lang/jnigen/generics/GrandParent$StaticParent$Child");
+ if (_c_GrandParent_StaticParent_Child == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent_StaticParent_Child,
+ &_f_GrandParent_StaticParent_Child__parentValue, "parentValue",
+ "Ljava/lang/Object;");
+ (*jniEnv)->SetObjectField(
+ jniEnv, self_, _f_GrandParent_StaticParent_Child__parentValue, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_GrandParent_StaticParent_Child__value = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_GrandParent_StaticParent_Child__value(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_StaticParent_Child,
+ "com/github/dart_lang/jnigen/generics/GrandParent$StaticParent$Child");
+ if (_c_GrandParent_StaticParent_Child == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent_StaticParent_Child,
+ &_f_GrandParent_StaticParent_Child__value, "value",
+ "Ljava/lang/Object;");
+ jobject _result = (*jniEnv)->GetObjectField(
+ jniEnv, self_, _f_GrandParent_StaticParent_Child__value);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_GrandParent_StaticParent_Child__value(jobject self_,
+ jobject value) {
+ load_env();
+ load_class_global_ref(
+ &_c_GrandParent_StaticParent_Child,
+ "com/github/dart_lang/jnigen/generics/GrandParent$StaticParent$Child");
+ if (_c_GrandParent_StaticParent_Child == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_GrandParent_StaticParent_Child,
+ &_f_GrandParent_StaticParent_Child__value, "value",
+ "Ljava/lang/Object;");
+ (*jniEnv)->SetObjectField(jniEnv, self_,
+ _f_GrandParent_StaticParent_Child__value, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.generics.MyMap
+jclass _c_MyMap = NULL;
+
+jmethodID _m_MyMap__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyMap__new0() {
+ load_env();
+ load_class_global_ref(&_c_MyMap,
+ "com/github/dart_lang/jnigen/generics/MyMap");
+ if (_c_MyMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyMap, &_m_MyMap__new0, "<init>", "()V");
+ if (_m_MyMap__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_MyMap, _m_MyMap__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_MyMap__get0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyMap__get0(jobject self_, jobject key) {
+ load_env();
+ load_class_global_ref(&_c_MyMap,
+ "com/github/dart_lang/jnigen/generics/MyMap");
+ if (_c_MyMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyMap, &_m_MyMap__get0, "get",
+ "(Ljava/lang/Object;)Ljava/lang/Object;");
+ if (_m_MyMap__get0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_MyMap__get0, key);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_MyMap__put = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyMap__put(jobject self_, jobject key, jobject value) {
+ load_env();
+ load_class_global_ref(&_c_MyMap,
+ "com/github/dart_lang/jnigen/generics/MyMap");
+ if (_c_MyMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyMap, &_m_MyMap__put, "put",
+ "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+ if (_m_MyMap__put == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_MyMap__put, key, value);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_MyMap__entryStack = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyMap__entryStack(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_MyMap,
+ "com/github/dart_lang/jnigen/generics/MyMap");
+ if (_c_MyMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyMap, &_m_MyMap__entryStack, "entryStack",
+ "()Lcom/github/dart_lang/jnigen/generics/MyStack;");
+ if (_m_MyMap__entryStack == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_MyMap__entryStack);
+ return to_global_ref_result(_result);
+}
+
+// com.github.dart_lang.jnigen.generics.MyMap$MyEntry
+jclass _c_MyMap_MyEntry = NULL;
+
+jmethodID _m_MyMap_MyEntry__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyMap_MyEntry__new0(jobject _parent, jobject key, jobject value) {
+ load_env();
+ load_class_global_ref(&_c_MyMap_MyEntry,
+ "com/github/dart_lang/jnigen/generics/MyMap$MyEntry");
+ if (_c_MyMap_MyEntry == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyMap_MyEntry, &_m_MyMap_MyEntry__new0, "<init>",
+ "(Lcom/github/dart_lang/jnigen/generics/MyMap;Ljava/lang/"
+ "Object;Ljava/lang/Object;)V");
+ if (_m_MyMap_MyEntry__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(
+ jniEnv, _c_MyMap_MyEntry, _m_MyMap_MyEntry__new0, _parent, key, value);
+ return to_global_ref_result(_result);
+}
+
+jfieldID _f_MyMap_MyEntry__key = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_MyMap_MyEntry__key(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_MyMap_MyEntry,
+ "com/github/dart_lang/jnigen/generics/MyMap$MyEntry");
+ if (_c_MyMap_MyEntry == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_MyMap_MyEntry, &_f_MyMap_MyEntry__key, "key",
+ "Ljava/lang/Object;");
+ jobject _result =
+ (*jniEnv)->GetObjectField(jniEnv, self_, _f_MyMap_MyEntry__key);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_MyMap_MyEntry__key(jobject self_, jobject value) {
+ load_env();
+ load_class_global_ref(&_c_MyMap_MyEntry,
+ "com/github/dart_lang/jnigen/generics/MyMap$MyEntry");
+ if (_c_MyMap_MyEntry == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_MyMap_MyEntry, &_f_MyMap_MyEntry__key, "key",
+ "Ljava/lang/Object;");
+ (*jniEnv)->SetObjectField(jniEnv, self_, _f_MyMap_MyEntry__key, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_MyMap_MyEntry__value = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_MyMap_MyEntry__value(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_MyMap_MyEntry,
+ "com/github/dart_lang/jnigen/generics/MyMap$MyEntry");
+ if (_c_MyMap_MyEntry == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_MyMap_MyEntry, &_f_MyMap_MyEntry__value, "value",
+ "Ljava/lang/Object;");
+ jobject _result =
+ (*jniEnv)->GetObjectField(jniEnv, self_, _f_MyMap_MyEntry__value);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_MyMap_MyEntry__value(jobject self_, jobject value) {
+ load_env();
+ load_class_global_ref(&_c_MyMap_MyEntry,
+ "com/github/dart_lang/jnigen/generics/MyMap$MyEntry");
+ if (_c_MyMap_MyEntry == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_MyMap_MyEntry, &_f_MyMap_MyEntry__value, "value",
+ "Ljava/lang/Object;");
+ (*jniEnv)->SetObjectField(jniEnv, self_, _f_MyMap_MyEntry__value, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.generics.MyStack
+jclass _c_MyStack = NULL;
+
+jmethodID _m_MyStack__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyStack__new0() {
+ load_env();
+ load_class_global_ref(&_c_MyStack,
+ "com/github/dart_lang/jnigen/generics/MyStack");
+ if (_c_MyStack == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyStack, &_m_MyStack__new0, "<init>", "()V");
+ if (_m_MyStack__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_MyStack, _m_MyStack__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_MyStack__fromArray = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyStack__fromArray(jobject arr) {
+ load_env();
+ load_class_global_ref(&_c_MyStack,
+ "com/github/dart_lang/jnigen/generics/MyStack");
+ if (_c_MyStack == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_MyStack, &_m_MyStack__fromArray, "fromArray",
+ "([Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/MyStack;");
+ if (_m_MyStack__fromArray == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_MyStack, _m_MyStack__fromArray, arr);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_MyStack__fromArrayOfArrayOfGrandParents = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyStack__fromArrayOfArrayOfGrandParents(jobject arr) {
+ load_env();
+ load_class_global_ref(&_c_MyStack,
+ "com/github/dart_lang/jnigen/generics/MyStack");
+ if (_c_MyStack == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_MyStack, &_m_MyStack__fromArrayOfArrayOfGrandParents,
+ "fromArrayOfArrayOfGrandParents",
+ "([[Lcom/github/dart_lang/jnigen/generics/GrandParent;)Lcom/github/"
+ "dart_lang/jnigen/generics/MyStack;");
+ if (_m_MyStack__fromArrayOfArrayOfGrandParents == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_MyStack, _m_MyStack__fromArrayOfArrayOfGrandParents, arr);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_MyStack__of = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyStack__of() {
+ load_env();
+ load_class_global_ref(&_c_MyStack,
+ "com/github/dart_lang/jnigen/generics/MyStack");
+ if (_c_MyStack == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_MyStack, &_m_MyStack__of, "of",
+ "()Lcom/github/dart_lang/jnigen/generics/MyStack;");
+ if (_m_MyStack__of == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_MyStack, _m_MyStack__of);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_MyStack__of1 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyStack__of1(jobject obj) {
+ load_env();
+ load_class_global_ref(&_c_MyStack,
+ "com/github/dart_lang/jnigen/generics/MyStack");
+ if (_c_MyStack == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_MyStack, &_m_MyStack__of1, "of",
+ "(Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/MyStack;");
+ if (_m_MyStack__of1 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(jniEnv, _c_MyStack,
+ _m_MyStack__of1, obj);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_MyStack__of2 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyStack__of2(jobject obj, jobject obj2) {
+ load_env();
+ load_class_global_ref(&_c_MyStack,
+ "com/github/dart_lang/jnigen/generics/MyStack");
+ if (_c_MyStack == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_MyStack, &_m_MyStack__of2, "of",
+ "(Ljava/lang/Object;Ljava/lang/Object;)Lcom/github/"
+ "dart_lang/jnigen/generics/MyStack;");
+ if (_m_MyStack__of2 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_MyStack, _m_MyStack__of2, obj, obj2);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_MyStack__push = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyStack__push(jobject self_, jobject item) {
+ load_env();
+ load_class_global_ref(&_c_MyStack,
+ "com/github/dart_lang/jnigen/generics/MyStack");
+ if (_c_MyStack == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyStack, &_m_MyStack__push, "push", "(Ljava/lang/Object;)V");
+ if (_m_MyStack__push == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_MyStack__push, item);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_MyStack__pop = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyStack__pop(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_MyStack,
+ "com/github/dart_lang/jnigen/generics/MyStack");
+ if (_c_MyStack == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyStack, &_m_MyStack__pop, "pop", "()Ljava/lang/Object;");
+ if (_m_MyStack__pop == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_, _m_MyStack__pop);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_MyStack__size = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyStack__size(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_MyStack,
+ "com/github/dart_lang/jnigen/generics/MyStack");
+ if (_c_MyStack == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyStack, &_m_MyStack__size, "size", "()I");
+ if (_m_MyStack__size == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int32_t _result = (*jniEnv)->CallIntMethod(jniEnv, self_, _m_MyStack__size);
+ return (JniResult){.value = {.i = _result}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.generics.StringKeyedMap
+jclass _c_StringKeyedMap = NULL;
+
+jmethodID _m_StringKeyedMap__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult StringKeyedMap__new0() {
+ load_env();
+ load_class_global_ref(&_c_StringKeyedMap,
+ "com/github/dart_lang/jnigen/generics/StringKeyedMap");
+ if (_c_StringKeyedMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_StringKeyedMap, &_m_StringKeyedMap__new0, "<init>", "()V");
+ if (_m_StringKeyedMap__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_StringKeyedMap, _m_StringKeyedMap__new0);
+ return to_global_ref_result(_result);
+}
+
+// com.github.dart_lang.jnigen.generics.StringMap
+jclass _c_StringMap = NULL;
+
+jmethodID _m_StringMap__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult StringMap__new0() {
+ load_env();
+ load_class_global_ref(&_c_StringMap,
+ "com/github/dart_lang/jnigen/generics/StringMap");
+ if (_c_StringMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_StringMap, &_m_StringMap__new0, "<init>", "()V");
+ if (_m_StringMap__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_StringMap, _m_StringMap__new0);
+ return to_global_ref_result(_result);
+}
+
+// com.github.dart_lang.jnigen.generics.StringStack
+jclass _c_StringStack = NULL;
+
+jmethodID _m_StringStack__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult StringStack__new0() {
+ load_env();
+ load_class_global_ref(&_c_StringStack,
+ "com/github/dart_lang/jnigen/generics/StringStack");
+ if (_c_StringStack == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_StringStack, &_m_StringStack__new0, "<init>", "()V");
+ if (_m_StringStack__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_StringStack, _m_StringStack__new0);
+ return to_global_ref_result(_result);
+}
+
+// com.github.dart_lang.jnigen.generics.StringValuedMap
+jclass _c_StringValuedMap = NULL;
+
+jmethodID _m_StringValuedMap__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult StringValuedMap__new0() {
+ load_env();
+ load_class_global_ref(&_c_StringValuedMap,
+ "com/github/dart_lang/jnigen/generics/StringValuedMap");
+ if (_c_StringValuedMap == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_StringValuedMap, &_m_StringValuedMap__new0, "<init>", "()V");
+ if (_m_StringValuedMap__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_StringValuedMap,
+ _m_StringValuedMap__new0);
+ return to_global_ref_result(_result);
+}
+
+// com.github.dart_lang.jnigen.interfaces.MyInterface
+jclass _c_MyInterface = NULL;
+
+jmethodID _m_MyInterface__voidCallback = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyInterface__voidCallback(jobject self_, jobject s) {
+ load_env();
+ load_class_global_ref(&_c_MyInterface,
+ "com/github/dart_lang/jnigen/interfaces/MyInterface");
+ if (_c_MyInterface == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyInterface, &_m_MyInterface__voidCallback, "voidCallback",
+ "(Ljava/lang/String;)V");
+ if (_m_MyInterface__voidCallback == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_MyInterface__voidCallback, s);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_MyInterface__stringCallback = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyInterface__stringCallback(jobject self_, jobject s) {
+ load_env();
+ load_class_global_ref(&_c_MyInterface,
+ "com/github/dart_lang/jnigen/interfaces/MyInterface");
+ if (_c_MyInterface == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyInterface, &_m_MyInterface__stringCallback, "stringCallback",
+ "(Ljava/lang/String;)Ljava/lang/String;");
+ if (_m_MyInterface__stringCallback == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(
+ jniEnv, self_, _m_MyInterface__stringCallback, s);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_MyInterface__varCallback = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyInterface__varCallback(jobject self_, jobject t) {
+ load_env();
+ load_class_global_ref(&_c_MyInterface,
+ "com/github/dart_lang/jnigen/interfaces/MyInterface");
+ if (_c_MyInterface == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyInterface, &_m_MyInterface__varCallback, "varCallback",
+ "(Ljava/lang/Object;)Ljava/lang/Object;");
+ if (_m_MyInterface__varCallback == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallObjectMethod(jniEnv, self_,
+ _m_MyInterface__varCallback, t);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_MyInterface__manyPrimitives = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyInterface__manyPrimitives(jobject self_,
+ int32_t a,
+ uint8_t b,
+ uint16_t c,
+ double d) {
+ load_env();
+ load_class_global_ref(&_c_MyInterface,
+ "com/github/dart_lang/jnigen/interfaces/MyInterface");
+ if (_c_MyInterface == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyInterface, &_m_MyInterface__manyPrimitives, "manyPrimitives",
+ "(IZCD)J");
+ if (_m_MyInterface__manyPrimitives == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ int64_t _result = (*jniEnv)->CallLongMethod(
+ jniEnv, self_, _m_MyInterface__manyPrimitives, a, b, c, d);
+ return (JniResult){.value = {.j = _result}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.interfaces.MyInterfaceConsumer
+jclass _c_MyInterfaceConsumer = NULL;
+
+jmethodID _m_MyInterfaceConsumer__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyInterfaceConsumer__new0() {
+ load_env();
+ load_class_global_ref(
+ &_c_MyInterfaceConsumer,
+ "com/github/dart_lang/jnigen/interfaces/MyInterfaceConsumer");
+ if (_c_MyInterfaceConsumer == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyInterfaceConsumer, &_m_MyInterfaceConsumer__new0, "<init>",
+ "()V");
+ if (_m_MyInterfaceConsumer__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_MyInterfaceConsumer,
+ _m_MyInterfaceConsumer__new0);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_MyInterfaceConsumer__consumeOnAnotherThread = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyInterfaceConsumer__consumeOnAnotherThread(jobject myInterface,
+ jobject s,
+ int32_t a,
+ uint8_t b,
+ uint16_t c,
+ double d,
+ jobject t) {
+ load_env();
+ load_class_global_ref(
+ &_c_MyInterfaceConsumer,
+ "com/github/dart_lang/jnigen/interfaces/MyInterfaceConsumer");
+ if (_c_MyInterfaceConsumer == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_MyInterfaceConsumer,
+ &_m_MyInterfaceConsumer__consumeOnAnotherThread,
+ "consumeOnAnotherThread",
+ "(Lcom/github/dart_lang/jnigen/interfaces/"
+ "MyInterface;Ljava/lang/String;IZCDLjava/lang/Object;)V");
+ if (_m_MyInterfaceConsumer__consumeOnAnotherThread == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallStaticVoidMethod(
+ jniEnv, _c_MyInterfaceConsumer,
+ _m_MyInterfaceConsumer__consumeOnAnotherThread, myInterface, s, a, b, c,
+ d, t);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_MyInterfaceConsumer__consumeOnSameThread = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyInterfaceConsumer__consumeOnSameThread(jobject myInterface,
+ jobject s,
+ int32_t a,
+ uint8_t b,
+ uint16_t c,
+ double d,
+ jobject t) {
+ load_env();
+ load_class_global_ref(
+ &_c_MyInterfaceConsumer,
+ "com/github/dart_lang/jnigen/interfaces/MyInterfaceConsumer");
+ if (_c_MyInterfaceConsumer == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_MyInterfaceConsumer,
+ &_m_MyInterfaceConsumer__consumeOnSameThread,
+ "consumeOnSameThread",
+ "(Lcom/github/dart_lang/jnigen/interfaces/"
+ "MyInterface;Ljava/lang/String;IZCDLjava/lang/Object;)V");
+ if (_m_MyInterfaceConsumer__consumeOnSameThread == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallStaticVoidMethod(jniEnv, _c_MyInterfaceConsumer,
+ _m_MyInterfaceConsumer__consumeOnSameThread,
+ myInterface, s, a, b, c, d, t);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.interfaces.MyRunnable
+jclass _c_MyRunnable = NULL;
+
+jmethodID _m_MyRunnable__run = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyRunnable__run(jobject self_) {
+ load_env();
+ load_class_global_ref(&_c_MyRunnable,
+ "com/github/dart_lang/jnigen/interfaces/MyRunnable");
+ if (_c_MyRunnable == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyRunnable, &_m_MyRunnable__run, "run", "()V");
+ if (_m_MyRunnable__run == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_, _m_MyRunnable__run);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.interfaces.MyRunnableRunner
+jclass _c_MyRunnableRunner = NULL;
+
+jmethodID _m_MyRunnableRunner__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyRunnableRunner__new0(jobject runnable) {
+ load_env();
+ load_class_global_ref(
+ &_c_MyRunnableRunner,
+ "com/github/dart_lang/jnigen/interfaces/MyRunnableRunner");
+ if (_c_MyRunnableRunner == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyRunnableRunner, &_m_MyRunnableRunner__new0, "<init>",
+ "(Lcom/github/dart_lang/jnigen/interfaces/MyRunnable;)V");
+ if (_m_MyRunnableRunner__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->NewObject(jniEnv, _c_MyRunnableRunner,
+ _m_MyRunnableRunner__new0, runnable);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_MyRunnableRunner__runOnSameThread = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyRunnableRunner__runOnSameThread(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_MyRunnableRunner,
+ "com/github/dart_lang/jnigen/interfaces/MyRunnableRunner");
+ if (_c_MyRunnableRunner == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyRunnableRunner, &_m_MyRunnableRunner__runOnSameThread,
+ "runOnSameThread", "()V");
+ if (_m_MyRunnableRunner__runOnSameThread == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_MyRunnableRunner__runOnSameThread);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jmethodID _m_MyRunnableRunner__runOnAnotherThread = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyRunnableRunner__runOnAnotherThread(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_MyRunnableRunner,
+ "com/github/dart_lang/jnigen/interfaces/MyRunnableRunner");
+ if (_c_MyRunnableRunner == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyRunnableRunner, &_m_MyRunnableRunner__runOnAnotherThread,
+ "runOnAnotherThread", "()V");
+ if (_m_MyRunnableRunner__runOnAnotherThread == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ (*jniEnv)->CallVoidMethod(jniEnv, self_,
+ _m_MyRunnableRunner__runOnAnotherThread);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+jfieldID _f_MyRunnableRunner__error = NULL;
+FFI_PLUGIN_EXPORT
+JniResult get_MyRunnableRunner__error(jobject self_) {
+ load_env();
+ load_class_global_ref(
+ &_c_MyRunnableRunner,
+ "com/github/dart_lang/jnigen/interfaces/MyRunnableRunner");
+ if (_c_MyRunnableRunner == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_MyRunnableRunner, &_f_MyRunnableRunner__error, "error",
+ "Ljava/lang/Throwable;");
+ jobject _result =
+ (*jniEnv)->GetObjectField(jniEnv, self_, _f_MyRunnableRunner__error);
+ return to_global_ref_result(_result);
+}
+
+FFI_PLUGIN_EXPORT
+JniResult set_MyRunnableRunner__error(jobject self_, jobject value) {
+ load_env();
+ load_class_global_ref(
+ &_c_MyRunnableRunner,
+ "com/github/dart_lang/jnigen/interfaces/MyRunnableRunner");
+ if (_c_MyRunnableRunner == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_field(_c_MyRunnableRunner, &_f_MyRunnableRunner__error, "error",
+ "Ljava/lang/Throwable;");
+ (*jniEnv)->SetObjectField(jniEnv, self_, _f_MyRunnableRunner__error, value);
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+}
+
+// com.github.dart_lang.jnigen.annotations.JsonSerializable$Case
+jclass _c_JsonSerializable_Case = NULL;
+
+jmethodID _m_JsonSerializable_Case__values = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonSerializable_Case__values() {
+ load_env();
+ load_class_global_ref(
+ &_c_JsonSerializable_Case,
+ "com/github/dart_lang/jnigen/annotations/JsonSerializable$Case");
+ if (_c_JsonSerializable_Case == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(
+ _c_JsonSerializable_Case, &_m_JsonSerializable_Case__values, "values",
+ "()[Lcom/github/dart_lang/jnigen/annotations/JsonSerializable$Case;");
+ if (_m_JsonSerializable_Case__values == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_JsonSerializable_Case, _m_JsonSerializable_Case__values);
+ return to_global_ref_result(_result);
+}
+
+jmethodID _m_JsonSerializable_Case__valueOf = NULL;
+FFI_PLUGIN_EXPORT
+JniResult JsonSerializable_Case__valueOf(jobject name) {
+ load_env();
+ load_class_global_ref(
+ &_c_JsonSerializable_Case,
+ "com/github/dart_lang/jnigen/annotations/JsonSerializable$Case");
+ if (_c_JsonSerializable_Case == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_static_method(_c_JsonSerializable_Case,
+ &_m_JsonSerializable_Case__valueOf, "valueOf",
+ "(Ljava/lang/String;)Lcom/github/dart_lang/jnigen/"
+ "annotations/JsonSerializable$Case;");
+ if (_m_JsonSerializable_Case__valueOf == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result = (*jniEnv)->CallStaticObjectMethod(
+ jniEnv, _c_JsonSerializable_Case, _m_JsonSerializable_Case__valueOf,
+ name);
+ return to_global_ref_result(_result);
+}
+
+// com.github.dart_lang.jnigen.annotations.MyDataClass
+jclass _c_MyDataClass = NULL;
+
+jmethodID _m_MyDataClass__new0 = NULL;
+FFI_PLUGIN_EXPORT
+JniResult MyDataClass__new0() {
+ load_env();
+ load_class_global_ref(&_c_MyDataClass,
+ "com/github/dart_lang/jnigen/annotations/MyDataClass");
+ if (_c_MyDataClass == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ load_method(_c_MyDataClass, &_m_MyDataClass__new0, "<init>", "()V");
+ if (_m_MyDataClass__new0 == NULL)
+ return (JniResult){.value = {.j = 0}, .exception = check_exception()};
+ jobject _result =
+ (*jniEnv)->NewObject(jniEnv, _c_MyDataClass, _m_MyDataClass__new0);
+ return to_global_ref_result(_result);
+}
diff --git a/pkgs/jnigen/test/simple_package_test/c_based/dart_bindings/simple_package.dart b/pkgs/jnigen/test/simple_package_test/c_based/dart_bindings/simple_package.dart
new file mode 100644
index 0000000..8149d4e
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/c_based/dart_bindings/simple_package.dart
@@ -0,0 +1,3999 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+// ignore_for_file: annotate_overrides
+// ignore_for_file: camel_case_extensions
+// ignore_for_file: camel_case_types
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: doc_directive_unknown
+// ignore_for_file: file_names
+// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: overridden_fields
+// ignore_for_file: unnecessary_cast
+// ignore_for_file: unused_element
+// ignore_for_file: unused_field
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: unused_shown_name
+
+import "dart:isolate" show ReceivePort;
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+import "package:jni/jni.dart" as jni;
+
+// Auto-generated initialization code.
+
+final ffi.Pointer<T> Function<T extends ffi.NativeType>(String sym) jniLookup =
+ ProtectedJniExtensions.initGeneratedLibrary("simple_package");
+
+/// from: com.github.dart_lang.jnigen.simple_package.Color
+class Color extends jni.JObject {
+ @override
+ late final jni.JObjType<Color> $type = type;
+
+ Color.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $ColorType();
+ static final _values =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("Color__values")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public com.github.dart_lang.jnigen.simple_package.Color[] values()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<Color> values() {
+ return const jni.JArrayType($ColorType()).fromRef(_values().object);
+ }
+
+ static final _valueOf = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("Color__valueOf")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public com.github.dart_lang.jnigen.simple_package.Color valueOf(java.lang.String name)
+ /// The returned object must be released after use, by calling the [release] method.
+ static Color valueOf(
+ jni.JString name,
+ ) {
+ return const $ColorType().fromRef(_valueOf(name.reference).object);
+ }
+}
+
+final class $ColorType extends jni.JObjType<Color> {
+ const $ColorType();
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/simple_package/Color;";
+
+ @override
+ Color fromRef(jni.JObjectPtr ref) => Color.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($ColorType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($ColorType) && other is $ColorType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.simple_package.Example
+class Example extends jni.JObject {
+ @override
+ late final jni.JObjType<Example> $type = type;
+
+ Example.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $ExampleType();
+
+ /// from: static public final int ON
+ static const ON = 1;
+
+ /// from: static public final int OFF
+ static const OFF = 0;
+
+ /// from: static public final double PI
+ static const PI = 3.14159;
+
+ /// from: static public final char SEMICOLON
+ static const SEMICOLON = 59;
+
+ /// from: static public final java.lang.String SEMICOLON_STRING
+ static const SEMICOLON_STRING = r""";""";
+
+ static final _get_unusedRandom =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Example__unusedRandom")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public final java.util.Random unusedRandom
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JObject get unusedRandom =>
+ const jni.JObjectType().fromRef(_get_unusedRandom().object);
+
+ static final _get_protectedField = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_Example__protectedField")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_protectedField = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(jni.JObjectPtr,
+ ffi.Pointer<ffi.Void>)>>("set_Example__protectedField")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected java.util.Random protectedField
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject get protectedField =>
+ const jni.JObjectType().fromRef(_get_protectedField(reference).object);
+
+ /// from: protected java.util.Random protectedField
+ /// The returned object must be released after use, by calling the [release] method.
+ set protectedField(jni.JObject value) =>
+ _set_protectedField(reference, value.reference).check();
+
+ static final _getAmount =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Example__getAmount")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public int getAmount()
+ static int getAmount() {
+ return _getAmount().integer;
+ }
+
+ static final _getPi =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("Example__getPi")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public double getPi()
+ static double getPi() {
+ return _getPi().doubleFloat;
+ }
+
+ static final _getAsterisk =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Example__getAsterisk")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public char getAsterisk()
+ static int getAsterisk() {
+ return _getAsterisk().char;
+ }
+
+ static final _getName =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Example__getName")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public java.lang.String getName()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString getName() {
+ return const jni.JStringType().fromRef(_getName().object);
+ }
+
+ static final _getNestedInstance =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Example__getNestedInstance")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public com.github.dart_lang.jnigen.simple_package.Example.Nested getNestedInstance()
+ /// The returned object must be released after use, by calling the [release] method.
+ static Example_Nested getNestedInstance() {
+ return const $Example_NestedType().fromRef(_getNestedInstance().object);
+ }
+
+ static final _setAmount =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Int32)>>(
+ "Example__setAmount")
+ .asFunction<jni.JniResult Function(int)>();
+
+ /// from: static public void setAmount(int newAmount)
+ static void setAmount(
+ int newAmount,
+ ) {
+ return _setAmount(newAmount).check();
+ }
+
+ static final _setName = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Example__setName")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public void setName(java.lang.String newName)
+ static void setName(
+ jni.JString newName,
+ ) {
+ return _setName(newName.reference).check();
+ }
+
+ static final _setNestedInstance = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Example__setNestedInstance")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public void setNestedInstance(com.github.dart_lang.jnigen.simple_package.Example.Nested newNested)
+ static void setNestedInstance(
+ Example_Nested newNested,
+ ) {
+ return _setNestedInstance(newNested.reference).check();
+ }
+
+ static final _max4 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Int32, ffi.Int32, ffi.Int32, ffi.Int32)>>("Example__max4")
+ .asFunction<jni.JniResult Function(int, int, int, int)>();
+
+ /// from: static public int max4(int a, int b, int c, int d)
+ static int max4(
+ int a,
+ int b,
+ int c,
+ int d,
+ ) {
+ return _max4(a, b, c, d).integer;
+ }
+
+ static final _max8 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Int32, ffi.Int32, ffi.Int32, ffi.Int32,
+ ffi.Int32, ffi.Int32, ffi.Int32, ffi.Int32)>>("Example__max8")
+ .asFunction<
+ jni.JniResult Function(int, int, int, int, int, int, int, int)>();
+
+ /// from: static public int max8(int a, int b, int c, int d, int e, int f, int g, int h)
+ static int max8(
+ int a,
+ int b,
+ int c,
+ int d,
+ int e,
+ int f,
+ int g,
+ int h,
+ ) {
+ return _max8(a, b, c, d, e, f, g, h).integer;
+ }
+
+ static final _getNumber = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Example__getNumber")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int getNumber()
+ int getNumber() {
+ return _getNumber(reference).integer;
+ }
+
+ static final _setNumber = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Int32)>>("Example__setNumber")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public void setNumber(int number)
+ void setNumber(
+ int number,
+ ) {
+ return _setNumber(reference, number).check();
+ }
+
+ static final _getIsUp = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Example__getIsUp")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean getIsUp()
+ bool getIsUp() {
+ return _getIsUp(reference).boolean;
+ }
+
+ static final _setUp = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Uint8)>>("Example__setUp")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public void setUp(boolean isUp)
+ void setUp(
+ bool isUp,
+ ) {
+ return _setUp(reference, isUp ? 1 : 0).check();
+ }
+
+ static final _getCodename = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Example__getCodename")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getCodename()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JString getCodename() {
+ return const jni.JStringType().fromRef(_getCodename(reference).object);
+ }
+
+ static final _setCodename = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("Example__setCodename")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setCodename(java.lang.String codename)
+ void setCodename(
+ jni.JString codename,
+ ) {
+ return _setCodename(reference, codename.reference).check();
+ }
+
+ static final _getRandom = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Example__getRandom")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.util.Random getRandom()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject getRandom() {
+ return const jni.JObjectType().fromRef(_getRandom(reference).object);
+ }
+
+ static final _setRandom = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("Example__setRandom")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void setRandom(java.util.Random random)
+ void setRandom(
+ jni.JObject random,
+ ) {
+ return _setRandom(reference, random.reference).check();
+ }
+
+ static final _getRandomLong = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Example__getRandomLong")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public long getRandomLong()
+ int getRandomLong() {
+ return _getRandomLong(reference).long;
+ }
+
+ static final _add4Longs = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Int64,
+ ffi.Int64, ffi.Int64, ffi.Int64)>>("Example__add4Longs")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, int, int, int, int)>();
+
+ /// from: public long add4Longs(long a, long b, long c, long d)
+ int add4Longs(
+ int a,
+ int b,
+ int c,
+ int d,
+ ) {
+ return _add4Longs(reference, a, b, c, d).long;
+ }
+
+ static final _add8Longs = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Int64,
+ ffi.Int64,
+ ffi.Int64,
+ ffi.Int64,
+ ffi.Int64,
+ ffi.Int64,
+ ffi.Int64,
+ ffi.Int64)>>("Example__add8Longs")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, int, int, int, int, int, int, int, int)>();
+
+ /// from: public long add8Longs(long a, long b, long c, long d, long e, long f, long g, long h)
+ int add8Longs(
+ int a,
+ int b,
+ int c,
+ int d,
+ int e,
+ int f,
+ int g,
+ int h,
+ ) {
+ return _add8Longs(reference, a, b, c, d, e, f, g, h).long;
+ }
+
+ static final _getRandomNumericString = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("Example__getRandomNumericString")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String getRandomNumericString(java.util.Random random)
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JString getRandomNumericString(
+ jni.JObject random,
+ ) {
+ return const jni.JStringType()
+ .fromRef(_getRandomNumericString(reference, random.reference).object);
+ }
+
+ static final _protectedMethod = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("Example__protectedMethod")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: protected void protectedMethod(java.lang.String a, java.lang.String b)
+ void protectedMethod(
+ jni.JString a,
+ jni.JString b,
+ ) {
+ return _protectedMethod(reference, a.reference, b.reference).check();
+ }
+
+ static final _finalMethod = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Example__finalMethod")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public final void finalMethod()
+ void finalMethod() {
+ return _finalMethod(reference).check();
+ }
+
+ static final _getList = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Example__getList")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.util.List<java.lang.String> getList()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JList<jni.JString> getList() {
+ return const jni.JListType(jni.JStringType())
+ .fromRef(_getList(reference).object);
+ }
+
+ static final _joinStrings = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("Example__joinStrings")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String joinStrings(java.util.List<java.lang.String> values, java.lang.String delim)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Joins the strings in the list using the given delimiter.
+ jni.JString joinStrings(
+ jni.JList<jni.JString> values,
+ jni.JString delim,
+ ) {
+ return const jni.JStringType().fromRef(
+ _joinStrings(reference, values.reference, delim.reference).object);
+ }
+
+ static final _methodWithSeveralParams = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Uint16,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("Example__methodWithSeveralParams")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ int,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void methodWithSeveralParams(char ch, java.lang.String s, int[] a, T t, java.util.List<T> lt, java.util.Map<java.lang.String,? extends java.lang.CharSequence> wm)
+ void methodWithSeveralParams<$T extends jni.JObject>(
+ int ch,
+ jni.JString s,
+ jni.JArray<jni.jint> a,
+ $T t,
+ jni.JList<$T> lt,
+ jni.JMap<jni.JString, jni.JObject> wm, {
+ jni.JObjType<$T>? T,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ (lt.$type as jni.JListType).E,
+ t.$type,
+ ]) as jni.JObjType<$T>;
+ return _methodWithSeveralParams(reference, ch, s.reference, a.reference,
+ t.reference, lt.reference, wm.reference)
+ .check();
+ }
+
+ static final _new0 =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("Example__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example() {
+ return Example.fromRef(_new0().object);
+ }
+
+ static final _new1 =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Int32)>>(
+ "Example__new1")
+ .asFunction<jni.JniResult Function(int)>();
+
+ /// from: public void <init>(int number)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example.new1(
+ int number,
+ ) {
+ return Example.fromRef(_new1(number).object);
+ }
+
+ static final _new2 = jniLookup<
+ ffi.NativeFunction<jni.JniResult Function(ffi.Int32, ffi.Uint8)>>(
+ "Example__new2")
+ .asFunction<jni.JniResult Function(int, int)>();
+
+ /// from: public void <init>(int number, boolean isUp)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example.new2(
+ int number,
+ bool isUp,
+ ) {
+ return Example.fromRef(_new2(number, isUp ? 1 : 0).object);
+ }
+
+ static final _new3 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Int32, ffi.Uint8,
+ ffi.Pointer<ffi.Void>)>>("Example__new3")
+ .asFunction<jni.JniResult Function(int, int, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(int number, boolean isUp, java.lang.String codename)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example.new3(
+ int number,
+ bool isUp,
+ jni.JString codename,
+ ) {
+ return Example.fromRef(
+ _new3(number, isUp ? 1 : 0, codename.reference).object);
+ }
+
+ static final _new4 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Int32, ffi.Int32, ffi.Int32, ffi.Int32,
+ ffi.Int32, ffi.Int32, ffi.Int32, ffi.Int32)>>("Example__new4")
+ .asFunction<
+ jni.JniResult Function(int, int, int, int, int, int, int, int)>();
+
+ /// from: public void <init>(int a, int b, int c, int d, int e, int f, int g, int h)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example.new4(
+ int a,
+ int b,
+ int c,
+ int d,
+ int e,
+ int f,
+ int g,
+ int h,
+ ) {
+ return Example.fromRef(_new4(a, b, c, d, e, f, g, h).object);
+ }
+
+ static final _whichExample = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Example__whichExample")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int whichExample()
+ int whichExample() {
+ return _whichExample(reference).integer;
+ }
+
+ static final _addInts = jniLookup<
+ ffi.NativeFunction<jni.JniResult Function(ffi.Int32, ffi.Int32)>>(
+ "Example__addInts")
+ .asFunction<jni.JniResult Function(int, int)>();
+
+ /// from: static public int addInts(int a, int b)
+ static int addInts(
+ int a,
+ int b,
+ ) {
+ return _addInts(a, b).integer;
+ }
+
+ static final _getArr =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("Example__getArr")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public int[] getArr()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<jni.jint> getArr() {
+ return const jni.JArrayType(jni.jintType()).fromRef(_getArr().object);
+ }
+
+ static final _addAll = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("Example__addAll")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public int addAll(int[] arr)
+ static int addAll(
+ jni.JArray<jni.jint> arr,
+ ) {
+ return _addAll(arr.reference).integer;
+ }
+
+ static final _getSelf = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Example__getSelf")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.github.dart_lang.jnigen.simple_package.Example getSelf()
+ /// The returned object must be released after use, by calling the [release] method.
+ Example getSelf() {
+ return const $ExampleType().fromRef(_getSelf(reference).object);
+ }
+
+ static final _throwException =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Example__throwException")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public void throwException()
+ static void throwException() {
+ return _throwException().check();
+ }
+
+ static final _overloaded = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Example__overloaded")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void overloaded()
+ void overloaded() {
+ return _overloaded(reference).check();
+ }
+
+ static final _overloaded1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Int32,
+ ffi.Pointer<ffi.Void>)>>("Example__overloaded1")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, int, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void overloaded(int a, java.lang.String b)
+ void overloaded1(
+ int a,
+ jni.JString b,
+ ) {
+ return _overloaded1(reference, a, b.reference).check();
+ }
+
+ static final _overloaded2 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Int32)>>("Example__overloaded2")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public void overloaded(int a)
+ void overloaded2(
+ int a,
+ ) {
+ return _overloaded2(reference, a).check();
+ }
+
+ static final _overloaded3 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("Example__overloaded3")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void overloaded(java.util.List<java.lang.Integer> a, java.lang.String b)
+ void overloaded3(
+ jni.JList<jni.JInteger> a,
+ jni.JString b,
+ ) {
+ return _overloaded3(reference, a.reference, b.reference).check();
+ }
+
+ static final _overloaded4 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("Example__overloaded4")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void overloaded(java.util.List<java.lang.Integer> a)
+ void overloaded4(
+ jni.JList<jni.JInteger> a,
+ ) {
+ return _overloaded4(reference, a.reference).check();
+ }
+}
+
+final class $ExampleType extends jni.JObjType<Example> {
+ const $ExampleType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/simple_package/Example;";
+
+ @override
+ Example fromRef(jni.JObjectPtr ref) => Example.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($ExampleType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($ExampleType) && other is $ExampleType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.simple_package.Example$Nested
+class Example_Nested extends jni.JObject {
+ @override
+ late final jni.JObjType<Example_Nested> $type = type;
+
+ Example_Nested.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $Example_NestedType();
+ static final _new0 =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Uint8)>>(
+ "Example_Nested__new0")
+ .asFunction<jni.JniResult Function(int)>();
+
+ /// from: public void <init>(boolean value)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example_Nested(
+ bool value,
+ ) {
+ return Example_Nested.fromRef(_new0(value ? 1 : 0).object);
+ }
+
+ static final _usesAnonymousInnerClass = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Example_Nested__usesAnonymousInnerClass")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void usesAnonymousInnerClass()
+ void usesAnonymousInnerClass() {
+ return _usesAnonymousInnerClass(reference).check();
+ }
+
+ static final _getValue = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Example_Nested__getValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public boolean getValue()
+ bool getValue() {
+ return _getValue(reference).boolean;
+ }
+
+ static final _setValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Uint8)>>("Example_Nested__setValue")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();
+
+ /// from: public void setValue(boolean value)
+ void setValue(
+ bool value,
+ ) {
+ return _setValue(reference, value ? 1 : 0).check();
+ }
+}
+
+final class $Example_NestedType extends jni.JObjType<Example_Nested> {
+ const $Example_NestedType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/simple_package/Example$Nested;";
+
+ @override
+ Example_Nested fromRef(jni.JObjectPtr ref) => Example_Nested.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($Example_NestedType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($Example_NestedType) &&
+ other is $Example_NestedType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.simple_package.Example$Nested$NestedTwice
+class Example_Nested_NestedTwice extends jni.JObject {
+ @override
+ late final jni.JObjType<Example_Nested_NestedTwice> $type = type;
+
+ Example_Nested_NestedTwice.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $Example_Nested_NestedTwiceType();
+ static final _get_ZERO =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Example_Nested_NestedTwice__ZERO")
+ .asFunction<jni.JniResult Function()>();
+
+ static final _set_ZERO =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Int32)>>(
+ "set_Example_Nested_NestedTwice__ZERO")
+ .asFunction<jni.JniResult Function(int)>();
+
+ /// from: static public int ZERO
+ static int get ZERO => _get_ZERO().integer;
+
+ /// from: static public int ZERO
+ static set ZERO(int value) => _set_ZERO(value).check();
+
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Example_Nested_NestedTwice__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example_Nested_NestedTwice() {
+ return Example_Nested_NestedTwice.fromRef(_new0().object);
+ }
+}
+
+final class $Example_Nested_NestedTwiceType
+ extends jni.JObjType<Example_Nested_NestedTwice> {
+ const $Example_Nested_NestedTwiceType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/simple_package/Example$Nested$NestedTwice;";
+
+ @override
+ Example_Nested_NestedTwice fromRef(jni.JObjectPtr ref) =>
+ Example_Nested_NestedTwice.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($Example_Nested_NestedTwiceType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($Example_Nested_NestedTwiceType) &&
+ other is $Example_Nested_NestedTwiceType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.simple_package.Example$NonStaticNested
+class Example_NonStaticNested extends jni.JObject {
+ @override
+ late final jni.JObjType<Example_NonStaticNested> $type = type;
+
+ Example_NonStaticNested.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $Example_NonStaticNestedType();
+ static final _get_ok = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_Example_NonStaticNested__ok")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_ok = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(jni.JObjectPtr,
+ ffi.Uint8)>>("set_Example_NonStaticNested__ok")
+ .asFunction<jni.JniResult Function(jni.JObjectPtr, int)>();
+
+ /// from: public boolean ok
+ bool get ok => _get_ok(reference).boolean;
+
+ /// from: public boolean ok
+ set ok(bool value) => _set_ok(reference, value ? 1 : 0).check();
+
+ static final _new0 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Example_NonStaticNested__new0")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(com.github.dart_lang.jnigen.simple_package.Example $parent)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example_NonStaticNested(
+ Example $parent,
+ ) {
+ return Example_NonStaticNested.fromRef(_new0($parent.reference).object);
+ }
+}
+
+final class $Example_NonStaticNestedType
+ extends jni.JObjType<Example_NonStaticNested> {
+ const $Example_NonStaticNestedType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/simple_package/Example$NonStaticNested;";
+
+ @override
+ Example_NonStaticNested fromRef(jni.JObjectPtr ref) =>
+ Example_NonStaticNested.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($Example_NonStaticNestedType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($Example_NonStaticNestedType) &&
+ other is $Example_NonStaticNestedType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.simple_package.Exceptions
+class Exceptions extends jni.JObject {
+ @override
+ late final jni.JObjType<Exceptions> $type = type;
+
+ Exceptions.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $ExceptionsType();
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Exceptions__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Exceptions() {
+ return Exceptions.fromRef(_new0().object);
+ }
+
+ static final _new1 =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Float)>>(
+ "Exceptions__new1")
+ .asFunction<jni.JniResult Function(double)>();
+
+ /// from: public void <init>(float x)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Exceptions.new1(
+ double x,
+ ) {
+ return Exceptions.fromRef(_new1(x).object);
+ }
+
+ static final _new2 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Int32, ffi.Int32, ffi.Int32, ffi.Int32,
+ ffi.Int32, ffi.Int32)>>("Exceptions__new2")
+ .asFunction<jni.JniResult Function(int, int, int, int, int, int)>();
+
+ /// from: public void <init>(int a, int b, int c, int d, int e, int f)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Exceptions.new2(
+ int a,
+ int b,
+ int c,
+ int d,
+ int e,
+ int f,
+ ) {
+ return Exceptions.fromRef(_new2(a, b, c, d, e, f).object);
+ }
+
+ static final _staticObjectMethod =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Exceptions__staticObjectMethod")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public java.lang.Object staticObjectMethod()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JObject staticObjectMethod() {
+ return const jni.JObjectType().fromRef(_staticObjectMethod().object);
+ }
+
+ static final _staticIntMethod =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Exceptions__staticIntMethod")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public int staticIntMethod()
+ static int staticIntMethod() {
+ return _staticIntMethod().integer;
+ }
+
+ static final _staticObjectArrayMethod =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Exceptions__staticObjectArrayMethod")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public java.lang.Object[] staticObjectArrayMethod()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<jni.JObject> staticObjectArrayMethod() {
+ return const jni.JArrayType(jni.JObjectType())
+ .fromRef(_staticObjectArrayMethod().object);
+ }
+
+ static final _staticIntArrayMethod =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Exceptions__staticIntArrayMethod")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public int[] staticIntArrayMethod()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<jni.jint> staticIntArrayMethod() {
+ return const jni.JArrayType(jni.jintType())
+ .fromRef(_staticIntArrayMethod().object);
+ }
+
+ static final _objectMethod = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Exceptions__objectMethod")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.Object objectMethod()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject objectMethod() {
+ return const jni.JObjectType().fromRef(_objectMethod(reference).object);
+ }
+
+ static final _intMethod = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Exceptions__intMethod")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int intMethod()
+ int intMethod() {
+ return _intMethod(reference).integer;
+ }
+
+ static final _objectArrayMethod = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Exceptions__objectArrayMethod")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.Object[] objectArrayMethod()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JArray<jni.JObject> objectArrayMethod() {
+ return const jni.JArrayType(jni.JObjectType())
+ .fromRef(_objectArrayMethod(reference).object);
+ }
+
+ static final _intArrayMethod = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Exceptions__intArrayMethod")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int[] intArrayMethod()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JArray<jni.jint> intArrayMethod() {
+ return const jni.JArrayType(jni.jintType())
+ .fromRef(_intArrayMethod(reference).object);
+ }
+
+ static final _throwNullPointerException = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Exceptions__throwNullPointerException")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int throwNullPointerException()
+ int throwNullPointerException() {
+ return _throwNullPointerException(reference).integer;
+ }
+
+ static final _throwFileNotFoundException = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Exceptions__throwFileNotFoundException")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.io.InputStream throwFileNotFoundException()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject throwFileNotFoundException() {
+ return const jni.JObjectType()
+ .fromRef(_throwFileNotFoundException(reference).object);
+ }
+
+ static final _throwClassCastException = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Exceptions__throwClassCastException")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.io.FileInputStream throwClassCastException()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject throwClassCastException() {
+ return const jni.JObjectType()
+ .fromRef(_throwClassCastException(reference).object);
+ }
+
+ static final _throwArrayIndexException = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Exceptions__throwArrayIndexException")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int throwArrayIndexException()
+ int throwArrayIndexException() {
+ return _throwArrayIndexException(reference).integer;
+ }
+
+ static final _throwArithmeticException = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Exceptions__throwArithmeticException")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int throwArithmeticException()
+ int throwArithmeticException() {
+ return _throwArithmeticException(reference).integer;
+ }
+
+ static final _throwLoremIpsum =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Exceptions__throwLoremIpsum")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public void throwLoremIpsum()
+ static void throwLoremIpsum() {
+ return _throwLoremIpsum().check();
+ }
+}
+
+final class $ExceptionsType extends jni.JObjType<Exceptions> {
+ const $ExceptionsType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/simple_package/Exceptions;";
+
+ @override
+ Exceptions fromRef(jni.JObjectPtr ref) => Exceptions.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($ExceptionsType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($ExceptionsType) && other is $ExceptionsType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.simple_package.Fields
+class Fields extends jni.JObject {
+ @override
+ late final jni.JObjType<Fields> $type = type;
+
+ Fields.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $FieldsType();
+ static final _get_amount =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Fields__amount")
+ .asFunction<jni.JniResult Function()>();
+
+ static final _set_amount =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Int32)>>(
+ "set_Fields__amount")
+ .asFunction<jni.JniResult Function(int)>();
+
+ /// from: static public int amount
+ static int get amount => _get_amount().integer;
+
+ /// from: static public int amount
+ static set amount(int value) => _set_amount(value).check();
+
+ static final _get_pi =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("get_Fields__pi")
+ .asFunction<jni.JniResult Function()>();
+
+ static final _set_pi =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Double)>>(
+ "set_Fields__pi")
+ .asFunction<jni.JniResult Function(double)>();
+
+ /// from: static public double pi
+ static double get pi => _get_pi().doubleFloat;
+
+ /// from: static public double pi
+ static set pi(double value) => _set_pi(value).check();
+
+ static final _get_asterisk =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Fields__asterisk")
+ .asFunction<jni.JniResult Function()>();
+
+ static final _set_asterisk =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Uint16)>>(
+ "set_Fields__asterisk")
+ .asFunction<jni.JniResult Function(int)>();
+
+ /// from: static public char asterisk
+ static int get asterisk => _get_asterisk().char;
+
+ /// from: static public char asterisk
+ static set asterisk(int value) => _set_asterisk(value).check();
+
+ static final _get_name =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Fields__name")
+ .asFunction<jni.JniResult Function()>();
+
+ static final _set_name = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "set_Fields__name")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public java.lang.String name
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get name =>
+ const jni.JStringType().fromRef(_get_name().object);
+
+ /// from: static public java.lang.String name
+ /// The returned object must be released after use, by calling the [release] method.
+ static set name(jni.JString value) => _set_name(value.reference).check();
+
+ static final _get_i = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_Fields__i")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_i = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>("set_Fields__i")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.Integer i
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JInteger get i =>
+ const jni.JIntegerType().fromRef(_get_i(reference).object);
+
+ /// from: public java.lang.Integer i
+ /// The returned object must be released after use, by calling the [release] method.
+ set i(jni.JInteger value) => _set_i(reference, value.reference).check();
+
+ static final _get_trillion = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_Fields__trillion")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_trillion = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr, ffi.Int64)>>("set_Fields__trillion")
+ .asFunction<jni.JniResult Function(jni.JObjectPtr, int)>();
+
+ /// from: public long trillion
+ int get trillion => _get_trillion(reference).long;
+
+ /// from: public long trillion
+ set trillion(int value) => _set_trillion(reference, value).check();
+
+ static final _get_isAchillesDead = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_Fields__isAchillesDead")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_isAchillesDead = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr, ffi.Uint8)>>("set_Fields__isAchillesDead")
+ .asFunction<jni.JniResult Function(jni.JObjectPtr, int)>();
+
+ /// from: public boolean isAchillesDead
+ bool get isAchillesDead => _get_isAchillesDead(reference).boolean;
+
+ /// from: public boolean isAchillesDead
+ set isAchillesDead(bool value) =>
+ _set_isAchillesDead(reference, value ? 1 : 0).check();
+
+ static final _get_bestFighterInGreece = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_Fields__bestFighterInGreece")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_bestFighterInGreece = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(jni.JObjectPtr,
+ ffi.Pointer<ffi.Void>)>>("set_Fields__bestFighterInGreece")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.String bestFighterInGreece
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JString get bestFighterInGreece => const jni.JStringType()
+ .fromRef(_get_bestFighterInGreece(reference).object);
+
+ /// from: public java.lang.String bestFighterInGreece
+ /// The returned object must be released after use, by calling the [release] method.
+ set bestFighterInGreece(jni.JString value) =>
+ _set_bestFighterInGreece(reference, value.reference).check();
+
+ static final _get_random = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_Fields__random")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_random = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>("set_Fields__random")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.util.Random random
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject get random =>
+ const jni.JObjectType().fromRef(_get_random(reference).object);
+
+ /// from: public java.util.Random random
+ /// The returned object must be released after use, by calling the [release] method.
+ set random(jni.JObject value) =>
+ _set_random(reference, value.reference).check();
+
+ static final _get_euroSymbol =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Fields__euroSymbol")
+ .asFunction<jni.JniResult Function()>();
+
+ static final _set_euroSymbol =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Uint16)>>(
+ "set_Fields__euroSymbol")
+ .asFunction<jni.JniResult Function(int)>();
+
+ /// from: static public char euroSymbol
+ static int get euroSymbol => _get_euroSymbol().char;
+
+ /// from: static public char euroSymbol
+ static set euroSymbol(int value) => _set_euroSymbol(value).check();
+
+ static final _new0 =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("Fields__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Fields() {
+ return Fields.fromRef(_new0().object);
+ }
+}
+
+final class $FieldsType extends jni.JObjType<Fields> {
+ const $FieldsType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/simple_package/Fields;";
+
+ @override
+ Fields fromRef(jni.JObjectPtr ref) => Fields.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($FieldsType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($FieldsType) && other is $FieldsType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.simple_package.Fields$Nested
+class Fields_Nested extends jni.JObject {
+ @override
+ late final jni.JObjType<Fields_Nested> $type = type;
+
+ Fields_Nested.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $Fields_NestedType();
+ static final _get_hundred = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_Fields_Nested__hundred")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_hundred = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr, ffi.Int64)>>("set_Fields_Nested__hundred")
+ .asFunction<jni.JniResult Function(jni.JObjectPtr, int)>();
+
+ /// from: public long hundred
+ int get hundred => _get_hundred(reference).long;
+
+ /// from: public long hundred
+ set hundred(int value) => _set_hundred(reference, value).check();
+
+ static final _get_BEST_GOD =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_Fields_Nested__BEST_GOD")
+ .asFunction<jni.JniResult Function()>();
+
+ static final _set_BEST_GOD = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "set_Fields_Nested__BEST_GOD")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public java.lang.String BEST_GOD
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get BEST_GOD =>
+ const jni.JStringType().fromRef(_get_BEST_GOD().object);
+
+ /// from: static public java.lang.String BEST_GOD
+ /// The returned object must be released after use, by calling the [release] method.
+ static set BEST_GOD(jni.JString value) =>
+ _set_BEST_GOD(value.reference).check();
+
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "Fields_Nested__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Fields_Nested() {
+ return Fields_Nested.fromRef(_new0().object);
+ }
+}
+
+final class $Fields_NestedType extends jni.JObjType<Fields_Nested> {
+ const $Fields_NestedType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/simple_package/Fields$Nested;";
+
+ @override
+ Fields_Nested fromRef(jni.JObjectPtr ref) => Fields_Nested.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($Fields_NestedType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($Fields_NestedType) &&
+ other is $Fields_NestedType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.pkg2.C2
+class C2 extends jni.JObject {
+ @override
+ late final jni.JObjType<C2> $type = type;
+
+ C2.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $C2Type();
+ static final _get_CONSTANT =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "get_C2__CONSTANT")
+ .asFunction<jni.JniResult Function()>();
+
+ static final _set_CONSTANT =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Int32)>>(
+ "set_C2__CONSTANT")
+ .asFunction<jni.JniResult Function(int)>();
+
+ /// from: static public int CONSTANT
+ static int get CONSTANT => _get_CONSTANT().integer;
+
+ /// from: static public int CONSTANT
+ static set CONSTANT(int value) => _set_CONSTANT(value).check();
+
+ static final _new0 =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("C2__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory C2() {
+ return C2.fromRef(_new0().object);
+ }
+}
+
+final class $C2Type extends jni.JObjType<C2> {
+ const $C2Type();
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/pkg2/C2;";
+
+ @override
+ C2 fromRef(jni.JObjectPtr ref) => C2.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($C2Type).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($C2Type) && other is $C2Type;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.pkg2.Example
+class Example1 extends jni.JObject {
+ @override
+ late final jni.JObjType<Example1> $type = type;
+
+ Example1.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $Example1Type();
+ static final _new0 =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("Example1__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example1() {
+ return Example1.fromRef(_new0().object);
+ }
+
+ static final _whichExample = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "Example1__whichExample")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int whichExample()
+ int whichExample() {
+ return _whichExample(reference).integer;
+ }
+}
+
+final class $Example1Type extends jni.JObjType<Example1> {
+ const $Example1Type();
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/pkg2/Example;";
+
+ @override
+ Example1 fromRef(jni.JObjectPtr ref) => Example1.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($Example1Type).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($Example1Type) && other is $Example1Type;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.GenericTypeParams
+class GenericTypeParams<$S extends jni.JObject, $K extends jni.JObject>
+ extends jni.JObject {
+ @override
+ late final jni.JObjType<GenericTypeParams<$S, $K>> $type = type(S, K);
+
+ final jni.JObjType<$S> S;
+ final jni.JObjType<$K> K;
+
+ GenericTypeParams.fromRef(
+ this.S,
+ this.K,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static $GenericTypeParamsType<$S, $K>
+ type<$S extends jni.JObject, $K extends jni.JObject>(
+ jni.JObjType<$S> S,
+ jni.JObjType<$K> K,
+ ) {
+ return $GenericTypeParamsType(
+ S,
+ K,
+ );
+ }
+
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "GenericTypeParams__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory GenericTypeParams({
+ required jni.JObjType<$S> S,
+ required jni.JObjType<$K> K,
+ }) {
+ return GenericTypeParams.fromRef(S, K, _new0().object);
+ }
+}
+
+final class $GenericTypeParamsType<$S extends jni.JObject,
+ $K extends jni.JObject> extends jni.JObjType<GenericTypeParams<$S, $K>> {
+ final jni.JObjType<$S> S;
+ final jni.JObjType<$K> K;
+
+ const $GenericTypeParamsType(
+ this.S,
+ this.K,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/generics/GenericTypeParams;";
+
+ @override
+ GenericTypeParams<$S, $K> fromRef(jni.JObjectPtr ref) =>
+ GenericTypeParams.fromRef(S, K, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($GenericTypeParamsType, S, K);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($GenericTypeParamsType<$S, $K>) &&
+ other is $GenericTypeParamsType<$S, $K> &&
+ S == other.S &&
+ K == other.K;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.GrandParent
+class GrandParent<$T extends jni.JObject> extends jni.JObject {
+ @override
+ late final jni.JObjType<GrandParent<$T>> $type = type(T);
+
+ final jni.JObjType<$T> T;
+
+ GrandParent.fromRef(
+ this.T,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static $GrandParentType<$T> type<$T extends jni.JObject>(
+ jni.JObjType<$T> T,
+ ) {
+ return $GrandParentType(
+ T,
+ );
+ }
+
+ static final _get_value = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_GrandParent__value")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_value = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(jni.JObjectPtr,
+ ffi.Pointer<ffi.Void>)>>("set_GrandParent__value")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public T value
+ /// The returned object must be released after use, by calling the [release] method.
+ $T get value => T.fromRef(_get_value(reference).object);
+
+ /// from: public T value
+ /// The returned object must be released after use, by calling the [release] method.
+ set value($T value) => _set_value(reference, value.reference).check();
+
+ static final _new0 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "GrandParent__new0")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(T value)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory GrandParent(
+ $T value, {
+ jni.JObjType<$T>? T,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ value.$type,
+ ]) as jni.JObjType<$T>;
+ return GrandParent.fromRef(T, _new0(value.reference).object);
+ }
+
+ static final _stringParent = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "GrandParent__stringParent")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.github.dart_lang.jnigen.generics.GrandParent<T>.Parent<java.lang.String> stringParent()
+ /// The returned object must be released after use, by calling the [release] method.
+ GrandParent_Parent<jni.JObject, jni.JString> stringParent() {
+ return const $GrandParent_ParentType(jni.JObjectType(), jni.JStringType())
+ .fromRef(_stringParent(reference).object);
+ }
+
+ static final _varParent = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("GrandParent__varParent")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.github.dart_lang.jnigen.generics.GrandParent<T>.Parent<S> varParent(S nestedValue)
+ /// The returned object must be released after use, by calling the [release] method.
+ GrandParent_Parent<jni.JObject, $S> varParent<$S extends jni.JObject>(
+ $S nestedValue, {
+ jni.JObjType<$S>? S,
+ }) {
+ S ??= jni.lowestCommonSuperType([
+ nestedValue.$type,
+ ]) as jni.JObjType<$S>;
+ return $GrandParent_ParentType(const jni.JObjectType(), S)
+ .fromRef(_varParent(reference, nestedValue.reference).object);
+ }
+
+ static final _stringStaticParent =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "GrandParent__stringStaticParent")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public com.github.dart_lang.jnigen.generics.GrandParent.StaticParent<java.lang.String> stringStaticParent()
+ /// The returned object must be released after use, by calling the [release] method.
+ static GrandParent_StaticParent<jni.JString> stringStaticParent() {
+ return const $GrandParent_StaticParentType(jni.JStringType())
+ .fromRef(_stringStaticParent().object);
+ }
+
+ static final _varStaticParent = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "GrandParent__varStaticParent")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public com.github.dart_lang.jnigen.generics.GrandParent.StaticParent<S> varStaticParent(S value)
+ /// The returned object must be released after use, by calling the [release] method.
+ static GrandParent_StaticParent<$S> varStaticParent<$S extends jni.JObject>(
+ $S value, {
+ jni.JObjType<$S>? S,
+ }) {
+ S ??= jni.lowestCommonSuperType([
+ value.$type,
+ ]) as jni.JObjType<$S>;
+ return $GrandParent_StaticParentType(S)
+ .fromRef(_varStaticParent(value.reference).object);
+ }
+
+ static final _staticParentWithSameType = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "GrandParent__staticParentWithSameType")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.github.dart_lang.jnigen.generics.GrandParent.StaticParent<T> staticParentWithSameType()
+ /// The returned object must be released after use, by calling the [release] method.
+ GrandParent_StaticParent<$T> staticParentWithSameType() {
+ return $GrandParent_StaticParentType(T)
+ .fromRef(_staticParentWithSameType(reference).object);
+ }
+}
+
+final class $GrandParentType<$T extends jni.JObject>
+ extends jni.JObjType<GrandParent<$T>> {
+ final jni.JObjType<$T> T;
+
+ const $GrandParentType(
+ this.T,
+ );
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/generics/GrandParent;";
+
+ @override
+ GrandParent<$T> fromRef(jni.JObjectPtr ref) => GrandParent.fromRef(T, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($GrandParentType, T);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($GrandParentType<$T>) &&
+ other is $GrandParentType<$T> &&
+ T == other.T;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.GrandParent$Parent
+class GrandParent_Parent<$T extends jni.JObject, $S extends jni.JObject>
+ extends jni.JObject {
+ @override
+ late final jni.JObjType<GrandParent_Parent<$T, $S>> $type = type(T, S);
+
+ final jni.JObjType<$T> T;
+ final jni.JObjType<$S> S;
+
+ GrandParent_Parent.fromRef(
+ this.T,
+ this.S,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static $GrandParent_ParentType<$T, $S>
+ type<$T extends jni.JObject, $S extends jni.JObject>(
+ jni.JObjType<$T> T,
+ jni.JObjType<$S> S,
+ ) {
+ return $GrandParent_ParentType(
+ T,
+ S,
+ );
+ }
+
+ static final _get_parentValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_GrandParent_Parent__parentValue")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_parentValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>(
+ "set_GrandParent_Parent__parentValue")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public T parentValue
+ /// The returned object must be released after use, by calling the [release] method.
+ $T get parentValue => T.fromRef(_get_parentValue(reference).object);
+
+ /// from: public T parentValue
+ /// The returned object must be released after use, by calling the [release] method.
+ set parentValue($T value) =>
+ _set_parentValue(reference, value.reference).check();
+
+ static final _get_value = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_GrandParent_Parent__value")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_value = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(jni.JObjectPtr,
+ ffi.Pointer<ffi.Void>)>>("set_GrandParent_Parent__value")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public S value
+ /// The returned object must be released after use, by calling the [release] method.
+ $S get value => S.fromRef(_get_value(reference).object);
+
+ /// from: public S value
+ /// The returned object must be released after use, by calling the [release] method.
+ set value($S value) => _set_value(reference, value.reference).check();
+
+ static final _new0 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("GrandParent_Parent__new0")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(com.github.dart_lang.jnigen.generics.GrandParent $parent, S newValue)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory GrandParent_Parent(
+ GrandParent<$T> $parent,
+ $S newValue, {
+ jni.JObjType<$T>? T,
+ jni.JObjType<$S>? S,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ ($parent.$type as $GrandParentType).T,
+ ]) as jni.JObjType<$T>;
+ S ??= jni.lowestCommonSuperType([
+ newValue.$type,
+ ]) as jni.JObjType<$S>;
+ return GrandParent_Parent.fromRef(
+ T, S, _new0($parent.reference, newValue.reference).object);
+ }
+}
+
+final class $GrandParent_ParentType<$T extends jni.JObject,
+ $S extends jni.JObject> extends jni.JObjType<GrandParent_Parent<$T, $S>> {
+ final jni.JObjType<$T> T;
+ final jni.JObjType<$S> S;
+
+ const $GrandParent_ParentType(
+ this.T,
+ this.S,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent;";
+
+ @override
+ GrandParent_Parent<$T, $S> fromRef(jni.JObjectPtr ref) =>
+ GrandParent_Parent.fromRef(T, S, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($GrandParent_ParentType, T, S);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($GrandParent_ParentType<$T, $S>) &&
+ other is $GrandParent_ParentType<$T, $S> &&
+ T == other.T &&
+ S == other.S;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.GrandParent$Parent$Child
+class GrandParent_Parent_Child<$T extends jni.JObject, $S extends jni.JObject,
+ $U extends jni.JObject> extends jni.JObject {
+ @override
+ late final jni.JObjType<GrandParent_Parent_Child<$T, $S, $U>> $type =
+ type(T, S, U);
+
+ final jni.JObjType<$T> T;
+ final jni.JObjType<$S> S;
+ final jni.JObjType<$U> U;
+
+ GrandParent_Parent_Child.fromRef(
+ this.T,
+ this.S,
+ this.U,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static $GrandParent_Parent_ChildType<$T, $S, $U> type<$T extends jni.JObject,
+ $S extends jni.JObject, $U extends jni.JObject>(
+ jni.JObjType<$T> T,
+ jni.JObjType<$S> S,
+ jni.JObjType<$U> U,
+ ) {
+ return $GrandParent_Parent_ChildType(
+ T,
+ S,
+ U,
+ );
+ }
+
+ static final _get_grandParentValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_GrandParent_Parent_Child__grandParentValue")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_grandParentValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>(
+ "set_GrandParent_Parent_Child__grandParentValue")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public T grandParentValue
+ /// The returned object must be released after use, by calling the [release] method.
+ $T get grandParentValue => T.fromRef(_get_grandParentValue(reference).object);
+
+ /// from: public T grandParentValue
+ /// The returned object must be released after use, by calling the [release] method.
+ set grandParentValue($T value) =>
+ _set_grandParentValue(reference, value.reference).check();
+
+ static final _get_parentValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_GrandParent_Parent_Child__parentValue")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_parentValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>(
+ "set_GrandParent_Parent_Child__parentValue")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public S parentValue
+ /// The returned object must be released after use, by calling the [release] method.
+ $S get parentValue => S.fromRef(_get_parentValue(reference).object);
+
+ /// from: public S parentValue
+ /// The returned object must be released after use, by calling the [release] method.
+ set parentValue($S value) =>
+ _set_parentValue(reference, value.reference).check();
+
+ static final _get_value = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_GrandParent_Parent_Child__value")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_value = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>(
+ "set_GrandParent_Parent_Child__value")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public U value
+ /// The returned object must be released after use, by calling the [release] method.
+ $U get value => U.fromRef(_get_value(reference).object);
+
+ /// from: public U value
+ /// The returned object must be released after use, by calling the [release] method.
+ set value($U value) => _set_value(reference, value.reference).check();
+
+ static final _new0 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("GrandParent_Parent_Child__new0")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(com.github.dart_lang.jnigen.generics.GrandParent$Parent $parent, U newValue)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory GrandParent_Parent_Child(
+ GrandParent_Parent<$T, $S> $parent,
+ $U newValue, {
+ jni.JObjType<$T>? T,
+ jni.JObjType<$S>? S,
+ jni.JObjType<$U>? U,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ ($parent.$type as $GrandParent_ParentType).T,
+ ]) as jni.JObjType<$T>;
+ S ??= jni.lowestCommonSuperType([
+ ($parent.$type as $GrandParent_ParentType).S,
+ ]) as jni.JObjType<$S>;
+ U ??= jni.lowestCommonSuperType([
+ newValue.$type,
+ ]) as jni.JObjType<$U>;
+ return GrandParent_Parent_Child.fromRef(
+ T, S, U, _new0($parent.reference, newValue.reference).object);
+ }
+}
+
+final class $GrandParent_Parent_ChildType<$T extends jni.JObject,
+ $S extends jni.JObject, $U extends jni.JObject>
+ extends jni.JObjType<GrandParent_Parent_Child<$T, $S, $U>> {
+ final jni.JObjType<$T> T;
+ final jni.JObjType<$S> S;
+ final jni.JObjType<$U> U;
+
+ const $GrandParent_Parent_ChildType(
+ this.T,
+ this.S,
+ this.U,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent$Child;";
+
+ @override
+ GrandParent_Parent_Child<$T, $S, $U> fromRef(jni.JObjectPtr ref) =>
+ GrandParent_Parent_Child.fromRef(T, S, U, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($GrandParent_Parent_ChildType, T, S, U);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($GrandParent_Parent_ChildType<$T, $S, $U>) &&
+ other is $GrandParent_Parent_ChildType<$T, $S, $U> &&
+ T == other.T &&
+ S == other.S &&
+ U == other.U;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.GrandParent$StaticParent
+class GrandParent_StaticParent<$S extends jni.JObject> extends jni.JObject {
+ @override
+ late final jni.JObjType<GrandParent_StaticParent<$S>> $type = type(S);
+
+ final jni.JObjType<$S> S;
+
+ GrandParent_StaticParent.fromRef(
+ this.S,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static $GrandParent_StaticParentType<$S> type<$S extends jni.JObject>(
+ jni.JObjType<$S> S,
+ ) {
+ return $GrandParent_StaticParentType(
+ S,
+ );
+ }
+
+ static final _get_value = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_GrandParent_StaticParent__value")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_value = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>(
+ "set_GrandParent_StaticParent__value")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public S value
+ /// The returned object must be released after use, by calling the [release] method.
+ $S get value => S.fromRef(_get_value(reference).object);
+
+ /// from: public S value
+ /// The returned object must be released after use, by calling the [release] method.
+ set value($S value) => _set_value(reference, value.reference).check();
+
+ static final _new0 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "GrandParent_StaticParent__new0")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(S value)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory GrandParent_StaticParent(
+ $S value, {
+ jni.JObjType<$S>? S,
+ }) {
+ S ??= jni.lowestCommonSuperType([
+ value.$type,
+ ]) as jni.JObjType<$S>;
+ return GrandParent_StaticParent.fromRef(S, _new0(value.reference).object);
+ }
+}
+
+final class $GrandParent_StaticParentType<$S extends jni.JObject>
+ extends jni.JObjType<GrandParent_StaticParent<$S>> {
+ final jni.JObjType<$S> S;
+
+ const $GrandParent_StaticParentType(
+ this.S,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;";
+
+ @override
+ GrandParent_StaticParent<$S> fromRef(jni.JObjectPtr ref) =>
+ GrandParent_StaticParent.fromRef(S, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($GrandParent_StaticParentType, S);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($GrandParent_StaticParentType<$S>) &&
+ other is $GrandParent_StaticParentType<$S> &&
+ S == other.S;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.GrandParent$StaticParent$Child
+class GrandParent_StaticParent_Child<$S extends jni.JObject,
+ $U extends jni.JObject> extends jni.JObject {
+ @override
+ late final jni.JObjType<GrandParent_StaticParent_Child<$S, $U>> $type =
+ type(S, U);
+
+ final jni.JObjType<$S> S;
+ final jni.JObjType<$U> U;
+
+ GrandParent_StaticParent_Child.fromRef(
+ this.S,
+ this.U,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static $GrandParent_StaticParent_ChildType<$S, $U>
+ type<$S extends jni.JObject, $U extends jni.JObject>(
+ jni.JObjType<$S> S,
+ jni.JObjType<$U> U,
+ ) {
+ return $GrandParent_StaticParent_ChildType(
+ S,
+ U,
+ );
+ }
+
+ static final _get_parentValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_GrandParent_StaticParent_Child__parentValue")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_parentValue = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>(
+ "set_GrandParent_StaticParent_Child__parentValue")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public S parentValue
+ /// The returned object must be released after use, by calling the [release] method.
+ $S get parentValue => S.fromRef(_get_parentValue(reference).object);
+
+ /// from: public S parentValue
+ /// The returned object must be released after use, by calling the [release] method.
+ set parentValue($S value) =>
+ _set_parentValue(reference, value.reference).check();
+
+ static final _get_value = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_GrandParent_StaticParent_Child__value")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_value = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr, ffi.Pointer<ffi.Void>)>>(
+ "set_GrandParent_StaticParent_Child__value")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public U value
+ /// The returned object must be released after use, by calling the [release] method.
+ $U get value => U.fromRef(_get_value(reference).object);
+
+ /// from: public U value
+ /// The returned object must be released after use, by calling the [release] method.
+ set value($U value) => _set_value(reference, value.reference).check();
+
+ static final _new0 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
+ "GrandParent_StaticParent_Child__new0")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(com.github.dart_lang.jnigen.generics.GrandParent$StaticParent $parent, S parentValue, U value)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory GrandParent_StaticParent_Child(
+ GrandParent_StaticParent<$S> $parent,
+ $S parentValue,
+ $U value, {
+ jni.JObjType<$S>? S,
+ jni.JObjType<$U>? U,
+ }) {
+ S ??= jni.lowestCommonSuperType([
+ parentValue.$type,
+ ($parent.$type as $GrandParent_StaticParentType).S,
+ ]) as jni.JObjType<$S>;
+ U ??= jni.lowestCommonSuperType([
+ value.$type,
+ ]) as jni.JObjType<$U>;
+ return GrandParent_StaticParent_Child.fromRef(
+ S,
+ U,
+ _new0($parent.reference, parentValue.reference, value.reference)
+ .object);
+ }
+}
+
+final class $GrandParent_StaticParent_ChildType<$S extends jni.JObject,
+ $U extends jni.JObject>
+ extends jni.JObjType<GrandParent_StaticParent_Child<$S, $U>> {
+ final jni.JObjType<$S> S;
+ final jni.JObjType<$U> U;
+
+ const $GrandParent_StaticParent_ChildType(
+ this.S,
+ this.U,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent$Child;";
+
+ @override
+ GrandParent_StaticParent_Child<$S, $U> fromRef(jni.JObjectPtr ref) =>
+ GrandParent_StaticParent_Child.fromRef(S, U, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($GrandParent_StaticParent_ChildType, S, U);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($GrandParent_StaticParent_ChildType<$S, $U>) &&
+ other is $GrandParent_StaticParent_ChildType<$S, $U> &&
+ S == other.S &&
+ U == other.U;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.MyMap
+class MyMap<$K extends jni.JObject, $V extends jni.JObject>
+ extends jni.JObject {
+ @override
+ late final jni.JObjType<MyMap<$K, $V>> $type = type(K, V);
+
+ final jni.JObjType<$K> K;
+ final jni.JObjType<$V> V;
+
+ MyMap.fromRef(
+ this.K,
+ this.V,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static $MyMapType<$K, $V>
+ type<$K extends jni.JObject, $V extends jni.JObject>(
+ jni.JObjType<$K> K,
+ jni.JObjType<$V> V,
+ ) {
+ return $MyMapType(
+ K,
+ V,
+ );
+ }
+
+ static final _new0 =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("MyMap__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory MyMap({
+ required jni.JObjType<$K> K,
+ required jni.JObjType<$V> V,
+ }) {
+ return MyMap.fromRef(K, V, _new0().object);
+ }
+
+ static final _get0 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>("MyMap__get0")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public V get(K key)
+ /// The returned object must be released after use, by calling the [release] method.
+ $V get0(
+ $K key,
+ ) {
+ return V.fromRef(_get0(reference, key.reference).object);
+ }
+
+ static final _put = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>("MyMap__put")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public V put(K key, V value)
+ /// The returned object must be released after use, by calling the [release] method.
+ $V put(
+ $K key,
+ $V value,
+ ) {
+ return V.fromRef(_put(reference, key.reference, value.reference).object);
+ }
+
+ static final _entryStack = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "MyMap__entryStack")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public com.github.dart_lang.jnigen.generics.MyStack<com.github.dart_lang.jnigen.generics.MyMap<K,V>.MyEntry> entryStack()
+ /// The returned object must be released after use, by calling the [release] method.
+ MyStack<MyMap_MyEntry<jni.JObject, jni.JObject>> entryStack() {
+ return const $MyStackType(
+ $MyMap_MyEntryType(jni.JObjectType(), jni.JObjectType()))
+ .fromRef(_entryStack(reference).object);
+ }
+}
+
+final class $MyMapType<$K extends jni.JObject, $V extends jni.JObject>
+ extends jni.JObjType<MyMap<$K, $V>> {
+ final jni.JObjType<$K> K;
+ final jni.JObjType<$V> V;
+
+ const $MyMapType(
+ this.K,
+ this.V,
+ );
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/generics/MyMap;";
+
+ @override
+ MyMap<$K, $V> fromRef(jni.JObjectPtr ref) => MyMap.fromRef(K, V, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($MyMapType, K, V);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($MyMapType<$K, $V>) &&
+ other is $MyMapType<$K, $V> &&
+ K == other.K &&
+ V == other.V;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.MyMap$MyEntry
+class MyMap_MyEntry<$K extends jni.JObject, $V extends jni.JObject>
+ extends jni.JObject {
+ @override
+ late final jni.JObjType<MyMap_MyEntry<$K, $V>> $type = type(K, V);
+
+ final jni.JObjType<$K> K;
+ final jni.JObjType<$V> V;
+
+ MyMap_MyEntry.fromRef(
+ this.K,
+ this.V,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static $MyMap_MyEntryType<$K, $V>
+ type<$K extends jni.JObject, $V extends jni.JObject>(
+ jni.JObjType<$K> K,
+ jni.JObjType<$V> V,
+ ) {
+ return $MyMap_MyEntryType(
+ K,
+ V,
+ );
+ }
+
+ static final _get_key = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_MyMap_MyEntry__key")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_key = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(jni.JObjectPtr,
+ ffi.Pointer<ffi.Void>)>>("set_MyMap_MyEntry__key")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public K key
+ /// The returned object must be released after use, by calling the [release] method.
+ $K get key => K.fromRef(_get_key(reference).object);
+
+ /// from: public K key
+ /// The returned object must be released after use, by calling the [release] method.
+ set key($K value) => _set_key(reference, value.reference).check();
+
+ static final _get_value = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_MyMap_MyEntry__value")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_value = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(jni.JObjectPtr,
+ ffi.Pointer<ffi.Void>)>>("set_MyMap_MyEntry__value")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public V value
+ /// The returned object must be released after use, by calling the [release] method.
+ $V get value => V.fromRef(_get_value(reference).object);
+
+ /// from: public V value
+ /// The returned object must be released after use, by calling the [release] method.
+ set value($V value) => _set_value(reference, value.reference).check();
+
+ static final _new0 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("MyMap_MyEntry__new0")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(com.github.dart_lang.jnigen.generics.MyMap $parent, K key, V value)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory MyMap_MyEntry(
+ MyMap<$K, $V> $parent,
+ $K key,
+ $V value, {
+ jni.JObjType<$K>? K,
+ jni.JObjType<$V>? V,
+ }) {
+ K ??= jni.lowestCommonSuperType([
+ key.$type,
+ ($parent.$type as $MyMapType).K,
+ ]) as jni.JObjType<$K>;
+ V ??= jni.lowestCommonSuperType([
+ value.$type,
+ ($parent.$type as $MyMapType).V,
+ ]) as jni.JObjType<$V>;
+ return MyMap_MyEntry.fromRef(
+ K, V, _new0($parent.reference, key.reference, value.reference).object);
+ }
+}
+
+final class $MyMap_MyEntryType<$K extends jni.JObject, $V extends jni.JObject>
+ extends jni.JObjType<MyMap_MyEntry<$K, $V>> {
+ final jni.JObjType<$K> K;
+ final jni.JObjType<$V> V;
+
+ const $MyMap_MyEntryType(
+ this.K,
+ this.V,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/generics/MyMap$MyEntry;";
+
+ @override
+ MyMap_MyEntry<$K, $V> fromRef(jni.JObjectPtr ref) =>
+ MyMap_MyEntry.fromRef(K, V, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($MyMap_MyEntryType, K, V);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($MyMap_MyEntryType<$K, $V>) &&
+ other is $MyMap_MyEntryType<$K, $V> &&
+ K == other.K &&
+ V == other.V;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.MyStack
+class MyStack<$T extends jni.JObject> extends jni.JObject {
+ @override
+ late final jni.JObjType<MyStack<$T>> $type = type(T);
+
+ final jni.JObjType<$T> T;
+
+ MyStack.fromRef(
+ this.T,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static $MyStackType<$T> type<$T extends jni.JObject>(
+ jni.JObjType<$T> T,
+ ) {
+ return $MyStackType(
+ T,
+ );
+ }
+
+ static final _new0 =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("MyStack__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory MyStack({
+ required jni.JObjType<$T> T,
+ }) {
+ return MyStack.fromRef(T, _new0().object);
+ }
+
+ static final _fromArray = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "MyStack__fromArray")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public com.github.dart_lang.jnigen.generics.MyStack<T> fromArray(T[] arr)
+ /// The returned object must be released after use, by calling the [release] method.
+ static MyStack<$T> fromArray<$T extends jni.JObject>(
+ jni.JArray<$T> arr, {
+ jni.JObjType<$T>? T,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ ((arr.$type as jni.JArrayType).elementType as jni.JObjType),
+ ]) as jni.JObjType<$T>;
+ return $MyStackType(T).fromRef(_fromArray(arr.reference).object);
+ }
+
+ static final _fromArrayOfArrayOfGrandParents = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "MyStack__fromArrayOfArrayOfGrandParents")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public com.github.dart_lang.jnigen.generics.MyStack<S> fromArrayOfArrayOfGrandParents(com.github.dart_lang.jnigen.generics.GrandParent<S>[][] arr)
+ /// The returned object must be released after use, by calling the [release] method.
+ static MyStack<$S> fromArrayOfArrayOfGrandParents<$S extends jni.JObject>(
+ jni.JArray<jni.JArray<GrandParent<$S>>> arr, {
+ jni.JObjType<$S>? S,
+ }) {
+ S ??= jni.lowestCommonSuperType([
+ (((((arr.$type as jni.JArrayType).elementType as jni.JObjType)
+ as jni.JArrayType)
+ .elementType as jni.JObjType) as $GrandParentType)
+ .T,
+ ]) as jni.JObjType<$S>;
+ return $MyStackType(S)
+ .fromRef(_fromArrayOfArrayOfGrandParents(arr.reference).object);
+ }
+
+ static final _of =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("MyStack__of")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public com.github.dart_lang.jnigen.generics.MyStack<T> of()
+ /// The returned object must be released after use, by calling the [release] method.
+ static MyStack<$T> of<$T extends jni.JObject>({
+ required jni.JObjType<$T> T,
+ }) {
+ return $MyStackType(T).fromRef(_of().object);
+ }
+
+ static final _of1 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("MyStack__of1")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public com.github.dart_lang.jnigen.generics.MyStack<T> of(T obj)
+ /// The returned object must be released after use, by calling the [release] method.
+ static MyStack<$T> of1<$T extends jni.JObject>(
+ $T obj, {
+ jni.JObjType<$T>? T,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ obj.$type,
+ ]) as jni.JObjType<$T>;
+ return $MyStackType(T).fromRef(_of1(obj.reference).object);
+ }
+
+ static final _of2 = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("MyStack__of2")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public com.github.dart_lang.jnigen.generics.MyStack<T> of(T obj, T obj2)
+ /// The returned object must be released after use, by calling the [release] method.
+ static MyStack<$T> of2<$T extends jni.JObject>(
+ $T obj,
+ $T obj2, {
+ jni.JObjType<$T>? T,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ obj2.$type,
+ obj.$type,
+ ]) as jni.JObjType<$T>;
+ return $MyStackType(T).fromRef(_of2(obj.reference, obj2.reference).object);
+ }
+
+ static final _push = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("MyStack__push")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void push(T item)
+ void push(
+ $T item,
+ ) {
+ return _push(reference, item.reference).check();
+ }
+
+ static final _pop = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("MyStack__pop")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public T pop()
+ /// The returned object must be released after use, by calling the [release] method.
+ $T pop() {
+ return T.fromRef(_pop(reference).object);
+ }
+
+ static final _size = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("MyStack__size")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public int size()
+ int size() {
+ return _size(reference).integer;
+ }
+}
+
+final class $MyStackType<$T extends jni.JObject>
+ extends jni.JObjType<MyStack<$T>> {
+ final jni.JObjType<$T> T;
+
+ const $MyStackType(
+ this.T,
+ );
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/generics/MyStack;";
+
+ @override
+ MyStack<$T> fromRef(jni.JObjectPtr ref) => MyStack.fromRef(T, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($MyStackType, T);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($MyStackType<$T>) &&
+ other is $MyStackType<$T> &&
+ T == other.T;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.StringKeyedMap
+class StringKeyedMap<$V extends jni.JObject> extends MyMap<jni.JString, $V> {
+ @override
+ late final jni.JObjType<StringKeyedMap<$V>> $type = type(V);
+
+ final jni.JObjType<$V> V;
+
+ StringKeyedMap.fromRef(
+ this.V,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(const jni.JStringType(), V, ref);
+
+ /// The type which includes information such as the signature of this class.
+ static $StringKeyedMapType<$V> type<$V extends jni.JObject>(
+ jni.JObjType<$V> V,
+ ) {
+ return $StringKeyedMapType(
+ V,
+ );
+ }
+
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "StringKeyedMap__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory StringKeyedMap({
+ required jni.JObjType<$V> V,
+ }) {
+ return StringKeyedMap.fromRef(V, _new0().object);
+ }
+}
+
+final class $StringKeyedMapType<$V extends jni.JObject>
+ extends jni.JObjType<StringKeyedMap<$V>> {
+ final jni.JObjType<$V> V;
+
+ const $StringKeyedMapType(
+ this.V,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/generics/StringKeyedMap;";
+
+ @override
+ StringKeyedMap<$V> fromRef(jni.JObjectPtr ref) =>
+ StringKeyedMap.fromRef(V, ref);
+
+ @override
+ jni.JObjType get superType => $MyMapType(const jni.JStringType(), V);
+
+ @override
+ final superCount = 2;
+
+ @override
+ int get hashCode => Object.hash($StringKeyedMapType, V);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($StringKeyedMapType<$V>) &&
+ other is $StringKeyedMapType<$V> &&
+ V == other.V;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.StringMap
+class StringMap extends StringKeyedMap<jni.JString> {
+ @override
+ late final jni.JObjType<StringMap> $type = type;
+
+ StringMap.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(const jni.JStringType(), ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $StringMapType();
+ static final _new0 =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>("StringMap__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory StringMap() {
+ return StringMap.fromRef(_new0().object);
+ }
+}
+
+final class $StringMapType extends jni.JObjType<StringMap> {
+ const $StringMapType();
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/generics/StringMap;";
+
+ @override
+ StringMap fromRef(jni.JObjectPtr ref) => StringMap.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const $StringKeyedMapType(jni.JStringType());
+
+ @override
+ final superCount = 3;
+
+ @override
+ int get hashCode => ($StringMapType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($StringMapType) && other is $StringMapType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.StringStack
+class StringStack extends MyStack<jni.JString> {
+ @override
+ late final jni.JObjType<StringStack> $type = type;
+
+ StringStack.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(const jni.JStringType(), ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $StringStackType();
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "StringStack__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory StringStack() {
+ return StringStack.fromRef(_new0().object);
+ }
+}
+
+final class $StringStackType extends jni.JObjType<StringStack> {
+ const $StringStackType();
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/generics/StringStack;";
+
+ @override
+ StringStack fromRef(jni.JObjectPtr ref) => StringStack.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const $MyStackType(jni.JStringType());
+
+ @override
+ final superCount = 2;
+
+ @override
+ int get hashCode => ($StringStackType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($StringStackType) && other is $StringStackType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.StringValuedMap
+class StringValuedMap<$K extends jni.JObject> extends MyMap<$K, jni.JString> {
+ @override
+ late final jni.JObjType<StringValuedMap<$K>> $type = type(K);
+
+ final jni.JObjType<$K> K;
+
+ StringValuedMap.fromRef(
+ this.K,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(K, const jni.JStringType(), ref);
+
+ /// The type which includes information such as the signature of this class.
+ static $StringValuedMapType<$K> type<$K extends jni.JObject>(
+ jni.JObjType<$K> K,
+ ) {
+ return $StringValuedMapType(
+ K,
+ );
+ }
+
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "StringValuedMap__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory StringValuedMap({
+ required jni.JObjType<$K> K,
+ }) {
+ return StringValuedMap.fromRef(K, _new0().object);
+ }
+}
+
+final class $StringValuedMapType<$K extends jni.JObject>
+ extends jni.JObjType<StringValuedMap<$K>> {
+ final jni.JObjType<$K> K;
+
+ const $StringValuedMapType(
+ this.K,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/generics/StringValuedMap;";
+
+ @override
+ StringValuedMap<$K> fromRef(jni.JObjectPtr ref) =>
+ StringValuedMap.fromRef(K, ref);
+
+ @override
+ jni.JObjType get superType => $MyMapType(K, const jni.JStringType());
+
+ @override
+ final superCount = 2;
+
+ @override
+ int get hashCode => Object.hash($StringValuedMapType, K);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($StringValuedMapType<$K>) &&
+ other is $StringValuedMapType<$K> &&
+ K == other.K;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.interfaces.MyInterface
+class MyInterface<$T extends jni.JObject> extends jni.JObject {
+ @override
+ late final jni.JObjType<MyInterface<$T>> $type = type(T);
+
+ final jni.JObjType<$T> T;
+
+ MyInterface.fromRef(
+ this.T,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static $MyInterfaceType<$T> type<$T extends jni.JObject>(
+ jni.JObjType<$T> T,
+ ) {
+ return $MyInterfaceType(
+ T,
+ );
+ }
+
+ static final _voidCallback = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("MyInterface__voidCallback")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract void voidCallback(java.lang.String s)
+ void voidCallback(
+ jni.JString s,
+ ) {
+ return _voidCallback(reference, s.reference).check();
+ }
+
+ static final _stringCallback = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("MyInterface__stringCallback")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract java.lang.String stringCallback(java.lang.String s)
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JString stringCallback(
+ jni.JString s,
+ ) {
+ return const jni.JStringType()
+ .fromRef(_stringCallback(reference, s.reference).object);
+ }
+
+ static final _varCallback = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>)>>("MyInterface__varCallback")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract T varCallback(T t)
+ /// The returned object must be released after use, by calling the [release] method.
+ $T varCallback(
+ $T t,
+ ) {
+ return T.fromRef(_varCallback(reference, t.reference).object);
+ }
+
+ static final _manyPrimitives = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32,
+ ffi.Uint8,
+ ffi.Uint16,
+ ffi.Double)>>("MyInterface__manyPrimitives")
+ .asFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>, int, int, int, double)>();
+
+ /// from: public abstract long manyPrimitives(int a, boolean b, char c, double d)
+ int manyPrimitives(
+ int a,
+ bool b,
+ int c,
+ double d,
+ ) {
+ return _manyPrimitives(reference, a, b ? 1 : 0, c, d).long;
+ }
+
+ /// Maps a specific port to the implemented interface.
+ static final Map<int, $MyInterfaceImpl> _$impls = {};
+ ReceivePort? _$p;
+
+ static jni.JObjectPtr _$invoke(
+ int port,
+ jni.JObjectPtr descriptor,
+ jni.JObjectPtr args,
+ ) {
+ return _$invokeMethod(
+ port,
+ $MethodInvocation.fromAddresses(
+ 0,
+ descriptor.address,
+ args.address,
+ ),
+ );
+ }
+
+ static final ffi.Pointer<
+ ffi.NativeFunction<
+ jni.JObjectPtr Function(
+ ffi.Uint64, jni.JObjectPtr, jni.JObjectPtr)>>
+ _$invokePointer = ffi.Pointer.fromFunction(_$invoke);
+
+ static ffi.Pointer<ffi.Void> _$invokeMethod(
+ int $p,
+ $MethodInvocation $i,
+ ) {
+ try {
+ final $d = $i.methodDescriptor.toDartString(releaseOriginal: true);
+ final $a = $i.args;
+ if ($d == r"voidCallback(Ljava/lang/String;)V") {
+ _$impls[$p]!.voidCallback(
+ $a[0].castTo(const jni.JStringType(), releaseOriginal: true),
+ );
+ return jni.nullptr;
+ }
+ if ($d == r"stringCallback(Ljava/lang/String;)Ljava/lang/String;") {
+ final $r = _$impls[$p]!.stringCallback(
+ $a[0].castTo(const jni.JStringType(), releaseOriginal: true),
+ );
+ return ($r as jni.JObject).castTo(const jni.JObjectType()).toPointer();
+ }
+ if ($d == r"varCallback(Ljava/lang/Object;)Ljava/lang/Object;") {
+ final $r = _$impls[$p]!.varCallback(
+ $a[0].castTo(_$impls[$p]!.T, releaseOriginal: true),
+ );
+ return ($r as jni.JObject).castTo(const jni.JObjectType()).toPointer();
+ }
+ if ($d == r"manyPrimitives(IZCD)J") {
+ final $r = _$impls[$p]!.manyPrimitives(
+ $a[0]
+ .castTo(const jni.JIntegerType(), releaseOriginal: true)
+ .intValue(releaseOriginal: true),
+ $a[1]
+ .castTo(const jni.JBooleanType(), releaseOriginal: true)
+ .booleanValue(releaseOriginal: true),
+ $a[2]
+ .castTo(const jni.JCharacterType(), releaseOriginal: true)
+ .charValue(releaseOriginal: true),
+ $a[3]
+ .castTo(const jni.JDoubleType(), releaseOriginal: true)
+ .doubleValue(releaseOriginal: true),
+ );
+ return jni.JLong($r).toPointer();
+ }
+ } catch (e) {
+ return ProtectedJniExtensions.newDartException(e.toString());
+ }
+ return jni.nullptr;
+ }
+
+ factory MyInterface.implement(
+ $MyInterfaceImpl<$T> $impl,
+ ) {
+ final $p = ReceivePort();
+ final $x = MyInterface.fromRef(
+ $impl.T,
+ ProtectedJniExtensions.newPortProxy(
+ r"com.github.dart_lang.jnigen.interfaces.MyInterface",
+ $p,
+ _$invokePointer,
+ ),
+ ).._$p = $p;
+ final $a = $p.sendPort.nativePort;
+ _$impls[$a] = $impl;
+ $p.listen(($m) {
+ if ($m == null) {
+ _$impls.remove($p.sendPort.nativePort);
+ $p.close();
+ return;
+ }
+ final $i = $MethodInvocation.fromMessage($m as List<dynamic>);
+ final $r = _$invokeMethod($p.sendPort.nativePort, $i);
+ ProtectedJniExtensions.returnResult($i.result, $r);
+ });
+ return $x;
+ }
+ static Map<int, $MyInterfaceImpl> get $impls => _$impls;
+}
+
+abstract interface class $MyInterfaceImpl<$T extends jni.JObject> {
+ factory $MyInterfaceImpl({
+ required jni.JObjType<$T> T,
+ required void Function(jni.JString s) voidCallback,
+ required jni.JString Function(jni.JString s) stringCallback,
+ required $T Function($T t) varCallback,
+ required int Function(int a, bool b, int c, double d) manyPrimitives,
+ }) = _$MyInterfaceImpl;
+
+ jni.JObjType<$T> get T;
+
+ void voidCallback(jni.JString s);
+ jni.JString stringCallback(jni.JString s);
+ $T varCallback($T t);
+ int manyPrimitives(int a, bool b, int c, double d);
+}
+
+class _$MyInterfaceImpl<$T extends jni.JObject>
+ implements $MyInterfaceImpl<$T> {
+ _$MyInterfaceImpl({
+ required this.T,
+ required void Function(jni.JString s) voidCallback,
+ required jni.JString Function(jni.JString s) stringCallback,
+ required $T Function($T t) varCallback,
+ required int Function(int a, bool b, int c, double d) manyPrimitives,
+ }) : _voidCallback = voidCallback,
+ _stringCallback = stringCallback,
+ _varCallback = varCallback,
+ _manyPrimitives = manyPrimitives;
+
+ @override
+ final jni.JObjType<$T> T;
+
+ final void Function(jni.JString s) _voidCallback;
+ final jni.JString Function(jni.JString s) _stringCallback;
+ final $T Function($T t) _varCallback;
+ final int Function(int a, bool b, int c, double d) _manyPrimitives;
+
+ void voidCallback(jni.JString s) {
+ return _voidCallback(s);
+ }
+
+ jni.JString stringCallback(jni.JString s) {
+ return _stringCallback(s);
+ }
+
+ $T varCallback($T t) {
+ return _varCallback(t);
+ }
+
+ int manyPrimitives(int a, bool b, int c, double d) {
+ return _manyPrimitives(a, b, c, d);
+ }
+}
+
+final class $MyInterfaceType<$T extends jni.JObject>
+ extends jni.JObjType<MyInterface<$T>> {
+ final jni.JObjType<$T> T;
+
+ const $MyInterfaceType(
+ this.T,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/interfaces/MyInterface;";
+
+ @override
+ MyInterface<$T> fromRef(jni.JObjectPtr ref) => MyInterface.fromRef(T, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($MyInterfaceType, T);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($MyInterfaceType<$T>) &&
+ other is $MyInterfaceType<$T> &&
+ T == other.T;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.interfaces.MyInterfaceConsumer
+class MyInterfaceConsumer extends jni.JObject {
+ @override
+ late final jni.JObjType<MyInterfaceConsumer> $type = type;
+
+ MyInterfaceConsumer.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $MyInterfaceConsumerType();
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "MyInterfaceConsumer__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory MyInterfaceConsumer() {
+ return MyInterfaceConsumer.fromRef(_new0().object);
+ }
+
+ static final _consumeOnAnotherThread = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32,
+ ffi.Uint8,
+ ffi.Uint16,
+ ffi.Double,
+ ffi.Pointer<ffi.Void>)>>(
+ "MyInterfaceConsumer__consumeOnAnotherThread")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ int, int, int, double, ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public void consumeOnAnotherThread(com.github.dart_lang.jnigen.interfaces.MyInterface<T> myInterface, java.lang.String s, int a, boolean b, char c, double d, T t)
+ static void consumeOnAnotherThread<$T extends jni.JObject>(
+ MyInterface<$T> myInterface,
+ jni.JString s,
+ int a,
+ bool b,
+ int c,
+ double d,
+ $T t, {
+ jni.JObjType<$T>? T,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ t.$type,
+ (myInterface.$type as $MyInterfaceType).T,
+ ]) as jni.JObjType<$T>;
+ return _consumeOnAnotherThread(
+ myInterface.reference, s.reference, a, b ? 1 : 0, c, d, t.reference)
+ .check();
+ }
+
+ static final _consumeOnSameThread = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ ffi.Pointer<ffi.Void>,
+ ffi.Pointer<ffi.Void>,
+ ffi.Int32,
+ ffi.Uint8,
+ ffi.Uint16,
+ ffi.Double,
+ ffi.Pointer<ffi.Void>)>>(
+ "MyInterfaceConsumer__consumeOnSameThread")
+ .asFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
+ int, int, int, double, ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public void consumeOnSameThread(com.github.dart_lang.jnigen.interfaces.MyInterface<T> myInterface, java.lang.String s, int a, boolean b, char c, double d, T t)
+ static void consumeOnSameThread<$T extends jni.JObject>(
+ MyInterface<$T> myInterface,
+ jni.JString s,
+ int a,
+ bool b,
+ int c,
+ double d,
+ $T t, {
+ jni.JObjType<$T>? T,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ t.$type,
+ (myInterface.$type as $MyInterfaceType).T,
+ ]) as jni.JObjType<$T>;
+ return _consumeOnSameThread(
+ myInterface.reference, s.reference, a, b ? 1 : 0, c, d, t.reference)
+ .check();
+ }
+}
+
+final class $MyInterfaceConsumerType extends jni.JObjType<MyInterfaceConsumer> {
+ const $MyInterfaceConsumerType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/interfaces/MyInterfaceConsumer;";
+
+ @override
+ MyInterfaceConsumer fromRef(jni.JObjectPtr ref) =>
+ MyInterfaceConsumer.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($MyInterfaceConsumerType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($MyInterfaceConsumerType) &&
+ other is $MyInterfaceConsumerType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.interfaces.MyRunnable
+class MyRunnable extends jni.JObject {
+ @override
+ late final jni.JObjType<MyRunnable> $type = type;
+
+ MyRunnable.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $MyRunnableType();
+ static final _run = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(ffi.Pointer<ffi.Void>)>>("MyRunnable__run")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public abstract void run()
+ void run() {
+ return _run(reference).check();
+ }
+
+ /// Maps a specific port to the implemented interface.
+ static final Map<int, $MyRunnableImpl> _$impls = {};
+ ReceivePort? _$p;
+
+ static jni.JObjectPtr _$invoke(
+ int port,
+ jni.JObjectPtr descriptor,
+ jni.JObjectPtr args,
+ ) {
+ return _$invokeMethod(
+ port,
+ $MethodInvocation.fromAddresses(
+ 0,
+ descriptor.address,
+ args.address,
+ ),
+ );
+ }
+
+ static final ffi.Pointer<
+ ffi.NativeFunction<
+ jni.JObjectPtr Function(
+ ffi.Uint64, jni.JObjectPtr, jni.JObjectPtr)>>
+ _$invokePointer = ffi.Pointer.fromFunction(_$invoke);
+
+ static ffi.Pointer<ffi.Void> _$invokeMethod(
+ int $p,
+ $MethodInvocation $i,
+ ) {
+ try {
+ final $d = $i.methodDescriptor.toDartString(releaseOriginal: true);
+ final $a = $i.args;
+ if ($d == r"run()V") {
+ _$impls[$p]!.run();
+ return jni.nullptr;
+ }
+ } catch (e) {
+ return ProtectedJniExtensions.newDartException(e.toString());
+ }
+ return jni.nullptr;
+ }
+
+ factory MyRunnable.implement(
+ $MyRunnableImpl $impl,
+ ) {
+ final $p = ReceivePort();
+ final $x = MyRunnable.fromRef(
+ ProtectedJniExtensions.newPortProxy(
+ r"com.github.dart_lang.jnigen.interfaces.MyRunnable",
+ $p,
+ _$invokePointer,
+ ),
+ ).._$p = $p;
+ final $a = $p.sendPort.nativePort;
+ _$impls[$a] = $impl;
+ $p.listen(($m) {
+ if ($m == null) {
+ _$impls.remove($p.sendPort.nativePort);
+ $p.close();
+ return;
+ }
+ final $i = $MethodInvocation.fromMessage($m as List<dynamic>);
+ final $r = _$invokeMethod($p.sendPort.nativePort, $i);
+ ProtectedJniExtensions.returnResult($i.result, $r);
+ });
+ return $x;
+ }
+}
+
+abstract interface class $MyRunnableImpl {
+ factory $MyRunnableImpl({
+ required void Function() run,
+ }) = _$MyRunnableImpl;
+
+ void run();
+}
+
+class _$MyRunnableImpl implements $MyRunnableImpl {
+ _$MyRunnableImpl({
+ required void Function() run,
+ }) : _run = run;
+
+ final void Function() _run;
+
+ void run() {
+ return _run();
+ }
+}
+
+final class $MyRunnableType extends jni.JObjType<MyRunnable> {
+ const $MyRunnableType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/interfaces/MyRunnable;";
+
+ @override
+ MyRunnable fromRef(jni.JObjectPtr ref) => MyRunnable.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($MyRunnableType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($MyRunnableType) && other is $MyRunnableType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.interfaces.MyRunnableRunner
+class MyRunnableRunner extends jni.JObject {
+ @override
+ late final jni.JObjType<MyRunnableRunner> $type = type;
+
+ MyRunnableRunner.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $MyRunnableRunnerType();
+ static final _get_error = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>>("get_MyRunnableRunner__error")
+ .asFunction<
+ jni.JniResult Function(
+ jni.JObjectPtr,
+ )>();
+
+ static final _set_error = jniLookup<
+ ffi.NativeFunction<
+ jni.JniResult Function(jni.JObjectPtr,
+ ffi.Pointer<ffi.Void>)>>("set_MyRunnableRunner__error")
+ .asFunction<
+ jni.JniResult Function(jni.JObjectPtr, ffi.Pointer<ffi.Void>)>();
+
+ /// from: public java.lang.Throwable error
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject get error =>
+ const jni.JObjectType().fromRef(_get_error(reference).object);
+
+ /// from: public java.lang.Throwable error
+ /// The returned object must be released after use, by calling the [release] method.
+ set error(jni.JObject value) =>
+ _set_error(reference, value.reference).check();
+
+ static final _new0 = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "MyRunnableRunner__new0")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void <init>(com.github.dart_lang.jnigen.interfaces.MyRunnable runnable)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory MyRunnableRunner(
+ MyRunnable runnable,
+ ) {
+ return MyRunnableRunner.fromRef(_new0(runnable.reference).object);
+ }
+
+ static final _runOnSameThread = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "MyRunnableRunner__runOnSameThread")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void runOnSameThread()
+ void runOnSameThread() {
+ return _runOnSameThread(reference).check();
+ }
+
+ static final _runOnAnotherThread = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "MyRunnableRunner__runOnAnotherThread")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: public void runOnAnotherThread()
+ void runOnAnotherThread() {
+ return _runOnAnotherThread(reference).check();
+ }
+}
+
+final class $MyRunnableRunnerType extends jni.JObjType<MyRunnableRunner> {
+ const $MyRunnableRunnerType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/interfaces/MyRunnableRunner;";
+
+ @override
+ MyRunnableRunner fromRef(jni.JObjectPtr ref) => MyRunnableRunner.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($MyRunnableRunnerType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($MyRunnableRunnerType) &&
+ other is $MyRunnableRunnerType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.annotations.JsonSerializable$Case
+class JsonSerializable_Case extends jni.JObject {
+ @override
+ late final jni.JObjType<JsonSerializable_Case> $type = type;
+
+ JsonSerializable_Case.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $JsonSerializable_CaseType();
+ static final _values =
+ jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "JsonSerializable_Case__values")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: static public com.github.dart_lang.jnigen.annotations.JsonSerializable.Case[] values()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<JsonSerializable_Case> values() {
+ return const jni.JArrayType($JsonSerializable_CaseType())
+ .fromRef(_values().object);
+ }
+
+ static final _valueOf = jniLookup<
+ ffi
+ .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
+ "JsonSerializable_Case__valueOf")
+ .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();
+
+ /// from: static public com.github.dart_lang.jnigen.annotations.JsonSerializable.Case valueOf(java.lang.String name)
+ /// The returned object must be released after use, by calling the [release] method.
+ static JsonSerializable_Case valueOf(
+ jni.JString name,
+ ) {
+ return const $JsonSerializable_CaseType()
+ .fromRef(_valueOf(name.reference).object);
+ }
+}
+
+final class $JsonSerializable_CaseType
+ extends jni.JObjType<JsonSerializable_Case> {
+ const $JsonSerializable_CaseType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/annotations/JsonSerializable$Case;";
+
+ @override
+ JsonSerializable_Case fromRef(jni.JObjectPtr ref) =>
+ JsonSerializable_Case.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($JsonSerializable_CaseType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($JsonSerializable_CaseType) &&
+ other is $JsonSerializable_CaseType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.annotations.MyDataClass
+class MyDataClass extends jni.JObject {
+ @override
+ late final jni.JObjType<MyDataClass> $type = type;
+
+ MyDataClass.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $MyDataClassType();
+ static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
+ "MyDataClass__new0")
+ .asFunction<jni.JniResult Function()>();
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory MyDataClass() {
+ return MyDataClass.fromRef(_new0().object);
+ }
+}
+
+final class $MyDataClassType extends jni.JObjType<MyDataClass> {
+ const $MyDataClassType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/annotations/MyDataClass;";
+
+ @override
+ MyDataClass fromRef(jni.JObjectPtr ref) => MyDataClass.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($MyDataClassType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($MyDataClassType) && other is $MyDataClassType;
+ }
+}
diff --git a/pkgs/jnigen/test/simple_package_test/dart_only/dart_bindings/simple_package.dart b/pkgs/jnigen/test/simple_package_test/dart_only/dart_bindings/simple_package.dart
new file mode 100644
index 0000000..8e0f1ce
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/dart_only/dart_bindings/simple_package.dart
@@ -0,0 +1,3806 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Autogenerated by jnigen. DO NOT EDIT!
+
+// ignore_for_file: annotate_overrides
+// ignore_for_file: camel_case_extensions
+// ignore_for_file: camel_case_types
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: doc_directive_unknown
+// ignore_for_file: file_names
+// ignore_for_file: lines_longer_than_80_chars
+// ignore_for_file: no_leading_underscores_for_local_identifiers
+// ignore_for_file: non_constant_identifier_names
+// ignore_for_file: overridden_fields
+// ignore_for_file: unnecessary_cast
+// ignore_for_file: unused_element
+// ignore_for_file: unused_field
+// ignore_for_file: unused_import
+// ignore_for_file: unused_local_variable
+// ignore_for_file: unused_shown_name
+
+import "dart:isolate" show ReceivePort;
+import "dart:ffi" as ffi;
+import "package:jni/internal_helpers_for_jnigen.dart";
+import "package:jni/jni.dart" as jni;
+
+/// from: com.github.dart_lang.jnigen.simple_package.Color
+class Color extends jni.JObject {
+ @override
+ late final jni.JObjType<Color> $type = type;
+
+ Color.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/github/dart_lang/jnigen/simple_package/Color");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $ColorType();
+ static final _id_values = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"values",
+ r"()[Lcom/github/dart_lang/jnigen/simple_package/Color;");
+
+ /// from: static public com.github.dart_lang.jnigen.simple_package.Color[] values()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<Color> values() {
+ return const jni.JArrayType($ColorType()).fromRef(jni.Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _id_values,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_valueOf = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"valueOf",
+ r"(Ljava/lang/String;)Lcom/github/dart_lang/jnigen/simple_package/Color;");
+
+ /// from: static public com.github.dart_lang.jnigen.simple_package.Color valueOf(java.lang.String name)
+ /// The returned object must be released after use, by calling the [release] method.
+ static Color valueOf(
+ jni.JString name,
+ ) {
+ return const $ColorType().fromRef(jni.Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _id_valueOf,
+ jni.JniCallType.objectType, [name.reference]).object);
+ }
+}
+
+final class $ColorType extends jni.JObjType<Color> {
+ const $ColorType();
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/simple_package/Color;";
+
+ @override
+ Color fromRef(jni.JObjectPtr ref) => Color.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($ColorType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($ColorType) && other is $ColorType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.simple_package.Example
+class Example extends jni.JObject {
+ @override
+ late final jni.JObjType<Example> $type = type;
+
+ Example.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/github/dart_lang/jnigen/simple_package/Example");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $ExampleType();
+
+ /// from: static public final int ON
+ static const ON = 1;
+
+ /// from: static public final int OFF
+ static const OFF = 0;
+
+ /// from: static public final double PI
+ static const PI = 3.14159;
+
+ /// from: static public final char SEMICOLON
+ static const SEMICOLON = 59;
+
+ /// from: static public final java.lang.String SEMICOLON_STRING
+ static const SEMICOLON_STRING = r""";""";
+
+ static final _id_unusedRandom = jni.Jni.accessors.getStaticFieldIDOf(
+ _class.reference,
+ r"unusedRandom",
+ r"Ljava/util/Random;",
+ );
+
+ /// from: static public final java.util.Random unusedRandom
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JObject get unusedRandom =>
+ const jni.JObjectType().fromRef(jni.Jni.accessors
+ .getStaticField(
+ _class.reference, _id_unusedRandom, jni.JniCallType.objectType)
+ .object);
+
+ static final _id_protectedField = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"protectedField",
+ r"Ljava/util/Random;",
+ );
+
+ /// from: protected java.util.Random protectedField
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject get protectedField =>
+ const jni.JObjectType().fromRef(jni.Jni.accessors
+ .getField(reference, _id_protectedField, jni.JniCallType.objectType)
+ .object);
+
+ /// from: protected java.util.Random protectedField
+ /// The returned object must be released after use, by calling the [release] method.
+ set protectedField(jni.JObject value) => jni.Jni.env
+ .SetObjectField(reference, _id_protectedField, value.reference);
+
+ static final _id_getAmount = jni.Jni.accessors
+ .getStaticMethodIDOf(_class.reference, r"getAmount", r"()I");
+
+ /// from: static public int getAmount()
+ static int getAmount() {
+ return jni.Jni.accessors.callStaticMethodWithArgs(
+ _class.reference, _id_getAmount, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_getPi =
+ jni.Jni.accessors.getStaticMethodIDOf(_class.reference, r"getPi", r"()D");
+
+ /// from: static public double getPi()
+ static double getPi() {
+ return jni.Jni.accessors.callStaticMethodWithArgs(_class.reference,
+ _id_getPi, jni.JniCallType.doubleType, []).doubleFloat;
+ }
+
+ static final _id_getAsterisk = jni.Jni.accessors
+ .getStaticMethodIDOf(_class.reference, r"getAsterisk", r"()C");
+
+ /// from: static public char getAsterisk()
+ static int getAsterisk() {
+ return jni.Jni.accessors.callStaticMethodWithArgs(
+ _class.reference, _id_getAsterisk, jni.JniCallType.charType, []).char;
+ }
+
+ static final _id_getName = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference, r"getName", r"()Ljava/lang/String;");
+
+ /// from: static public java.lang.String getName()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString getName() {
+ return const jni.JStringType().fromRef(jni.Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _id_getName,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_getNestedInstance = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"getNestedInstance",
+ r"()Lcom/github/dart_lang/jnigen/simple_package/Example$Nested;");
+
+ /// from: static public com.github.dart_lang.jnigen.simple_package.Example.Nested getNestedInstance()
+ /// The returned object must be released after use, by calling the [release] method.
+ static Example_Nested getNestedInstance() {
+ return const $Example_NestedType().fromRef(jni.Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _id_getNestedInstance,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_setAmount = jni.Jni.accessors
+ .getStaticMethodIDOf(_class.reference, r"setAmount", r"(I)V");
+
+ /// from: static public void setAmount(int newAmount)
+ static void setAmount(
+ int newAmount,
+ ) {
+ return jni.Jni.accessors.callStaticMethodWithArgs(
+ _class.reference,
+ _id_setAmount,
+ jni.JniCallType.voidType,
+ [jni.JValueInt(newAmount)]).check();
+ }
+
+ static final _id_setName = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference, r"setName", r"(Ljava/lang/String;)V");
+
+ /// from: static public void setName(java.lang.String newName)
+ static void setName(
+ jni.JString newName,
+ ) {
+ return jni.Jni.accessors.callStaticMethodWithArgs(_class.reference,
+ _id_setName, jni.JniCallType.voidType, [newName.reference]).check();
+ }
+
+ static final _id_setNestedInstance = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"setNestedInstance",
+ r"(Lcom/github/dart_lang/jnigen/simple_package/Example$Nested;)V");
+
+ /// from: static public void setNestedInstance(com.github.dart_lang.jnigen.simple_package.Example.Nested newNested)
+ static void setNestedInstance(
+ Example_Nested newNested,
+ ) {
+ return jni.Jni.accessors.callStaticMethodWithArgs(
+ _class.reference,
+ _id_setNestedInstance,
+ jni.JniCallType.voidType,
+ [newNested.reference]).check();
+ }
+
+ static final _id_max4 = jni.Jni.accessors
+ .getStaticMethodIDOf(_class.reference, r"max4", r"(IIII)I");
+
+ /// from: static public int max4(int a, int b, int c, int d)
+ static int max4(
+ int a,
+ int b,
+ int c,
+ int d,
+ ) {
+ return jni.Jni.accessors.callStaticMethodWithArgs(
+ _class.reference, _id_max4, jni.JniCallType.intType, [
+ jni.JValueInt(a),
+ jni.JValueInt(b),
+ jni.JValueInt(c),
+ jni.JValueInt(d)
+ ]).integer;
+ }
+
+ static final _id_max8 = jni.Jni.accessors
+ .getStaticMethodIDOf(_class.reference, r"max8", r"(IIIIIIII)I");
+
+ /// from: static public int max8(int a, int b, int c, int d, int e, int f, int g, int h)
+ static int max8(
+ int a,
+ int b,
+ int c,
+ int d,
+ int e,
+ int f,
+ int g,
+ int h,
+ ) {
+ return jni.Jni.accessors.callStaticMethodWithArgs(
+ _class.reference, _id_max8, jni.JniCallType.intType, [
+ jni.JValueInt(a),
+ jni.JValueInt(b),
+ jni.JValueInt(c),
+ jni.JValueInt(d),
+ jni.JValueInt(e),
+ jni.JValueInt(f),
+ jni.JValueInt(g),
+ jni.JValueInt(h)
+ ]).integer;
+ }
+
+ static final _id_getNumber =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"getNumber", r"()I");
+
+ /// from: public int getNumber()
+ int getNumber() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getNumber, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_setNumber =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"setNumber", r"(I)V");
+
+ /// from: public void setNumber(int number)
+ void setNumber(
+ int number,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_setNumber,
+ jni.JniCallType.voidType, [jni.JValueInt(number)]).check();
+ }
+
+ static final _id_getIsUp =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"getIsUp", r"()Z");
+
+ /// from: public boolean getIsUp()
+ bool getIsUp() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getIsUp, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_setUp =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"setUp", r"(Z)V");
+
+ /// from: public void setUp(boolean isUp)
+ void setUp(
+ bool isUp,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_setUp, jni.JniCallType.voidType, [isUp ? 1 : 0]).check();
+ }
+
+ static final _id_getCodename = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getCodename", r"()Ljava/lang/String;");
+
+ /// from: public java.lang.String getCodename()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JString getCodename() {
+ return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getCodename, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_setCodename = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"setCodename", r"(Ljava/lang/String;)V");
+
+ /// from: public void setCodename(java.lang.String codename)
+ void setCodename(
+ jni.JString codename,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_setCodename,
+ jni.JniCallType.voidType, [codename.reference]).check();
+ }
+
+ static final _id_getRandom = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getRandom", r"()Ljava/util/Random;");
+
+ /// from: public java.util.Random getRandom()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject getRandom() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getRandom, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_setRandom = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"setRandom", r"(Ljava/util/Random;)V");
+
+ /// from: public void setRandom(java.util.Random random)
+ void setRandom(
+ jni.JObject random,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_setRandom,
+ jni.JniCallType.voidType, [random.reference]).check();
+ }
+
+ static final _id_getRandomLong = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getRandomLong", r"()J");
+
+ /// from: public long getRandomLong()
+ int getRandomLong() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getRandomLong, jni.JniCallType.longType, []).long;
+ }
+
+ static final _id_add4Longs = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"add4Longs", r"(JJJJ)J");
+
+ /// from: public long add4Longs(long a, long b, long c, long d)
+ int add4Longs(
+ int a,
+ int b,
+ int c,
+ int d,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_add4Longs, jni.JniCallType.longType, [a, b, c, d]).long;
+ }
+
+ static final _id_add8Longs = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"add8Longs", r"(JJJJJJJJ)J");
+
+ /// from: public long add8Longs(long a, long b, long c, long d, long e, long f, long g, long h)
+ int add8Longs(
+ int a,
+ int b,
+ int c,
+ int d,
+ int e,
+ int f,
+ int g,
+ int h,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_add8Longs,
+ jni.JniCallType.longType, [a, b, c, d, e, f, g, h]).long;
+ }
+
+ static final _id_getRandomNumericString = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"getRandomNumericString",
+ r"(Ljava/util/Random;)Ljava/lang/String;");
+
+ /// from: public java.lang.String getRandomNumericString(java.util.Random random)
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JString getRandomNumericString(
+ jni.JObject random,
+ ) {
+ return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_getRandomNumericString,
+ jni.JniCallType.objectType,
+ [random.reference]).object);
+ }
+
+ static final _id_protectedMethod = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"protectedMethod",
+ r"(Ljava/lang/String;Ljava/lang/String;)V");
+
+ /// from: protected void protectedMethod(java.lang.String a, java.lang.String b)
+ void protectedMethod(
+ jni.JString a,
+ jni.JString b,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_protectedMethod,
+ jni.JniCallType.voidType, [a.reference, b.reference]).check();
+ }
+
+ static final _id_finalMethod =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"finalMethod", r"()V");
+
+ /// from: public final void finalMethod()
+ void finalMethod() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_finalMethod, jni.JniCallType.voidType, []).check();
+ }
+
+ static final _id_getList = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"getList", r"()Ljava/util/List;");
+
+ /// from: public java.util.List<java.lang.String> getList()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JList<jni.JString> getList() {
+ return const jni.JListType(jni.JStringType()).fromRef(jni.Jni.accessors
+ .callMethodWithArgs(
+ reference, _id_getList, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_joinStrings = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"joinStrings",
+ r"(Ljava/util/List;Ljava/lang/String;)Ljava/lang/String;");
+
+ /// from: public java.lang.String joinStrings(java.util.List<java.lang.String> values, java.lang.String delim)
+ /// The returned object must be released after use, by calling the [release] method.
+ ///
+ /// Joins the strings in the list using the given delimiter.
+ jni.JString joinStrings(
+ jni.JList<jni.JString> values,
+ jni.JString delim,
+ ) {
+ return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_joinStrings,
+ jni.JniCallType.objectType,
+ [values.reference, delim.reference]).object);
+ }
+
+ static final _id_methodWithSeveralParams = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"methodWithSeveralParams",
+ r"(CLjava/lang/String;[ILjava/lang/CharSequence;Ljava/util/List;Ljava/util/Map;)V");
+
+ /// from: public void methodWithSeveralParams(char ch, java.lang.String s, int[] a, T t, java.util.List<T> lt, java.util.Map<java.lang.String,? extends java.lang.CharSequence> wm)
+ void methodWithSeveralParams<$T extends jni.JObject>(
+ int ch,
+ jni.JString s,
+ jni.JArray<jni.jint> a,
+ $T t,
+ jni.JList<$T> lt,
+ jni.JMap<jni.JString, jni.JObject> wm, {
+ jni.JObjType<$T>? T,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ (lt.$type as jni.JListType).E,
+ t.$type,
+ ]) as jni.JObjType<$T>;
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_methodWithSeveralParams, jni.JniCallType.voidType, [
+ jni.JValueChar(ch),
+ s.reference,
+ a.reference,
+ t.reference,
+ lt.reference,
+ wm.reference
+ ]).check();
+ }
+
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example() {
+ return Example.fromRef(jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+
+ static final _id_new1 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"(I)V");
+
+ /// from: public void <init>(int number)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example.new1(
+ int number,
+ ) {
+ return Example.fromRef(jni.Jni.accessors.newObjectWithArgs(
+ _class.reference, _id_new1, [jni.JValueInt(number)]).object);
+ }
+
+ static final _id_new2 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"(IZ)V");
+
+ /// from: public void <init>(int number, boolean isUp)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example.new2(
+ int number,
+ bool isUp,
+ ) {
+ return Example.fromRef(jni.Jni.accessors.newObjectWithArgs(_class.reference,
+ _id_new2, [jni.JValueInt(number), isUp ? 1 : 0]).object);
+ }
+
+ static final _id_new3 = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"<init>", r"(IZLjava/lang/String;)V");
+
+ /// from: public void <init>(int number, boolean isUp, java.lang.String codename)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example.new3(
+ int number,
+ bool isUp,
+ jni.JString codename,
+ ) {
+ return Example.fromRef(jni.Jni.accessors.newObjectWithArgs(
+ _class.reference,
+ _id_new3,
+ [jni.JValueInt(number), isUp ? 1 : 0, codename.reference]).object);
+ }
+
+ static final _id_new4 = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"<init>", r"(IIIIIIII)V");
+
+ /// from: public void <init>(int a, int b, int c, int d, int e, int f, int g, int h)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example.new4(
+ int a,
+ int b,
+ int c,
+ int d,
+ int e,
+ int f,
+ int g,
+ int h,
+ ) {
+ return Example.fromRef(
+ jni.Jni.accessors.newObjectWithArgs(_class.reference, _id_new4, [
+ jni.JValueInt(a),
+ jni.JValueInt(b),
+ jni.JValueInt(c),
+ jni.JValueInt(d),
+ jni.JValueInt(e),
+ jni.JValueInt(f),
+ jni.JValueInt(g),
+ jni.JValueInt(h)
+ ]).object);
+ }
+
+ static final _id_whichExample = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"whichExample", r"()I");
+
+ /// from: public int whichExample()
+ int whichExample() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_whichExample, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_addInts = jni.Jni.accessors
+ .getStaticMethodIDOf(_class.reference, r"addInts", r"(II)I");
+
+ /// from: static public int addInts(int a, int b)
+ static int addInts(
+ int a,
+ int b,
+ ) {
+ return jni.Jni.accessors.callStaticMethodWithArgs(
+ _class.reference,
+ _id_addInts,
+ jni.JniCallType.intType,
+ [jni.JValueInt(a), jni.JValueInt(b)]).integer;
+ }
+
+ static final _id_getArr = jni.Jni.accessors
+ .getStaticMethodIDOf(_class.reference, r"getArr", r"()[I");
+
+ /// from: static public int[] getArr()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<jni.jint> getArr() {
+ return const jni.JArrayType(jni.jintType()).fromRef(jni.Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _id_getArr,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_addAll = jni.Jni.accessors
+ .getStaticMethodIDOf(_class.reference, r"addAll", r"([I)I");
+
+ /// from: static public int addAll(int[] arr)
+ static int addAll(
+ jni.JArray<jni.jint> arr,
+ ) {
+ return jni.Jni.accessors.callStaticMethodWithArgs(_class.reference,
+ _id_addAll, jni.JniCallType.intType, [arr.reference]).integer;
+ }
+
+ static final _id_getSelf = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"getSelf", r"()Lcom/github/dart_lang/jnigen/simple_package/Example;");
+
+ /// from: public com.github.dart_lang.jnigen.simple_package.Example getSelf()
+ /// The returned object must be released after use, by calling the [release] method.
+ Example getSelf() {
+ return const $ExampleType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getSelf, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_throwException = jni.Jni.accessors
+ .getStaticMethodIDOf(_class.reference, r"throwException", r"()V");
+
+ /// from: static public void throwException()
+ static void throwException() {
+ return jni.Jni.accessors.callStaticMethodWithArgs(_class.reference,
+ _id_throwException, jni.JniCallType.voidType, []).check();
+ }
+
+ static final _id_overloaded =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"overloaded", r"()V");
+
+ /// from: public void overloaded()
+ void overloaded() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_overloaded, jni.JniCallType.voidType, []).check();
+ }
+
+ static final _id_overloaded1 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"overloaded", r"(ILjava/lang/String;)V");
+
+ /// from: public void overloaded(int a, java.lang.String b)
+ void overloaded1(
+ int a,
+ jni.JString b,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_overloaded1,
+ jni.JniCallType.voidType, [jni.JValueInt(a), b.reference]).check();
+ }
+
+ static final _id_overloaded2 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"overloaded", r"(I)V");
+
+ /// from: public void overloaded(int a)
+ void overloaded2(
+ int a,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_overloaded2,
+ jni.JniCallType.voidType, [jni.JValueInt(a)]).check();
+ }
+
+ static final _id_overloaded3 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"overloaded",
+ r"(Ljava/util/List;Ljava/lang/String;)V");
+
+ /// from: public void overloaded(java.util.List<java.lang.Integer> a, java.lang.String b)
+ void overloaded3(
+ jni.JList<jni.JInteger> a,
+ jni.JString b,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_overloaded3,
+ jni.JniCallType.voidType, [a.reference, b.reference]).check();
+ }
+
+ static final _id_overloaded4 = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"overloaded", r"(Ljava/util/List;)V");
+
+ /// from: public void overloaded(java.util.List<java.lang.Integer> a)
+ void overloaded4(
+ jni.JList<jni.JInteger> a,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_overloaded4,
+ jni.JniCallType.voidType, [a.reference]).check();
+ }
+}
+
+final class $ExampleType extends jni.JObjType<Example> {
+ const $ExampleType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/simple_package/Example;";
+
+ @override
+ Example fromRef(jni.JObjectPtr ref) => Example.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($ExampleType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($ExampleType) && other is $ExampleType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.simple_package.Example$Nested
+class Example_Nested extends jni.JObject {
+ @override
+ late final jni.JObjType<Example_Nested> $type = type;
+
+ Example_Nested.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = jni.Jni.findJClass(
+ r"com/github/dart_lang/jnigen/simple_package/Example$Nested");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $Example_NestedType();
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"(Z)V");
+
+ /// from: public void <init>(boolean value)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example_Nested(
+ bool value,
+ ) {
+ return Example_Nested.fromRef(jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, [value ? 1 : 0]).object);
+ }
+
+ static final _id_usesAnonymousInnerClass = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"usesAnonymousInnerClass", r"()V");
+
+ /// from: public void usesAnonymousInnerClass()
+ void usesAnonymousInnerClass() {
+ return jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_usesAnonymousInnerClass, jni.JniCallType.voidType, []).check();
+ }
+
+ static final _id_getValue =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"getValue", r"()Z");
+
+ /// from: public boolean getValue()
+ bool getValue() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_getValue, jni.JniCallType.booleanType, []).boolean;
+ }
+
+ static final _id_setValue =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"setValue", r"(Z)V");
+
+ /// from: public void setValue(boolean value)
+ void setValue(
+ bool value,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_setValue,
+ jni.JniCallType.voidType, [value ? 1 : 0]).check();
+ }
+}
+
+final class $Example_NestedType extends jni.JObjType<Example_Nested> {
+ const $Example_NestedType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/simple_package/Example$Nested;";
+
+ @override
+ Example_Nested fromRef(jni.JObjectPtr ref) => Example_Nested.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($Example_NestedType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($Example_NestedType) &&
+ other is $Example_NestedType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.simple_package.Example$Nested$NestedTwice
+class Example_Nested_NestedTwice extends jni.JObject {
+ @override
+ late final jni.JObjType<Example_Nested_NestedTwice> $type = type;
+
+ Example_Nested_NestedTwice.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = jni.Jni.findJClass(
+ r"com/github/dart_lang/jnigen/simple_package/Example$Nested$NestedTwice");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $Example_Nested_NestedTwiceType();
+ static final _id_ZERO = jni.Jni.accessors.getStaticFieldIDOf(
+ _class.reference,
+ r"ZERO",
+ r"I",
+ );
+
+ /// from: static public int ZERO
+ static int get ZERO => jni.Jni.accessors
+ .getStaticField(_class.reference, _id_ZERO, jni.JniCallType.intType)
+ .integer;
+
+ /// from: static public int ZERO
+ static set ZERO(int value) =>
+ jni.Jni.env.SetStaticIntField(_class.reference, _id_ZERO, value);
+
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example_Nested_NestedTwice() {
+ return Example_Nested_NestedTwice.fromRef(jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+}
+
+final class $Example_Nested_NestedTwiceType
+ extends jni.JObjType<Example_Nested_NestedTwice> {
+ const $Example_Nested_NestedTwiceType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/simple_package/Example$Nested$NestedTwice;";
+
+ @override
+ Example_Nested_NestedTwice fromRef(jni.JObjectPtr ref) =>
+ Example_Nested_NestedTwice.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($Example_Nested_NestedTwiceType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($Example_Nested_NestedTwiceType) &&
+ other is $Example_Nested_NestedTwiceType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.simple_package.Example$NonStaticNested
+class Example_NonStaticNested extends jni.JObject {
+ @override
+ late final jni.JObjType<Example_NonStaticNested> $type = type;
+
+ Example_NonStaticNested.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = jni.Jni.findJClass(
+ r"com/github/dart_lang/jnigen/simple_package/Example$NonStaticNested");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $Example_NonStaticNestedType();
+ static final _id_ok = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"ok",
+ r"Z",
+ );
+
+ /// from: public boolean ok
+ bool get ok => jni.Jni.accessors
+ .getField(reference, _id_ok, jni.JniCallType.booleanType)
+ .boolean;
+
+ /// from: public boolean ok
+ set ok(bool value) =>
+ jni.Jni.env.SetBooleanField(reference, _id_ok, value ? 1 : 0);
+
+ static final _id_new0 = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"<init>", r"(Lcom/github/dart_lang/jnigen/simple_package/Example;)V");
+
+ /// from: public void <init>(com.github.dart_lang.jnigen.simple_package.Example $parent)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example_NonStaticNested(
+ Example $parent,
+ ) {
+ return Example_NonStaticNested.fromRef(jni.Jni.accessors.newObjectWithArgs(
+ _class.reference, _id_new0, [$parent.reference]).object);
+ }
+}
+
+final class $Example_NonStaticNestedType
+ extends jni.JObjType<Example_NonStaticNested> {
+ const $Example_NonStaticNestedType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/simple_package/Example$NonStaticNested;";
+
+ @override
+ Example_NonStaticNested fromRef(jni.JObjectPtr ref) =>
+ Example_NonStaticNested.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($Example_NonStaticNestedType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($Example_NonStaticNestedType) &&
+ other is $Example_NonStaticNestedType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.simple_package.Exceptions
+class Exceptions extends jni.JObject {
+ @override
+ late final jni.JObjType<Exceptions> $type = type;
+
+ Exceptions.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = jni.Jni.findJClass(
+ r"com/github/dart_lang/jnigen/simple_package/Exceptions");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $ExceptionsType();
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Exceptions() {
+ return Exceptions.fromRef(jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+
+ static final _id_new1 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"(F)V");
+
+ /// from: public void <init>(float x)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Exceptions.new1(
+ double x,
+ ) {
+ return Exceptions.fromRef(jni.Jni.accessors.newObjectWithArgs(
+ _class.reference, _id_new1, [jni.JValueFloat(x)]).object);
+ }
+
+ static final _id_new2 = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"<init>", r"(IIIIII)V");
+
+ /// from: public void <init>(int a, int b, int c, int d, int e, int f)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Exceptions.new2(
+ int a,
+ int b,
+ int c,
+ int d,
+ int e,
+ int f,
+ ) {
+ return Exceptions.fromRef(
+ jni.Jni.accessors.newObjectWithArgs(_class.reference, _id_new2, [
+ jni.JValueInt(a),
+ jni.JValueInt(b),
+ jni.JValueInt(c),
+ jni.JValueInt(d),
+ jni.JValueInt(e),
+ jni.JValueInt(f)
+ ]).object);
+ }
+
+ static final _id_staticObjectMethod = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference, r"staticObjectMethod", r"()Ljava/lang/Object;");
+
+ /// from: static public java.lang.Object staticObjectMethod()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JObject staticObjectMethod() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _id_staticObjectMethod,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_staticIntMethod = jni.Jni.accessors
+ .getStaticMethodIDOf(_class.reference, r"staticIntMethod", r"()I");
+
+ /// from: static public int staticIntMethod()
+ static int staticIntMethod() {
+ return jni.Jni.accessors.callStaticMethodWithArgs(_class.reference,
+ _id_staticIntMethod, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_staticObjectArrayMethod = jni.Jni.accessors
+ .getStaticMethodIDOf(_class.reference, r"staticObjectArrayMethod",
+ r"()[Ljava/lang/Object;");
+
+ /// from: static public java.lang.Object[] staticObjectArrayMethod()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<jni.JObject> staticObjectArrayMethod() {
+ return const jni.JArrayType(jni.JObjectType()).fromRef(jni.Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _id_staticObjectArrayMethod,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_staticIntArrayMethod = jni.Jni.accessors
+ .getStaticMethodIDOf(_class.reference, r"staticIntArrayMethod", r"()[I");
+
+ /// from: static public int[] staticIntArrayMethod()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<jni.jint> staticIntArrayMethod() {
+ return const jni.JArrayType(jni.jintType()).fromRef(jni.Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _id_staticIntArrayMethod,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_objectMethod = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"objectMethod", r"()Ljava/lang/Object;");
+
+ /// from: public java.lang.Object objectMethod()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject objectMethod() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_objectMethod, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_intMethod =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"intMethod", r"()I");
+
+ /// from: public int intMethod()
+ int intMethod() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_intMethod, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_objectArrayMethod = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"objectArrayMethod", r"()[Ljava/lang/Object;");
+
+ /// from: public java.lang.Object[] objectArrayMethod()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JArray<jni.JObject> objectArrayMethod() {
+ return const jni.JArrayType(jni.JObjectType()).fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_objectArrayMethod,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_intArrayMethod = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"intArrayMethod", r"()[I");
+
+ /// from: public int[] intArrayMethod()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JArray<jni.jint> intArrayMethod() {
+ return const jni.JArrayType(jni.jintType()).fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_intArrayMethod,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_throwNullPointerException = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"throwNullPointerException", r"()I");
+
+ /// from: public int throwNullPointerException()
+ int throwNullPointerException() {
+ return jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_throwNullPointerException, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_throwFileNotFoundException = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"throwFileNotFoundException",
+ r"()Ljava/io/InputStream;");
+
+ /// from: public java.io.InputStream throwFileNotFoundException()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject throwFileNotFoundException() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_throwFileNotFoundException,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_throwClassCastException = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"throwClassCastException",
+ r"()Ljava/io/FileInputStream;");
+
+ /// from: public java.io.FileInputStream throwClassCastException()
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject throwClassCastException() {
+ return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_throwClassCastException,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_throwArrayIndexException = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"throwArrayIndexException", r"()I");
+
+ /// from: public int throwArrayIndexException()
+ int throwArrayIndexException() {
+ return jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_throwArrayIndexException, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_throwArithmeticException = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"throwArithmeticException", r"()I");
+
+ /// from: public int throwArithmeticException()
+ int throwArithmeticException() {
+ return jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_throwArithmeticException, jni.JniCallType.intType, []).integer;
+ }
+
+ static final _id_throwLoremIpsum = jni.Jni.accessors
+ .getStaticMethodIDOf(_class.reference, r"throwLoremIpsum", r"()V");
+
+ /// from: static public void throwLoremIpsum()
+ static void throwLoremIpsum() {
+ return jni.Jni.accessors.callStaticMethodWithArgs(_class.reference,
+ _id_throwLoremIpsum, jni.JniCallType.voidType, []).check();
+ }
+}
+
+final class $ExceptionsType extends jni.JObjType<Exceptions> {
+ const $ExceptionsType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/simple_package/Exceptions;";
+
+ @override
+ Exceptions fromRef(jni.JObjectPtr ref) => Exceptions.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($ExceptionsType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($ExceptionsType) && other is $ExceptionsType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.simple_package.Fields
+class Fields extends jni.JObject {
+ @override
+ late final jni.JObjType<Fields> $type = type;
+
+ Fields.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/github/dart_lang/jnigen/simple_package/Fields");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $FieldsType();
+ static final _id_amount = jni.Jni.accessors.getStaticFieldIDOf(
+ _class.reference,
+ r"amount",
+ r"I",
+ );
+
+ /// from: static public int amount
+ static int get amount => jni.Jni.accessors
+ .getStaticField(_class.reference, _id_amount, jni.JniCallType.intType)
+ .integer;
+
+ /// from: static public int amount
+ static set amount(int value) =>
+ jni.Jni.env.SetStaticIntField(_class.reference, _id_amount, value);
+
+ static final _id_pi = jni.Jni.accessors.getStaticFieldIDOf(
+ _class.reference,
+ r"pi",
+ r"D",
+ );
+
+ /// from: static public double pi
+ static double get pi => jni.Jni.accessors
+ .getStaticField(_class.reference, _id_pi, jni.JniCallType.doubleType)
+ .doubleFloat;
+
+ /// from: static public double pi
+ static set pi(double value) =>
+ jni.Jni.env.SetStaticDoubleField(_class.reference, _id_pi, value);
+
+ static final _id_asterisk = jni.Jni.accessors.getStaticFieldIDOf(
+ _class.reference,
+ r"asterisk",
+ r"C",
+ );
+
+ /// from: static public char asterisk
+ static int get asterisk => jni.Jni.accessors
+ .getStaticField(_class.reference, _id_asterisk, jni.JniCallType.charType)
+ .char;
+
+ /// from: static public char asterisk
+ static set asterisk(int value) =>
+ jni.Jni.env.SetStaticCharField(_class.reference, _id_asterisk, value);
+
+ static final _id_name = jni.Jni.accessors.getStaticFieldIDOf(
+ _class.reference,
+ r"name",
+ r"Ljava/lang/String;",
+ );
+
+ /// from: static public java.lang.String name
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get name => const jni.JStringType().fromRef(jni
+ .Jni.accessors
+ .getStaticField(_class.reference, _id_name, jni.JniCallType.objectType)
+ .object);
+
+ /// from: static public java.lang.String name
+ /// The returned object must be released after use, by calling the [release] method.
+ static set name(jni.JString value) => jni.Jni.env
+ .SetStaticObjectField(_class.reference, _id_name, value.reference);
+
+ static final _id_i = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"i",
+ r"Ljava/lang/Integer;",
+ );
+
+ /// from: public java.lang.Integer i
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JInteger get i => const jni.JIntegerType().fromRef(jni.Jni.accessors
+ .getField(reference, _id_i, jni.JniCallType.objectType)
+ .object);
+
+ /// from: public java.lang.Integer i
+ /// The returned object must be released after use, by calling the [release] method.
+ set i(jni.JInteger value) =>
+ jni.Jni.env.SetObjectField(reference, _id_i, value.reference);
+
+ static final _id_trillion = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"trillion",
+ r"J",
+ );
+
+ /// from: public long trillion
+ int get trillion => jni.Jni.accessors
+ .getField(reference, _id_trillion, jni.JniCallType.longType)
+ .long;
+
+ /// from: public long trillion
+ set trillion(int value) =>
+ jni.Jni.env.SetLongField(reference, _id_trillion, value);
+
+ static final _id_isAchillesDead = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"isAchillesDead",
+ r"Z",
+ );
+
+ /// from: public boolean isAchillesDead
+ bool get isAchillesDead => jni.Jni.accessors
+ .getField(reference, _id_isAchillesDead, jni.JniCallType.booleanType)
+ .boolean;
+
+ /// from: public boolean isAchillesDead
+ set isAchillesDead(bool value) =>
+ jni.Jni.env.SetBooleanField(reference, _id_isAchillesDead, value ? 1 : 0);
+
+ static final _id_bestFighterInGreece = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"bestFighterInGreece",
+ r"Ljava/lang/String;",
+ );
+
+ /// from: public java.lang.String bestFighterInGreece
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JString get bestFighterInGreece => const jni.JStringType().fromRef(jni
+ .Jni.accessors
+ .getField(reference, _id_bestFighterInGreece, jni.JniCallType.objectType)
+ .object);
+
+ /// from: public java.lang.String bestFighterInGreece
+ /// The returned object must be released after use, by calling the [release] method.
+ set bestFighterInGreece(jni.JString value) => jni.Jni.env
+ .SetObjectField(reference, _id_bestFighterInGreece, value.reference);
+
+ static final _id_random = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"random",
+ r"Ljava/util/Random;",
+ );
+
+ /// from: public java.util.Random random
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject get random => const jni.JObjectType().fromRef(jni.Jni.accessors
+ .getField(reference, _id_random, jni.JniCallType.objectType)
+ .object);
+
+ /// from: public java.util.Random random
+ /// The returned object must be released after use, by calling the [release] method.
+ set random(jni.JObject value) =>
+ jni.Jni.env.SetObjectField(reference, _id_random, value.reference);
+
+ static final _id_euroSymbol = jni.Jni.accessors.getStaticFieldIDOf(
+ _class.reference,
+ r"euroSymbol",
+ r"C",
+ );
+
+ /// from: static public char euroSymbol
+ static int get euroSymbol => jni.Jni.accessors
+ .getStaticField(
+ _class.reference, _id_euroSymbol, jni.JniCallType.charType)
+ .char;
+
+ /// from: static public char euroSymbol
+ static set euroSymbol(int value) =>
+ jni.Jni.env.SetStaticCharField(_class.reference, _id_euroSymbol, value);
+
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Fields() {
+ return Fields.fromRef(jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+}
+
+final class $FieldsType extends jni.JObjType<Fields> {
+ const $FieldsType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/simple_package/Fields;";
+
+ @override
+ Fields fromRef(jni.JObjectPtr ref) => Fields.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($FieldsType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($FieldsType) && other is $FieldsType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.simple_package.Fields$Nested
+class Fields_Nested extends jni.JObject {
+ @override
+ late final jni.JObjType<Fields_Nested> $type = type;
+
+ Fields_Nested.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = jni.Jni.findJClass(
+ r"com/github/dart_lang/jnigen/simple_package/Fields$Nested");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $Fields_NestedType();
+ static final _id_hundred = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"hundred",
+ r"J",
+ );
+
+ /// from: public long hundred
+ int get hundred => jni.Jni.accessors
+ .getField(reference, _id_hundred, jni.JniCallType.longType)
+ .long;
+
+ /// from: public long hundred
+ set hundred(int value) =>
+ jni.Jni.env.SetLongField(reference, _id_hundred, value);
+
+ static final _id_BEST_GOD = jni.Jni.accessors.getStaticFieldIDOf(
+ _class.reference,
+ r"BEST_GOD",
+ r"Ljava/lang/String;",
+ );
+
+ /// from: static public java.lang.String BEST_GOD
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JString get BEST_GOD =>
+ const jni.JStringType().fromRef(jni.Jni.accessors
+ .getStaticField(
+ _class.reference, _id_BEST_GOD, jni.JniCallType.objectType)
+ .object);
+
+ /// from: static public java.lang.String BEST_GOD
+ /// The returned object must be released after use, by calling the [release] method.
+ static set BEST_GOD(jni.JString value) => jni.Jni.env
+ .SetStaticObjectField(_class.reference, _id_BEST_GOD, value.reference);
+
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Fields_Nested() {
+ return Fields_Nested.fromRef(jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+}
+
+final class $Fields_NestedType extends jni.JObjType<Fields_Nested> {
+ const $Fields_NestedType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/simple_package/Fields$Nested;";
+
+ @override
+ Fields_Nested fromRef(jni.JObjectPtr ref) => Fields_Nested.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($Fields_NestedType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($Fields_NestedType) &&
+ other is $Fields_NestedType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.pkg2.C2
+class C2 extends jni.JObject {
+ @override
+ late final jni.JObjType<C2> $type = type;
+
+ C2.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/github/dart_lang/jnigen/pkg2/C2");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $C2Type();
+ static final _id_CONSTANT = jni.Jni.accessors.getStaticFieldIDOf(
+ _class.reference,
+ r"CONSTANT",
+ r"I",
+ );
+
+ /// from: static public int CONSTANT
+ static int get CONSTANT => jni.Jni.accessors
+ .getStaticField(_class.reference, _id_CONSTANT, jni.JniCallType.intType)
+ .integer;
+
+ /// from: static public int CONSTANT
+ static set CONSTANT(int value) =>
+ jni.Jni.env.SetStaticIntField(_class.reference, _id_CONSTANT, value);
+
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory C2() {
+ return C2.fromRef(jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+}
+
+final class $C2Type extends jni.JObjType<C2> {
+ const $C2Type();
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/pkg2/C2;";
+
+ @override
+ C2 fromRef(jni.JObjectPtr ref) => C2.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($C2Type).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($C2Type) && other is $C2Type;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.pkg2.Example
+class Example1 extends jni.JObject {
+ @override
+ late final jni.JObjType<Example1> $type = type;
+
+ Example1.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/github/dart_lang/jnigen/pkg2/Example");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $Example1Type();
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory Example1() {
+ return Example1.fromRef(jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+
+ static final _id_whichExample = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"whichExample", r"()I");
+
+ /// from: public int whichExample()
+ int whichExample() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_whichExample, jni.JniCallType.intType, []).integer;
+ }
+}
+
+final class $Example1Type extends jni.JObjType<Example1> {
+ const $Example1Type();
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/pkg2/Example;";
+
+ @override
+ Example1 fromRef(jni.JObjectPtr ref) => Example1.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($Example1Type).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($Example1Type) && other is $Example1Type;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.GenericTypeParams
+class GenericTypeParams<$S extends jni.JObject, $K extends jni.JObject>
+ extends jni.JObject {
+ @override
+ late final jni.JObjType<GenericTypeParams<$S, $K>> $type = type(S, K);
+
+ final jni.JObjType<$S> S;
+ final jni.JObjType<$K> K;
+
+ GenericTypeParams.fromRef(
+ this.S,
+ this.K,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = jni.Jni.findJClass(
+ r"com/github/dart_lang/jnigen/generics/GenericTypeParams");
+
+ /// The type which includes information such as the signature of this class.
+ static $GenericTypeParamsType<$S, $K>
+ type<$S extends jni.JObject, $K extends jni.JObject>(
+ jni.JObjType<$S> S,
+ jni.JObjType<$K> K,
+ ) {
+ return $GenericTypeParamsType(
+ S,
+ K,
+ );
+ }
+
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory GenericTypeParams({
+ required jni.JObjType<$S> S,
+ required jni.JObjType<$K> K,
+ }) {
+ return GenericTypeParams.fromRef(
+ S,
+ K,
+ jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+}
+
+final class $GenericTypeParamsType<$S extends jni.JObject,
+ $K extends jni.JObject> extends jni.JObjType<GenericTypeParams<$S, $K>> {
+ final jni.JObjType<$S> S;
+ final jni.JObjType<$K> K;
+
+ const $GenericTypeParamsType(
+ this.S,
+ this.K,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/generics/GenericTypeParams;";
+
+ @override
+ GenericTypeParams<$S, $K> fromRef(jni.JObjectPtr ref) =>
+ GenericTypeParams.fromRef(S, K, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($GenericTypeParamsType, S, K);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($GenericTypeParamsType<$S, $K>) &&
+ other is $GenericTypeParamsType<$S, $K> &&
+ S == other.S &&
+ K == other.K;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.GrandParent
+class GrandParent<$T extends jni.JObject> extends jni.JObject {
+ @override
+ late final jni.JObjType<GrandParent<$T>> $type = type(T);
+
+ final jni.JObjType<$T> T;
+
+ GrandParent.fromRef(
+ this.T,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/github/dart_lang/jnigen/generics/GrandParent");
+
+ /// The type which includes information such as the signature of this class.
+ static $GrandParentType<$T> type<$T extends jni.JObject>(
+ jni.JObjType<$T> T,
+ ) {
+ return $GrandParentType(
+ T,
+ );
+ }
+
+ static final _id_value = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"value",
+ r"Ljava/lang/Object;",
+ );
+
+ /// from: public T value
+ /// The returned object must be released after use, by calling the [release] method.
+ $T get value => T.fromRef(jni.Jni.accessors
+ .getField(reference, _id_value, jni.JniCallType.objectType)
+ .object);
+
+ /// from: public T value
+ /// The returned object must be released after use, by calling the [release] method.
+ set value($T value) =>
+ jni.Jni.env.SetObjectField(reference, _id_value, value.reference);
+
+ static final _id_new0 = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"<init>", r"(Ljava/lang/Object;)V");
+
+ /// from: public void <init>(T value)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory GrandParent(
+ $T value, {
+ jni.JObjType<$T>? T,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ value.$type,
+ ]) as jni.JObjType<$T>;
+ return GrandParent.fromRef(
+ T,
+ jni.Jni.accessors.newObjectWithArgs(
+ _class.reference, _id_new0, [value.reference]).object);
+ }
+
+ static final _id_stringParent = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"stringParent",
+ r"()Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent;");
+
+ /// from: public com.github.dart_lang.jnigen.generics.GrandParent<T>.Parent<java.lang.String> stringParent()
+ /// The returned object must be released after use, by calling the [release] method.
+ GrandParent_Parent<jni.JObject, jni.JString> stringParent() {
+ return const $GrandParent_ParentType(jni.JObjectType(), jni.JStringType())
+ .fromRef(jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_stringParent, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_varParent = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"varParent",
+ r"(Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent;");
+
+ /// from: public com.github.dart_lang.jnigen.generics.GrandParent<T>.Parent<S> varParent(S nestedValue)
+ /// The returned object must be released after use, by calling the [release] method.
+ GrandParent_Parent<jni.JObject, $S> varParent<$S extends jni.JObject>(
+ $S nestedValue, {
+ jni.JObjType<$S>? S,
+ }) {
+ S ??= jni.lowestCommonSuperType([
+ nestedValue.$type,
+ ]) as jni.JObjType<$S>;
+ return $GrandParent_ParentType(const jni.JObjectType(), S).fromRef(
+ jni.Jni.accessors.callMethodWithArgs(reference, _id_varParent,
+ jni.JniCallType.objectType, [nestedValue.reference]).object);
+ }
+
+ static final _id_stringStaticParent = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"stringStaticParent",
+ r"()Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;");
+
+ /// from: static public com.github.dart_lang.jnigen.generics.GrandParent.StaticParent<java.lang.String> stringStaticParent()
+ /// The returned object must be released after use, by calling the [release] method.
+ static GrandParent_StaticParent<jni.JString> stringStaticParent() {
+ return const $GrandParent_StaticParentType(jni.JStringType()).fromRef(
+ jni.Jni.accessors.callStaticMethodWithArgs(_class.reference,
+ _id_stringStaticParent, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_varStaticParent = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"varStaticParent",
+ r"(Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;");
+
+ /// from: static public com.github.dart_lang.jnigen.generics.GrandParent.StaticParent<S> varStaticParent(S value)
+ /// The returned object must be released after use, by calling the [release] method.
+ static GrandParent_StaticParent<$S> varStaticParent<$S extends jni.JObject>(
+ $S value, {
+ jni.JObjType<$S>? S,
+ }) {
+ S ??= jni.lowestCommonSuperType([
+ value.$type,
+ ]) as jni.JObjType<$S>;
+ return $GrandParent_StaticParentType(S).fromRef(jni.Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _id_varStaticParent,
+ jni.JniCallType.objectType, [value.reference]).object);
+ }
+
+ static final _id_staticParentWithSameType = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"staticParentWithSameType",
+ r"()Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;");
+
+ /// from: public com.github.dart_lang.jnigen.generics.GrandParent.StaticParent<T> staticParentWithSameType()
+ /// The returned object must be released after use, by calling the [release] method.
+ GrandParent_StaticParent<$T> staticParentWithSameType() {
+ return $GrandParent_StaticParentType(T).fromRef(jni.Jni.accessors
+ .callMethodWithArgs(reference, _id_staticParentWithSameType,
+ jni.JniCallType.objectType, []).object);
+ }
+}
+
+final class $GrandParentType<$T extends jni.JObject>
+ extends jni.JObjType<GrandParent<$T>> {
+ final jni.JObjType<$T> T;
+
+ const $GrandParentType(
+ this.T,
+ );
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/generics/GrandParent;";
+
+ @override
+ GrandParent<$T> fromRef(jni.JObjectPtr ref) => GrandParent.fromRef(T, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($GrandParentType, T);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($GrandParentType<$T>) &&
+ other is $GrandParentType<$T> &&
+ T == other.T;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.GrandParent$Parent
+class GrandParent_Parent<$T extends jni.JObject, $S extends jni.JObject>
+ extends jni.JObject {
+ @override
+ late final jni.JObjType<GrandParent_Parent<$T, $S>> $type = type(T, S);
+
+ final jni.JObjType<$T> T;
+ final jni.JObjType<$S> S;
+
+ GrandParent_Parent.fromRef(
+ this.T,
+ this.S,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = jni.Jni.findJClass(
+ r"com/github/dart_lang/jnigen/generics/GrandParent$Parent");
+
+ /// The type which includes information such as the signature of this class.
+ static $GrandParent_ParentType<$T, $S>
+ type<$T extends jni.JObject, $S extends jni.JObject>(
+ jni.JObjType<$T> T,
+ jni.JObjType<$S> S,
+ ) {
+ return $GrandParent_ParentType(
+ T,
+ S,
+ );
+ }
+
+ static final _id_parentValue = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"parentValue",
+ r"Ljava/lang/Object;",
+ );
+
+ /// from: public T parentValue
+ /// The returned object must be released after use, by calling the [release] method.
+ $T get parentValue => T.fromRef(jni.Jni.accessors
+ .getField(reference, _id_parentValue, jni.JniCallType.objectType)
+ .object);
+
+ /// from: public T parentValue
+ /// The returned object must be released after use, by calling the [release] method.
+ set parentValue($T value) =>
+ jni.Jni.env.SetObjectField(reference, _id_parentValue, value.reference);
+
+ static final _id_value = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"value",
+ r"Ljava/lang/Object;",
+ );
+
+ /// from: public S value
+ /// The returned object must be released after use, by calling the [release] method.
+ $S get value => S.fromRef(jni.Jni.accessors
+ .getField(reference, _id_value, jni.JniCallType.objectType)
+ .object);
+
+ /// from: public S value
+ /// The returned object must be released after use, by calling the [release] method.
+ set value($S value) =>
+ jni.Jni.env.SetObjectField(reference, _id_value, value.reference);
+
+ static final _id_new0 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"<init>",
+ r"(Lcom/github/dart_lang/jnigen/generics/GrandParent;Ljava/lang/Object;)V");
+
+ /// from: public void <init>(com.github.dart_lang.jnigen.generics.GrandParent $parent, S newValue)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory GrandParent_Parent(
+ GrandParent<$T> $parent,
+ $S newValue, {
+ jni.JObjType<$T>? T,
+ jni.JObjType<$S>? S,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ ($parent.$type as $GrandParentType).T,
+ ]) as jni.JObjType<$T>;
+ S ??= jni.lowestCommonSuperType([
+ newValue.$type,
+ ]) as jni.JObjType<$S>;
+ return GrandParent_Parent.fromRef(
+ T,
+ S,
+ jni.Jni.accessors.newObjectWithArgs(_class.reference, _id_new0,
+ [$parent.reference, newValue.reference]).object);
+ }
+}
+
+final class $GrandParent_ParentType<$T extends jni.JObject,
+ $S extends jni.JObject> extends jni.JObjType<GrandParent_Parent<$T, $S>> {
+ final jni.JObjType<$T> T;
+ final jni.JObjType<$S> S;
+
+ const $GrandParent_ParentType(
+ this.T,
+ this.S,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent;";
+
+ @override
+ GrandParent_Parent<$T, $S> fromRef(jni.JObjectPtr ref) =>
+ GrandParent_Parent.fromRef(T, S, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($GrandParent_ParentType, T, S);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($GrandParent_ParentType<$T, $S>) &&
+ other is $GrandParent_ParentType<$T, $S> &&
+ T == other.T &&
+ S == other.S;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.GrandParent$Parent$Child
+class GrandParent_Parent_Child<$T extends jni.JObject, $S extends jni.JObject,
+ $U extends jni.JObject> extends jni.JObject {
+ @override
+ late final jni.JObjType<GrandParent_Parent_Child<$T, $S, $U>> $type =
+ type(T, S, U);
+
+ final jni.JObjType<$T> T;
+ final jni.JObjType<$S> S;
+ final jni.JObjType<$U> U;
+
+ GrandParent_Parent_Child.fromRef(
+ this.T,
+ this.S,
+ this.U,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = jni.Jni.findJClass(
+ r"com/github/dart_lang/jnigen/generics/GrandParent$Parent$Child");
+
+ /// The type which includes information such as the signature of this class.
+ static $GrandParent_Parent_ChildType<$T, $S, $U> type<$T extends jni.JObject,
+ $S extends jni.JObject, $U extends jni.JObject>(
+ jni.JObjType<$T> T,
+ jni.JObjType<$S> S,
+ jni.JObjType<$U> U,
+ ) {
+ return $GrandParent_Parent_ChildType(
+ T,
+ S,
+ U,
+ );
+ }
+
+ static final _id_grandParentValue = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"grandParentValue",
+ r"Ljava/lang/Object;",
+ );
+
+ /// from: public T grandParentValue
+ /// The returned object must be released after use, by calling the [release] method.
+ $T get grandParentValue => T.fromRef(jni.Jni.accessors
+ .getField(reference, _id_grandParentValue, jni.JniCallType.objectType)
+ .object);
+
+ /// from: public T grandParentValue
+ /// The returned object must be released after use, by calling the [release] method.
+ set grandParentValue($T value) => jni.Jni.env
+ .SetObjectField(reference, _id_grandParentValue, value.reference);
+
+ static final _id_parentValue = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"parentValue",
+ r"Ljava/lang/Object;",
+ );
+
+ /// from: public S parentValue
+ /// The returned object must be released after use, by calling the [release] method.
+ $S get parentValue => S.fromRef(jni.Jni.accessors
+ .getField(reference, _id_parentValue, jni.JniCallType.objectType)
+ .object);
+
+ /// from: public S parentValue
+ /// The returned object must be released after use, by calling the [release] method.
+ set parentValue($S value) =>
+ jni.Jni.env.SetObjectField(reference, _id_parentValue, value.reference);
+
+ static final _id_value = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"value",
+ r"Ljava/lang/Object;",
+ );
+
+ /// from: public U value
+ /// The returned object must be released after use, by calling the [release] method.
+ $U get value => U.fromRef(jni.Jni.accessors
+ .getField(reference, _id_value, jni.JniCallType.objectType)
+ .object);
+
+ /// from: public U value
+ /// The returned object must be released after use, by calling the [release] method.
+ set value($U value) =>
+ jni.Jni.env.SetObjectField(reference, _id_value, value.reference);
+
+ static final _id_new0 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"<init>",
+ r"(Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent;Ljava/lang/Object;)V");
+
+ /// from: public void <init>(com.github.dart_lang.jnigen.generics.GrandParent$Parent $parent, U newValue)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory GrandParent_Parent_Child(
+ GrandParent_Parent<$T, $S> $parent,
+ $U newValue, {
+ jni.JObjType<$T>? T,
+ jni.JObjType<$S>? S,
+ jni.JObjType<$U>? U,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ ($parent.$type as $GrandParent_ParentType).T,
+ ]) as jni.JObjType<$T>;
+ S ??= jni.lowestCommonSuperType([
+ ($parent.$type as $GrandParent_ParentType).S,
+ ]) as jni.JObjType<$S>;
+ U ??= jni.lowestCommonSuperType([
+ newValue.$type,
+ ]) as jni.JObjType<$U>;
+ return GrandParent_Parent_Child.fromRef(
+ T,
+ S,
+ U,
+ jni.Jni.accessors.newObjectWithArgs(_class.reference, _id_new0,
+ [$parent.reference, newValue.reference]).object);
+ }
+}
+
+final class $GrandParent_Parent_ChildType<$T extends jni.JObject,
+ $S extends jni.JObject, $U extends jni.JObject>
+ extends jni.JObjType<GrandParent_Parent_Child<$T, $S, $U>> {
+ final jni.JObjType<$T> T;
+ final jni.JObjType<$S> S;
+ final jni.JObjType<$U> U;
+
+ const $GrandParent_Parent_ChildType(
+ this.T,
+ this.S,
+ this.U,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/generics/GrandParent$Parent$Child;";
+
+ @override
+ GrandParent_Parent_Child<$T, $S, $U> fromRef(jni.JObjectPtr ref) =>
+ GrandParent_Parent_Child.fromRef(T, S, U, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($GrandParent_Parent_ChildType, T, S, U);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($GrandParent_Parent_ChildType<$T, $S, $U>) &&
+ other is $GrandParent_Parent_ChildType<$T, $S, $U> &&
+ T == other.T &&
+ S == other.S &&
+ U == other.U;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.GrandParent$StaticParent
+class GrandParent_StaticParent<$S extends jni.JObject> extends jni.JObject {
+ @override
+ late final jni.JObjType<GrandParent_StaticParent<$S>> $type = type(S);
+
+ final jni.JObjType<$S> S;
+
+ GrandParent_StaticParent.fromRef(
+ this.S,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = jni.Jni.findJClass(
+ r"com/github/dart_lang/jnigen/generics/GrandParent$StaticParent");
+
+ /// The type which includes information such as the signature of this class.
+ static $GrandParent_StaticParentType<$S> type<$S extends jni.JObject>(
+ jni.JObjType<$S> S,
+ ) {
+ return $GrandParent_StaticParentType(
+ S,
+ );
+ }
+
+ static final _id_value = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"value",
+ r"Ljava/lang/Object;",
+ );
+
+ /// from: public S value
+ /// The returned object must be released after use, by calling the [release] method.
+ $S get value => S.fromRef(jni.Jni.accessors
+ .getField(reference, _id_value, jni.JniCallType.objectType)
+ .object);
+
+ /// from: public S value
+ /// The returned object must be released after use, by calling the [release] method.
+ set value($S value) =>
+ jni.Jni.env.SetObjectField(reference, _id_value, value.reference);
+
+ static final _id_new0 = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"<init>", r"(Ljava/lang/Object;)V");
+
+ /// from: public void <init>(S value)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory GrandParent_StaticParent(
+ $S value, {
+ jni.JObjType<$S>? S,
+ }) {
+ S ??= jni.lowestCommonSuperType([
+ value.$type,
+ ]) as jni.JObjType<$S>;
+ return GrandParent_StaticParent.fromRef(
+ S,
+ jni.Jni.accessors.newObjectWithArgs(
+ _class.reference, _id_new0, [value.reference]).object);
+ }
+}
+
+final class $GrandParent_StaticParentType<$S extends jni.JObject>
+ extends jni.JObjType<GrandParent_StaticParent<$S>> {
+ final jni.JObjType<$S> S;
+
+ const $GrandParent_StaticParentType(
+ this.S,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;";
+
+ @override
+ GrandParent_StaticParent<$S> fromRef(jni.JObjectPtr ref) =>
+ GrandParent_StaticParent.fromRef(S, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($GrandParent_StaticParentType, S);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($GrandParent_StaticParentType<$S>) &&
+ other is $GrandParent_StaticParentType<$S> &&
+ S == other.S;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.GrandParent$StaticParent$Child
+class GrandParent_StaticParent_Child<$S extends jni.JObject,
+ $U extends jni.JObject> extends jni.JObject {
+ @override
+ late final jni.JObjType<GrandParent_StaticParent_Child<$S, $U>> $type =
+ type(S, U);
+
+ final jni.JObjType<$S> S;
+ final jni.JObjType<$U> U;
+
+ GrandParent_StaticParent_Child.fromRef(
+ this.S,
+ this.U,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = jni.Jni.findJClass(
+ r"com/github/dart_lang/jnigen/generics/GrandParent$StaticParent$Child");
+
+ /// The type which includes information such as the signature of this class.
+ static $GrandParent_StaticParent_ChildType<$S, $U>
+ type<$S extends jni.JObject, $U extends jni.JObject>(
+ jni.JObjType<$S> S,
+ jni.JObjType<$U> U,
+ ) {
+ return $GrandParent_StaticParent_ChildType(
+ S,
+ U,
+ );
+ }
+
+ static final _id_parentValue = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"parentValue",
+ r"Ljava/lang/Object;",
+ );
+
+ /// from: public S parentValue
+ /// The returned object must be released after use, by calling the [release] method.
+ $S get parentValue => S.fromRef(jni.Jni.accessors
+ .getField(reference, _id_parentValue, jni.JniCallType.objectType)
+ .object);
+
+ /// from: public S parentValue
+ /// The returned object must be released after use, by calling the [release] method.
+ set parentValue($S value) =>
+ jni.Jni.env.SetObjectField(reference, _id_parentValue, value.reference);
+
+ static final _id_value = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"value",
+ r"Ljava/lang/Object;",
+ );
+
+ /// from: public U value
+ /// The returned object must be released after use, by calling the [release] method.
+ $U get value => U.fromRef(jni.Jni.accessors
+ .getField(reference, _id_value, jni.JniCallType.objectType)
+ .object);
+
+ /// from: public U value
+ /// The returned object must be released after use, by calling the [release] method.
+ set value($U value) =>
+ jni.Jni.env.SetObjectField(reference, _id_value, value.reference);
+
+ static final _id_new0 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"<init>",
+ r"(Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent;Ljava/lang/Object;Ljava/lang/Object;)V");
+
+ /// from: public void <init>(com.github.dart_lang.jnigen.generics.GrandParent$StaticParent $parent, S parentValue, U value)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory GrandParent_StaticParent_Child(
+ GrandParent_StaticParent<$S> $parent,
+ $S parentValue,
+ $U value, {
+ jni.JObjType<$S>? S,
+ jni.JObjType<$U>? U,
+ }) {
+ S ??= jni.lowestCommonSuperType([
+ parentValue.$type,
+ ($parent.$type as $GrandParent_StaticParentType).S,
+ ]) as jni.JObjType<$S>;
+ U ??= jni.lowestCommonSuperType([
+ value.$type,
+ ]) as jni.JObjType<$U>;
+ return GrandParent_StaticParent_Child.fromRef(
+ S,
+ U,
+ jni.Jni.accessors.newObjectWithArgs(_class.reference, _id_new0, [
+ $parent.reference,
+ parentValue.reference,
+ value.reference
+ ]).object);
+ }
+}
+
+final class $GrandParent_StaticParent_ChildType<$S extends jni.JObject,
+ $U extends jni.JObject>
+ extends jni.JObjType<GrandParent_StaticParent_Child<$S, $U>> {
+ final jni.JObjType<$S> S;
+ final jni.JObjType<$U> U;
+
+ const $GrandParent_StaticParent_ChildType(
+ this.S,
+ this.U,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/generics/GrandParent$StaticParent$Child;";
+
+ @override
+ GrandParent_StaticParent_Child<$S, $U> fromRef(jni.JObjectPtr ref) =>
+ GrandParent_StaticParent_Child.fromRef(S, U, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($GrandParent_StaticParent_ChildType, S, U);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($GrandParent_StaticParent_ChildType<$S, $U>) &&
+ other is $GrandParent_StaticParent_ChildType<$S, $U> &&
+ S == other.S &&
+ U == other.U;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.MyMap
+class MyMap<$K extends jni.JObject, $V extends jni.JObject>
+ extends jni.JObject {
+ @override
+ late final jni.JObjType<MyMap<$K, $V>> $type = type(K, V);
+
+ final jni.JObjType<$K> K;
+ final jni.JObjType<$V> V;
+
+ MyMap.fromRef(
+ this.K,
+ this.V,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/github/dart_lang/jnigen/generics/MyMap");
+
+ /// The type which includes information such as the signature of this class.
+ static $MyMapType<$K, $V>
+ type<$K extends jni.JObject, $V extends jni.JObject>(
+ jni.JObjType<$K> K,
+ jni.JObjType<$V> V,
+ ) {
+ return $MyMapType(
+ K,
+ V,
+ );
+ }
+
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory MyMap({
+ required jni.JObjType<$K> K,
+ required jni.JObjType<$V> V,
+ }) {
+ return MyMap.fromRef(
+ K,
+ V,
+ jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+
+ static final _id_get0 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"get", r"(Ljava/lang/Object;)Ljava/lang/Object;");
+
+ /// from: public V get(K key)
+ /// The returned object must be released after use, by calling the [release] method.
+ $V get0(
+ $K key,
+ ) {
+ return V.fromRef(jni.Jni.accessors.callMethodWithArgs(reference, _id_get0,
+ jni.JniCallType.objectType, [key.reference]).object);
+ }
+
+ static final _id_put = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"put", r"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+
+ /// from: public V put(K key, V value)
+ /// The returned object must be released after use, by calling the [release] method.
+ $V put(
+ $K key,
+ $V value,
+ ) {
+ return V.fromRef(jni.Jni.accessors.callMethodWithArgs(reference, _id_put,
+ jni.JniCallType.objectType, [key.reference, value.reference]).object);
+ }
+
+ static final _id_entryStack = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"entryStack",
+ r"()Lcom/github/dart_lang/jnigen/generics/MyStack;");
+
+ /// from: public com.github.dart_lang.jnigen.generics.MyStack<com.github.dart_lang.jnigen.generics.MyMap<K,V>.MyEntry> entryStack()
+ /// The returned object must be released after use, by calling the [release] method.
+ MyStack<MyMap_MyEntry<jni.JObject, jni.JObject>> entryStack() {
+ return const $MyStackType(
+ $MyMap_MyEntryType(jni.JObjectType(), jni.JObjectType()))
+ .fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_entryStack, jni.JniCallType.objectType, []).object);
+ }
+}
+
+final class $MyMapType<$K extends jni.JObject, $V extends jni.JObject>
+ extends jni.JObjType<MyMap<$K, $V>> {
+ final jni.JObjType<$K> K;
+ final jni.JObjType<$V> V;
+
+ const $MyMapType(
+ this.K,
+ this.V,
+ );
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/generics/MyMap;";
+
+ @override
+ MyMap<$K, $V> fromRef(jni.JObjectPtr ref) => MyMap.fromRef(K, V, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($MyMapType, K, V);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($MyMapType<$K, $V>) &&
+ other is $MyMapType<$K, $V> &&
+ K == other.K &&
+ V == other.V;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.MyMap$MyEntry
+class MyMap_MyEntry<$K extends jni.JObject, $V extends jni.JObject>
+ extends jni.JObject {
+ @override
+ late final jni.JObjType<MyMap_MyEntry<$K, $V>> $type = type(K, V);
+
+ final jni.JObjType<$K> K;
+ final jni.JObjType<$V> V;
+
+ MyMap_MyEntry.fromRef(
+ this.K,
+ this.V,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/github/dart_lang/jnigen/generics/MyMap$MyEntry");
+
+ /// The type which includes information such as the signature of this class.
+ static $MyMap_MyEntryType<$K, $V>
+ type<$K extends jni.JObject, $V extends jni.JObject>(
+ jni.JObjType<$K> K,
+ jni.JObjType<$V> V,
+ ) {
+ return $MyMap_MyEntryType(
+ K,
+ V,
+ );
+ }
+
+ static final _id_key = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"key",
+ r"Ljava/lang/Object;",
+ );
+
+ /// from: public K key
+ /// The returned object must be released after use, by calling the [release] method.
+ $K get key => K.fromRef(jni.Jni.accessors
+ .getField(reference, _id_key, jni.JniCallType.objectType)
+ .object);
+
+ /// from: public K key
+ /// The returned object must be released after use, by calling the [release] method.
+ set key($K value) =>
+ jni.Jni.env.SetObjectField(reference, _id_key, value.reference);
+
+ static final _id_value = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"value",
+ r"Ljava/lang/Object;",
+ );
+
+ /// from: public V value
+ /// The returned object must be released after use, by calling the [release] method.
+ $V get value => V.fromRef(jni.Jni.accessors
+ .getField(reference, _id_value, jni.JniCallType.objectType)
+ .object);
+
+ /// from: public V value
+ /// The returned object must be released after use, by calling the [release] method.
+ set value($V value) =>
+ jni.Jni.env.SetObjectField(reference, _id_value, value.reference);
+
+ static final _id_new0 = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"<init>",
+ r"(Lcom/github/dart_lang/jnigen/generics/MyMap;Ljava/lang/Object;Ljava/lang/Object;)V");
+
+ /// from: public void <init>(com.github.dart_lang.jnigen.generics.MyMap $parent, K key, V value)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory MyMap_MyEntry(
+ MyMap<$K, $V> $parent,
+ $K key,
+ $V value, {
+ jni.JObjType<$K>? K,
+ jni.JObjType<$V>? V,
+ }) {
+ K ??= jni.lowestCommonSuperType([
+ key.$type,
+ ($parent.$type as $MyMapType).K,
+ ]) as jni.JObjType<$K>;
+ V ??= jni.lowestCommonSuperType([
+ value.$type,
+ ($parent.$type as $MyMapType).V,
+ ]) as jni.JObjType<$V>;
+ return MyMap_MyEntry.fromRef(
+ K,
+ V,
+ jni.Jni.accessors.newObjectWithArgs(_class.reference, _id_new0,
+ [$parent.reference, key.reference, value.reference]).object);
+ }
+}
+
+final class $MyMap_MyEntryType<$K extends jni.JObject, $V extends jni.JObject>
+ extends jni.JObjType<MyMap_MyEntry<$K, $V>> {
+ final jni.JObjType<$K> K;
+ final jni.JObjType<$V> V;
+
+ const $MyMap_MyEntryType(
+ this.K,
+ this.V,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/generics/MyMap$MyEntry;";
+
+ @override
+ MyMap_MyEntry<$K, $V> fromRef(jni.JObjectPtr ref) =>
+ MyMap_MyEntry.fromRef(K, V, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($MyMap_MyEntryType, K, V);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($MyMap_MyEntryType<$K, $V>) &&
+ other is $MyMap_MyEntryType<$K, $V> &&
+ K == other.K &&
+ V == other.V;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.MyStack
+class MyStack<$T extends jni.JObject> extends jni.JObject {
+ @override
+ late final jni.JObjType<MyStack<$T>> $type = type(T);
+
+ final jni.JObjType<$T> T;
+
+ MyStack.fromRef(
+ this.T,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/github/dart_lang/jnigen/generics/MyStack");
+
+ /// The type which includes information such as the signature of this class.
+ static $MyStackType<$T> type<$T extends jni.JObject>(
+ jni.JObjType<$T> T,
+ ) {
+ return $MyStackType(
+ T,
+ );
+ }
+
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory MyStack({
+ required jni.JObjType<$T> T,
+ }) {
+ return MyStack.fromRef(
+ T,
+ jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+
+ static final _id_fromArray = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"fromArray",
+ r"([Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/MyStack;");
+
+ /// from: static public com.github.dart_lang.jnigen.generics.MyStack<T> fromArray(T[] arr)
+ /// The returned object must be released after use, by calling the [release] method.
+ static MyStack<$T> fromArray<$T extends jni.JObject>(
+ jni.JArray<$T> arr, {
+ jni.JObjType<$T>? T,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ ((arr.$type as jni.JArrayType).elementType as jni.JObjType),
+ ]) as jni.JObjType<$T>;
+ return $MyStackType(T).fromRef(jni.Jni.accessors.callStaticMethodWithArgs(
+ _class.reference,
+ _id_fromArray,
+ jni.JniCallType.objectType,
+ [arr.reference]).object);
+ }
+
+ static final _id_fromArrayOfArrayOfGrandParents = jni.Jni.accessors
+ .getStaticMethodIDOf(_class.reference, r"fromArrayOfArrayOfGrandParents",
+ r"([[Lcom/github/dart_lang/jnigen/generics/GrandParent;)Lcom/github/dart_lang/jnigen/generics/MyStack;");
+
+ /// from: static public com.github.dart_lang.jnigen.generics.MyStack<S> fromArrayOfArrayOfGrandParents(com.github.dart_lang.jnigen.generics.GrandParent<S>[][] arr)
+ /// The returned object must be released after use, by calling the [release] method.
+ static MyStack<$S> fromArrayOfArrayOfGrandParents<$S extends jni.JObject>(
+ jni.JArray<jni.JArray<GrandParent<$S>>> arr, {
+ jni.JObjType<$S>? S,
+ }) {
+ S ??= jni.lowestCommonSuperType([
+ (((((arr.$type as jni.JArrayType).elementType as jni.JObjType)
+ as jni.JArrayType)
+ .elementType as jni.JObjType) as $GrandParentType)
+ .T,
+ ]) as jni.JObjType<$S>;
+ return $MyStackType(S).fromRef(jni.Jni.accessors.callStaticMethodWithArgs(
+ _class.reference,
+ _id_fromArrayOfArrayOfGrandParents,
+ jni.JniCallType.objectType,
+ [arr.reference]).object);
+ }
+
+ static final _id_of = jni.Jni.accessors.getStaticMethodIDOf(_class.reference,
+ r"of", r"()Lcom/github/dart_lang/jnigen/generics/MyStack;");
+
+ /// from: static public com.github.dart_lang.jnigen.generics.MyStack<T> of()
+ /// The returned object must be released after use, by calling the [release] method.
+ static MyStack<$T> of<$T extends jni.JObject>({
+ required jni.JObjType<$T> T,
+ }) {
+ return $MyStackType(T).fromRef(jni.Jni.accessors.callStaticMethodWithArgs(
+ _class.reference, _id_of, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_of1 = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"of",
+ r"(Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/MyStack;");
+
+ /// from: static public com.github.dart_lang.jnigen.generics.MyStack<T> of(T obj)
+ /// The returned object must be released after use, by calling the [release] method.
+ static MyStack<$T> of1<$T extends jni.JObject>(
+ $T obj, {
+ jni.JObjType<$T>? T,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ obj.$type,
+ ]) as jni.JObjType<$T>;
+ return $MyStackType(T).fromRef(jni.Jni.accessors.callStaticMethodWithArgs(
+ _class.reference,
+ _id_of1,
+ jni.JniCallType.objectType,
+ [obj.reference]).object);
+ }
+
+ static final _id_of2 = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"of",
+ r"(Ljava/lang/Object;Ljava/lang/Object;)Lcom/github/dart_lang/jnigen/generics/MyStack;");
+
+ /// from: static public com.github.dart_lang.jnigen.generics.MyStack<T> of(T obj, T obj2)
+ /// The returned object must be released after use, by calling the [release] method.
+ static MyStack<$T> of2<$T extends jni.JObject>(
+ $T obj,
+ $T obj2, {
+ jni.JObjType<$T>? T,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ obj2.$type,
+ obj.$type,
+ ]) as jni.JObjType<$T>;
+ return $MyStackType(T).fromRef(jni.Jni.accessors.callStaticMethodWithArgs(
+ _class.reference,
+ _id_of2,
+ jni.JniCallType.objectType,
+ [obj.reference, obj2.reference]).object);
+ }
+
+ static final _id_push = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"push", r"(Ljava/lang/Object;)V");
+
+ /// from: public void push(T item)
+ void push(
+ $T item,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_push,
+ jni.JniCallType.voidType, [item.reference]).check();
+ }
+
+ static final _id_pop = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"pop", r"()Ljava/lang/Object;");
+
+ /// from: public T pop()
+ /// The returned object must be released after use, by calling the [release] method.
+ $T pop() {
+ return T.fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_pop, jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_size =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"size", r"()I");
+
+ /// from: public int size()
+ int size() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_size, jni.JniCallType.intType, []).integer;
+ }
+}
+
+final class $MyStackType<$T extends jni.JObject>
+ extends jni.JObjType<MyStack<$T>> {
+ final jni.JObjType<$T> T;
+
+ const $MyStackType(
+ this.T,
+ );
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/generics/MyStack;";
+
+ @override
+ MyStack<$T> fromRef(jni.JObjectPtr ref) => MyStack.fromRef(T, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($MyStackType, T);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($MyStackType<$T>) &&
+ other is $MyStackType<$T> &&
+ T == other.T;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.StringKeyedMap
+class StringKeyedMap<$V extends jni.JObject> extends MyMap<jni.JString, $V> {
+ @override
+ late final jni.JObjType<StringKeyedMap<$V>> $type = type(V);
+
+ final jni.JObjType<$V> V;
+
+ StringKeyedMap.fromRef(
+ this.V,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(const jni.JStringType(), V, ref);
+
+ static final _class = jni.Jni.findJClass(
+ r"com/github/dart_lang/jnigen/generics/StringKeyedMap");
+
+ /// The type which includes information such as the signature of this class.
+ static $StringKeyedMapType<$V> type<$V extends jni.JObject>(
+ jni.JObjType<$V> V,
+ ) {
+ return $StringKeyedMapType(
+ V,
+ );
+ }
+
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory StringKeyedMap({
+ required jni.JObjType<$V> V,
+ }) {
+ return StringKeyedMap.fromRef(
+ V,
+ jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+}
+
+final class $StringKeyedMapType<$V extends jni.JObject>
+ extends jni.JObjType<StringKeyedMap<$V>> {
+ final jni.JObjType<$V> V;
+
+ const $StringKeyedMapType(
+ this.V,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/generics/StringKeyedMap;";
+
+ @override
+ StringKeyedMap<$V> fromRef(jni.JObjectPtr ref) =>
+ StringKeyedMap.fromRef(V, ref);
+
+ @override
+ jni.JObjType get superType => $MyMapType(const jni.JStringType(), V);
+
+ @override
+ final superCount = 2;
+
+ @override
+ int get hashCode => Object.hash($StringKeyedMapType, V);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($StringKeyedMapType<$V>) &&
+ other is $StringKeyedMapType<$V> &&
+ V == other.V;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.StringMap
+class StringMap extends StringKeyedMap<jni.JString> {
+ @override
+ late final jni.JObjType<StringMap> $type = type;
+
+ StringMap.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(const jni.JStringType(), ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/github/dart_lang/jnigen/generics/StringMap");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $StringMapType();
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory StringMap() {
+ return StringMap.fromRef(jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+}
+
+final class $StringMapType extends jni.JObjType<StringMap> {
+ const $StringMapType();
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/generics/StringMap;";
+
+ @override
+ StringMap fromRef(jni.JObjectPtr ref) => StringMap.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const $StringKeyedMapType(jni.JStringType());
+
+ @override
+ final superCount = 3;
+
+ @override
+ int get hashCode => ($StringMapType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($StringMapType) && other is $StringMapType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.StringStack
+class StringStack extends MyStack<jni.JString> {
+ @override
+ late final jni.JObjType<StringStack> $type = type;
+
+ StringStack.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(const jni.JStringType(), ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/github/dart_lang/jnigen/generics/StringStack");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $StringStackType();
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory StringStack() {
+ return StringStack.fromRef(jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+}
+
+final class $StringStackType extends jni.JObjType<StringStack> {
+ const $StringStackType();
+
+ @override
+ String get signature => r"Lcom/github/dart_lang/jnigen/generics/StringStack;";
+
+ @override
+ StringStack fromRef(jni.JObjectPtr ref) => StringStack.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const $MyStackType(jni.JStringType());
+
+ @override
+ final superCount = 2;
+
+ @override
+ int get hashCode => ($StringStackType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($StringStackType) && other is $StringStackType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.generics.StringValuedMap
+class StringValuedMap<$K extends jni.JObject> extends MyMap<$K, jni.JString> {
+ @override
+ late final jni.JObjType<StringValuedMap<$K>> $type = type(K);
+
+ final jni.JObjType<$K> K;
+
+ StringValuedMap.fromRef(
+ this.K,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(K, const jni.JStringType(), ref);
+
+ static final _class = jni.Jni.findJClass(
+ r"com/github/dart_lang/jnigen/generics/StringValuedMap");
+
+ /// The type which includes information such as the signature of this class.
+ static $StringValuedMapType<$K> type<$K extends jni.JObject>(
+ jni.JObjType<$K> K,
+ ) {
+ return $StringValuedMapType(
+ K,
+ );
+ }
+
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory StringValuedMap({
+ required jni.JObjType<$K> K,
+ }) {
+ return StringValuedMap.fromRef(
+ K,
+ jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+}
+
+final class $StringValuedMapType<$K extends jni.JObject>
+ extends jni.JObjType<StringValuedMap<$K>> {
+ final jni.JObjType<$K> K;
+
+ const $StringValuedMapType(
+ this.K,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/generics/StringValuedMap;";
+
+ @override
+ StringValuedMap<$K> fromRef(jni.JObjectPtr ref) =>
+ StringValuedMap.fromRef(K, ref);
+
+ @override
+ jni.JObjType get superType => $MyMapType(K, const jni.JStringType());
+
+ @override
+ final superCount = 2;
+
+ @override
+ int get hashCode => Object.hash($StringValuedMapType, K);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($StringValuedMapType<$K>) &&
+ other is $StringValuedMapType<$K> &&
+ K == other.K;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.interfaces.MyInterface
+class MyInterface<$T extends jni.JObject> extends jni.JObject {
+ @override
+ late final jni.JObjType<MyInterface<$T>> $type = type(T);
+
+ final jni.JObjType<$T> T;
+
+ MyInterface.fromRef(
+ this.T,
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/github/dart_lang/jnigen/interfaces/MyInterface");
+
+ /// The type which includes information such as the signature of this class.
+ static $MyInterfaceType<$T> type<$T extends jni.JObject>(
+ jni.JObjType<$T> T,
+ ) {
+ return $MyInterfaceType(
+ T,
+ );
+ }
+
+ static final _id_voidCallback = jni.Jni.accessors.getMethodIDOf(
+ _class.reference, r"voidCallback", r"(Ljava/lang/String;)V");
+
+ /// from: public abstract void voidCallback(java.lang.String s)
+ void voidCallback(
+ jni.JString s,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(reference, _id_voidCallback,
+ jni.JniCallType.voidType, [s.reference]).check();
+ }
+
+ static final _id_stringCallback = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"stringCallback",
+ r"(Ljava/lang/String;)Ljava/lang/String;");
+
+ /// from: public abstract java.lang.String stringCallback(java.lang.String s)
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JString stringCallback(
+ jni.JString s,
+ ) {
+ return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_stringCallback,
+ jni.JniCallType.objectType,
+ [s.reference]).object);
+ }
+
+ static final _id_varCallback = jni.Jni.accessors.getMethodIDOf(
+ _class.reference,
+ r"varCallback",
+ r"(Ljava/lang/Object;)Ljava/lang/Object;");
+
+ /// from: public abstract T varCallback(T t)
+ /// The returned object must be released after use, by calling the [release] method.
+ $T varCallback(
+ $T t,
+ ) {
+ return T.fromRef(jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_varCallback, jni.JniCallType.objectType, [t.reference]).object);
+ }
+
+ static final _id_manyPrimitives = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"manyPrimitives", r"(IZCD)J");
+
+ /// from: public abstract long manyPrimitives(int a, boolean b, char c, double d)
+ int manyPrimitives(
+ int a,
+ bool b,
+ int c,
+ double d,
+ ) {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference,
+ _id_manyPrimitives,
+ jni.JniCallType.longType,
+ [jni.JValueInt(a), b ? 1 : 0, jni.JValueChar(c), d]).long;
+ }
+
+ /// Maps a specific port to the implemented interface.
+ static final Map<int, $MyInterfaceImpl> _$impls = {};
+ ReceivePort? _$p;
+
+ static jni.JObjectPtr _$invoke(
+ int port,
+ jni.JObjectPtr descriptor,
+ jni.JObjectPtr args,
+ ) {
+ return _$invokeMethod(
+ port,
+ $MethodInvocation.fromAddresses(
+ 0,
+ descriptor.address,
+ args.address,
+ ),
+ );
+ }
+
+ static final ffi.Pointer<
+ ffi.NativeFunction<
+ jni.JObjectPtr Function(
+ ffi.Uint64, jni.JObjectPtr, jni.JObjectPtr)>>
+ _$invokePointer = ffi.Pointer.fromFunction(_$invoke);
+
+ static ffi.Pointer<ffi.Void> _$invokeMethod(
+ int $p,
+ $MethodInvocation $i,
+ ) {
+ try {
+ final $d = $i.methodDescriptor.toDartString(releaseOriginal: true);
+ final $a = $i.args;
+ if ($d == r"voidCallback(Ljava/lang/String;)V") {
+ _$impls[$p]!.voidCallback(
+ $a[0].castTo(const jni.JStringType(), releaseOriginal: true),
+ );
+ return jni.nullptr;
+ }
+ if ($d == r"stringCallback(Ljava/lang/String;)Ljava/lang/String;") {
+ final $r = _$impls[$p]!.stringCallback(
+ $a[0].castTo(const jni.JStringType(), releaseOriginal: true),
+ );
+ return ($r as jni.JObject).castTo(const jni.JObjectType()).toPointer();
+ }
+ if ($d == r"varCallback(Ljava/lang/Object;)Ljava/lang/Object;") {
+ final $r = _$impls[$p]!.varCallback(
+ $a[0].castTo(_$impls[$p]!.T, releaseOriginal: true),
+ );
+ return ($r as jni.JObject).castTo(const jni.JObjectType()).toPointer();
+ }
+ if ($d == r"manyPrimitives(IZCD)J") {
+ final $r = _$impls[$p]!.manyPrimitives(
+ $a[0]
+ .castTo(const jni.JIntegerType(), releaseOriginal: true)
+ .intValue(releaseOriginal: true),
+ $a[1]
+ .castTo(const jni.JBooleanType(), releaseOriginal: true)
+ .booleanValue(releaseOriginal: true),
+ $a[2]
+ .castTo(const jni.JCharacterType(), releaseOriginal: true)
+ .charValue(releaseOriginal: true),
+ $a[3]
+ .castTo(const jni.JDoubleType(), releaseOriginal: true)
+ .doubleValue(releaseOriginal: true),
+ );
+ return jni.JLong($r).toPointer();
+ }
+ } catch (e) {
+ return ProtectedJniExtensions.newDartException(e.toString());
+ }
+ return jni.nullptr;
+ }
+
+ factory MyInterface.implement(
+ $MyInterfaceImpl<$T> $impl,
+ ) {
+ final $p = ReceivePort();
+ final $x = MyInterface.fromRef(
+ $impl.T,
+ ProtectedJniExtensions.newPortProxy(
+ r"com.github.dart_lang.jnigen.interfaces.MyInterface",
+ $p,
+ _$invokePointer,
+ ),
+ ).._$p = $p;
+ final $a = $p.sendPort.nativePort;
+ _$impls[$a] = $impl;
+ $p.listen(($m) {
+ if ($m == null) {
+ _$impls.remove($p.sendPort.nativePort);
+ $p.close();
+ return;
+ }
+ final $i = $MethodInvocation.fromMessage($m as List<dynamic>);
+ final $r = _$invokeMethod($p.sendPort.nativePort, $i);
+ ProtectedJniExtensions.returnResult($i.result, $r);
+ });
+ return $x;
+ }
+ static Map<int, $MyInterfaceImpl> get $impls => _$impls;
+}
+
+abstract interface class $MyInterfaceImpl<$T extends jni.JObject> {
+ factory $MyInterfaceImpl({
+ required jni.JObjType<$T> T,
+ required void Function(jni.JString s) voidCallback,
+ required jni.JString Function(jni.JString s) stringCallback,
+ required $T Function($T t) varCallback,
+ required int Function(int a, bool b, int c, double d) manyPrimitives,
+ }) = _$MyInterfaceImpl;
+
+ jni.JObjType<$T> get T;
+
+ void voidCallback(jni.JString s);
+ jni.JString stringCallback(jni.JString s);
+ $T varCallback($T t);
+ int manyPrimitives(int a, bool b, int c, double d);
+}
+
+class _$MyInterfaceImpl<$T extends jni.JObject>
+ implements $MyInterfaceImpl<$T> {
+ _$MyInterfaceImpl({
+ required this.T,
+ required void Function(jni.JString s) voidCallback,
+ required jni.JString Function(jni.JString s) stringCallback,
+ required $T Function($T t) varCallback,
+ required int Function(int a, bool b, int c, double d) manyPrimitives,
+ }) : _voidCallback = voidCallback,
+ _stringCallback = stringCallback,
+ _varCallback = varCallback,
+ _manyPrimitives = manyPrimitives;
+
+ @override
+ final jni.JObjType<$T> T;
+
+ final void Function(jni.JString s) _voidCallback;
+ final jni.JString Function(jni.JString s) _stringCallback;
+ final $T Function($T t) _varCallback;
+ final int Function(int a, bool b, int c, double d) _manyPrimitives;
+
+ void voidCallback(jni.JString s) {
+ return _voidCallback(s);
+ }
+
+ jni.JString stringCallback(jni.JString s) {
+ return _stringCallback(s);
+ }
+
+ $T varCallback($T t) {
+ return _varCallback(t);
+ }
+
+ int manyPrimitives(int a, bool b, int c, double d) {
+ return _manyPrimitives(a, b, c, d);
+ }
+}
+
+final class $MyInterfaceType<$T extends jni.JObject>
+ extends jni.JObjType<MyInterface<$T>> {
+ final jni.JObjType<$T> T;
+
+ const $MyInterfaceType(
+ this.T,
+ );
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/interfaces/MyInterface;";
+
+ @override
+ MyInterface<$T> fromRef(jni.JObjectPtr ref) => MyInterface.fromRef(T, ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => Object.hash($MyInterfaceType, T);
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($MyInterfaceType<$T>) &&
+ other is $MyInterfaceType<$T> &&
+ T == other.T;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.interfaces.MyInterfaceConsumer
+class MyInterfaceConsumer extends jni.JObject {
+ @override
+ late final jni.JObjType<MyInterfaceConsumer> $type = type;
+
+ MyInterfaceConsumer.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = jni.Jni.findJClass(
+ r"com/github/dart_lang/jnigen/interfaces/MyInterfaceConsumer");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $MyInterfaceConsumerType();
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory MyInterfaceConsumer() {
+ return MyInterfaceConsumer.fromRef(jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+
+ static final _id_consumeOnAnotherThread = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"consumeOnAnotherThread",
+ r"(Lcom/github/dart_lang/jnigen/interfaces/MyInterface;Ljava/lang/String;IZCDLjava/lang/Object;)V");
+
+ /// from: static public void consumeOnAnotherThread(com.github.dart_lang.jnigen.interfaces.MyInterface<T> myInterface, java.lang.String s, int a, boolean b, char c, double d, T t)
+ static void consumeOnAnotherThread<$T extends jni.JObject>(
+ MyInterface<$T> myInterface,
+ jni.JString s,
+ int a,
+ bool b,
+ int c,
+ double d,
+ $T t, {
+ jni.JObjType<$T>? T,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ t.$type,
+ (myInterface.$type as $MyInterfaceType).T,
+ ]) as jni.JObjType<$T>;
+ return jni.Jni.accessors.callStaticMethodWithArgs(_class.reference,
+ _id_consumeOnAnotherThread, jni.JniCallType.voidType, [
+ myInterface.reference,
+ s.reference,
+ jni.JValueInt(a),
+ b ? 1 : 0,
+ jni.JValueChar(c),
+ d,
+ t.reference
+ ]).check();
+ }
+
+ static final _id_consumeOnSameThread = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"consumeOnSameThread",
+ r"(Lcom/github/dart_lang/jnigen/interfaces/MyInterface;Ljava/lang/String;IZCDLjava/lang/Object;)V");
+
+ /// from: static public void consumeOnSameThread(com.github.dart_lang.jnigen.interfaces.MyInterface<T> myInterface, java.lang.String s, int a, boolean b, char c, double d, T t)
+ static void consumeOnSameThread<$T extends jni.JObject>(
+ MyInterface<$T> myInterface,
+ jni.JString s,
+ int a,
+ bool b,
+ int c,
+ double d,
+ $T t, {
+ jni.JObjType<$T>? T,
+ }) {
+ T ??= jni.lowestCommonSuperType([
+ t.$type,
+ (myInterface.$type as $MyInterfaceType).T,
+ ]) as jni.JObjType<$T>;
+ return jni.Jni.accessors.callStaticMethodWithArgs(
+ _class.reference, _id_consumeOnSameThread, jni.JniCallType.voidType, [
+ myInterface.reference,
+ s.reference,
+ jni.JValueInt(a),
+ b ? 1 : 0,
+ jni.JValueChar(c),
+ d,
+ t.reference
+ ]).check();
+ }
+}
+
+final class $MyInterfaceConsumerType extends jni.JObjType<MyInterfaceConsumer> {
+ const $MyInterfaceConsumerType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/interfaces/MyInterfaceConsumer;";
+
+ @override
+ MyInterfaceConsumer fromRef(jni.JObjectPtr ref) =>
+ MyInterfaceConsumer.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($MyInterfaceConsumerType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($MyInterfaceConsumerType) &&
+ other is $MyInterfaceConsumerType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.interfaces.MyRunnable
+class MyRunnable extends jni.JObject {
+ @override
+ late final jni.JObjType<MyRunnable> $type = type;
+
+ MyRunnable.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class =
+ jni.Jni.findJClass(r"com/github/dart_lang/jnigen/interfaces/MyRunnable");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $MyRunnableType();
+ static final _id_run =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"run", r"()V");
+
+ /// from: public abstract void run()
+ void run() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_run, jni.JniCallType.voidType, []).check();
+ }
+
+ /// Maps a specific port to the implemented interface.
+ static final Map<int, $MyRunnableImpl> _$impls = {};
+ ReceivePort? _$p;
+
+ static jni.JObjectPtr _$invoke(
+ int port,
+ jni.JObjectPtr descriptor,
+ jni.JObjectPtr args,
+ ) {
+ return _$invokeMethod(
+ port,
+ $MethodInvocation.fromAddresses(
+ 0,
+ descriptor.address,
+ args.address,
+ ),
+ );
+ }
+
+ static final ffi.Pointer<
+ ffi.NativeFunction<
+ jni.JObjectPtr Function(
+ ffi.Uint64, jni.JObjectPtr, jni.JObjectPtr)>>
+ _$invokePointer = ffi.Pointer.fromFunction(_$invoke);
+
+ static ffi.Pointer<ffi.Void> _$invokeMethod(
+ int $p,
+ $MethodInvocation $i,
+ ) {
+ try {
+ final $d = $i.methodDescriptor.toDartString(releaseOriginal: true);
+ final $a = $i.args;
+ if ($d == r"run()V") {
+ _$impls[$p]!.run();
+ return jni.nullptr;
+ }
+ } catch (e) {
+ return ProtectedJniExtensions.newDartException(e.toString());
+ }
+ return jni.nullptr;
+ }
+
+ factory MyRunnable.implement(
+ $MyRunnableImpl $impl,
+ ) {
+ final $p = ReceivePort();
+ final $x = MyRunnable.fromRef(
+ ProtectedJniExtensions.newPortProxy(
+ r"com.github.dart_lang.jnigen.interfaces.MyRunnable",
+ $p,
+ _$invokePointer,
+ ),
+ ).._$p = $p;
+ final $a = $p.sendPort.nativePort;
+ _$impls[$a] = $impl;
+ $p.listen(($m) {
+ if ($m == null) {
+ _$impls.remove($p.sendPort.nativePort);
+ $p.close();
+ return;
+ }
+ final $i = $MethodInvocation.fromMessage($m as List<dynamic>);
+ final $r = _$invokeMethod($p.sendPort.nativePort, $i);
+ ProtectedJniExtensions.returnResult($i.result, $r);
+ });
+ return $x;
+ }
+}
+
+abstract interface class $MyRunnableImpl {
+ factory $MyRunnableImpl({
+ required void Function() run,
+ }) = _$MyRunnableImpl;
+
+ void run();
+}
+
+class _$MyRunnableImpl implements $MyRunnableImpl {
+ _$MyRunnableImpl({
+ required void Function() run,
+ }) : _run = run;
+
+ final void Function() _run;
+
+ void run() {
+ return _run();
+ }
+}
+
+final class $MyRunnableType extends jni.JObjType<MyRunnable> {
+ const $MyRunnableType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/interfaces/MyRunnable;";
+
+ @override
+ MyRunnable fromRef(jni.JObjectPtr ref) => MyRunnable.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($MyRunnableType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($MyRunnableType) && other is $MyRunnableType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.interfaces.MyRunnableRunner
+class MyRunnableRunner extends jni.JObject {
+ @override
+ late final jni.JObjType<MyRunnableRunner> $type = type;
+
+ MyRunnableRunner.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = jni.Jni.findJClass(
+ r"com/github/dart_lang/jnigen/interfaces/MyRunnableRunner");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $MyRunnableRunnerType();
+ static final _id_error = jni.Jni.accessors.getFieldIDOf(
+ _class.reference,
+ r"error",
+ r"Ljava/lang/Throwable;",
+ );
+
+ /// from: public java.lang.Throwable error
+ /// The returned object must be released after use, by calling the [release] method.
+ jni.JObject get error => const jni.JObjectType().fromRef(jni.Jni.accessors
+ .getField(reference, _id_error, jni.JniCallType.objectType)
+ .object);
+
+ /// from: public java.lang.Throwable error
+ /// The returned object must be released after use, by calling the [release] method.
+ set error(jni.JObject value) =>
+ jni.Jni.env.SetObjectField(reference, _id_error, value.reference);
+
+ static final _id_new0 = jni.Jni.accessors.getMethodIDOf(_class.reference,
+ r"<init>", r"(Lcom/github/dart_lang/jnigen/interfaces/MyRunnable;)V");
+
+ /// from: public void <init>(com.github.dart_lang.jnigen.interfaces.MyRunnable runnable)
+ /// The returned object must be released after use, by calling the [release] method.
+ factory MyRunnableRunner(
+ MyRunnable runnable,
+ ) {
+ return MyRunnableRunner.fromRef(jni.Jni.accessors.newObjectWithArgs(
+ _class.reference, _id_new0, [runnable.reference]).object);
+ }
+
+ static final _id_runOnSameThread = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"runOnSameThread", r"()V");
+
+ /// from: public void runOnSameThread()
+ void runOnSameThread() {
+ return jni.Jni.accessors.callMethodWithArgs(
+ reference, _id_runOnSameThread, jni.JniCallType.voidType, []).check();
+ }
+
+ static final _id_runOnAnotherThread = jni.Jni.accessors
+ .getMethodIDOf(_class.reference, r"runOnAnotherThread", r"()V");
+
+ /// from: public void runOnAnotherThread()
+ void runOnAnotherThread() {
+ return jni.Jni.accessors.callMethodWithArgs(reference,
+ _id_runOnAnotherThread, jni.JniCallType.voidType, []).check();
+ }
+}
+
+final class $MyRunnableRunnerType extends jni.JObjType<MyRunnableRunner> {
+ const $MyRunnableRunnerType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/interfaces/MyRunnableRunner;";
+
+ @override
+ MyRunnableRunner fromRef(jni.JObjectPtr ref) => MyRunnableRunner.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($MyRunnableRunnerType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($MyRunnableRunnerType) &&
+ other is $MyRunnableRunnerType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.annotations.JsonSerializable$Case
+class JsonSerializable_Case extends jni.JObject {
+ @override
+ late final jni.JObjType<JsonSerializable_Case> $type = type;
+
+ JsonSerializable_Case.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = jni.Jni.findJClass(
+ r"com/github/dart_lang/jnigen/annotations/JsonSerializable$Case");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $JsonSerializable_CaseType();
+ static final _id_values = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"values",
+ r"()[Lcom/github/dart_lang/jnigen/annotations/JsonSerializable$Case;");
+
+ /// from: static public com.github.dart_lang.jnigen.annotations.JsonSerializable.Case[] values()
+ /// The returned object must be released after use, by calling the [release] method.
+ static jni.JArray<JsonSerializable_Case> values() {
+ return const jni.JArrayType($JsonSerializable_CaseType()).fromRef(
+ jni.Jni.accessors.callStaticMethodWithArgs(_class.reference, _id_values,
+ jni.JniCallType.objectType, []).object);
+ }
+
+ static final _id_valueOf = jni.Jni.accessors.getStaticMethodIDOf(
+ _class.reference,
+ r"valueOf",
+ r"(Ljava/lang/String;)Lcom/github/dart_lang/jnigen/annotations/JsonSerializable$Case;");
+
+ /// from: static public com.github.dart_lang.jnigen.annotations.JsonSerializable.Case valueOf(java.lang.String name)
+ /// The returned object must be released after use, by calling the [release] method.
+ static JsonSerializable_Case valueOf(
+ jni.JString name,
+ ) {
+ return const $JsonSerializable_CaseType().fromRef(jni.Jni.accessors
+ .callStaticMethodWithArgs(_class.reference, _id_valueOf,
+ jni.JniCallType.objectType, [name.reference]).object);
+ }
+}
+
+final class $JsonSerializable_CaseType
+ extends jni.JObjType<JsonSerializable_Case> {
+ const $JsonSerializable_CaseType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/annotations/JsonSerializable$Case;";
+
+ @override
+ JsonSerializable_Case fromRef(jni.JObjectPtr ref) =>
+ JsonSerializable_Case.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($JsonSerializable_CaseType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($JsonSerializable_CaseType) &&
+ other is $JsonSerializable_CaseType;
+ }
+}
+
+/// from: com.github.dart_lang.jnigen.annotations.MyDataClass
+class MyDataClass extends jni.JObject {
+ @override
+ late final jni.JObjType<MyDataClass> $type = type;
+
+ MyDataClass.fromRef(
+ jni.JObjectPtr ref,
+ ) : super.fromRef(ref);
+
+ static final _class = jni.Jni.findJClass(
+ r"com/github/dart_lang/jnigen/annotations/MyDataClass");
+
+ /// The type which includes information such as the signature of this class.
+ static const type = $MyDataClassType();
+ static final _id_new0 =
+ jni.Jni.accessors.getMethodIDOf(_class.reference, r"<init>", r"()V");
+
+ /// from: public void <init>()
+ /// The returned object must be released after use, by calling the [release] method.
+ factory MyDataClass() {
+ return MyDataClass.fromRef(jni.Jni.accessors
+ .newObjectWithArgs(_class.reference, _id_new0, []).object);
+ }
+}
+
+final class $MyDataClassType extends jni.JObjType<MyDataClass> {
+ const $MyDataClassType();
+
+ @override
+ String get signature =>
+ r"Lcom/github/dart_lang/jnigen/annotations/MyDataClass;";
+
+ @override
+ MyDataClass fromRef(jni.JObjectPtr ref) => MyDataClass.fromRef(ref);
+
+ @override
+ jni.JObjType get superType => const jni.JObjectType();
+
+ @override
+ final superCount = 1;
+
+ @override
+ int get hashCode => ($MyDataClassType).hashCode;
+
+ @override
+ bool operator ==(Object other) {
+ return other.runtimeType == ($MyDataClassType) && other is $MyDataClassType;
+ }
+}
diff --git a/pkgs/jnigen/test/simple_package_test/generate.dart b/pkgs/jnigen/test/simple_package_test/generate.dart
new file mode 100644
index 0000000..9f59888
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/generate.dart
@@ -0,0 +1,94 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:jnigen/src/config/experiments.dart';
+import 'package:logging/logging.dart';
+import 'package:path/path.dart';
+import 'package:jnigen/jnigen.dart';
+
+const testName = 'simple_package_test';
+final testRoot = join('test', testName);
+final javaPath = join(testRoot, 'java');
+
+const preamble = '''
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+''';
+
+var javaPrefix = join('com', 'github', 'dart_lang', 'jnigen');
+
+var javaFiles = [
+ join(javaPrefix, 'simple_package', 'Example.java'),
+ join(javaPrefix, 'pkg2', 'C2.java'),
+ join(javaPrefix, 'pkg2', 'Example.java'),
+ join(javaPrefix, 'generics', 'MyStack.java'),
+ join(javaPrefix, 'generics', 'MyMap.java'),
+ join(javaPrefix, 'generics', 'GrandParent.java'),
+ join(javaPrefix, 'generics', 'StringStack.java'),
+ join(javaPrefix, 'generics', 'StringValuedMap.java'),
+ join(javaPrefix, 'generics', 'StringKeyedMap.java'),
+ join(javaPrefix, 'interfaces', 'MyRunnable.java'),
+ join(javaPrefix, 'interfaces', 'MyRunnableRunner.java'),
+ join(javaPrefix, 'interfaces', 'MyInterface.java'),
+ join(javaPrefix, 'interfaces', 'MyInterfaceConsumer.java'),
+ join(javaPrefix, 'annotations', 'JsonSerializable.java'),
+ join(javaPrefix, 'annotations', 'MyDataClass.java'),
+];
+
+void compileJavaSources(String workingDir, List<String> files) async {
+ final procRes = Process.runSync('javac', files, workingDirectory: workingDir);
+ if (procRes.exitCode != 0) {
+ throw "javac exited with ${procRes.exitCode}\n"
+ "${procRes.stderr}";
+ }
+}
+
+Config getConfig([BindingsType bindingsType = BindingsType.cBased]) {
+ compileJavaSources(javaPath, javaFiles);
+ final typeDir = bindingsType.getConfigString();
+ final cWrapperDir = Uri.directory(join(testRoot, typeDir, "c_bindings"));
+ final dartWrappersRoot = Uri.directory(
+ join(testRoot, typeDir, "dart_bindings"),
+ );
+ final config = Config(
+ sourcePath: [Uri.directory(javaPath)],
+ classPath: [Uri.directory(javaPath)],
+ classes: [
+ 'com.github.dart_lang.jnigen.simple_package',
+ 'com.github.dart_lang.jnigen.pkg2',
+ 'com.github.dart_lang.jnigen.generics',
+ 'com.github.dart_lang.jnigen.interfaces',
+ 'com.github.dart_lang.jnigen.annotations',
+ ],
+ logLevel: Level.INFO,
+ customClassBody: {
+ 'com.github.dart_lang.jnigen.interfaces.MyInterface': r'''
+ static Map<int, $MyInterfaceImpl> get $impls => _$impls;
+'''
+ },
+ outputConfig: OutputConfig(
+ bindingsType: bindingsType,
+ cConfig: CCodeOutputConfig(
+ path: cWrapperDir,
+ libraryName: 'simple_package',
+ ),
+ dartConfig: DartCodeOutputConfig(
+ path: dartWrappersRoot.resolve('simple_package.dart'),
+ structure: OutputStructure.singleFile,
+ ),
+ ),
+ preamble: preamble,
+ experiments: {Experiment.interfaceImplementation},
+ );
+ return config;
+}
+
+void main() async {
+ await generateJniBindings(getConfig(BindingsType.cBased));
+ await generateJniBindings(getConfig(BindingsType.dartOnly));
+}
diff --git a/pkgs/jnigen/test/simple_package_test/generated_files_test.dart b/pkgs/jnigen/test/simple_package_test/generated_files_test.dart
new file mode 100644
index 0000000..0f595d2
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/generated_files_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:jnigen/jnigen.dart';
+import 'package:test/test.dart';
+
+import 'generate.dart';
+import '../test_util/test_util.dart';
+
+void main() async {
+ await checkLocallyBuiltDependencies();
+
+ generateAndCompareBothModes(
+ 'Generate and compare bindings for simple_package java files',
+ getConfig(BindingsType.cBased),
+ getConfig(BindingsType.dartOnly),
+ );
+
+ test("Generate and analyze bindings for simple_package - pure dart",
+ () async {
+ await generateAndAnalyzeBindings(
+ getConfig(BindingsType.dartOnly),
+ );
+ }); // test if generated file == expected file
+}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/annotations/JsonSerializable.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/annotations/JsonSerializable.java
new file mode 100644
index 0000000..af7071e
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/annotations/JsonSerializable.java
@@ -0,0 +1,19 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.annotations;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+public @interface JsonSerializable {
+ public static enum Case {
+ SNAKE_CASE,
+ KEBAB_CASE,
+ CAMEL_CASE
+ }
+
+ public Case value();
+}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/annotations/MyDataClass.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/annotations/MyDataClass.java
new file mode 100644
index 0000000..ff71b69
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/annotations/MyDataClass.java
@@ -0,0 +1,8 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.annotations;
+
+@JsonSerializable(JsonSerializable.Case.CAMEL_CASE)
+public class MyDataClass {}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/GenericTypeParams.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/GenericTypeParams.java
new file mode 100644
index 0000000..2a41875
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/GenericTypeParams.java
@@ -0,0 +1,9 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.generics;
+
+public class GenericTypeParams<S extends CharSequence, K extends GenericTypeParams<S, K>> {}
+
+// TODO: Add more cases of generic parameters
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/GrandParent.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/GrandParent.java
new file mode 100644
index 0000000..b703403
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/GrandParent.java
@@ -0,0 +1,74 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.generics;
+
+public class GrandParent<T> {
+ public T value;
+
+ public GrandParent(T value) {
+ this.value = value;
+ }
+
+ public Parent<String> stringParent() {
+ return new Parent<>("Hello");
+ }
+
+ public <S> Parent<S> varParent(S nestedValue) {
+ return new Parent<>(nestedValue);
+ }
+
+ public static StaticParent<String> stringStaticParent() {
+ return new StaticParent<>("Hello");
+ }
+
+ public static <S> StaticParent<S> varStaticParent(S value) {
+ return new StaticParent<>(value);
+ }
+
+ public StaticParent<T> staticParentWithSameType() {
+ return new StaticParent<>(value);
+ }
+
+ // This doesn't have access to T
+ public static class StaticParent<S> {
+ public S value;
+
+ public StaticParent(S value) {
+ this.value = value;
+ }
+
+ public class Child<U> {
+ public S parentValue;
+ public U value;
+
+ public Child(S parentValue, U value) {
+ this.parentValue = parentValue;
+ this.value = value;
+ }
+ }
+ }
+
+ public class Parent<S> {
+ public T parentValue;
+ public S value;
+
+ public Parent(S newValue) {
+ parentValue = GrandParent.this.value;
+ value = newValue;
+ }
+
+ public class Child<U> {
+ public T grandParentValue;
+ public S parentValue;
+ public U value;
+
+ public Child(U newValue) {
+ this.grandParentValue = GrandParent.this.value;
+ this.parentValue = Parent.this.value;
+ this.value = newValue;
+ }
+ }
+ }
+}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/MyMap.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/MyMap.java
new file mode 100644
index 0000000..21392ae
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/MyMap.java
@@ -0,0 +1,42 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.generics;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class MyMap<K, V> {
+ public class MyEntry {
+ public K key;
+ public V value;
+
+ public MyEntry(K key, V value) {
+ this.key = key;
+ this.value = value;
+ }
+ }
+
+ private Map<K, V> map;
+
+ public MyMap() {
+ map = new HashMap<>();
+ }
+
+ public V get(K key) {
+ return map.get(key);
+ }
+
+ public V put(K key, V value) {
+ return map.put(key, value);
+ }
+
+ public MyStack<MyEntry> entryStack() {
+ var stack = new MyStack<MyEntry>();
+ map.entrySet().stream()
+ .map(e -> new MyEntry(e.getKey(), e.getValue()))
+ .forEach(e -> stack.push(e));
+ return stack;
+ }
+}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/MyStack.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/MyStack.java
new file mode 100644
index 0000000..c4e2d06
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/MyStack.java
@@ -0,0 +1,59 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.generics;
+
+import java.util.Stack;
+
+public class MyStack<T> {
+ private Stack<T> stack;
+
+ public MyStack() {
+ stack = new Stack<>();
+ }
+
+ public static <T> MyStack<T> fromArray(T[] arr) {
+ var stack = new MyStack<T>();
+ for (int i = 0; i < arr.length; ++i) {
+ stack.push(arr[i]);
+ }
+ return stack;
+ }
+
+ public static <S> MyStack<S> fromArrayOfArrayOfGrandParents(GrandParent<S>[][] arr) {
+ // just for testing
+ var stack = new MyStack<S>();
+ stack.push(arr[0][0].value);
+ return stack;
+ }
+
+ public static <T> MyStack<T> of() {
+ return new MyStack<T>();
+ }
+
+ public static <T> MyStack<T> of(T obj) {
+ var stack = new MyStack<T>();
+ stack.push(obj);
+ return stack;
+ }
+
+ public static <T> MyStack<T> of(T obj, T obj2) {
+ var stack = new MyStack<T>();
+ stack.push(obj);
+ stack.push(obj2);
+ return stack;
+ }
+
+ public void push(T item) {
+ stack.push(item);
+ }
+
+ public T pop() {
+ return stack.pop();
+ }
+
+ public int size() {
+ return stack.size();
+ }
+}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/StringKeyedMap.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/StringKeyedMap.java
new file mode 100644
index 0000000..1ca40aa
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/StringKeyedMap.java
@@ -0,0 +1,7 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.generics;
+
+public class StringKeyedMap<V> extends MyMap<String, V> {}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/StringMap.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/StringMap.java
new file mode 100644
index 0000000..05f9365
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/StringMap.java
@@ -0,0 +1,7 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.generics;
+
+public class StringMap extends StringKeyedMap<String> {}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/StringStack.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/StringStack.java
new file mode 100644
index 0000000..87fd041
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/StringStack.java
@@ -0,0 +1,7 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.generics;
+
+public class StringStack extends MyStack<String> {}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/StringValuedMap.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/StringValuedMap.java
new file mode 100644
index 0000000..c005ae0
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/generics/StringValuedMap.java
@@ -0,0 +1,7 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.generics;
+
+public class StringValuedMap<K> extends MyMap<K, String> {}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/BaseClass.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/BaseClass.java
new file mode 100644
index 0000000..f9157e4
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/BaseClass.java
@@ -0,0 +1,7 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.inheritance;
+
+public class BaseClass<T extends CharSequence> {}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/GenericDerivedClass.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/GenericDerivedClass.java
new file mode 100644
index 0000000..5829657
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/GenericDerivedClass.java
@@ -0,0 +1,7 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.inheritance;
+
+public class GenericDerivedClass<T extends CharSequence> extends BaseClass<T> {}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/SpecificDerivedClass.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/SpecificDerivedClass.java
new file mode 100644
index 0000000..6c33e83
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/inheritance/SpecificDerivedClass.java
@@ -0,0 +1,7 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.inheritance;
+
+public class SpecificDerivedClass extends BaseClass<String> {}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/MyInterface.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/MyInterface.java
new file mode 100644
index 0000000..97b243e
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/MyInterface.java
@@ -0,0 +1,15 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.interfaces;
+
+public interface MyInterface<T> {
+ void voidCallback(String s);
+
+ String stringCallback(String s);
+
+ T varCallback(T t);
+
+ long manyPrimitives(int a, boolean b, char c, double d);
+}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/MyInterfaceConsumer.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/MyInterfaceConsumer.java
new file mode 100644
index 0000000..b4eeb2f
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/MyInterfaceConsumer.java
@@ -0,0 +1,21 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.interfaces;
+
+public class MyInterfaceConsumer {
+ public static <T> void consumeOnAnotherThread(
+ MyInterface<T> myInterface, String s, int a, boolean b, char c, double d, T t) {
+ var thread = new Thread(() -> consumeOnSameThread(myInterface, s, a, b, c, d, t));
+ thread.start();
+ }
+
+ public static <T> void consumeOnSameThread(
+ MyInterface<T> myInterface, String s, int a, boolean b, char c, double d, T t) {
+ String result = myInterface.stringCallback(s);
+ myInterface.voidCallback(result);
+ myInterface.manyPrimitives(a, b, c, d);
+ myInterface.varCallback(t);
+ }
+}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/MyRunnable.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/MyRunnable.java
new file mode 100644
index 0000000..4a39f81
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/MyRunnable.java
@@ -0,0 +1,9 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.interfaces;
+
+public interface MyRunnable {
+ void run();
+}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/MyRunnableRunner.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/MyRunnableRunner.java
new file mode 100644
index 0000000..2903f37
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/interfaces/MyRunnableRunner.java
@@ -0,0 +1,28 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.interfaces;
+
+public class MyRunnableRunner {
+ final MyRunnable runnable;
+
+ public Throwable error;
+
+ public MyRunnableRunner(MyRunnable runnable) {
+ this.runnable = runnable;
+ }
+
+ public void runOnSameThread() {
+ try {
+ runnable.run();
+ } catch (Throwable e) {
+ error = e;
+ }
+ }
+
+ public void runOnAnotherThread() {
+ var thread = new Thread(this::runOnSameThread);
+ thread.start();
+ }
+}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/pkg2/C2.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/pkg2/C2.java
new file mode 100644
index 0000000..fde1e6d
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/pkg2/C2.java
@@ -0,0 +1,9 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.pkg2;
+
+public class C2 {
+ public static int CONSTANT = 12;
+}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/pkg2/Example.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/pkg2/Example.java
new file mode 100644
index 0000000..6cce455
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/pkg2/Example.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This class is named the same as `Example` in other package to verify the renaming works.
+
+package com.github.dart_lang.jnigen.pkg2;
+
+public class Example {
+ public int whichExample() {
+ return 1;
+ }
+}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/simple_package/Color.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/simple_package/Color.java
new file mode 100644
index 0000000..efb96c6
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/simple_package/Color.java
@@ -0,0 +1,14 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.simple_package;
+
+public enum Color {
+ RED,
+ BLUE,
+ BLACK,
+ GREEN,
+ YELLOW,
+ LIME
+}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/simple_package/Example.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/simple_package/Example.java
new file mode 100644
index 0000000..b96156e
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/simple_package/Example.java
@@ -0,0 +1,238 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.simple_package;
+
+import java.util.*;
+
+public class Example {
+ // static fields - primitive & string
+ public static final int ON = 1;
+ public static final int OFF = 0;
+ public static final double PI = 3.14159;
+ public static final char SEMICOLON = ';';
+ public static final String SEMICOLON_STRING = ";";
+
+ public static final Random unusedRandom = new Random();
+
+ private static int amount = 500;
+ private static double pi = 3.14159;
+ private static char asterisk = '*';
+ private static String name = "Ragnar Lothbrok";
+
+ // Static fields - object
+ private static Nested nested = new Nested(true);
+
+ // static methods
+ public static int getAmount() {
+ return amount;
+ }
+
+ public static double getPi() {
+ return pi;
+ }
+
+ public static char getAsterisk() {
+ return asterisk;
+ }
+
+ public static String getName() {
+ return name;
+ }
+
+ public static Nested getNestedInstance() {
+ return nested;
+ }
+
+ // void functions with 1 parameter
+ public static void setAmount(int newAmount) {
+ amount = newAmount;
+ }
+
+ public static void setName(String newName) {
+ name = newName;
+ }
+
+ public static void setNestedInstance(Nested newNested) {
+ nested = newNested;
+ }
+
+ // void functions with many parameters
+ public static int max4(int a, int b, int c, int d) {
+ return Integer.max(Integer.max(a, b), Integer.max(c, d));
+ }
+
+ public static int max8(int a, int b, int c, int d, int e, int f, int g, int h) {
+ return Integer.max(max4(a, b, c, d), max4(e, f, g, h));
+ }
+
+ // Instance fields - primitive and string
+ private int number = 0;
+ private boolean isUp = false;
+ private String codename = "achilles";
+
+ // Instance fields - object
+ private Random random = new Random();
+
+ // Instance methods
+ public int getNumber() {
+ return number;
+ }
+
+ public void setNumber(int number) {
+ this.number = number;
+ }
+
+ public boolean getIsUp() {
+ return isUp;
+ }
+
+ public void setUp(boolean isUp) {
+ this.isUp = isUp;
+ }
+
+ public String getCodename() {
+ return codename;
+ }
+
+ public void setCodename(String codename) {
+ this.codename = codename;
+ }
+
+ public Random getRandom() {
+ return random;
+ }
+
+ public void setRandom(Random random) {
+ this.random = random;
+ }
+
+ public long getRandomLong() {
+ return random.nextLong();
+ }
+
+ public long add4Longs(long a, long b, long c, long d) {
+ return a + b + c + d;
+ }
+
+ public long add8Longs(long a, long b, long c, long d, long e, long f, long g, long h) {
+ return a + b + c + d + e + f + g + h;
+ }
+
+ public String getRandomNumericString(Random random) {
+ return String.format(
+ "%d%d%d%d", random.nextInt(10), random.nextInt(10), random.nextInt(10), random.nextInt(10));
+ }
+
+ private void privateMethod(String a, String b) {}
+
+ protected void protectedMethod(String a, String b) {}
+
+ protected Random protectedField;
+
+ public final void finalMethod() {}
+
+ public List<String> getList() {
+ return null;
+ }
+
+ /** Joins the strings in the list using the given delimiter. */
+ public String joinStrings(List<String> values, String delim) {
+ return null;
+ }
+
+ public <T extends CharSequence> void methodWithSeveralParams(
+ char ch, String s, int[] a, T t, List<T> lt, Map<String, ? extends CharSequence> wm) {}
+
+ public Example() {
+ this(0);
+ }
+
+ public Example(int number) {
+ this(number, true);
+ }
+
+ public Example(int number, boolean isUp) {
+ this(number, isUp, "achilles");
+ }
+
+ public Example(int number, boolean isUp, String codename) {
+ this.number = number;
+ this.isUp = isUp;
+ this.codename = codename;
+ }
+
+ public Example(int a, int b, int c, int d, int e, int f, int g, int h) {
+ this(a + b + c + d + e + f + g + h);
+ }
+
+ public int whichExample() {
+ return 0;
+ }
+
+ public static int addInts(int a, int b) {
+ return a + b;
+ }
+
+ public static int[] getArr() {
+ return new int[] {1, 2, 3};
+ }
+
+ public static int addAll(int[] arr) {
+ return Arrays.stream(arr).sum();
+ }
+
+ public Example getSelf() {
+ return this;
+ }
+
+ public static void throwException() {
+ throw new RuntimeException("Hello");
+ }
+
+ public void overloaded() {}
+
+ public void overloaded(int a, String b) {}
+
+ public void overloaded(int a) {}
+
+ public void overloaded(List<Integer> a, String b) {}
+
+ public void overloaded(List<Integer> a) {}
+
+ public class NonStaticNested {
+ public boolean ok;
+ }
+
+ public static class Nested {
+ private boolean value;
+
+ public Nested(boolean value) {
+ this.value = value;
+ }
+
+ public void usesAnonymousInnerClass() {
+ new Thread(
+ new Runnable() {
+ @Override
+ public void run() {
+ System.out.println("2982157093127690243");
+ }
+ })
+ .start();
+ }
+
+ public boolean getValue() {
+ return value;
+ }
+
+ public void setValue(boolean value) {
+ this.value = value;
+ }
+
+ public static class NestedTwice {
+ public static int ZERO = 0;
+ }
+ }
+}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/simple_package/Exceptions.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/simple_package/Exceptions.java
new file mode 100644
index 0000000..e0e79b3
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/simple_package/Exceptions.java
@@ -0,0 +1,82 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.simple_package;
+
+import java.io.*;
+import java.util.*;
+
+public class Exceptions {
+ public Exceptions() {}
+
+ // constructor throwing exception
+ public Exceptions(float x) {
+ throw new IllegalArgumentException("Float is not a serious type");
+ }
+
+ public Exceptions(int a, int b, int c, int d, int e, int f) {
+ throw new IllegalArgumentException("Too many arguments, but none in your favor");
+ }
+
+ public static Object staticObjectMethod() {
+ throw new RuntimeException(":-/");
+ }
+
+ public static int staticIntMethod() {
+ throw new RuntimeException("\\-:");
+ }
+
+ public static Object[] staticObjectArrayMethod() {
+ throw new RuntimeException(":-/[]");
+ }
+
+ public static int[] staticIntArrayMethod() {
+ throw new RuntimeException("\\-:[]");
+ }
+
+ public Object objectMethod() {
+ throw new RuntimeException("['--']");
+ }
+
+ public int intMethod() {
+ throw new RuntimeException("[-_-]");
+ }
+
+ public Object[] objectArrayMethod() {
+ throw new RuntimeException(":-/[]");
+ }
+
+ public int[] intArrayMethod() {
+ throw new RuntimeException("\\-:[]");
+ }
+
+ public int throwNullPointerException() {
+ Random random = null;
+ return random.nextInt();
+ }
+
+ public InputStream throwFileNotFoundException() throws IOException {
+ return new FileInputStream("/dev/nulll/59613/287");
+ }
+
+ public FileInputStream throwClassCastException() {
+ InputStream x = System.in;
+ return (FileInputStream) x;
+ }
+
+ public int throwArrayIndexException() {
+ int[] nums = {1, 2};
+ return nums[4];
+ }
+
+ public int throwArithmeticException() {
+ int x = 10;
+ int y = 100 - 100 + 1 - 1;
+ return x / y;
+ }
+
+ public static void throwLoremIpsum() {
+ throw new RuntimeException("Lorem Ipsum");
+ }
+}
diff --git a/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/simple_package/Fields.java b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/simple_package/Fields.java
new file mode 100644
index 0000000..face69c
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/java/com/github/dart_lang/jnigen/simple_package/Fields.java
@@ -0,0 +1,34 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.github.dart_lang.jnigen.simple_package;
+
+import java.util.*;
+
+public class Fields {
+ // static fields - non-final primitive & string
+ public static int amount = 500;
+ public static double pi = 3.14159;
+ public static char asterisk = '*';
+ public static String name = "Earl Haraldson";
+
+ // Static fields - object
+ public Integer i = 100;
+
+ // Instance fields - primitive and string
+ public long trillion = 1024L * 1024L * 1024L * 1024L;
+ public boolean isAchillesDead = false;
+ public String bestFighterInGreece = "Achilles";
+
+ // Instance fields - object
+ public Random random = new Random();
+
+ // Static and instance fields in nested class.
+ public static class Nested {
+ public long hundred = 100L;
+ public static String BEST_GOD = "Pallas Athena";
+ }
+
+ public static char euroSymbol = '\u20ac';
+}
diff --git a/pkgs/jnigen/test/simple_package_test/runtime_test_registrant.dart b/pkgs/jnigen/test/simple_package_test/runtime_test_registrant.dart
new file mode 100644
index 0000000..3791f9e
--- /dev/null
+++ b/pkgs/jnigen/test/simple_package_test/runtime_test_registrant.dart
@@ -0,0 +1,741 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:test/test.dart';
+import 'package:jni/jni.dart';
+
+import '../test_util/callback_types.dart';
+
+import 'c_based/dart_bindings/simple_package.dart';
+
+const pi = 3.14159;
+const fpDelta = 0.001;
+const trillion = 1024 * 1024 * 1024 * 1024;
+
+void _runJavaGC() {
+ final managementFactory =
+ Jni.findJClass('java/lang/management/ManagementFactory');
+ final bean = managementFactory.callStaticMethodByName<JObject>(
+ 'getRuntimeMXBean', '()Ljava/lang/management/RuntimeMXBean;', []);
+ final pid = bean.callMethodByName<int>('getPid', '()J', []);
+ ProcessResult result;
+ do {
+ result = Process.runSync('jcmd', [pid.toString(), 'GC.run']);
+ sleep(const Duration(milliseconds: 100));
+ } while (result.exitCode != 0);
+}
+
+void registerTests(String groupName, TestRunnerCallback test) {
+ group(groupName, () {
+ test('static final fields - int', () {
+ expect(Example.ON, equals(1));
+ expect(Example.OFF, equals(0));
+ expect(Example.PI, closeTo(pi, fpDelta));
+ expect(Example.SEMICOLON, equals(';'.codeUnitAt(0)));
+ expect(Example.SEMICOLON_STRING, equals(';'));
+ });
+
+ test('Static methods - primitive', () {
+ // same test can be run at a replicated (dart-only) test, check for both
+ // possible values.
+ expect(Example.getAmount(), isIn([1012, 500]));
+ Example.setAmount(1012);
+ expect(Example.getAmount(), equals(1012));
+ expect(Example.getAsterisk(), equals('*'.codeUnitAt(0)));
+ expect(C2.CONSTANT, equals(12));
+ });
+
+ test('Static fields & methods - string', () {
+ expect(
+ Example.getName().toDartString(releaseOriginal: true),
+ isIn(["Ragnar Lothbrok", "Theseus"]),
+ );
+ Example.setName("Theseus".toJString());
+ expect(
+ Example.getName().toDartString(releaseOriginal: true),
+ equals("Theseus"),
+ );
+ });
+
+ test('Static fields and methods - Object', () {
+ final nested = Example.getNestedInstance();
+ expect(nested.getValue(), isIn([true, false]));
+ nested.setValue(false);
+ expect(nested.getValue(), isFalse);
+ });
+
+ test('static methods with several arguments', () {
+ expect(Example.addInts(10, 15), equals(25));
+ expect(Example.max4(-1, 15, 30, 12), equals(30));
+ expect(Example.max8(1, 4, 8, 2, 4, 10, 8, 6), equals(10));
+ });
+
+ test('Instance methods (getters & setters)', () {
+ final e = Example();
+ expect(e.getNumber(), equals(0));
+ expect(e.getIsUp(), true);
+ expect(e.getCodename().toDartString(), equals("achilles"));
+ e.setNumber(1);
+ e.setUp(false);
+ e.setCodename("spartan".toJString());
+ expect(e.getIsUp(), false);
+ expect(e.getNumber(), 1);
+ expect(e.getCodename().toDartString(), equals("spartan"));
+ e.release();
+ });
+
+ test('Instance methods with several arguments', () {
+ final e = Example();
+ expect(e.add4Longs(1, 2, 3, 4), equals(10));
+ expect(e.add8Longs(1, 1, 2, 2, 3, 3, 12, 24), equals(48));
+ expect(
+ e.add4Longs(trillion, trillion, trillion, trillion),
+ equals(4 * trillion),
+ );
+ expect(
+ e.add8Longs(trillion, -trillion, trillion, -trillion, trillion,
+ -trillion, -trillion, -trillion),
+ equals(2 * -trillion),
+ );
+ e.release();
+ });
+
+ test('Misc. instance methods', () {
+ final e = Example();
+ final rand = e.getRandom();
+ expect(rand.isNull, isFalse);
+ final _ = e.getRandomLong();
+ final id =
+ e.getRandomNumericString(rand).toDartString(releaseOriginal: true);
+ expect(int.parse(id), lessThan(10000));
+ e.setNumber(145);
+ expect(
+ e.getSelf().getSelf().getSelf().getSelf().getNumber(),
+ equals(145),
+ );
+ e.release();
+ });
+
+ test('Constructors', () {
+ final e0 = Example();
+ expect(e0.getNumber(), 0);
+ expect(e0.getIsUp(), true);
+ expect(e0.getCodename().toDartString(), equals('achilles'));
+ final e1 = Example.new1(111);
+ expect(e1.getNumber(), equals(111));
+ expect(e1.getIsUp(), true);
+ expect(e1.getCodename().toDartString(), "achilles");
+ final e2 = Example.new2(122, false);
+ expect(e2.getNumber(), equals(122));
+ expect(e2.getIsUp(), false);
+ expect(e2.getCodename().toDartString(), "achilles");
+ final e3 = Example.new3(133, false, "spartan".toJString());
+ expect(e3.getNumber(), equals(133));
+ expect(e3.getIsUp(), false);
+ expect(e3.getCodename().toDartString(), "spartan");
+ });
+
+ test('Static (non-final) fields', () {
+ // Other replica test may already have modified this, so assert both
+ // values.
+ expect(Fields.amount, isIn([500, 101]));
+ Fields.amount = 101;
+ expect(Fields.amount, equals(101));
+
+ expect(Fields.asterisk, equals('*'.codeUnitAt(0)));
+
+ expect(
+ Fields.name.toDartString(),
+ isIn(["Earl Haraldson", "Ragnar Lothbrok"]),
+ );
+
+ Fields.name = "Ragnar Lothbrok".toJString();
+ expect(Fields.name.toDartString(), equals("Ragnar Lothbrok"));
+
+ expect(Fields.pi, closeTo(pi, fpDelta));
+ });
+
+ test('Instance fields', () {
+ final f = Fields();
+ expect(f.trillion, equals(trillion));
+
+ expect(f.isAchillesDead, isFalse);
+ expect(f.bestFighterInGreece.toDartString(), equals("Achilles"));
+ // "For your glory walks hand-in-hand with your doom." - Thetis.
+ f.isAchillesDead = true;
+ // I don't know much Greek mythology. But Troy was released in 2004,
+ // and 300 was released in 2006, so it's Leonidas I.
+ f.bestFighterInGreece = "Leonidas I".toJString();
+ expect(f.isAchillesDead, isTrue);
+ expect(f.bestFighterInGreece.toDartString(), "Leonidas I");
+ });
+
+ test('Fields from nested class', () {
+ expect(Fields_Nested().hundred, equals(100));
+ // Hector of Troy may disagree.
+ expect(Fields_Nested.BEST_GOD.toDartString(), equals('Pallas Athena'));
+ });
+
+ test('static methods arrays', () {
+ final array = Example.getArr();
+ expect(array[0], 1);
+ expect(array[1], 2);
+ expect(array[2], 3);
+ expect(Example.addAll(array), 6);
+ array[0] = 4;
+ expect(Example.addAll(array), 9);
+ });
+
+ test('array of the class', () {
+ final ex1 = Example();
+ final ex2 = Example();
+ ex1.setNumber(1);
+ ex2.setNumber(2);
+ final array = JArray(Example.type, 2);
+ array[0] = ex1;
+ array[1] = ex2;
+ expect(array[0].getNumber(), 1);
+ expect(array[1].getNumber(), 2);
+ array.release();
+ ex1.release();
+ ex2.release();
+ });
+
+ test("Check bindings for same-named classes", () {
+ expect(Example().whichExample(), 0);
+ expect(Example1().whichExample(), 1);
+ });
+
+ test('Unicode char', () {
+ expect(Fields.euroSymbol, equals('\u20AC'.codeUnitAt(0)));
+ });
+
+ group('exception tests', () {
+ void throwsException(void Function() f) {
+ expect(f, throwsA(isA<JniException>()));
+ }
+
+ test('Example throw exception', () {
+ throwsException(Example.throwException);
+ });
+
+ test('Exception from method returning Object', () {
+ throwsException(Exceptions.staticObjectMethod);
+ throwsException(Exceptions.staticObjectArrayMethod);
+ final x = Exceptions();
+ throwsException(x.objectMethod);
+ throwsException(x.objectArrayMethod);
+ });
+
+ test('Exception from method returning int', () {
+ throwsException(Exceptions.staticIntMethod);
+ throwsException(Exceptions.staticIntArrayMethod);
+ final x = Exceptions();
+ throwsException(x.intMethod);
+ throwsException(x.intArrayMethod);
+ });
+
+ test('Exception from constructor', () {
+ throwsException(() => Exceptions.new1(6.8));
+ throwsException(() => Exceptions.new2(1, 2, 3, 4, 5, 6));
+ });
+
+ test('Exception contains error message & stack trace', () {
+ try {
+ Exceptions.throwLoremIpsum();
+ } on JniException catch (e) {
+ expect(e.message, stringContainsInOrder(["Lorem Ipsum"]));
+ expect(
+ e.toString(),
+ stringContainsInOrder(["Lorem Ipsum", "throwLoremIpsum"]),
+ );
+ return;
+ }
+ throw AssertionError("No exception was thrown");
+ });
+ });
+
+ group('generics', () {
+ test('GrandParent constructor', () {
+ using((arena) {
+ final grandParent =
+ GrandParent('Hello'.toJString()..releasedBy(arena))
+ ..releasedBy(arena);
+ expect(grandParent, isA<GrandParent<JString>>());
+ expect(grandParent.$type, isA<$GrandParentType<JString>>());
+ expect(
+ grandParent.value.toDartString(releaseOriginal: true), 'Hello');
+ });
+ });
+ test('MyStack<T>', () {
+ using((arena) {
+ final stack = MyStack(T: JString.type)..releasedBy(arena);
+ stack.push('Hello'.toJString()..releasedBy(arena));
+ stack.push('World'.toJString()..releasedBy(arena));
+ expect(stack.pop().toDartString(releaseOriginal: true), 'World');
+ expect(stack.pop().toDartString(releaseOriginal: true), 'Hello');
+ });
+ });
+ test('Different stacks have different types, same stacks have same types',
+ () {
+ using((arena) {
+ final aStringStack = MyStack(T: JString.type)..releasedBy(arena);
+ final anotherStringStack = MyStack(T: JString.type)
+ ..releasedBy(arena);
+ final anObjectStack = MyStack(T: JObject.type)..releasedBy(arena);
+ expect(aStringStack.$type, anotherStringStack.$type);
+ expect(
+ aStringStack.$type.hashCode,
+ anotherStringStack.$type.hashCode,
+ );
+ expect(aStringStack.$type, isNot(anObjectStack.$type));
+ expect(
+ aStringStack.$type.hashCode,
+ isNot(anObjectStack.$type.hashCode),
+ );
+ });
+ });
+ test('MyMap<K, V>', () {
+ using((arena) {
+ final map = MyMap(K: JString.type, V: Example.type)
+ ..releasedBy(arena);
+ final helloExample = Example.new1(1)..releasedBy(arena);
+ final worldExample = Example.new1(2)..releasedBy(arena);
+ map.put('Hello'.toJString()..releasedBy(arena), helloExample);
+ map.put('World'.toJString()..releasedBy(arena), worldExample);
+ expect(
+ (map.get0('Hello'.toJString()..releasedBy(arena))
+ ..releasedBy(arena))
+ .getNumber(),
+ 1,
+ );
+ expect(
+ (map.get0('World'.toJString()..releasedBy(arena))
+ ..releasedBy(arena))
+ .getNumber(),
+ 2,
+ );
+ expect(
+ ((map.entryStack()..releasedBy(arena)).pop()..releasedBy(arena))
+ .key
+ .castTo(JString.type, releaseOriginal: true)
+ .toDartString(releaseOriginal: true),
+ anyOf('Hello', 'World'),
+ );
+ });
+ });
+ group('classes extending generics', () {
+ test('StringStack', () {
+ using((arena) {
+ final stringStack = StringStack()..releasedBy(arena);
+ stringStack.push('Hello'.toJString()..releasedBy(arena));
+ expect(
+ stringStack.pop().toDartString(releaseOriginal: true), 'Hello');
+ });
+ });
+ test('StringKeyedMap', () {
+ using((arena) {
+ final map = StringKeyedMap(V: Example.type)..releasedBy(arena);
+ final example = Example()..releasedBy(arena);
+ map.put('Hello'.toJString()..releasedBy(arena), example);
+ expect(
+ (map.get0('Hello'.toJString()..releasedBy(arena))
+ ..releasedBy(arena))
+ .getNumber(),
+ 0,
+ );
+ });
+ });
+ test('StringValuedMap', () {
+ using((arena) {
+ final map = StringValuedMap(K: Example.type)..releasedBy(arena);
+ final example = Example()..releasedBy(arena);
+ map.put(example, 'Hello'.toJString()..releasedBy(arena));
+ expect(
+ map.get0(example).toDartString(releaseOriginal: true),
+ 'Hello',
+ );
+ });
+ });
+ test('StringMap', () {
+ using((arena) {
+ final map = StringMap()..releasedBy(arena);
+ map.put('hello'.toJString()..releasedBy(arena),
+ 'world'.toJString()..releasedBy(arena));
+ expect(
+ map
+ .get0('hello'.toJString()..releasedBy(arena))
+ .toDartString(releaseOriginal: true),
+ 'world',
+ );
+ });
+ });
+ });
+ test('superclass count', () {
+ expect(JObject.type.superCount, 0);
+ expect(MyMap.type(JObject.type, JObject.type).superCount, 1);
+ expect(StringKeyedMap.type(JObject.type).superCount, 2);
+ expect(StringValuedMap.type(JObject.type).superCount, 2);
+ expect(StringMap.type.superCount, 3);
+ });
+ test('nested generics', () {
+ using((arena) {
+ final grandParent =
+ GrandParent(T: JString.type, "!".toJString()..releasedBy(arena))
+ ..releasedBy(arena);
+ expect(
+ grandParent.value.toDartString(releaseOriginal: true),
+ "!",
+ );
+
+ final strStaticParent = GrandParent.stringStaticParent()
+ ..releasedBy(arena);
+ expect(
+ strStaticParent.value.toDartString(releaseOriginal: true),
+ "Hello",
+ );
+
+ final exampleStaticParent = GrandParent.varStaticParent(
+ S: Example.type, Example()..releasedBy(arena))
+ ..releasedBy(arena);
+ expect(
+ (exampleStaticParent.value..releasedBy(arena)).getNumber(),
+ 0,
+ );
+
+ final strParent = grandParent.stringParent()..releasedBy(arena);
+ expect(
+ strParent.parentValue
+ .castTo(JString.type, releaseOriginal: true)
+ .toDartString(releaseOriginal: true),
+ "!",
+ );
+ expect(
+ strParent.value.toDartString(releaseOriginal: true),
+ "Hello",
+ );
+
+ final exampleParent = grandParent.varParent(
+ S: Example.type, Example()..releasedBy(arena))
+ ..releasedBy(arena);
+ expect(
+ exampleParent.parentValue
+ .castTo(JString.type, releaseOriginal: true)
+ .toDartString(releaseOriginal: true),
+ "!",
+ );
+ expect(
+ (exampleParent.value..releasedBy(arena)).getNumber(),
+ 0,
+ );
+ // TODO(#139): test constructing Child, currently does not work due
+ // to a problem with C-bindings.
+ });
+ });
+ });
+ test('Constructing non-static nested classes', () {
+ using((arena) {
+ final grandParent = GrandParent(1.toJInteger())..releasedBy(arena);
+ final parent = GrandParent_Parent(grandParent, 2.toJInteger())
+ ..releasedBy(arena);
+ final child = GrandParent_Parent_Child(parent, 3.toJInteger())
+ ..releasedBy(arena);
+ expect(grandParent.value.intValue(releaseOriginal: true), 1);
+ expect(parent.parentValue.intValue(releaseOriginal: true), 1);
+ expect(parent.value.intValue(releaseOriginal: true), 2);
+ expect(child.grandParentValue.intValue(releaseOriginal: true), 1);
+ expect(child.parentValue.intValue(releaseOriginal: true), 2);
+ expect(child.value.intValue(releaseOriginal: true), 3);
+ });
+ });
+
+ group('Generic type inference', () {
+ test('MyStack.of1', () {
+ using((arena) {
+ final emptyStack = MyStack(T: JString.type)..releasedBy(arena);
+ expect(emptyStack.size(), 0);
+ final stack = MyStack.of1(
+ "Hello".toJString()..releasedBy(arena),
+ )..releasedBy(arena);
+ expect(stack, isA<MyStack<JString>>());
+ expect(stack.$type, isA<$MyStackType<JString>>());
+ expect(
+ stack.pop().toDartString(releaseOriginal: true),
+ "Hello",
+ );
+ });
+ });
+ test('MyStack.of 2 strings', () {
+ using((arena) {
+ final stack = MyStack.of2(
+ "Hello".toJString()..releasedBy(arena),
+ "World".toJString()..releasedBy(arena),
+ )..releasedBy(arena);
+ expect(stack, isA<MyStack<JString>>());
+ expect(stack.$type, isA<$MyStackType<JString>>());
+ expect(
+ stack.pop().toDartString(releaseOriginal: true),
+ "World",
+ );
+ expect(
+ stack.pop().toDartString(releaseOriginal: true),
+ "Hello",
+ );
+ });
+ });
+ test('MyStack.of a string and an array', () {
+ using((arena) {
+ final array = JArray.filled(1, "World".toJString()..releasedBy(arena))
+ ..releasedBy(arena);
+ final stack = MyStack.of2(
+ "Hello".toJString()..releasedBy(arena),
+ array,
+ )..releasedBy(arena);
+ expect(stack, isA<MyStack<JObject>>());
+ expect(stack.$type, isA<$MyStackType<JObject>>());
+ expect(
+ stack
+ .pop()
+ .castTo(JArray.type(JString.type), releaseOriginal: true)[0]
+ .toDartString(releaseOriginal: true),
+ "World",
+ );
+ expect(
+ stack
+ .pop()
+ .castTo(JString.type, releaseOriginal: true)
+ .toDartString(releaseOriginal: true),
+ "Hello",
+ );
+ });
+ });
+ test('MyStack.from array of string', () {
+ using((arena) {
+ final array = JArray.filled(1, "Hello".toJString()..releasedBy(arena))
+ ..releasedBy(arena);
+ final stack = MyStack.fromArray(array)..releasedBy(arena);
+ expect(stack, isA<MyStack<JString>>());
+ expect(stack.$type, isA<$MyStackType<JString>>());
+ expect(
+ stack.pop().toDartString(releaseOriginal: true),
+ "Hello",
+ );
+ });
+ });
+ test('MyStack.fromArrayOfArrayOfGrandParents', () {
+ using((arena) {
+ final firstDimention = JArray.filled(
+ 1,
+ GrandParent("Hello".toJString()..releasedBy(arena))
+ ..releasedBy(arena),
+ )..releasedBy(arena);
+ final twoDimentionalArray = JArray.filled(1, firstDimention)
+ ..releasedBy(arena);
+ final stack =
+ MyStack.fromArrayOfArrayOfGrandParents(twoDimentionalArray)
+ ..releasedBy(arena);
+ expect(stack, isA<MyStack<JString>>());
+ expect(stack.$type, isA<$MyStackType<JString>>());
+ expect(
+ stack.pop().toDartString(releaseOriginal: true),
+ "Hello",
+ );
+ });
+ });
+ });
+ });
+
+ group('interface implementation', () {
+ for (final (threading, consume) in [
+ ('another thread', MyInterfaceConsumer.consumeOnAnotherThread),
+ ('the same thread', MyInterfaceConsumer.consumeOnSameThread),
+ ]) {
+ test('MyInterface.implement on $threading', () async {
+ final voidCallbackResult = Completer<JString>();
+ final varCallbackResult = Completer<JInteger>();
+ final manyPrimitivesResult = Completer<int>();
+ // We can use this trick to access self, instead of generating a `thiz`
+ // or `self` argument for each one of the callbacks.
+ late final MyInterface<JInteger> myInterface;
+ myInterface = MyInterface.implement(
+ $MyInterfaceImpl(
+ voidCallback: (s) {
+ voidCallbackResult.complete(s);
+ },
+ stringCallback: (s) {
+ return (s.toDartString(releaseOriginal: true) * 2).toJString();
+ },
+ varCallback: (JInteger t) {
+ final result =
+ (t.intValue(releaseOriginal: true) * 2).toJInteger();
+ varCallbackResult.complete(result);
+ return result;
+ },
+ manyPrimitives: (a, b, c, d) {
+ if (b) {
+ final result = a + c + d.toInt();
+ manyPrimitivesResult.complete(result);
+ return result;
+ } else {
+ // Call self, add to [a] when [b] is false and change b to true.
+ return myInterface.manyPrimitives(a + 1, true, c, d);
+ }
+ },
+ T: JInteger.type,
+ ),
+ );
+ // [stringCallback] is going to be called first using [s].
+ // The result of it is going to be used as the argument for
+ // [voidCallback].
+ // The other two methods will be called individually using the passed
+ // arguments afterwards.
+ consume(
+ myInterface,
+ // For stringCallback:
+ 'hello'.toJString(),
+ // For manyPrimitives:
+ -1,
+ false,
+ 3,
+ 3.14,
+ // For varCallback
+ 7.toJInteger(),
+ );
+ final voidCallback = await voidCallbackResult.future;
+ expect(voidCallback.toDartString(releaseOriginal: true), 'hellohello');
+
+ final varCallback = await varCallbackResult.future;
+ expect(varCallback.intValue(), 14);
+
+ final manyPrimitives = await manyPrimitivesResult.future;
+ expect(manyPrimitives, -1 + 3 + 3.14.toInt() + 1);
+
+ // Currently we have one implementation of the interface.
+ expect(MyInterface.$impls, hasLength(1));
+ myInterface.release();
+ // Running System.gc() and waiting.
+ _runJavaGC();
+ for (var i = 0; i < 8; ++i) {
+ await Future<void>.delayed(Duration(milliseconds: (1 << i) * 100));
+ if (MyInterface.$impls.isEmpty) {
+ break;
+ }
+ }
+ // Since the interface is now deleted, the cleaner must signal to Dart
+ // to clean up.
+ expect(MyInterface.$impls, isEmpty);
+ });
+ }
+ group('Dart exceptions are handled', () {
+ for (final exception in [UnimplementedError(), 'Hello!']) {
+ for (final sameThread in [true, false]) {
+ test(
+ 'on ${sameThread ? 'the same thread' : 'another thread'}'
+ ' throwing $exception', () async {
+ final runnable = MyRunnable.implement(
+ $MyRunnableImpl(
+ run: () {
+ throw exception;
+ },
+ ),
+ );
+ final runner = MyRunnableRunner(runnable);
+ if (sameThread) {
+ runner.runOnSameThread();
+ } else {
+ runner.runOnAnotherThread();
+ }
+ while (runner.error.isNull) {
+ await Future<void>.delayed(const Duration(milliseconds: 100));
+ }
+ expect(
+ Jni.env.IsInstanceOf(
+ runner.error.reference,
+ Jni.findClass('java/lang/reflect/UndeclaredThrowableException'),
+ ),
+ isTrue,
+ );
+ final cause = runner.error.callMethodByName<JObject>(
+ 'getCause', '()Ljava/lang/Throwable;', []);
+ expect(
+ Jni.env.IsInstanceOf(
+ cause.reference,
+ Jni.findClass(
+ 'com/github/dart_lang/jni/PortProxy\$DartException'),
+ ),
+ isTrue,
+ );
+ expect(cause.toString(), contains(exception.toString()));
+ });
+ }
+ }
+ });
+ });
+
+ group('$groupName (load tests)', () {
+ const k4 = 4 * 1024; // This is a round number, unlike say 4000
+ const k256 = 256 * 1024;
+ test('Create large number of JNI references without deleting', () {
+ for (int i = 0; i < k4; i++) {
+ final e = Example.new1(i);
+ expect(e.getNumber(), equals(i));
+ }
+ });
+ test('Create many JNI refs with scoped deletion', () {
+ for (int i = 0; i < k256; i++) {
+ using((arena) {
+ final e = Example.new1(i)..releasedBy(arena);
+ expect(e.getNumber(), equals(i));
+ });
+ }
+ });
+ test('Create many JNI refs with scoped deletion, in batches', () {
+ for (int i = 0; i < 256; i++) {
+ using((arena) {
+ for (int i = 0; i < 1024; i++) {
+ final e = Example.new1(i)..releasedBy(arena);
+ expect(e.getNumber(), equals(i));
+ }
+ });
+ }
+ });
+ test('Create large number of JNI refs with manual delete', () {
+ for (int i = 0; i < k256; i++) {
+ final e = Example.new1(i);
+ expect(e.getNumber(), equals(i));
+ e.release();
+ }
+ });
+ test('Method returning primitive type does not create references', () {
+ using((arena) {
+ final e = Example.new1(64)..releasedBy(arena);
+ for (int i = 0; i < k256; i++) {
+ expect(e.getNumber(), equals(64));
+ }
+ });
+ });
+ test('Class references are cached', () {
+ final asterisk = '*'.codeUnitAt(0);
+ for (int i = 0; i < k256; i++) {
+ expect(Fields.asterisk, equals(asterisk));
+ }
+ });
+ void testPassageOfTime(int n) {
+ test('Refs are not inadvertently deleted after $n seconds', () {
+ final f = Fields();
+ expect(f.trillion, equals(trillion));
+ sleep(Duration(seconds: n));
+ expect(f.trillion, equals(trillion));
+ });
+ }
+
+ if (!Platform.isAndroid) {
+ testPassageOfTime(1);
+ testPassageOfTime(4);
+ }
+ });
+}
diff --git a/pkgs/jnigen/test/summary_generation_test.dart b/pkgs/jnigen/test/summary_generation_test.dart
new file mode 100644
index 0000000..62eee3b
--- /dev/null
+++ b/pkgs/jnigen/test/summary_generation_test.dart
@@ -0,0 +1,174 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// These tests validate summary generation in various scenarios.
+// Currently, no validation of the summary content itself is done.
+
+@Tags(['summarizer_test'])
+
+import 'dart:math';
+
+import 'package:jnigen/src/config/config.dart';
+import 'package:jnigen/src/elements/elements.dart';
+import 'package:jnigen/src/summary/summary.dart';
+
+import 'package:path/path.dart' hide equals;
+import 'package:test/test.dart';
+
+import 'test_util/summary_util.dart';
+import 'test_util/test_util.dart';
+
+const nestedClasses = [
+ 'com.github.dart_lang.jnigen.simple_package.Example\$Nested',
+ 'com.github.dart_lang.jnigen.simple_package.Example\$Nested\$NestedTwice',
+ 'com.github.dart_lang.jnigen.generics.GrandParent\$StaticParent',
+ 'com.github.dart_lang.jnigen.generics.GrandParent\$StaticParent\$Child',
+ 'com.github.dart_lang.jnigen.generics.GrandParent\$Parent',
+ 'com.github.dart_lang.jnigen.generics.GrandParent\$Parent\$Child',
+];
+
+void expectSummaryHasAllClasses(Classes? classes) {
+ expect(classes, isNotNull);
+ final decls = classes!.decls;
+ expect(decls.entries.length, greaterThanOrEqualTo(javaFiles.length));
+ final declNames = decls.keys.toSet();
+ final expectedClasses =
+ javaClasses.where((name) => !name.contains("annotations.")).toList();
+ // Nested classes should be included automatically with parent class.
+ // change this part if you change this behavior intentionally.
+ expectedClasses.addAll(nestedClasses);
+ expect(declNames, containsAll(expectedClasses));
+}
+
+/// Packs files indicated by [artifacts], each relative to [artifactDir] into
+/// a JAR file at [jarPath].
+Future<void> createJar({
+ required String artifactDir,
+ required List<String> artifacts,
+ required String jarPath,
+}) async {
+ await runCommand(
+ 'jar',
+ ['cf', relative(jarPath, from: artifactDir), ...artifacts],
+ workingDirectory: artifactDir,
+ );
+}
+
+final random = Random.secure();
+
+void testSuccessCase(String description, Config config) {
+ config.classes = summarizerClassesSpec;
+ test(description, () async {
+ final classes = await getSummary(config);
+ expectSummaryHasAllClasses(classes);
+ });
+}
+
+void testFailureCase(
+ String description, Config config, String nonExistingClass) {
+ test(description, () async {
+ final insertPosition = random.nextInt(config.classes.length + 1);
+ config.classes = summarizerClassesSpec.sublist(0, insertPosition) +
+ [nonExistingClass] +
+ summarizerClassesSpec.sublist(insertPosition);
+ try {
+ await getSummary(config);
+ } on SummaryParseException catch (e) {
+ expect(e.stderr, isNotNull);
+ expect(e.stderr!, stringContainsInOrder(["Not found", nonExistingClass]));
+ return;
+ }
+ throw AssertionError("No exception was caught");
+ });
+}
+
+void testAllCases({
+ List<String>? sourcePath,
+ List<String>? classPath,
+}) {
+ testSuccessCase(
+ '- valid config',
+ getSummaryGenerationConfig(sourcePath: sourcePath, classPath: classPath),
+ );
+ testFailureCase(
+ '- should fail with non-existing class',
+ getSummaryGenerationConfig(sourcePath: sourcePath, classPath: classPath),
+ 'com.github.dart_lang.jnigen.DoesNotExist',
+ );
+ testFailureCase(
+ '- should fail with non-existing package',
+ getSummaryGenerationConfig(sourcePath: sourcePath, classPath: classPath),
+ 'com.github.dart_lang.notexist',
+ );
+}
+
+void main() async {
+ await checkLocallyBuiltDependencies();
+ final tempDir = getTempDir("jnigen_summary_tests_");
+
+ group('Test summary generation from compiled JAR', () {
+ final targetDir = tempDir.createTempSync("compiled_jar_test_");
+ final jarPath = join(targetDir.absolute.path, 'classes.jar');
+ setUpAll(() async {
+ await compileJavaFiles(simplePackageDir, targetDir);
+ final classFiles = findFilesWithSuffix(targetDir, '.class');
+ await createJar(
+ artifactDir: targetDir.path, artifacts: classFiles, jarPath: jarPath);
+ });
+ testAllCases(classPath: [jarPath]);
+ });
+
+ group('Test summary generation from source JAR', () {
+ final targetDir = tempDir.createTempSync("source_jar_test_");
+ final jarPath = join(targetDir.path, 'sources.jar');
+ setUpAll(() async {
+ await createJar(
+ artifactDir: simplePackageDir.path,
+ artifacts: javaFiles,
+ jarPath: jarPath);
+ });
+ testAllCases(sourcePath: [jarPath]);
+ });
+
+ group('Test summary generation from source folder', () {
+ testAllCases(sourcePath: [simplePackagePath]);
+ });
+
+ group('Test summary generation from compiled classes in directory', () {
+ final targetDir = tempDir.createTempSync("compiled_classes_test_");
+ setUpAll(() => compileJavaFiles(simplePackageDir, targetDir));
+ testAllCases(classPath: [targetDir.path]);
+ });
+
+ // Test summary generation from combination of a source and class path
+ group('Test summary generation from combination', () {
+ final targetDir = tempDir.createTempSync("combination_test_");
+ final classesJarPath = join(targetDir.path, 'classes.jar');
+ // remove a class from source files and create a source JAR
+ final sourceFiles = javaFiles.toList();
+ sourceFiles.removeLast();
+ final sourceJarPath = join(targetDir.path, 'sources.jar');
+ setUpAll(() async {
+ await createJar(
+ artifactDir: simplePackageDir.path,
+ artifacts: sourceFiles,
+ jarPath: sourceJarPath,
+ );
+
+ await compileJavaFiles(simplePackageDir, targetDir);
+ final classFiles = findFilesWithSuffix(targetDir, '.class');
+ await createJar(
+ artifactDir: targetDir.path,
+ artifacts: classFiles,
+ jarPath: classesJarPath,
+ );
+ });
+ testAllCases(
+ classPath: [classesJarPath],
+ sourcePath: [sourceJarPath],
+ );
+ });
+
+ tearDownAll(() => deleteTempDirWithDelay(tempDir));
+}
diff --git a/pkgs/jnigen/test/summary_test.dart b/pkgs/jnigen/test/summary_test.dart
new file mode 100644
index 0000000..c83e798
--- /dev/null
+++ b/pkgs/jnigen/test/summary_test.dart
@@ -0,0 +1,323 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// These tests validate individual characteristics in summary
+// For example, the values of methods, arguments, types, generic params etc...
+@Tags(['summarizer_test'])
+
+import 'package:jnigen/src/elements/elements.dart';
+import 'package:jnigen/src/summary/summary.dart';
+import 'package:test/test.dart';
+
+import 'test_util/summary_util.dart';
+import 'test_util/test_util.dart';
+
+const jnigenPackage = 'com.github.dart_lang.jnigen';
+const simplePackage = "$jnigenPackage.simple_package";
+
+extension on Classes {
+ String _getSimpleName(ClassDecl c) {
+ return c.binaryName.split(".").last;
+ }
+
+ ClassDecl getClassBySimpleName(String simpleName) {
+ return decls.values.firstWhere((c) => _getSimpleName(c) == simpleName);
+ }
+
+ ClassDecl getClass(String dirName, String className) {
+ return decls['$jnigenPackage.$dirName.$className']!;
+ }
+
+ ClassDecl getExampleClass() {
+ return getClass('simple_package', 'Example');
+ }
+}
+
+extension on ClassDecl {
+ Method getMethod(String name) => methods.firstWhere((m) => m.name == name);
+ Field getField(String name) => fields.firstWhere((f) => f.name == name);
+}
+
+void registerCommonTests(Classes classes) {
+ test('static modifier', () {
+ final example = classes.getExampleClass();
+ final containsStatic = contains("static");
+ final notContainsStatic = isNot(containsStatic);
+ expect(example.getMethod("max4").modifiers, containsStatic);
+ expect(example.getMethod("getCodename").modifiers, notContainsStatic);
+ expect(example.getField("ON").modifiers, containsStatic);
+ expect(example.getField("codename").modifiers, notContainsStatic);
+ final nested = classes.getClassBySimpleName("Example\$Nested");
+ expect(nested.modifiers, containsStatic);
+ final nonStaticNested =
+ classes.getClassBySimpleName("Example\$NonStaticNested");
+ expect(nonStaticNested.modifiers, notContainsStatic);
+ });
+
+ test('Public, protected and private modifiers', () {
+ final example = classes.getExampleClass();
+ final hasPrivate = contains("private");
+ final hasProtected = contains("protected");
+ final hasPublic = contains("public");
+ final isPrivate = allOf(hasPrivate, isNot(hasProtected), isNot(hasPublic));
+ final isProtected =
+ allOf(isNot(hasPrivate), hasProtected, isNot(hasPublic));
+ final isPublic = allOf(isNot(hasPrivate), isNot(hasProtected), hasPublic);
+ expect(example.getMethod("getNumber").modifiers, isPublic);
+ expect(example.getMethod("privateMethod").modifiers, isPrivate);
+ expect(example.getMethod("protectedMethod").modifiers, isProtected);
+ expect(example.getField("OFF").modifiers, isPublic);
+ expect(example.getField("number").modifiers, isPrivate);
+ expect(example.getField("protectedField").modifiers, isProtected);
+ });
+
+ test('final modifier', () {
+ final example = classes.getExampleClass();
+ final isFinal = contains('final');
+ expect(example.getField("PI").modifiers, isFinal);
+ expect(example.getField("unusedRandom").modifiers, isFinal);
+ expect(example.getField("number").modifiers, isNot(isFinal));
+ expect(example.getMethod("finalMethod").modifiers, isFinal);
+ });
+
+ void assertToBeStringListType(TypeUsage listType) {
+ expect(listType.kind, equals(Kind.declared));
+ final listClassType = listType.type as DeclaredType;
+ expect(listClassType.binaryName, equals('java.util.List'));
+ expect(listClassType.params, hasLength(1));
+ final listTypeParam = listClassType.params[0];
+ expect(listTypeParam.kind, equals(Kind.declared));
+ expect(listTypeParam.type.name, equals('java.lang.String'));
+ }
+
+ test('return types', () {
+ final example = classes.getExampleClass();
+ expect(example.getMethod("getNumber").returnType.shorthand, equals("int"));
+ expect(example.getMethod("getName").returnType.shorthand,
+ equals("java.lang.String"));
+ expect(example.getMethod("getNestedInstance").returnType.name,
+ equals("$simplePackage.Example\$Nested"));
+ final listType = example.getMethod("getList").returnType;
+ assertToBeStringListType(listType);
+ });
+
+ test('parameter types', () {
+ final example = classes.getExampleClass();
+ final joinStrings = example.getMethod('joinStrings');
+ final listType = joinStrings.params[0].type;
+ assertToBeStringListType(listType);
+ final stringType = joinStrings.params[1].type;
+ expect(stringType.kind, Kind.declared);
+ expect((stringType.type as DeclaredType).binaryName, 'java.lang.String');
+ });
+
+ test('Parameters of several types', () {
+ final example = classes.getExampleClass();
+ final method = example.getMethod('methodWithSeveralParams');
+ expect(method.typeParams, hasLength(1));
+ expect(method.typeParams[0].name, 'T');
+ expect(method.typeParams[0].bounds[0].name, 'java.lang.CharSequence');
+
+ final charParam = method.params[0];
+ expect(charParam.type.kind, equals(Kind.primitive));
+ expect(charParam.type.name, equals('char'));
+
+ final stringParam = method.params[1];
+ expect(stringParam.type.kind, equals(Kind.declared));
+ expect((stringParam.type.type as DeclaredType).binaryName,
+ equals('java.lang.String'));
+
+ final arrayParam = method.params[2];
+ expect(arrayParam.type.kind, equals(Kind.array));
+ expect((arrayParam.type.type as ArrayType).type.name, equals('int'));
+
+ final typeVarParam = method.params[3];
+ expect(typeVarParam.type.kind, equals(Kind.typeVariable));
+ expect((typeVarParam.type.type as TypeVar).name, equals('T'));
+
+ final listParam = method.params[4];
+ expect(listParam.type.kind, equals(Kind.declared));
+ final listType = (listParam.type.type as DeclaredType);
+ expect(listType.binaryName, equals('java.util.List'));
+ expect(listType.params, hasLength(1));
+ final tType = listType.params[0];
+ expect(tType.kind, Kind.typeVariable);
+ expect((tType.type as TypeVar).name, equals('T'));
+
+ final wildcardMapParam = method.params[5];
+ expect(wildcardMapParam.type.kind, equals(Kind.declared));
+ final mapType = (wildcardMapParam.type.type as DeclaredType);
+ expect(mapType.binaryName, equals('java.util.Map'));
+ expect(mapType.params, hasLength(2));
+ final strType = mapType.params[0];
+ expect(strType.name, 'java.lang.String');
+ // TODO(#141): Wildcard implementation.
+ /*
+ final wildcardType = mapType.params[1];
+ expect(wildcardType.kind, equals(Kind.wildcard));
+ expect((wildcardType.type as Wildcard).extendsBound?.name,
+ equals('java.lang.CharSequence'));
+ */
+ });
+
+ test('superclass', () {
+ final baseClass = classes.getClass('inheritance', 'BaseClass');
+ expect(baseClass.typeParams, hasLength(1));
+ final typeParam = baseClass.typeParams.single;
+ expect(typeParam.bounds.map((b) => b.name).toList(),
+ ['java.lang.CharSequence']);
+
+ final specific = classes.getClass('inheritance', 'SpecificDerivedClass');
+ expect(specific.typeParams, hasLength(0));
+ expect(specific.superclass, isNotNull);
+ final specificSuper = specific.superclass!.type as DeclaredType;
+ expect(specificSuper.params[0].type, isA<DeclaredType>());
+ expect(specificSuper.params[0].type.name, equals('java.lang.String'));
+
+ final generic = classes.getClass('inheritance', 'GenericDerivedClass');
+ expect(generic.typeParams, hasLength(1));
+ expect(generic.typeParams[0].name, equals('T'));
+ expect(generic.typeParams[0].bounds.map((b) => b.name).toList(),
+ ['java.lang.CharSequence']);
+ expect(generic.superclass, isNotNull);
+ final genericSuper = generic.superclass!.type as DeclaredType;
+ expect(genericSuper.params[0].type, isA<TypeVar>());
+ expect(genericSuper.params[0].type.name, equals('T'));
+ });
+
+ test('constructor is included', () {
+ final example = classes.getExampleClass();
+ void assertOneCtorExistsWithArity(List<String> paramTypes) {
+ final arityCtors = example.methods
+ .where(
+ (m) => m.name == '<init>' && m.params.length == paramTypes.length)
+ .toList();
+ expect(arityCtors, hasLength(1));
+ final ctor = arityCtors[0];
+ expect(ctor.params.map((p) => p.type.name), equals(paramTypes));
+ }
+
+ assertOneCtorExistsWithArity([]);
+ assertOneCtorExistsWithArity(['int']);
+ assertOneCtorExistsWithArity(['int', 'boolean']);
+ assertOneCtorExistsWithArity(['int', 'boolean', 'java.lang.String']);
+ });
+
+ test('Overloaded methods', () {
+ final methods = classes
+ .getExampleClass()
+ .methods
+ .where((m) => m.name == 'overloaded')
+ .toList();
+ final signatures =
+ methods.map((m) => m.params.map((p) => p.type.name).toList()).toSet();
+ expect(
+ signatures,
+ equals({
+ <String>[],
+ ['int'],
+ ['int', 'java.lang.String'],
+ ['java.util.List'],
+ ['java.util.List', 'java.lang.String'],
+ }),
+ );
+ });
+
+ test('Declaration type (class vs interface vs enum)', () {
+ final example = classes.getExampleClass();
+ expect(example.declKind, DeclKind.classKind);
+ final myInterface = classes.getClass('interfaces', 'MyInterface');
+ expect(myInterface.declKind, DeclKind.interfaceKind);
+ final color = classes.getClass('simple_package', 'Color');
+ expect(color.declKind, DeclKind.enumKind);
+ });
+
+ test('Enum values', () {
+ final example = classes.getExampleClass();
+ expect(example.values, anyOf(isNull, isEmpty));
+ final color = classes.getClass('simple_package', 'Color');
+ const expectedEnumValues = {
+ 'RED',
+ 'BLUE',
+ 'BLACK',
+ 'GREEN',
+ 'YELLOW',
+ 'LIME'
+ };
+ expect(color.values?.toSet(), expectedEnumValues);
+ });
+
+ test('Static final field values', () {
+ final example = classes.getExampleClass();
+ expect(example.getField("ON").defaultValue, equals(1));
+ expect(example.getField("OFF").defaultValue, equals(0));
+ expect(example.getField("PI").defaultValue, closeTo(3.14159, 0.001));
+ expect(
+ example.getField("SEMICOLON").defaultValue, equals(';'.codeUnitAt(0)));
+ expect(example.getField("SEMICOLON_STRING").defaultValue, equals(';'));
+ });
+
+ test('self referencing generic parameters', () {
+ final gp = classes.getClass('generics', 'GenericTypeParams');
+ final typeParams = gp.typeParams;
+ expect(typeParams[0].name, equals('S'));
+ expect(typeParams[0].bounds.map((e) => e.name), ['java.lang.CharSequence']);
+ expect(typeParams[1].name, equals('K'));
+ final selfBound = typeParams[1].bounds[0];
+ expect(selfBound.kind, Kind.declared);
+ expect(selfBound.name,
+ equals('com.github.dart_lang.jnigen.generics.GenericTypeParams'));
+ final selfBoundType = selfBound.type as DeclaredType;
+ expect(selfBoundType.params, hasLength(2));
+ expect(selfBoundType.params.map((e) => e.name), ['S', 'K']);
+ expect(selfBoundType.params.map((e) => e.kind),
+ [Kind.typeVariable, Kind.typeVariable]);
+ });
+}
+
+void main() async {
+ await checkLocallyBuiltDependencies();
+
+ final tempDir = getTempDir("jnigen_summary_tests_");
+
+ final sourceConfig =
+ getSummaryGenerationConfig(sourcePath: [simplePackagePath]);
+ final parsedFromSource = await getSummary(sourceConfig);
+
+ final targetDir = tempDir.createTempSync("compiled_classes_test_");
+ await compileJavaFiles(simplePackageDir, targetDir);
+ final classConfig = getSummaryGenerationConfig(classPath: [targetDir.path]);
+ final parsedFromClasses = await getSummary(classConfig);
+
+ group('source summary', () {
+ registerCommonTests(parsedFromSource);
+ });
+
+ group('compiled summary', () {
+ registerCommonTests(parsedFromClasses);
+ });
+
+ group('source-based summary features', () {
+ final classes = parsedFromSource;
+ test('Parameter names', () {
+ final example = classes.getExampleClass();
+ final joinStrings = example.getMethod('joinStrings');
+ expect(
+ joinStrings.params.map((p) => p.name).toList(), ['values', 'delim']);
+ final methodWithSeveralParams =
+ example.getMethod("methodWithSeveralParams");
+ expect(methodWithSeveralParams.params.map((p) => p.name).toList(),
+ ['ch', 's', 'a', 't', 'lt', 'wm']);
+ });
+
+ test('Javadoc comment', () {
+ final example = classes.getExampleClass();
+ final joinStrings = example.getMethod('joinStrings');
+ expect(joinStrings.javadoc?.comment,
+ contains("Joins the strings in the list using the given delimiter."));
+ });
+ });
+
+ tearDownAll(() => tempDir.deleteSync(recursive: true));
+}
diff --git a/pkgs/jnigen/test/test_util/bindings_test_setup.dart b/pkgs/jnigen/test/test_util/bindings_test_setup.dart
new file mode 100644
index 0000000..c493ad1
--- /dev/null
+++ b/pkgs/jnigen/test/test_util/bindings_test_setup.dart
@@ -0,0 +1,77 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests on generated code.
+//
+// Both the simple java example & jackson core classes example have tests in
+// same file, because the test runner will reuse the process, which leads to
+// reuse of the old JVM with old classpath if we have separate tests with
+// different classpaths.
+
+import 'dart:io';
+
+import 'package:jni/jni.dart';
+import 'package:path/path.dart' hide equals;
+
+import 'test_util.dart';
+
+final simplePackageTest = join('test', 'simple_package_test');
+final jacksonCoreTest = join('test', 'jackson_core_test');
+final kotlinTest = join('test', 'kotlin_test');
+final jniJar = join('build', 'jni_libs', 'jni.jar');
+
+final simplePackageTestJava = join(simplePackageTest, 'java');
+final kotlinTestKotlin = join(kotlinTest, 'kotlin');
+
+late Directory tempClassDir;
+
+Future<void> bindingsTestSetup() async {
+ await runCommand('dart', [
+ 'run',
+ 'jni:setup',
+ '-p',
+ 'jni',
+ '-s',
+ join(simplePackageTest, 'c_based', 'c_bindings'),
+ '-s',
+ join(kotlinTest, 'c_based', 'c_bindings'),
+ '-s',
+ join(jacksonCoreTest, 'third_party', 'c_based', 'c_bindings'),
+ ]);
+ tempClassDir =
+ Directory.current.createTempSync("jnigen_runtime_test_classpath_");
+ await compileJavaFiles(Directory(simplePackageTestJava), tempClassDir);
+ await runCommand('dart', [
+ 'run',
+ 'jnigen:download_maven_jars',
+ '--config',
+ join(jacksonCoreTest, 'jnigen.yaml')
+ ]);
+
+ final jacksonJars = await getJarPaths(join(jacksonCoreTest, 'third_party'));
+
+ await runCommand(
+ 'mvn',
+ ['package'],
+ workingDirectory: kotlinTestKotlin,
+ runInShell: true,
+ );
+ // Jar including Kotlin runtime and dependencies.
+ final kotlinTestJar =
+ join(kotlinTestKotlin, 'target', 'kotlin_test-jar-with-dependencies.jar');
+
+ if (!Platform.isAndroid) {
+ Jni.spawn(dylibDir: join('build', 'jni_libs'), classPath: [
+ jniJar,
+ tempClassDir.path,
+ ...jacksonJars,
+ kotlinTestJar,
+ ]);
+ }
+ Jni.initDLApi();
+}
+
+void bindingsTestTeardown() {
+ tempClassDir.deleteSync(recursive: true);
+}
diff --git a/pkgs/jnigen/test/test_util/callback_types.dart b/pkgs/jnigen/test/test_util/callback_types.dart
new file mode 100644
index 0000000..3b3356e
--- /dev/null
+++ b/pkgs/jnigen/test/test_util/callback_types.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// These definitions could be in `test_util` but these are imported by android
+// integration tests, and we test_util imports several parts of package:jnigen.
+
+typedef TestCaseCallback = void Function();
+typedef TestRunnerCallback = void Function(
+ String description,
+ TestCaseCallback test,
+);
diff --git a/pkgs/jnigen/test/test_util/summary_util.dart b/pkgs/jnigen/test/test_util/summary_util.dart
new file mode 100644
index 0000000..0d44583
--- /dev/null
+++ b/pkgs/jnigen/test/test_util/summary_util.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:jnigen/src/config/config.dart';
+import 'package:jnigen/src/logging/logging.dart';
+import 'package:logging/logging.dart';
+import 'package:path/path.dart';
+
+import 'test_util.dart';
+
+String getClassNameFromPath(String path) {
+ if (!path.endsWith('.java')) {
+ throw ArgumentError('Filename must end with java');
+ }
+ return path
+ .replaceAll('/', '.')
+ .replaceAll('\\', '.')
+ .substring(0, path.length - 5);
+}
+
+/// test/simple_package_test/java
+final simplePackagePath = join('test', 'simple_package_test', 'java');
+
+/// Directory(test/simple_package_test/java)
+final simplePackageDir = Directory(simplePackagePath);
+
+/// All Java files in simple_package_test/java
+final javaFiles = findFilesWithSuffix(simplePackageDir, '.java');
+
+/// All Java classes in simple_package_test/java
+final javaClasses = javaFiles.map(getClassNameFromPath).toList();
+
+// Remove individual class listings from one package,
+// and add the package name instead, for testing.
+
+const removalPackageForSummaryTests = 'com.github.dart_lang.jnigen.pkg2';
+
+/// List of FQNs passed to summarizer for simple_package_test.
+final summarizerClassesSpec = [
+ ...javaClasses.where((e) => !e.startsWith('$removalPackageForSummaryTests.')),
+ removalPackageForSummaryTests,
+];
+
+Config getSummaryGenerationConfig(
+ {List<String>? sourcePath, List<String>? classPath}) {
+ return Config(
+ outputConfig: OutputConfig(
+ bindingsType: BindingsType.dartOnly,
+ dartConfig: DartCodeOutputConfig(
+ path: Uri.file('unused.dart'),
+ structure: OutputStructure.singleFile,
+ ),
+ ),
+ // Make a defensive copy of class list, if some test mutates the list...
+ classes: summarizerClassesSpec.toList(),
+ sourcePath: sourcePath?.map((e) => Uri.file(e)).toList(),
+ classPath: classPath?.map((e) => Uri.file(e)).toList(),
+ logLevel: Level.WARNING,
+ );
+}
+
+void deleteTempDirWithDelay(Directory directory) {
+ try {
+ if (Platform.isWindows) {
+ // This appears to avoid "file used by another process" errors.
+ sleep(const Duration(seconds: 1));
+ }
+ directory.deleteSync(recursive: true);
+ } on FileSystemException catch (e) {
+ log.warning("Cannot delete directory: $e");
+ }
+}
diff --git a/pkgs/jnigen/test/test_util/test_util.dart b/pkgs/jnigen/test/test_util/test_util.dart
new file mode 100644
index 0000000..8fbc7ce
--- /dev/null
+++ b/pkgs/jnigen/test/test_util/test_util.dart
@@ -0,0 +1,250 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:jnigen/jnigen.dart';
+import 'package:jnigen/src/util/find_package.dart';
+import 'package:path/path.dart' hide equals;
+import 'package:test/test.dart';
+import 'package:logging/logging.dart' show Level;
+
+import 'package:jnigen/src/logging/logging.dart';
+
+final _currentDirectory = Directory(".");
+
+// If changing these constants, grep for these values. In some places, test
+// package expects string literals.
+const largeTestTag = 'large_test';
+const summarizerTestTag = 'summarizer_test';
+
+Directory getTempDir(String prefix) {
+ return _currentDirectory.createTempSync(prefix);
+}
+
+Future<bool> isEmptyOrNotExistDir(String path) async {
+ final dir = Directory(path);
+ return (!await dir.exists()) || (await dir.list().length == 0);
+}
+
+/// Runs command, and prints output only if the exit status is non-zero.
+Future<int> runCommandReturningStatus(String exec, List<String> args,
+ {String? workingDirectory, bool runInShell = false}) async {
+ final proc = await Process.run(exec, args,
+ workingDirectory: workingDirectory, runInShell: runInShell);
+ if (proc.exitCode != 0) {
+ printError('command exited with exit status ${proc.exitCode}:\n'
+ '$exec ${args.join(" ")}\n');
+ printError(proc.stdout);
+ printError(proc.stderr);
+ }
+ return proc.exitCode;
+}
+
+Future<void> runCommand(
+ String exec,
+ List<String> args, {
+ String? workingDirectory,
+ bool runInShell = false,
+ String? messageOnFailure,
+}) async {
+ final status = await runCommandReturningStatus(
+ exec,
+ args,
+ workingDirectory: workingDirectory,
+ runInShell: runInShell,
+ );
+ if (status != 0) {
+ final message = messageOnFailure ?? 'Failed to execute $exec';
+ throw Exception('$message: Command exited with return code $status');
+ }
+}
+
+/// List all JAR files in [testRoot]/jar
+Future<List<String>> getJarPaths(String testRoot) async {
+ final jarPath = join(testRoot, 'jar');
+ if (!await Directory(jarPath).exists()) {
+ return [];
+ }
+ return Directory(jarPath)
+ .list()
+ .map((entry) => entry.path)
+ .where((path) => path.endsWith('.jar'))
+ .toList();
+}
+
+/// Read file normalizing CRLF to LF.
+String readFile(File file) => file.readAsStringSync().replaceAll('\r\n', '\n');
+
+/// Compares 2 hierarchies using `git diff --no-index`.
+void comparePaths(String path1, String path2) {
+ final diffCommand = [
+ "diff",
+ "--no-index",
+ if (stderr.supportsAnsiEscapes) "--color=always",
+ ];
+ final diffProc = Process.runSync("git", [...diffCommand, path1, path2]);
+ if (diffProc.exitCode != 0) {
+ final originalDiff = diffProc.stdout;
+ log.warning(
+ "Paths $path1 and $path2 differ, Running dart format on $path1.");
+ Process.runSync('dart', ['format', path1]);
+ final fallbackDiffProc =
+ Process.runSync("git", [...diffCommand, path1, path2]);
+ if (fallbackDiffProc.exitCode != 0) {
+ stderr.writeln(originalDiff);
+ throw Exception("Paths $path1 and $path2 differ");
+ }
+ }
+}
+
+Future<void> _generateTempBindings(Config config, Directory tempDir) async {
+ final tempSrc = tempDir.uri.resolve("src/");
+ final singleFile =
+ config.outputConfig.dartConfig.structure == OutputStructure.singleFile;
+ final tempLib = singleFile
+ ? tempDir.uri.resolve("generated.dart")
+ : tempDir.uri.resolve("lib/");
+ if (config.outputConfig.bindingsType == BindingsType.cBased) {
+ config.outputConfig.cConfig!.path = tempSrc;
+ }
+ config.outputConfig.dartConfig.path = tempLib;
+ config.logLevel = Level.WARNING;
+ await generateJniBindings(config);
+}
+
+/// Generates and compares bindings with reference bindings.
+///
+/// [dartReferenceBindings] can be directory or file depending on output
+/// configuration.
+///
+/// If the config generates C code, [cReferenceBindings] must be a non-null
+/// directory path.
+Future<void> generateAndCompareBindings(Config config) async {
+ final dartReferenceBindings =
+ config.outputConfig.dartConfig.path.toFilePath();
+ final cReferenceBindings = config.outputConfig.cConfig?.path.toFilePath();
+ final currentDir = Directory.current;
+ final tempDir = currentDir.createTempSync("jnigen_test_temp");
+ final tempSrc = tempDir.uri.resolve("src/");
+ final singleFile =
+ config.outputConfig.dartConfig.structure == OutputStructure.singleFile;
+ final tempLib = singleFile
+ ? tempDir.uri.resolve("generated.dart")
+ : tempDir.uri.resolve("lib/");
+ try {
+ await _generateTempBindings(config, tempDir);
+ comparePaths(dartReferenceBindings, tempLib.toFilePath());
+ if (config.outputConfig.bindingsType == BindingsType.cBased) {
+ comparePaths(cReferenceBindings!, tempSrc.toFilePath());
+ }
+ } finally {
+ tempDir.deleteSync(recursive: true);
+ }
+}
+
+Future<void> generateAndAnalyzeBindings(Config config) async {
+ final tempDir = Directory.current.createTempSync("jnigen_test_temp");
+ try {
+ await _generateTempBindings(config, tempDir);
+ final analyzeResult = Process.runSync("dart", ["analyze", tempDir.path]);
+ if (analyzeResult.exitCode != 0) {
+ stderr.write(analyzeResult.stdout);
+ fail('Analyzer exited with non-zero status (${analyzeResult.exitCode})');
+ }
+ } finally {
+ tempDir.deleteSync(recursive: true);
+ }
+}
+
+final summarizerJar = join('.', '.dart_tool', 'jnigen', 'ApiSummarizer.jar');
+
+Future<void> failIfSummarizerNotBuilt() async {
+ final jarExists = await File(summarizerJar).exists();
+ if (!jarExists) {
+ stderr.writeln();
+ log.fatal('Please build summarizer by running '
+ '`dart run jnigen:setup` and try again');
+ }
+ final isJarStale = jarExists &&
+ await isPackageModifiedAfter(
+ 'jnigen', await File(summarizerJar).lastModified(), 'java/');
+ if (isJarStale) {
+ stderr.writeln();
+ log.fatal('Summarizer is not rebuilt after recent changes. '
+ 'Please run `dart run jnigen:setup` and try again.');
+ }
+}
+
+const bindingTests = [
+ 'jackson_core_test',
+ 'simple_package_test',
+ 'kotlin_test',
+];
+
+const registrantName = 'runtime_test_registrant.dart';
+const replicaName = 'runtime_test_registrant_dartonly_generated.dart';
+
+void warnIfRuntimeTestsAreOutdated() {
+ final runtimeTests = join('test', 'generated_runtime_test.dart');
+ if (!File(runtimeTests).existsSync()) {
+ log.fatal('Runtime test files not found. To run binding '
+ 'runtime tests, please generate them by running '
+ '`dart run tool/generate_runtime_tests.dart`');
+ }
+ const regenInstr = 'Please run `dart run tool/generate_runtime_tests.dart` '
+ 'and try again.';
+ for (var testName in bindingTests) {
+ final registrant = File(join('test', testName, registrantName));
+ final replica = File(join('test', testName, replicaName));
+ if (!replica.existsSync()) {
+ log.fatal(
+ 'One or more generated runtime tests do not exist. $regenInstr',
+ );
+ }
+ if (replica.lastModifiedSync().isBefore(registrant.lastModifiedSync())) {
+ log.fatal(
+ 'One or more generated runtime tests are not up-to-date. $regenInstr',
+ );
+ }
+ }
+}
+
+/// Verifies if locally built dependencies (currently `ApiSummarizer`)
+/// are up-to-date.
+Future<void> checkLocallyBuiltDependencies() async {
+ await failIfSummarizerNotBuilt();
+ warnIfRuntimeTestsAreOutdated();
+}
+
+void generateAndCompareBothModes(
+ String description,
+ Config cBasedConfig,
+ Config dartOnlyConfig,
+) {
+ test('$description (cBased)', () async {
+ await generateAndCompareBindings(cBasedConfig);
+ });
+ test('$description (dartOnly)', () async {
+ await generateAndCompareBindings(dartOnlyConfig);
+ });
+}
+
+List<String> findFilesWithSuffix(Directory dir, String suffix) {
+ return dir
+ .listSync(recursive: true)
+ .map((entry) => relative(entry.path, from: dir.path))
+ .where((path) => path.endsWith(suffix))
+ .toList();
+}
+
+Future<void> compileJavaFiles(Directory root, Directory target) async {
+ final javaFiles = findFilesWithSuffix(root, '.java');
+ await runCommand(
+ 'javac',
+ ['-d', target.absolute.path, ...javaFiles],
+ workingDirectory: root.path,
+ messageOnFailure: 'Cannot compile java sources',
+ );
+}
diff --git a/pkgs/jnigen/tool/command_runner.dart b/pkgs/jnigen/tool/command_runner.dart
new file mode 100644
index 0000000..7bf925e
--- /dev/null
+++ b/pkgs/jnigen/tool/command_runner.dart
@@ -0,0 +1,109 @@
+import 'dart:io';
+
+const ansiRed = '\x1b[31m';
+const ansiDefault = '\x1b[39;49m';
+
+void printError(Object? message) {
+ if (stderr.supportsAnsiEscapes) {
+ message = '$ansiRed$message$ansiDefault';
+ }
+ stderr.writeln(message);
+}
+
+class StepFailure implements Exception {
+ StepFailure(this.name);
+ String name;
+ @override
+ String toString() => 'step failed: $name';
+}
+
+abstract class Step {
+ /// Runs this step, raises an exception if something fails.
+ Future<void> run();
+}
+
+class Callback implements Step {
+ Callback(this.name, this.function);
+ String name;
+ Future<void> Function() function;
+ @override
+ Future<void> run() => function();
+}
+
+class Command implements Step {
+ Command(this.exec, this.args, this.workingDirectory);
+ final String exec;
+ final List<String> args;
+ final Uri workingDirectory;
+
+ @override
+ Future<void> run() async {
+ final result = await Process.run(
+ exec,
+ args,
+ workingDirectory: workingDirectory.toFilePath(),
+ runInShell: true,
+ );
+ if (result.exitCode != 0) {
+ printError(result.stdout);
+ printError(result.stderr);
+ final commandString = "$exec ${args.join(" ")}";
+ stderr.writeln("failure executing command: $commandString");
+ throw StepFailure(commandString);
+ }
+ }
+}
+
+class Runner {
+ static final gitRoot = getRepositoryRoot();
+ Runner(this.name, this.defaultWorkingDir);
+ String name;
+ Uri defaultWorkingDir;
+ final steps = <Step>[];
+ final cleanupSteps = <Step>[];
+
+ void chainCommand(String exec, List<String> args, {Uri? workingDirectory}) =>
+ _addCommand(steps, exec, args, workingDirectory: workingDirectory);
+
+ void chainCleanupCommand(String exec, List<String> args,
+ {Uri? workingDirectory}) =>
+ _addCommand(cleanupSteps, exec, args, workingDirectory: workingDirectory);
+
+ void _addCommand(List<Step> list, String exec, List<String> args,
+ {Uri? workingDirectory}) {
+ list.add(Command(exec, args, (workingDirectory ?? defaultWorkingDir)));
+ }
+
+ void chainCallback(String name, Future<void> Function() callback) {
+ steps.add(Callback(name, callback));
+ }
+
+ Future<void> run() async {
+ stderr.writeln("started: $name");
+ var error = false;
+ for (var step in steps) {
+ try {
+ await step.run();
+ } on StepFailure catch (e) {
+ stderr.writeln(e);
+ error = true;
+ exitCode = 1;
+ break;
+ }
+ }
+ stderr.writeln('${error ? "failed" : "complete"}: $name');
+ for (var step in cleanupSteps) {
+ try {
+ await step.run();
+ } on Exception catch (e) {
+ printError("ERROR: $e");
+ }
+ }
+ }
+}
+
+Uri getRepositoryRoot() {
+ final gitCommand = Process.runSync("git", ["rev-parse", "--show-toplevel"]);
+ final output = gitCommand.stdout as String;
+ return Uri.directory(output.trim());
+}
diff --git a/pkgs/jnigen/tool/generate_runtime_tests.dart b/pkgs/jnigen/tool/generate_runtime_tests.dart
new file mode 100644
index 0000000..75a1ea2
--- /dev/null
+++ b/pkgs/jnigen/tool/generate_runtime_tests.dart
@@ -0,0 +1,183 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:path/path.dart';
+import 'package:args/args.dart';
+
+import 'package:jnigen/src/logging/logging.dart';
+
+final lineBreak = Platform.isWindows ? '\r\n' : '\n';
+
+void runCommand(String exec, List<String> args) {
+ final proc = Process.runSync(exec, args, runInShell: true);
+ log.info('Execute $exec ${args.join(" ")}');
+ if (proc.exitCode != 0) {
+ exitCode = proc.exitCode;
+ printError(proc.stdout);
+ printError(proc.stderr);
+ throw Exception('Command failed: $exec ${args.join(" ")}');
+ }
+}
+
+const testPath = 'test';
+const registrantFileName = 'runtime_test_registrant.dart';
+const dartOnlyRegistrantFileName =
+ 'runtime_test_registrant_dartonly_generated.dart';
+
+// Paths of generated files, should not be checked in.
+// If you change this, add the corresponding entry to .gitignore as well.
+const replicaSuffix = '_dartonly_generated.dart';
+final runnerFilePath = join(testPath, 'generated_runtime_test.dart');
+final androidRunnerFilePath =
+ join('android_test_runner', 'integration_test', 'runtime_test.dart');
+
+final generatedComment =
+ '// Generated file. Do not edit or check-in to version control.$lineBreak';
+const copyright = '''
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+''';
+
+const bindingTests = [
+ 'jackson_core_test',
+ 'simple_package_test',
+ 'kotlin_test',
+];
+
+const hasThirdPartyDir = {'jackson_core_test'};
+
+final _generatedFiles = <String>[
+ for (var testName in bindingTests)
+ join(testPath, testName, dartOnlyRegistrantFileName),
+ runnerFilePath,
+ androidRunnerFilePath,
+];
+
+void generateReplicasAndRunner() {
+ final imports = <String, String>{};
+ for (var testName in bindingTests) {
+ final registrant = join(testName, registrantFileName);
+ final registrantFile = File(join(testPath, registrant));
+ final contents = registrantFile
+ .readAsStringSync()
+ .replaceAll('c_based/dart_bindings/', 'dart_only/dart_bindings/');
+
+ final replica = registrant.replaceAll('.dart', replicaSuffix);
+ final replicaFile = File(join(testPath, replica));
+ replicaFile.writeAsStringSync('$generatedComment$lineBreak$contents');
+ log.info('Generated $replica');
+ imports['${testName}_c_based'] =
+ Uri.file(registrant).toFilePath(windows: false);
+ imports['${testName}_dart_only'] =
+ Uri.file(replica).toFilePath(windows: false);
+ }
+ final importStrings = imports.entries
+ .map((e) => 'import "${e.value}" as ${e.key};')
+ .join(lineBreak);
+ final androidImportStrings = imports.entries
+ .map((e) => 'import "../../test/${e.value}" as ${e.key};')
+ .join(lineBreak);
+ final runStrings = imports.keys
+ .map((name) => '$name.registerTests("$name", test);')
+ .join('$lineBreak ');
+ final runnerProgram = '''
+$generatedComment
+$copyright
+import 'package:test/test.dart';
+import 'test_util/bindings_test_setup.dart' as setup;
+
+$importStrings
+
+void main() {
+ setUpAll(setup.bindingsTestSetup);
+ $runStrings
+ tearDownAll(setup.bindingsTestTeardown);
+}
+''';
+ final runnerFile = File(runnerFilePath);
+ runnerFile.writeAsStringSync(runnerProgram);
+ log.info('Generated runner $runnerFilePath');
+
+ final androidRunnerProgram = '''
+$generatedComment
+$copyright
+import "package:flutter_test/flutter_test.dart";
+import "package:jni/jni.dart";
+
+$androidImportStrings
+
+typedef TestCaseCallback = void Function();
+
+void test(String description, TestCaseCallback testCase) {
+ testWidgets(description, (widgetTester) async => testCase());
+}
+
+void main() {
+ Jni.initDLApi();
+ $runStrings
+}
+''';
+ File(androidRunnerFilePath).writeAsStringSync(androidRunnerProgram);
+ log.info('Generated android runner: $androidRunnerFilePath');
+
+ final cMakePath =
+ join('android_test_runner', 'android', 'app', 'CMakeLists.txt');
+
+ final cmakeSubdirs = bindingTests.map((testName) {
+ final indirect = hasThirdPartyDir.contains(testName) ? '/third_party' : '';
+ return 'add_subdirectory'
+ '(../../../test/$testName$indirect/c_based/c_bindings '
+ '${testName}_build)';
+ }).join(lineBreak);
+ final cMakeConfig = '''
+## Parent CMake for Android native build target. This will build
+## all C bindings from tests.
+
+cmake_minimum_required(VERSION 3.10)
+
+project(simple_package VERSION 0.0.1 LANGUAGES C)
+
+$cmakeSubdirs
+''';
+ File(cMakePath).writeAsStringSync(cMakeConfig);
+ log.info('Wrote Android CMake file: $cMakePath');
+}
+
+void cleanup() {
+ for (var path in _generatedFiles) {
+ File(path).deleteSync();
+ log.info('Deleted $path');
+ }
+}
+
+void main(List<String> args) async {
+ final parser = ArgParser()
+ ..addFlag(
+ 'help',
+ abbr: 'h',
+ help: 'show help',
+ negatable: false,
+ )
+ ..addFlag(
+ 'clean',
+ abbr: 'c',
+ help: 'clear generated files',
+ negatable: false,
+ );
+ final argResults = parser.parse(args);
+ if (argResults['help']) {
+ stderr.writeln(
+ 'Generates runtime tests for both Dart-only and C based bindings.');
+ stderr.writeln(parser.usage);
+ return;
+ } else if (argResults['clean']) {
+ cleanup();
+ } else {
+ generateReplicasAndRunner();
+ runCommand('dart', ['format', ..._generatedFiles]);
+ }
+}
diff --git a/pkgs/jnigen/tool/pr_checks.dart b/pkgs/jnigen/tool/pr_checks.dart
new file mode 100644
index 0000000..3e983c2
--- /dev/null
+++ b/pkgs/jnigen/tool/pr_checks.dart
@@ -0,0 +1,180 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This is a script to run a subset of CI checks on development machine before
+// submitting PR. This prevents from accidentally forgetting to format or
+// remove an unused import.
+
+// This is rough around the edges. This script may give false positives such
+// as some gitignore'd temporary files failing the comparison.
+
+// On windows, please install 'diffutils' using your favorite package installer
+// for this script to work correctly. Also ensure that clang-format is on your
+// PATH.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:args/args.dart';
+
+import 'command_runner.dart';
+
+// Flags
+const _clone = 'clone';
+
+void main(List<String> arguments) async {
+ final parser = ArgParser()
+ ..addFlag(
+ _clone,
+ help: 'Run checks in a cloned copy of the project.',
+ defaultsTo: true,
+ negatable: true,
+ );
+ final argResults = parser.parse(arguments);
+ final shouldClone = argResults[_clone] as bool;
+ final gitRoot = getRepositoryRoot();
+
+ // change to project root
+ Directory.current = gitRoot.toFilePath();
+
+ var tempDir = Directory.current;
+ if (shouldClone) {
+ tempDir = Directory.current.createTempSync('jnigen_checks_clone_');
+ final gitClone = Runner("Clone jni", Directory.current.uri)
+ ..chainCommand('git', ['clone', '.', tempDir.path]);
+ await gitClone.run();
+ }
+
+ final jniPath = tempDir.uri.resolve("jni/");
+ final jnigenPath = tempDir.uri.resolve("jnigen/");
+ final pubGet = Runner("Pub get", tempDir.uri)
+ ..chainCommand("flutter", ["pub", "get", "--offline"],
+ workingDirectory: jniPath)
+ ..chainCommand("dart", ["pub", "get", "--offline"],
+ workingDirectory: jnigenPath);
+ await pubGet.run();
+
+ final jniAnalyze = Runner("Analyze JNI", jniPath);
+ jniAnalyze
+ ..chainCommand("dart", ["analyze", "--fatal-infos"])
+ ..chainCommand(
+ "dart", ["format", "--output=none", "--set-exit-if-changed", "."])
+ ..chainCommand(
+ "clang-format",
+ [
+ "--dry-run",
+ "-Werror",
+ "dartjni.c",
+ "dartjni.h",
+ "third_party/global_jni_env.c",
+ "third_party/global_jni_env.h",
+ ],
+ workingDirectory: jniPath.resolve("src/"));
+ final jniTest = Runner("Test JNI", jniPath)
+ ..chainCommand("dart", ["run", "jni:setup"])
+ ..chainCommand("dart", ["test", "-j", "1"]);
+ unawaited(jniAnalyze.run().then((f) => jniTest.run()));
+
+ List<String> getJavaFiles(String relativePath) =>
+ Directory.fromUri(jnigenPath.resolve(relativePath))
+ .listSync(recursive: true)
+ .where((file) => file.path.endsWith(".java"))
+ .map((file) => file.path)
+ .toList();
+
+ final javaFiles = getJavaFiles("java/") +
+ getJavaFiles("test/simple_package_test") +
+ getJavaFiles("example/in_app_java") +
+ getJavaFiles("example/notification_plugin");
+
+ final checkJavaFormat = Runner("Check java format", jnigenPath)
+ ..chainCommand(
+ "google-java-format", ["-n", "--set-exit-if-changed", ...javaFiles]);
+
+ unawaited(checkJavaFormat.run());
+
+ final ffigenBindingsPath = getRepositoryRoot()
+ .resolve("jni/lib/src/third_party/jni_bindings_generated.dart");
+ final ffigenBindings = File.fromUri(ffigenBindingsPath);
+ final oldBindingsText = ffigenBindings.readAsStringSync();
+ final ffigenCompare = Runner("Generate & Compare FFIGEN bindings", jniPath)
+ ..chainCommand("dart", ["run", "ffigen", "--config", "ffigen.yaml"])
+ ..chainCallback("compare bindings", () async {
+ final newBindingsText = await ffigenBindings.readAsString();
+ if (newBindingsText != oldBindingsText) {
+ await ffigenBindings.writeAsString(oldBindingsText);
+ throw "new JNI.h bindings differ from old bindings";
+ }
+ });
+ unawaited(ffigenCompare.run());
+
+ final jnigenAnalyze = Runner("Analyze jnigen", jnigenPath)
+ ..chainCommand("dart", ["analyze", "--fatal-infos"])
+ ..chainCommand(
+ "dart", ["format", "--output=none", "--set-exit-if-changed", "."])
+ ..chainCommand("dart", ["run", "jnigen:setup"]);
+
+ // Tests may need more time when running on systems with less cores.
+ // So '--timeout 2x' is specified.
+ final jnigenTest = Runner("Test jnigen", gitRoot.resolve("jnigen/"))
+ ..chainCommand("dart", ["test", "--timeout", "2x"]);
+
+ // Note: Running in_app_java and notification_plugin checks on source dir
+ // itself, because running flutter build in cloned dir will take time.
+ final compareInAppJavaBindings = Runner(
+ "Generate & compare InAppJava bindings",
+ gitRoot.resolve("jnigen/example/in_app_java"))
+ ..chainCommand("dart", [
+ "run",
+ "jnigen",
+ "--config",
+ "jnigen.yaml",
+ "-Doutput.c.path=src_temp/",
+ "-Doutput.dart.path=_temp.dart",
+ ])
+ ..chainCommand("diff", ["lib/android_utils.dart", "_temp.dart"])
+ ..chainCommand("diff", ["-qr", "src/android_utils/", "src_temp/"])
+ ..chainCleanupCommand("rm", ["-r", "_temp.dart", "src_temp"]);
+
+ final comparePdfboxBindings = Runner("Generate & compare PdfBox Bindings",
+ gitRoot.resolve("jnigen/example/pdfbox_plugin"))
+ ..chainCommand("dart", [
+ "run",
+ "jnigen",
+ "--config",
+ "jnigen.yaml",
+ "-Doutput.c.path=src_temp/",
+ "-Doutput.dart.path=lib_temp/",
+ ])
+ ..chainCommand("diff", ["-qr", "lib/src/third_party/", "lib_temp/"])
+ ..chainCommand("diff", ["-qr", "src/", "src_temp/"])
+ ..chainCleanupCommand("rm", ["-r", "lib_temp", "src_temp"]);
+
+ final compareNotificationPluginBindings = Runner(
+ "Generate & compare NotificationPlugin Bindings",
+ gitRoot.resolve("jnigen/example/notification_plugin"))
+ ..chainCommand("dart", [
+ "run",
+ "jnigen",
+ "--config",
+ "jnigen.yaml",
+ "-Doutput.c.path=src_temp/",
+ "-Doutput.dart.path=_temp.dart",
+ ])
+ ..chainCommand("diff", ["lib/notifications.dart", "_temp.dart"])
+ ..chainCommand("diff", ["-qr", "src/", "src_temp/"])
+ ..chainCleanupCommand("rm", ["-r", "_temp.dart", "src_temp"]);
+
+ unawaited(jnigenAnalyze.run().then((_) {
+ final test = jnigenTest.run();
+ final inAppJava = compareInAppJavaBindings.run();
+ final pdfBox = comparePdfboxBindings.run();
+ final notificationPlugin = compareNotificationPluginBindings.run();
+ return Future.wait([test, inAppJava, pdfBox, notificationPlugin]);
+ }).then((_) {
+ if (shouldClone) {
+ tempDir.deleteSync(recursive: true);
+ }
+ }));
+}
diff --git a/pkgs/jnigen/tool/regenerate_all_bindings.dart b/pkgs/jnigen/tool/regenerate_all_bindings.dart
new file mode 100644
index 0000000..19b7642
--- /dev/null
+++ b/pkgs/jnigen/tool/regenerate_all_bindings.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Run this script after any change which affects generated bindings.
+//
+// This will update all generated bindings in the whole repository.
+
+import 'dart:io';
+
+import 'command_runner.dart';
+
+const scripts = [
+ "test/jackson_core_test/generate.dart",
+ "test/simple_package_test/generate.dart",
+ "test/kotlin_test/generate.dart",
+];
+
+const yamlBasedExamples = [
+ "example/in_app_java",
+ "example/pdfbox_plugin",
+ "example/notification_plugin",
+ "example/kotlin_plugin",
+];
+
+void main() async {
+ final runners = <Runner>[];
+ final current = Directory.current.uri;
+ for (var script in scripts) {
+ runners.add(Runner("Run generate script: $script", current)
+ ..chainCommand("dart", ["run", script]));
+ }
+
+ for (var yamlDir in yamlBasedExamples) {
+ runners.add(
+ Runner("Regenerate bindings in $yamlDir", current.resolve(yamlDir))
+ ..chainCommand("dart", ["run", "jnigen", "--config", "jnigen.yaml"]));
+ }
+
+ await Future.wait(runners.map((runner) => runner.run()).toList());
+}