├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── jni-sys-macros ├── Cargo.toml ├── README.md └── src │ └── lib.rs ├── src └── lib.rs ├── systest ├── Cargo.toml ├── build.rs └── src │ └── main.rs └── tests ├── jni-to-union.rs └── trybuild ├── 01-jni-fail-read-1-2-from-1-1.rs ├── 01-jni-fail-read-1-2-from-1-1.stderr ├── 01-jni-fail-reserved-read.rs ├── 01-jni-fail-reserved-read.stderr └── 01-jni-to-union-basic-pass.rs /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: monthly 7 | open-pull-requests-limit: 10 8 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [pull_request, push] 4 | 5 | jobs: 6 | # Check code formatting. 7 | fmt: 8 | name: Rustfmt 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout sources 12 | uses: actions/checkout@v3 13 | - name: Install rust 14 | uses: actions-rs/toolchain@v1 15 | with: 16 | toolchain: stable 17 | components: rustfmt 18 | profile: minimal 19 | override: true 20 | - name: Run rustfmt 21 | uses: actions-rs/cargo@v1 22 | with: 23 | command: fmt 24 | args: --all -- --check 25 | 26 | # Static analyzer. 27 | clippy: 28 | name: Clippy 29 | runs-on: ubuntu-latest 30 | steps: 31 | - name: Checkout sources 32 | uses: actions/checkout@v3 33 | - name: Install rust 34 | uses: actions-rs/toolchain@v1 35 | with: 36 | toolchain: stable 37 | components: clippy 38 | profile: minimal 39 | override: true 40 | - name: Run clippy 41 | uses: actions-rs/clippy-check@v1 42 | with: 43 | token: ${{ secrets.GITHUB_TOKEN }} 44 | args: --all --tests -- -D warnings 45 | 46 | # Security audit. 47 | audit: 48 | name: Security audit 49 | runs-on: ubuntu-latest 50 | steps: 51 | - uses: actions/checkout@v3 52 | - uses: actions-rs/audit-check@v1 53 | with: 54 | token: ${{ secrets.GITHUB_TOKEN }} 55 | 56 | # Tests. 57 | test: 58 | name: ${{ matrix.build }} 59 | runs-on: ${{ matrix.os }} 60 | strategy: 61 | matrix: 62 | include: 63 | - build: Linux 64 | os: ubuntu-latest 65 | - build: macOS 66 | os: macOS-latest 67 | - build: Windows 68 | os: windows-latest 69 | steps: 70 | - name: Checkout sources 71 | uses: actions/checkout@v3 72 | - name: Install rust 73 | uses: actions-rs/toolchain@v1 74 | with: 75 | toolchain: 1.65.0 76 | profile: minimal 77 | override: true 78 | - name: Install java 79 | uses: actions/setup-java@v1 80 | with: 81 | distribution: temurin 82 | java-version: '20' 83 | - name: Build 84 | uses: actions-rs/cargo@v1 85 | with: 86 | command: build 87 | args: --features=jni19,jni20 --examples --all 88 | - name: Test default features 89 | uses: actions-rs/cargo@v1 90 | with: 91 | command: test 92 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | .idea 4 | *.iml 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [0.4.0] - 2023-09-25 11 | 12 | ### Added 13 | 14 | - Added `JNI_VERSION_9`, `JNI_VERSION_10`, `JNI_VERSION_19`, `JNI_VERSION_20` and `JNI_VERSION_21` constants 15 | - Added `GetModule()` to `JNINativeInterface` ([#22](https://github.com/jni-rs/jni-sys/pull/22)) 16 | - `IsVirtualThread()` to `JNINativeInterface` ([#32](https://github.com/jni-rs/jni-sys/pull/32)) 17 | - Implemented `Debug` trait for all types ([#31](https://github.com/jni-rs/jni-sys/pull/31)) 18 | - Added support for `no_std` environments ([#12](https://github.com/jni-rs/jni-sys/pull/12)) 19 | 20 | ### Changed 21 | 22 | - `jboolean` is now an alias for `bool` instead of `u8` ([#23](https://github.com/jni-rs/jni-sys/pull/23)) 23 | - The `JNIInvokeInterface_` and `JNINativeInterface_` structs were turned into unions that namespace functions by version ([#28](https://github.com/jni-rs/jni-sys/pull/28)): 24 | 25 | This makes it much clearer what version of JNI you require to access any function safely. 26 | 27 | So instead of a struct like: 28 | 29 | ```rust 30 | struct JNINativeInterface_ { 31 | pub reserved0: *mut c_void, 32 | .. 33 | pub GetVersion: unsafe extern "system" fn(env: *mut JNIEnv) -> jint, 34 | .. 35 | pub NewLocalRef: unsafe extern "system" fn(env: *mut JNIEnv, ref_: jobject) -> jobject, 36 | } 37 | ``` 38 | 39 | there is now a union like: 40 | 41 | ```rust 42 | union JNINativeInterface_ { 43 | v1_1: JNINativeInterface__1_1, 44 | v1_2: JNINativeInterface__1_2, 45 | reserved: JNINativeInterface__reserved, 46 | } 47 | ``` 48 | 49 | And you can access `GetVersion` like: `env.v1_1.GetVersion` and access `NewLocalRef` like: `env.v1_2.NewLocalRef`. 50 | 51 | Each version struct includes all functions for that version and lower, so it's also possible to access `GetVersion` like `env.v1_2.GetVersion`. 52 | 53 | - Function pointers are no longer wrapped in an `Option<>` ([#25](https://github.com/jni-rs/jni-sys/pull/25)) 54 | 55 | ## [0.3.0] - 2017-07-20 56 | 57 | ### Changed 58 | 59 | - Changed jvalue into a union 60 | 61 | [unreleased]: https://github.com/jni-rs/jni-sys/compare/v0.3.0...HEAD 62 | [0.3.0]: https://github.com/jni-rs/jni-sys/compare/v0.2.5...v0.3.0 63 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "jni-sys" 3 | version = "0.4.0" 4 | authors = ["Steven Fackler ", "Robert Bragg "] 5 | license = "MIT/Apache-2.0" 6 | description = "Rust definitions corresponding to jni.h" 7 | repository = "https://github.com/jni-rs/jni-sys" 8 | documentation = "https://docs.rs/jni-sys/0.4.0" 9 | readme = "README.md" 10 | categories = ["external-ffi-bindings"] 11 | keywords = ["java", "jni"] 12 | edition = "2021" 13 | rust-version = "1.65.0" 14 | exclude = [ 15 | "/.github", 16 | "/tests" 17 | ] 18 | 19 | [dependencies] 20 | jni-sys-macros = { version = "0.1", path = "jni-sys-macros" } 21 | 22 | [dev-dependencies] 23 | trybuild = "1" 24 | 25 | [workspace] 26 | members = [ 27 | "systest", 28 | "jni-sys-macros" 29 | ] 30 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 The rust-jni-sys Developers 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jni-sys 2 | 3 | [Documentation](https://docs.rs/jni-sys) 4 | 5 | Rust definitions corresponding to jni.h. 6 | 7 | ## License 8 | 9 | Licensed under either of 10 | 11 | * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 12 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) 13 | 14 | at your option. 15 | 16 | ### Contribution 17 | 18 | Unless you explicitly state otherwise, any contribution intentionally 19 | submitted for inclusion in the work by you, as defined in the Apache-2.0 20 | license, shall be dual licensed as above, without any additional terms or 21 | conditions. 22 | -------------------------------------------------------------------------------- /jni-sys-macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "jni-sys-macros" 3 | version = "0.1.0" 4 | authors = ["Robert Bragg "] 5 | license = "MIT/Apache-2.0" 6 | description = "Macros for jni-sys crate" 7 | repository = "https://github.com/jni-rs/jni-sys" 8 | documentation = "https://docs.rs/jni-sys-macros/0.1.0" 9 | readme = "README.md" 10 | categories = ["external-ffi-bindings"] 11 | keywords = ["java", "jni"] 12 | edition = "2021" 13 | 14 | [lib] 15 | proc-macro = true 16 | 17 | [dependencies] 18 | syn = { version = "2", features = ["full"] } 19 | quote = "1" 20 | -------------------------------------------------------------------------------- /jni-sys-macros/README.md: -------------------------------------------------------------------------------- 1 | # jni-sys-macros 2 | 3 | Internal proc macros for the [jni-sys](https://crates.io/crates/jni-sys) crate. 4 | -------------------------------------------------------------------------------- /jni-sys-macros/src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate proc_macro; 2 | 3 | use std::{cmp::Ordering, collections::HashSet}; 4 | 5 | use proc_macro::TokenStream; 6 | use quote::{format_ident, quote}; 7 | use syn::{parse_macro_input, spanned::Spanned, Data, DeriveInput, Fields, Ident, LitStr}; 8 | 9 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 10 | struct JniVersion { 11 | major: u16, 12 | minor: u16, 13 | } 14 | impl Default for JniVersion { 15 | fn default() -> Self { 16 | Self { major: 1, minor: 1 } 17 | } 18 | } 19 | impl Ord for JniVersion { 20 | fn cmp(&self, other: &Self) -> Ordering { 21 | match self.major.cmp(&other.major) { 22 | Ordering::Equal => self.minor.cmp(&other.minor), 23 | major_order => major_order, 24 | } 25 | } 26 | } 27 | impl PartialOrd for JniVersion { 28 | fn partial_cmp(&self, other: &Self) -> Option { 29 | Some(self.cmp(other)) 30 | } 31 | } 32 | 33 | impl syn::parse::Parse for JniVersion { 34 | fn parse(input: syn::parse::ParseStream) -> syn::Result { 35 | let version: LitStr = input.parse()?; 36 | let version = version.value(); 37 | if version == "reserved" { 38 | // We special case version 999 later instead of making JniVersion an enum 39 | return Ok(JniVersion { 40 | major: 999, 41 | minor: 0, 42 | }); 43 | } 44 | let mut split = version.splitn(2, '.'); 45 | const EXPECTED_MSG: &str = "Expected \"major.minor\" version number or \"reserved\""; 46 | let major = split 47 | .next() 48 | .ok_or(syn::Error::new(input.span(), EXPECTED_MSG))?; 49 | let major = major 50 | .parse::() 51 | .map_err(|_| syn::Error::new(input.span(), EXPECTED_MSG))?; 52 | let minor = split 53 | .next() 54 | .unwrap_or("0") 55 | .parse::() 56 | .map_err(|_| syn::Error::new(input.span(), EXPECTED_MSG))?; 57 | Ok(JniVersion { major, minor }) 58 | } 59 | } 60 | 61 | fn jni_to_union_impl(input: DeriveInput) -> syn::Result { 62 | let original_name = &input.ident; 63 | let original_visibility = &input.vis; 64 | 65 | let mut versions = HashSet::new(); 66 | let mut versioned_fields = vec![]; 67 | 68 | if let Data::Struct(data) = &input.data { 69 | if let Fields::Named(fields) = &data.fields { 70 | for field in &fields.named { 71 | // Default to version 1.1 72 | let mut min_version = JniVersion::default(); 73 | 74 | let mut field = field.clone(); 75 | 76 | let mut jni_added_attr = None; 77 | field.attrs.retain(|attr| { 78 | if attr.path().is_ident("jni_added") { 79 | jni_added_attr = Some(attr.clone()); 80 | false 81 | } else { 82 | true 83 | } 84 | }); 85 | if let Some(attr) = jni_added_attr { 86 | let version = attr.parse_args::()?; 87 | min_version = version; 88 | } 89 | 90 | versions.insert(min_version); 91 | versioned_fields.push((min_version, field.clone())); 92 | } 93 | 94 | // Quote structs and union 95 | let mut expanded = quote! {}; 96 | 97 | let mut union_members = quote!(); 98 | 99 | let mut versions: Vec<_> = versions.into_iter().collect(); 100 | versions.sort(); 101 | 102 | for version in versions { 103 | let (struct_ident, version_ident, version_suffix) = if version.major == 999 { 104 | ( 105 | Ident::new(&format!("{}_reserved", original_name), original_name.span()), 106 | Ident::new("reserved", original_name.span()), 107 | "reserved".to_string(), 108 | ) 109 | } else if version.minor == 0 { 110 | ( 111 | Ident::new( 112 | &format!("{}_{}", original_name, version.major), 113 | original_name.span(), 114 | ), 115 | Ident::new(&format!("v{}", version.major), original_name.span()), 116 | format!("{}", version.major), 117 | ) 118 | } else { 119 | let struct_ident = Ident::new( 120 | &format!("{}_{}_{}", original_name, version.major, version.minor), 121 | original_name.span(), 122 | ); 123 | let version_ident = Ident::new( 124 | &format!("v{}_{}", version.major, version.minor), 125 | original_name.span(), 126 | ); 127 | ( 128 | struct_ident, 129 | version_ident, 130 | format!("{}_{}", version.major, version.minor), 131 | ) 132 | }; 133 | 134 | let last = versioned_fields 135 | .iter() 136 | .rposition(|(v, _f)| v <= &version) 137 | .unwrap_or(versioned_fields.len()); 138 | let mut padding_idx = 0u32; 139 | 140 | let mut version_field_tokens = quote!(); 141 | for (i, (field_min_version, field)) in versioned_fields.iter().enumerate() { 142 | if i > last { 143 | break; 144 | } 145 | if field_min_version > &version { 146 | let reserved_ident = format_ident!("_padding_{}", padding_idx); 147 | padding_idx += 1; 148 | version_field_tokens.extend(quote! { #reserved_ident: *mut c_void, }); 149 | } else { 150 | version_field_tokens.extend(quote! { #field, }); 151 | } 152 | } 153 | expanded.extend(quote! { 154 | #[allow(non_snake_case, non_camel_case_types)] 155 | #[repr(C)] 156 | #[derive(Copy, Clone)] 157 | #original_visibility struct #struct_ident { 158 | #version_field_tokens 159 | } 160 | }); 161 | 162 | let api_comment = 163 | format!("API when JNI version >= `JNI_VERSION_{}`", version_suffix); 164 | union_members.extend(quote! { 165 | #[doc = #api_comment] 166 | #original_visibility #version_ident: #struct_ident, 167 | }); 168 | } 169 | 170 | expanded.extend(quote! { 171 | #[repr(C)] 172 | #original_visibility union #original_name { 173 | #union_members 174 | } 175 | }); 176 | 177 | return Ok(TokenStream::from(expanded)); 178 | } 179 | } 180 | 181 | Err(syn::Error::new( 182 | input.span(), 183 | "Expected a struct with fields", 184 | )) 185 | } 186 | 187 | #[proc_macro_attribute] 188 | pub fn jni_to_union(_attr: TokenStream, item: TokenStream) -> TokenStream { 189 | let input = parse_macro_input!(item as DeriveInput); 190 | 191 | match jni_to_union_impl(input) { 192 | Ok(tokens) => tokens, 193 | Err(err) => err.into_compile_error().into(), 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc(html_root_url = "https://docs.rs/jni-sys/0.3.0")] 2 | #![allow(non_snake_case, non_camel_case_types)] 3 | #![warn(rust_2018_idioms, missing_debug_implementations)] 4 | #![no_std] 5 | 6 | use core::ffi::c_char; 7 | use core::ffi::c_void; 8 | 9 | use jni_sys_macros::jni_to_union; 10 | 11 | // FIXME is this sufficiently correct? 12 | pub type va_list = *mut c_void; 13 | 14 | pub type jint = i32; 15 | pub type jlong = i64; 16 | pub type jbyte = i8; 17 | pub type jboolean = bool; 18 | pub type jchar = u16; 19 | pub type jshort = i16; 20 | pub type jfloat = f32; 21 | pub type jdouble = f64; 22 | pub type jsize = jint; 23 | 24 | #[derive(Debug)] 25 | pub enum _jobject {} 26 | pub type jobject = *mut _jobject; 27 | pub type jclass = jobject; 28 | pub type jthrowable = jobject; 29 | pub type jstring = jobject; 30 | pub type jarray = jobject; 31 | pub type jbooleanArray = jarray; 32 | pub type jbyteArray = jarray; 33 | pub type jcharArray = jarray; 34 | pub type jshortArray = jarray; 35 | pub type jintArray = jarray; 36 | pub type jlongArray = jarray; 37 | pub type jfloatArray = jarray; 38 | pub type jdoubleArray = jarray; 39 | pub type jobjectArray = jarray; 40 | pub type jweak = jobject; 41 | 42 | #[repr(C)] 43 | #[derive(Copy)] 44 | pub union jvalue { 45 | pub z: jboolean, 46 | pub b: jbyte, 47 | pub c: jchar, 48 | pub s: jshort, 49 | pub i: jint, 50 | pub j: jlong, 51 | pub f: jfloat, 52 | pub d: jdouble, 53 | pub l: jobject, 54 | } 55 | 56 | impl Clone for jvalue { 57 | fn clone(&self) -> Self { 58 | *self 59 | } 60 | } 61 | impl core::fmt::Debug for jvalue { 62 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 63 | let b = unsafe { self.b }; 64 | // For all except `jboolean` then any bitwise pattern is a valid value 65 | // so even though we don't know which specific type the given `jvalue` 66 | // represents we can effectively cast it to all possible types. 67 | f.debug_struct("jvalue") 68 | .field( 69 | "z", 70 | &if b == 0 { 71 | "false" 72 | } else if b == 1 { 73 | "true" 74 | } else { 75 | "invalid" 76 | }, 77 | ) 78 | .field("b", unsafe { &self.b }) 79 | .field("c", unsafe { &self.c }) 80 | .field("s", unsafe { &self.s }) 81 | .field("i", unsafe { &self.i }) 82 | .field("j", unsafe { &self.j }) 83 | .field("f", unsafe { &self.f }) 84 | .field("d", unsafe { &self.d }) 85 | .field("l", unsafe { &self.l }) 86 | .finish() 87 | } 88 | } 89 | 90 | #[derive(Debug)] 91 | pub enum _jfieldID {} 92 | pub type jfieldID = *mut _jfieldID; 93 | #[derive(Debug)] 94 | pub enum _jmethodID {} 95 | pub type jmethodID = *mut _jmethodID; 96 | 97 | #[derive(Clone, Copy, Debug)] 98 | #[repr(C)] 99 | pub enum jobjectRefType { 100 | JNIInvalidRefType = 0, 101 | JNILocalRefType = 1, 102 | JNIGlobalRefType = 2, 103 | JNIWeakGlobalRefType = 3, 104 | } 105 | 106 | pub const JNI_FALSE: jboolean = false; 107 | pub const JNI_TRUE: jboolean = true; 108 | 109 | pub const JNI_OK: jint = 0; 110 | pub const JNI_ERR: jint = -1; 111 | pub const JNI_EDETACHED: jint = -2; 112 | pub const JNI_EVERSION: jint = -3; 113 | pub const JNI_ENOMEM: jint = -4; 114 | pub const JNI_EEXIST: jint = -5; 115 | pub const JNI_EINVAL: jint = -6; 116 | 117 | pub const JNI_COMMIT: jint = 1; 118 | pub const JNI_ABORT: jint = 2; 119 | 120 | pub const JNI_VERSION_1_1: jint = 0x00010001; 121 | pub const JNI_VERSION_1_2: jint = 0x00010002; 122 | pub const JNI_VERSION_1_4: jint = 0x00010004; 123 | pub const JNI_VERSION_1_6: jint = 0x00010006; 124 | pub const JNI_VERSION_1_8: jint = 0x00010008; 125 | pub const JNI_VERSION_9: jint = 0x00090000; 126 | pub const JNI_VERSION_10: jint = 0x000a0000; 127 | pub const JNI_VERSION_19: jint = 0x00130000; 128 | pub const JNI_VERSION_20: jint = 0x00140000; 129 | pub const JNI_VERSION_21: jint = 0x00150000; 130 | 131 | #[repr(C)] 132 | #[derive(Copy, Debug)] 133 | pub struct JNINativeMethod { 134 | pub name: *mut c_char, 135 | pub signature: *mut c_char, 136 | pub fnPtr: *mut c_void, 137 | } 138 | 139 | impl Clone for JNINativeMethod { 140 | fn clone(&self) -> Self { 141 | *self 142 | } 143 | } 144 | 145 | pub type JNIEnv = *const JNINativeInterface_; 146 | pub type JavaVM = *const JNIInvokeInterface_; 147 | 148 | #[repr(C)] 149 | #[non_exhaustive] 150 | #[jni_to_union] 151 | #[derive(Copy, Clone)] 152 | pub struct JNINativeInterface_ { 153 | #[jni_added("reserved")] 154 | pub reserved0: *mut c_void, 155 | #[jni_added("reserved")] 156 | pub reserved1: *mut c_void, 157 | #[jni_added("reserved")] 158 | pub reserved2: *mut c_void, 159 | #[jni_added("reserved")] 160 | pub reserved3: *mut c_void, 161 | #[jni_added("1.1")] 162 | pub GetVersion: unsafe extern "system" fn(env: *mut JNIEnv) -> jint, 163 | pub DefineClass: unsafe extern "system" fn( 164 | env: *mut JNIEnv, 165 | name: *const c_char, 166 | loader: jobject, 167 | buf: *const jbyte, 168 | len: jsize, 169 | ) -> jclass, 170 | pub FindClass: unsafe extern "system" fn(env: *mut JNIEnv, name: *const c_char) -> jclass, 171 | #[jni_added("1.2")] 172 | pub FromReflectedMethod: 173 | unsafe extern "system" fn(env: *mut JNIEnv, method: jobject) -> jmethodID, 174 | #[jni_added("1.2")] 175 | pub FromReflectedField: unsafe extern "system" fn(env: *mut JNIEnv, field: jobject) -> jfieldID, 176 | #[jni_added("1.2")] 177 | pub ToReflectedMethod: unsafe extern "system" fn( 178 | env: *mut JNIEnv, 179 | cls: jclass, 180 | methodID: jmethodID, 181 | isStatic: jboolean, 182 | ) -> jobject, 183 | pub GetSuperclass: unsafe extern "system" fn(env: *mut JNIEnv, sub: jclass) -> jclass, 184 | pub IsAssignableFrom: 185 | unsafe extern "system" fn(env: *mut JNIEnv, sub: jclass, sup: jclass) -> jboolean, 186 | #[jni_added("1.2")] 187 | pub ToReflectedField: unsafe extern "system" fn( 188 | env: *mut JNIEnv, 189 | cls: jclass, 190 | fieldID: jfieldID, 191 | isStatic: jboolean, 192 | ) -> jobject, 193 | pub Throw: unsafe extern "system" fn(env: *mut JNIEnv, obj: jthrowable) -> jint, 194 | pub ThrowNew: 195 | unsafe extern "system" fn(env: *mut JNIEnv, clazz: jclass, msg: *const c_char) -> jint, 196 | pub ExceptionOccurred: unsafe extern "system" fn(env: *mut JNIEnv) -> jthrowable, 197 | pub ExceptionDescribe: unsafe extern "system" fn(env: *mut JNIEnv), 198 | pub ExceptionClear: unsafe extern "system" fn(env: *mut JNIEnv), 199 | pub FatalError: unsafe extern "system" fn(env: *mut JNIEnv, msg: *const c_char) -> !, 200 | #[jni_added("1.2")] 201 | pub PushLocalFrame: unsafe extern "system" fn(env: *mut JNIEnv, capacity: jint) -> jint, 202 | #[jni_added("1.2")] 203 | pub PopLocalFrame: unsafe extern "system" fn(env: *mut JNIEnv, result: jobject) -> jobject, 204 | pub NewGlobalRef: unsafe extern "system" fn(env: *mut JNIEnv, lobj: jobject) -> jobject, 205 | pub DeleteGlobalRef: unsafe extern "system" fn(env: *mut JNIEnv, gref: jobject), 206 | pub DeleteLocalRef: unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject), 207 | pub IsSameObject: 208 | unsafe extern "system" fn(env: *mut JNIEnv, obj1: jobject, obj2: jobject) -> jboolean, 209 | #[jni_added("1.2")] 210 | pub NewLocalRef: unsafe extern "system" fn(env: *mut JNIEnv, ref_: jobject) -> jobject, 211 | #[jni_added("1.2")] 212 | pub EnsureLocalCapacity: unsafe extern "system" fn(env: *mut JNIEnv, capacity: jint) -> jint, 213 | pub AllocObject: unsafe extern "system" fn(env: *mut JNIEnv, clazz: jclass) -> jobject, 214 | pub NewObject: 215 | unsafe extern "C" fn(env: *mut JNIEnv, clazz: jclass, methodID: jmethodID, ...) -> jobject, 216 | pub NewObjectV: unsafe extern "system" fn( 217 | env: *mut JNIEnv, 218 | clazz: jclass, 219 | methodID: jmethodID, 220 | args: va_list, 221 | ) -> jobject, 222 | pub NewObjectA: unsafe extern "system" fn( 223 | env: *mut JNIEnv, 224 | clazz: jclass, 225 | methodID: jmethodID, 226 | args: *const jvalue, 227 | ) -> jobject, 228 | pub GetObjectClass: unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject) -> jclass, 229 | pub IsInstanceOf: 230 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, clazz: jclass) -> jboolean, 231 | pub GetMethodID: unsafe extern "system" fn( 232 | env: *mut JNIEnv, 233 | clazz: jclass, 234 | name: *const c_char, 235 | sig: *const c_char, 236 | ) -> jmethodID, 237 | pub CallObjectMethod: 238 | unsafe extern "C" fn(env: *mut JNIEnv, obj: jobject, methodID: jmethodID, ...) -> jobject, 239 | pub CallObjectMethodV: unsafe extern "system" fn( 240 | env: *mut JNIEnv, 241 | obj: jobject, 242 | methodID: jmethodID, 243 | args: va_list, 244 | ) -> jobject, 245 | pub CallObjectMethodA: unsafe extern "system" fn( 246 | env: *mut JNIEnv, 247 | obj: jobject, 248 | methodID: jmethodID, 249 | args: *const jvalue, 250 | ) -> jobject, 251 | pub CallBooleanMethod: 252 | unsafe extern "C" fn(env: *mut JNIEnv, obj: jobject, methodID: jmethodID, ...) -> jboolean, 253 | pub CallBooleanMethodV: unsafe extern "system" fn( 254 | env: *mut JNIEnv, 255 | obj: jobject, 256 | methodID: jmethodID, 257 | args: va_list, 258 | ) -> jboolean, 259 | 260 | pub CallBooleanMethodA: unsafe extern "system" fn( 261 | env: *mut JNIEnv, 262 | obj: jobject, 263 | methodID: jmethodID, 264 | args: *const jvalue, 265 | ) -> jboolean, 266 | 267 | pub CallByteMethod: 268 | unsafe extern "C" fn(env: *mut JNIEnv, obj: jobject, methodID: jmethodID, ...) -> jbyte, 269 | 270 | pub CallByteMethodV: unsafe extern "system" fn( 271 | env: *mut JNIEnv, 272 | obj: jobject, 273 | methodID: jmethodID, 274 | args: va_list, 275 | ) -> jbyte, 276 | 277 | pub CallByteMethodA: unsafe extern "system" fn( 278 | env: *mut JNIEnv, 279 | obj: jobject, 280 | methodID: jmethodID, 281 | args: *const jvalue, 282 | ) -> jbyte, 283 | 284 | pub CallCharMethod: 285 | unsafe extern "C" fn(env: *mut JNIEnv, obj: jobject, methodID: jmethodID, ...) -> jchar, 286 | 287 | pub CallCharMethodV: unsafe extern "system" fn( 288 | env: *mut JNIEnv, 289 | obj: jobject, 290 | methodID: jmethodID, 291 | args: va_list, 292 | ) -> jchar, 293 | 294 | pub CallCharMethodA: unsafe extern "system" fn( 295 | env: *mut JNIEnv, 296 | obj: jobject, 297 | methodID: jmethodID, 298 | args: *const jvalue, 299 | ) -> jchar, 300 | 301 | pub CallShortMethod: 302 | unsafe extern "C" fn(env: *mut JNIEnv, obj: jobject, methodID: jmethodID, ...) -> jshort, 303 | 304 | pub CallShortMethodV: unsafe extern "system" fn( 305 | env: *mut JNIEnv, 306 | obj: jobject, 307 | methodID: jmethodID, 308 | args: va_list, 309 | ) -> jshort, 310 | 311 | pub CallShortMethodA: unsafe extern "system" fn( 312 | env: *mut JNIEnv, 313 | obj: jobject, 314 | methodID: jmethodID, 315 | args: *const jvalue, 316 | ) -> jshort, 317 | 318 | pub CallIntMethod: 319 | unsafe extern "C" fn(env: *mut JNIEnv, obj: jobject, methodID: jmethodID, ...) -> jint, 320 | 321 | pub CallIntMethodV: unsafe extern "system" fn( 322 | env: *mut JNIEnv, 323 | obj: jobject, 324 | methodID: jmethodID, 325 | args: va_list, 326 | ) -> jint, 327 | 328 | pub CallIntMethodA: unsafe extern "system" fn( 329 | env: *mut JNIEnv, 330 | obj: jobject, 331 | methodID: jmethodID, 332 | args: *const jvalue, 333 | ) -> jint, 334 | 335 | pub CallLongMethod: 336 | unsafe extern "C" fn(env: *mut JNIEnv, obj: jobject, methodID: jmethodID, ...) -> jlong, 337 | 338 | pub CallLongMethodV: unsafe extern "system" fn( 339 | env: *mut JNIEnv, 340 | obj: jobject, 341 | methodID: jmethodID, 342 | args: va_list, 343 | ) -> jlong, 344 | 345 | pub CallLongMethodA: unsafe extern "system" fn( 346 | env: *mut JNIEnv, 347 | obj: jobject, 348 | methodID: jmethodID, 349 | args: *const jvalue, 350 | ) -> jlong, 351 | 352 | pub CallFloatMethod: 353 | unsafe extern "C" fn(env: *mut JNIEnv, obj: jobject, methodID: jmethodID, ...) -> jfloat, 354 | 355 | pub CallFloatMethodV: unsafe extern "system" fn( 356 | env: *mut JNIEnv, 357 | obj: jobject, 358 | methodID: jmethodID, 359 | args: va_list, 360 | ) -> jfloat, 361 | 362 | pub CallFloatMethodA: unsafe extern "system" fn( 363 | env: *mut JNIEnv, 364 | obj: jobject, 365 | methodID: jmethodID, 366 | args: *const jvalue, 367 | ) -> jfloat, 368 | 369 | pub CallDoubleMethod: 370 | unsafe extern "C" fn(env: *mut JNIEnv, obj: jobject, methodID: jmethodID, ...) -> jdouble, 371 | 372 | pub CallDoubleMethodV: unsafe extern "system" fn( 373 | env: *mut JNIEnv, 374 | obj: jobject, 375 | methodID: jmethodID, 376 | args: va_list, 377 | ) -> jdouble, 378 | 379 | pub CallDoubleMethodA: unsafe extern "system" fn( 380 | env: *mut JNIEnv, 381 | obj: jobject, 382 | methodID: jmethodID, 383 | args: *const jvalue, 384 | ) -> jdouble, 385 | 386 | pub CallVoidMethod: 387 | unsafe extern "C" fn(env: *mut JNIEnv, obj: jobject, methodID: jmethodID, ...), 388 | pub CallVoidMethodV: unsafe extern "system" fn( 389 | env: *mut JNIEnv, 390 | obj: jobject, 391 | methodID: jmethodID, 392 | args: va_list, 393 | ), 394 | 395 | pub CallVoidMethodA: unsafe extern "system" fn( 396 | env: *mut JNIEnv, 397 | obj: jobject, 398 | methodID: jmethodID, 399 | args: *const jvalue, 400 | ), 401 | 402 | pub CallNonvirtualObjectMethod: unsafe extern "C" fn( 403 | env: *mut JNIEnv, 404 | obj: jobject, 405 | clazz: jclass, 406 | methodID: jmethodID, 407 | ... 408 | ) -> jobject, 409 | 410 | pub CallNonvirtualObjectMethodV: unsafe extern "system" fn( 411 | env: *mut JNIEnv, 412 | obj: jobject, 413 | clazz: jclass, 414 | methodID: jmethodID, 415 | args: va_list, 416 | ) -> jobject, 417 | 418 | pub CallNonvirtualObjectMethodA: unsafe extern "system" fn( 419 | env: *mut JNIEnv, 420 | obj: jobject, 421 | clazz: jclass, 422 | methodID: jmethodID, 423 | args: *const jvalue, 424 | ) -> jobject, 425 | 426 | pub CallNonvirtualBooleanMethod: unsafe extern "C" fn( 427 | env: *mut JNIEnv, 428 | obj: jobject, 429 | clazz: jclass, 430 | methodID: jmethodID, 431 | ... 432 | ) -> jboolean, 433 | 434 | pub CallNonvirtualBooleanMethodV: unsafe extern "system" fn( 435 | env: *mut JNIEnv, 436 | obj: jobject, 437 | clazz: jclass, 438 | methodID: jmethodID, 439 | args: va_list, 440 | ) -> jboolean, 441 | 442 | pub CallNonvirtualBooleanMethodA: unsafe extern "system" fn( 443 | env: *mut JNIEnv, 444 | obj: jobject, 445 | clazz: jclass, 446 | methodID: jmethodID, 447 | args: *const jvalue, 448 | ) -> jboolean, 449 | 450 | pub CallNonvirtualByteMethod: unsafe extern "C" fn( 451 | env: *mut JNIEnv, 452 | obj: jobject, 453 | clazz: jclass, 454 | methodID: jmethodID, 455 | ... 456 | ) -> jbyte, 457 | 458 | pub CallNonvirtualByteMethodV: unsafe extern "system" fn( 459 | env: *mut JNIEnv, 460 | obj: jobject, 461 | clazz: jclass, 462 | methodID: jmethodID, 463 | args: va_list, 464 | ) -> jbyte, 465 | 466 | pub CallNonvirtualByteMethodA: unsafe extern "system" fn( 467 | env: *mut JNIEnv, 468 | obj: jobject, 469 | clazz: jclass, 470 | methodID: jmethodID, 471 | args: *const jvalue, 472 | ) -> jbyte, 473 | 474 | pub CallNonvirtualCharMethod: unsafe extern "C" fn( 475 | env: *mut JNIEnv, 476 | obj: jobject, 477 | clazz: jclass, 478 | methodID: jmethodID, 479 | ... 480 | ) -> jchar, 481 | 482 | pub CallNonvirtualCharMethodV: unsafe extern "system" fn( 483 | env: *mut JNIEnv, 484 | obj: jobject, 485 | clazz: jclass, 486 | methodID: jmethodID, 487 | args: va_list, 488 | ) -> jchar, 489 | 490 | pub CallNonvirtualCharMethodA: unsafe extern "system" fn( 491 | env: *mut JNIEnv, 492 | obj: jobject, 493 | clazz: jclass, 494 | methodID: jmethodID, 495 | args: *const jvalue, 496 | ) -> jchar, 497 | 498 | pub CallNonvirtualShortMethod: unsafe extern "C" fn( 499 | env: *mut JNIEnv, 500 | obj: jobject, 501 | clazz: jclass, 502 | methodID: jmethodID, 503 | ... 504 | ) -> jshort, 505 | 506 | pub CallNonvirtualShortMethodV: unsafe extern "system" fn( 507 | env: *mut JNIEnv, 508 | obj: jobject, 509 | clazz: jclass, 510 | methodID: jmethodID, 511 | args: va_list, 512 | ) -> jshort, 513 | 514 | pub CallNonvirtualShortMethodA: unsafe extern "system" fn( 515 | env: *mut JNIEnv, 516 | obj: jobject, 517 | clazz: jclass, 518 | methodID: jmethodID, 519 | args: *const jvalue, 520 | ) -> jshort, 521 | 522 | pub CallNonvirtualIntMethod: unsafe extern "C" fn( 523 | env: *mut JNIEnv, 524 | obj: jobject, 525 | clazz: jclass, 526 | methodID: jmethodID, 527 | ... 528 | ) -> jint, 529 | 530 | pub CallNonvirtualIntMethodV: unsafe extern "system" fn( 531 | env: *mut JNIEnv, 532 | obj: jobject, 533 | clazz: jclass, 534 | methodID: jmethodID, 535 | args: va_list, 536 | ) -> jint, 537 | 538 | pub CallNonvirtualIntMethodA: unsafe extern "system" fn( 539 | env: *mut JNIEnv, 540 | obj: jobject, 541 | clazz: jclass, 542 | methodID: jmethodID, 543 | args: *const jvalue, 544 | ) -> jint, 545 | 546 | pub CallNonvirtualLongMethod: unsafe extern "C" fn( 547 | env: *mut JNIEnv, 548 | obj: jobject, 549 | clazz: jclass, 550 | methodID: jmethodID, 551 | ... 552 | ) -> jlong, 553 | 554 | pub CallNonvirtualLongMethodV: unsafe extern "system" fn( 555 | env: *mut JNIEnv, 556 | obj: jobject, 557 | clazz: jclass, 558 | methodID: jmethodID, 559 | args: va_list, 560 | ) -> jlong, 561 | 562 | pub CallNonvirtualLongMethodA: unsafe extern "system" fn( 563 | env: *mut JNIEnv, 564 | obj: jobject, 565 | clazz: jclass, 566 | methodID: jmethodID, 567 | args: *const jvalue, 568 | ) -> jlong, 569 | 570 | pub CallNonvirtualFloatMethod: unsafe extern "C" fn( 571 | env: *mut JNIEnv, 572 | obj: jobject, 573 | clazz: jclass, 574 | methodID: jmethodID, 575 | ... 576 | ) -> jfloat, 577 | 578 | pub CallNonvirtualFloatMethodV: unsafe extern "system" fn( 579 | env: *mut JNIEnv, 580 | obj: jobject, 581 | clazz: jclass, 582 | methodID: jmethodID, 583 | args: va_list, 584 | ) -> jfloat, 585 | 586 | pub CallNonvirtualFloatMethodA: unsafe extern "system" fn( 587 | env: *mut JNIEnv, 588 | obj: jobject, 589 | clazz: jclass, 590 | methodID: jmethodID, 591 | args: *const jvalue, 592 | ) -> jfloat, 593 | 594 | pub CallNonvirtualDoubleMethod: unsafe extern "C" fn( 595 | env: *mut JNIEnv, 596 | obj: jobject, 597 | clazz: jclass, 598 | methodID: jmethodID, 599 | ... 600 | ) -> jdouble, 601 | 602 | pub CallNonvirtualDoubleMethodV: unsafe extern "system" fn( 603 | env: *mut JNIEnv, 604 | obj: jobject, 605 | clazz: jclass, 606 | methodID: jmethodID, 607 | args: va_list, 608 | ) -> jdouble, 609 | 610 | pub CallNonvirtualDoubleMethodA: unsafe extern "system" fn( 611 | env: *mut JNIEnv, 612 | obj: jobject, 613 | clazz: jclass, 614 | methodID: jmethodID, 615 | args: *const jvalue, 616 | ) -> jdouble, 617 | 618 | pub CallNonvirtualVoidMethod: unsafe extern "C" fn( 619 | env: *mut JNIEnv, 620 | obj: jobject, 621 | clazz: jclass, 622 | methodID: jmethodID, 623 | ... 624 | ), 625 | 626 | pub CallNonvirtualVoidMethodV: unsafe extern "system" fn( 627 | env: *mut JNIEnv, 628 | obj: jobject, 629 | clazz: jclass, 630 | methodID: jmethodID, 631 | args: va_list, 632 | ), 633 | 634 | pub CallNonvirtualVoidMethodA: unsafe extern "system" fn( 635 | env: *mut JNIEnv, 636 | obj: jobject, 637 | clazz: jclass, 638 | methodID: jmethodID, 639 | args: *const jvalue, 640 | ), 641 | 642 | pub GetFieldID: unsafe extern "system" fn( 643 | env: *mut JNIEnv, 644 | clazz: jclass, 645 | name: *const c_char, 646 | sig: *const c_char, 647 | ) -> jfieldID, 648 | 649 | pub GetObjectField: 650 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID) -> jobject, 651 | 652 | pub GetBooleanField: 653 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID) -> jboolean, 654 | 655 | pub GetByteField: 656 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID) -> jbyte, 657 | 658 | pub GetCharField: 659 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID) -> jchar, 660 | 661 | pub GetShortField: 662 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID) -> jshort, 663 | 664 | pub GetIntField: 665 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID) -> jint, 666 | 667 | pub GetLongField: 668 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID) -> jlong, 669 | 670 | pub GetFloatField: 671 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID) -> jfloat, 672 | 673 | pub GetDoubleField: 674 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID) -> jdouble, 675 | 676 | pub SetObjectField: 677 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID, val: jobject), 678 | 679 | pub SetBooleanField: 680 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID, val: jboolean), 681 | 682 | pub SetByteField: 683 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID, val: jbyte), 684 | 685 | pub SetCharField: 686 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID, val: jchar), 687 | 688 | pub SetShortField: 689 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID, val: jshort), 690 | 691 | pub SetIntField: 692 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID, val: jint), 693 | 694 | pub SetLongField: 695 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID, val: jlong), 696 | 697 | pub SetFloatField: 698 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID, val: jfloat), 699 | 700 | pub SetDoubleField: 701 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject, fieldID: jfieldID, val: jdouble), 702 | 703 | pub GetStaticMethodID: unsafe extern "system" fn( 704 | env: *mut JNIEnv, 705 | clazz: jclass, 706 | name: *const c_char, 707 | sig: *const c_char, 708 | ) -> jmethodID, 709 | 710 | pub CallStaticObjectMethod: 711 | unsafe extern "C" fn(env: *mut JNIEnv, clazz: jclass, methodID: jmethodID, ...) -> jobject, 712 | 713 | pub CallStaticObjectMethodV: unsafe extern "system" fn( 714 | env: *mut JNIEnv, 715 | clazz: jclass, 716 | methodID: jmethodID, 717 | args: va_list, 718 | ) -> jobject, 719 | 720 | pub CallStaticObjectMethodA: unsafe extern "system" fn( 721 | env: *mut JNIEnv, 722 | clazz: jclass, 723 | methodID: jmethodID, 724 | args: *const jvalue, 725 | ) -> jobject, 726 | 727 | pub CallStaticBooleanMethod: 728 | unsafe extern "C" fn(env: *mut JNIEnv, clazz: jclass, methodID: jmethodID, ...) -> jboolean, 729 | 730 | pub CallStaticBooleanMethodV: unsafe extern "system" fn( 731 | env: *mut JNIEnv, 732 | clazz: jclass, 733 | methodID: jmethodID, 734 | args: va_list, 735 | ) -> jboolean, 736 | 737 | pub CallStaticBooleanMethodA: unsafe extern "system" fn( 738 | env: *mut JNIEnv, 739 | clazz: jclass, 740 | methodID: jmethodID, 741 | args: *const jvalue, 742 | ) -> jboolean, 743 | 744 | pub CallStaticByteMethod: 745 | unsafe extern "C" fn(env: *mut JNIEnv, clazz: jclass, methodID: jmethodID, ...) -> jbyte, 746 | 747 | pub CallStaticByteMethodV: unsafe extern "system" fn( 748 | env: *mut JNIEnv, 749 | clazz: jclass, 750 | methodID: jmethodID, 751 | args: va_list, 752 | ) -> jbyte, 753 | 754 | pub CallStaticByteMethodA: unsafe extern "system" fn( 755 | env: *mut JNIEnv, 756 | clazz: jclass, 757 | methodID: jmethodID, 758 | args: *const jvalue, 759 | ) -> jbyte, 760 | 761 | pub CallStaticCharMethod: 762 | unsafe extern "C" fn(env: *mut JNIEnv, clazz: jclass, methodID: jmethodID, ...) -> jchar, 763 | 764 | pub CallStaticCharMethodV: unsafe extern "system" fn( 765 | env: *mut JNIEnv, 766 | clazz: jclass, 767 | methodID: jmethodID, 768 | args: va_list, 769 | ) -> jchar, 770 | 771 | pub CallStaticCharMethodA: unsafe extern "system" fn( 772 | env: *mut JNIEnv, 773 | clazz: jclass, 774 | methodID: jmethodID, 775 | args: *const jvalue, 776 | ) -> jchar, 777 | 778 | pub CallStaticShortMethod: 779 | unsafe extern "C" fn(env: *mut JNIEnv, clazz: jclass, methodID: jmethodID, ...) -> jshort, 780 | 781 | pub CallStaticShortMethodV: unsafe extern "system" fn( 782 | env: *mut JNIEnv, 783 | clazz: jclass, 784 | methodID: jmethodID, 785 | args: va_list, 786 | ) -> jshort, 787 | 788 | pub CallStaticShortMethodA: unsafe extern "system" fn( 789 | env: *mut JNIEnv, 790 | clazz: jclass, 791 | methodID: jmethodID, 792 | args: *const jvalue, 793 | ) -> jshort, 794 | 795 | pub CallStaticIntMethod: 796 | unsafe extern "C" fn(env: *mut JNIEnv, clazz: jclass, methodID: jmethodID, ...) -> jint, 797 | 798 | pub CallStaticIntMethodV: unsafe extern "system" fn( 799 | env: *mut JNIEnv, 800 | clazz: jclass, 801 | methodID: jmethodID, 802 | args: va_list, 803 | ) -> jint, 804 | 805 | pub CallStaticIntMethodA: unsafe extern "system" fn( 806 | env: *mut JNIEnv, 807 | clazz: jclass, 808 | methodID: jmethodID, 809 | args: *const jvalue, 810 | ) -> jint, 811 | 812 | pub CallStaticLongMethod: 813 | unsafe extern "C" fn(env: *mut JNIEnv, clazz: jclass, methodID: jmethodID, ...) -> jlong, 814 | 815 | pub CallStaticLongMethodV: unsafe extern "system" fn( 816 | env: *mut JNIEnv, 817 | clazz: jclass, 818 | methodID: jmethodID, 819 | args: va_list, 820 | ) -> jlong, 821 | 822 | pub CallStaticLongMethodA: unsafe extern "system" fn( 823 | env: *mut JNIEnv, 824 | clazz: jclass, 825 | methodID: jmethodID, 826 | args: *const jvalue, 827 | ) -> jlong, 828 | 829 | pub CallStaticFloatMethod: 830 | unsafe extern "C" fn(env: *mut JNIEnv, clazz: jclass, methodID: jmethodID, ...) -> jfloat, 831 | 832 | pub CallStaticFloatMethodV: unsafe extern "system" fn( 833 | env: *mut JNIEnv, 834 | clazz: jclass, 835 | methodID: jmethodID, 836 | args: va_list, 837 | ) -> jfloat, 838 | 839 | pub CallStaticFloatMethodA: unsafe extern "system" fn( 840 | env: *mut JNIEnv, 841 | clazz: jclass, 842 | methodID: jmethodID, 843 | args: *const jvalue, 844 | ) -> jfloat, 845 | 846 | pub CallStaticDoubleMethod: 847 | unsafe extern "C" fn(env: *mut JNIEnv, clazz: jclass, methodID: jmethodID, ...) -> jdouble, 848 | 849 | pub CallStaticDoubleMethodV: unsafe extern "system" fn( 850 | env: *mut JNIEnv, 851 | clazz: jclass, 852 | methodID: jmethodID, 853 | args: va_list, 854 | ) -> jdouble, 855 | 856 | pub CallStaticDoubleMethodA: unsafe extern "system" fn( 857 | env: *mut JNIEnv, 858 | clazz: jclass, 859 | methodID: jmethodID, 860 | args: *const jvalue, 861 | ) -> jdouble, 862 | 863 | pub CallStaticVoidMethod: 864 | unsafe extern "C" fn(env: *mut JNIEnv, cls: jclass, methodID: jmethodID, ...), 865 | pub CallStaticVoidMethodV: unsafe extern "system" fn( 866 | env: *mut JNIEnv, 867 | cls: jclass, 868 | methodID: jmethodID, 869 | args: va_list, 870 | ), 871 | 872 | pub CallStaticVoidMethodA: unsafe extern "system" fn( 873 | env: *mut JNIEnv, 874 | cls: jclass, 875 | methodID: jmethodID, 876 | args: *const jvalue, 877 | ), 878 | 879 | pub GetStaticFieldID: unsafe extern "system" fn( 880 | env: *mut JNIEnv, 881 | clazz: jclass, 882 | name: *const c_char, 883 | sig: *const c_char, 884 | ) -> jfieldID, 885 | 886 | pub GetStaticObjectField: 887 | unsafe extern "system" fn(env: *mut JNIEnv, clazz: jclass, fieldID: jfieldID) -> jobject, 888 | 889 | pub GetStaticBooleanField: 890 | unsafe extern "system" fn(env: *mut JNIEnv, clazz: jclass, fieldID: jfieldID) -> jboolean, 891 | 892 | pub GetStaticByteField: 893 | unsafe extern "system" fn(env: *mut JNIEnv, clazz: jclass, fieldID: jfieldID) -> jbyte, 894 | 895 | pub GetStaticCharField: 896 | unsafe extern "system" fn(env: *mut JNIEnv, clazz: jclass, fieldID: jfieldID) -> jchar, 897 | 898 | pub GetStaticShortField: 899 | unsafe extern "system" fn(env: *mut JNIEnv, clazz: jclass, fieldID: jfieldID) -> jshort, 900 | 901 | pub GetStaticIntField: 902 | unsafe extern "system" fn(env: *mut JNIEnv, clazz: jclass, fieldID: jfieldID) -> jint, 903 | 904 | pub GetStaticLongField: 905 | unsafe extern "system" fn(env: *mut JNIEnv, clazz: jclass, fieldID: jfieldID) -> jlong, 906 | 907 | pub GetStaticFloatField: 908 | unsafe extern "system" fn(env: *mut JNIEnv, clazz: jclass, fieldID: jfieldID) -> jfloat, 909 | 910 | pub GetStaticDoubleField: 911 | unsafe extern "system" fn(env: *mut JNIEnv, clazz: jclass, fieldID: jfieldID) -> jdouble, 912 | 913 | pub SetStaticObjectField: unsafe extern "system" fn( 914 | env: *mut JNIEnv, 915 | clazz: jclass, 916 | fieldID: jfieldID, 917 | value: jobject, 918 | ), 919 | 920 | pub SetStaticBooleanField: unsafe extern "system" fn( 921 | env: *mut JNIEnv, 922 | clazz: jclass, 923 | fieldID: jfieldID, 924 | value: jboolean, 925 | ), 926 | 927 | pub SetStaticByteField: 928 | unsafe extern "system" fn(env: *mut JNIEnv, clazz: jclass, fieldID: jfieldID, value: jbyte), 929 | 930 | pub SetStaticCharField: 931 | unsafe extern "system" fn(env: *mut JNIEnv, clazz: jclass, fieldID: jfieldID, value: jchar), 932 | 933 | pub SetStaticShortField: unsafe extern "system" fn( 934 | env: *mut JNIEnv, 935 | clazz: jclass, 936 | fieldID: jfieldID, 937 | value: jshort, 938 | ), 939 | 940 | pub SetStaticIntField: 941 | unsafe extern "system" fn(env: *mut JNIEnv, clazz: jclass, fieldID: jfieldID, value: jint), 942 | 943 | pub SetStaticLongField: 944 | unsafe extern "system" fn(env: *mut JNIEnv, clazz: jclass, fieldID: jfieldID, value: jlong), 945 | 946 | pub SetStaticFloatField: unsafe extern "system" fn( 947 | env: *mut JNIEnv, 948 | clazz: jclass, 949 | fieldID: jfieldID, 950 | value: jfloat, 951 | ), 952 | 953 | pub SetStaticDoubleField: unsafe extern "system" fn( 954 | env: *mut JNIEnv, 955 | clazz: jclass, 956 | fieldID: jfieldID, 957 | value: jdouble, 958 | ), 959 | 960 | pub NewString: 961 | unsafe extern "system" fn(env: *mut JNIEnv, unicode: *const jchar, len: jsize) -> jstring, 962 | 963 | pub GetStringLength: unsafe extern "system" fn(env: *mut JNIEnv, str: jstring) -> jsize, 964 | pub GetStringChars: unsafe extern "system" fn( 965 | env: *mut JNIEnv, 966 | str: jstring, 967 | isCopy: *mut jboolean, 968 | ) -> *const jchar, 969 | 970 | pub ReleaseStringChars: 971 | unsafe extern "system" fn(env: *mut JNIEnv, str: jstring, chars: *const jchar), 972 | pub NewStringUTF: unsafe extern "system" fn(env: *mut JNIEnv, utf: *const c_char) -> jstring, 973 | pub GetStringUTFLength: unsafe extern "system" fn(env: *mut JNIEnv, str: jstring) -> jsize, 974 | pub GetStringUTFChars: unsafe extern "system" fn( 975 | env: *mut JNIEnv, 976 | str: jstring, 977 | isCopy: *mut jboolean, 978 | ) -> *const c_char, 979 | 980 | pub ReleaseStringUTFChars: 981 | unsafe extern "system" fn(env: *mut JNIEnv, str: jstring, chars: *const c_char), 982 | pub GetArrayLength: unsafe extern "system" fn(env: *mut JNIEnv, array: jarray) -> jsize, 983 | pub NewObjectArray: unsafe extern "system" fn( 984 | env: *mut JNIEnv, 985 | len: jsize, 986 | clazz: jclass, 987 | init: jobject, 988 | ) -> jobjectArray, 989 | 990 | pub GetObjectArrayElement: 991 | unsafe extern "system" fn(env: *mut JNIEnv, array: jobjectArray, index: jsize) -> jobject, 992 | 993 | pub SetObjectArrayElement: unsafe extern "system" fn( 994 | env: *mut JNIEnv, 995 | array: jobjectArray, 996 | index: jsize, 997 | val: jobject, 998 | ), 999 | 1000 | pub NewBooleanArray: unsafe extern "system" fn(env: *mut JNIEnv, len: jsize) -> jbooleanArray, 1001 | pub NewByteArray: unsafe extern "system" fn(env: *mut JNIEnv, len: jsize) -> jbyteArray, 1002 | pub NewCharArray: unsafe extern "system" fn(env: *mut JNIEnv, len: jsize) -> jcharArray, 1003 | pub NewShortArray: unsafe extern "system" fn(env: *mut JNIEnv, len: jsize) -> jshortArray, 1004 | pub NewIntArray: unsafe extern "system" fn(env: *mut JNIEnv, len: jsize) -> jintArray, 1005 | pub NewLongArray: unsafe extern "system" fn(env: *mut JNIEnv, len: jsize) -> jlongArray, 1006 | pub NewFloatArray: unsafe extern "system" fn(env: *mut JNIEnv, len: jsize) -> jfloatArray, 1007 | pub NewDoubleArray: unsafe extern "system" fn(env: *mut JNIEnv, len: jsize) -> jdoubleArray, 1008 | pub GetBooleanArrayElements: unsafe extern "system" fn( 1009 | env: *mut JNIEnv, 1010 | array: jbooleanArray, 1011 | isCopy: *mut jboolean, 1012 | ) -> *mut jboolean, 1013 | 1014 | pub GetByteArrayElements: unsafe extern "system" fn( 1015 | env: *mut JNIEnv, 1016 | array: jbyteArray, 1017 | isCopy: *mut jboolean, 1018 | ) -> *mut jbyte, 1019 | 1020 | pub GetCharArrayElements: unsafe extern "system" fn( 1021 | env: *mut JNIEnv, 1022 | array: jcharArray, 1023 | isCopy: *mut jboolean, 1024 | ) -> *mut jchar, 1025 | 1026 | pub GetShortArrayElements: unsafe extern "system" fn( 1027 | env: *mut JNIEnv, 1028 | array: jshortArray, 1029 | isCopy: *mut jboolean, 1030 | ) -> *mut jshort, 1031 | 1032 | pub GetIntArrayElements: unsafe extern "system" fn( 1033 | env: *mut JNIEnv, 1034 | array: jintArray, 1035 | isCopy: *mut jboolean, 1036 | ) -> *mut jint, 1037 | 1038 | pub GetLongArrayElements: unsafe extern "system" fn( 1039 | env: *mut JNIEnv, 1040 | array: jlongArray, 1041 | isCopy: *mut jboolean, 1042 | ) -> *mut jlong, 1043 | 1044 | pub GetFloatArrayElements: unsafe extern "system" fn( 1045 | env: *mut JNIEnv, 1046 | array: jfloatArray, 1047 | isCopy: *mut jboolean, 1048 | ) -> *mut jfloat, 1049 | 1050 | pub GetDoubleArrayElements: unsafe extern "system" fn( 1051 | env: *mut JNIEnv, 1052 | array: jdoubleArray, 1053 | isCopy: *mut jboolean, 1054 | ) -> *mut jdouble, 1055 | 1056 | pub ReleaseBooleanArrayElements: unsafe extern "system" fn( 1057 | env: *mut JNIEnv, 1058 | array: jbooleanArray, 1059 | elems: *mut jboolean, 1060 | mode: jint, 1061 | ), 1062 | 1063 | pub ReleaseByteArrayElements: unsafe extern "system" fn( 1064 | env: *mut JNIEnv, 1065 | array: jbyteArray, 1066 | elems: *mut jbyte, 1067 | mode: jint, 1068 | ), 1069 | 1070 | pub ReleaseCharArrayElements: unsafe extern "system" fn( 1071 | env: *mut JNIEnv, 1072 | array: jcharArray, 1073 | elems: *mut jchar, 1074 | mode: jint, 1075 | ), 1076 | 1077 | pub ReleaseShortArrayElements: unsafe extern "system" fn( 1078 | env: *mut JNIEnv, 1079 | array: jshortArray, 1080 | elems: *mut jshort, 1081 | mode: jint, 1082 | ), 1083 | 1084 | pub ReleaseIntArrayElements: 1085 | unsafe extern "system" fn(env: *mut JNIEnv, array: jintArray, elems: *mut jint, mode: jint), 1086 | 1087 | pub ReleaseLongArrayElements: unsafe extern "system" fn( 1088 | env: *mut JNIEnv, 1089 | array: jlongArray, 1090 | elems: *mut jlong, 1091 | mode: jint, 1092 | ), 1093 | 1094 | pub ReleaseFloatArrayElements: unsafe extern "system" fn( 1095 | env: *mut JNIEnv, 1096 | array: jfloatArray, 1097 | elems: *mut jfloat, 1098 | mode: jint, 1099 | ), 1100 | 1101 | pub ReleaseDoubleArrayElements: unsafe extern "system" fn( 1102 | env: *mut JNIEnv, 1103 | array: jdoubleArray, 1104 | elems: *mut jdouble, 1105 | mode: jint, 1106 | ), 1107 | 1108 | pub GetBooleanArrayRegion: unsafe extern "system" fn( 1109 | env: *mut JNIEnv, 1110 | array: jbooleanArray, 1111 | start: jsize, 1112 | l: jsize, 1113 | buf: *mut jboolean, 1114 | ), 1115 | 1116 | pub GetByteArrayRegion: unsafe extern "system" fn( 1117 | env: *mut JNIEnv, 1118 | array: jbyteArray, 1119 | start: jsize, 1120 | len: jsize, 1121 | buf: *mut jbyte, 1122 | ), 1123 | 1124 | pub GetCharArrayRegion: unsafe extern "system" fn( 1125 | env: *mut JNIEnv, 1126 | array: jcharArray, 1127 | start: jsize, 1128 | len: jsize, 1129 | buf: *mut jchar, 1130 | ), 1131 | 1132 | pub GetShortArrayRegion: unsafe extern "system" fn( 1133 | env: *mut JNIEnv, 1134 | array: jshortArray, 1135 | start: jsize, 1136 | len: jsize, 1137 | buf: *mut jshort, 1138 | ), 1139 | 1140 | pub GetIntArrayRegion: unsafe extern "system" fn( 1141 | env: *mut JNIEnv, 1142 | array: jintArray, 1143 | start: jsize, 1144 | len: jsize, 1145 | buf: *mut jint, 1146 | ), 1147 | 1148 | pub GetLongArrayRegion: unsafe extern "system" fn( 1149 | env: *mut JNIEnv, 1150 | array: jlongArray, 1151 | start: jsize, 1152 | len: jsize, 1153 | buf: *mut jlong, 1154 | ), 1155 | 1156 | pub GetFloatArrayRegion: unsafe extern "system" fn( 1157 | env: *mut JNIEnv, 1158 | array: jfloatArray, 1159 | start: jsize, 1160 | len: jsize, 1161 | buf: *mut jfloat, 1162 | ), 1163 | 1164 | pub GetDoubleArrayRegion: unsafe extern "system" fn( 1165 | env: *mut JNIEnv, 1166 | array: jdoubleArray, 1167 | start: jsize, 1168 | len: jsize, 1169 | buf: *mut jdouble, 1170 | ), 1171 | 1172 | pub SetBooleanArrayRegion: unsafe extern "system" fn( 1173 | env: *mut JNIEnv, 1174 | array: jbooleanArray, 1175 | start: jsize, 1176 | l: jsize, 1177 | buf: *const jboolean, 1178 | ), 1179 | 1180 | pub SetByteArrayRegion: unsafe extern "system" fn( 1181 | env: *mut JNIEnv, 1182 | array: jbyteArray, 1183 | start: jsize, 1184 | len: jsize, 1185 | buf: *const jbyte, 1186 | ), 1187 | 1188 | pub SetCharArrayRegion: unsafe extern "system" fn( 1189 | env: *mut JNIEnv, 1190 | array: jcharArray, 1191 | start: jsize, 1192 | len: jsize, 1193 | buf: *const jchar, 1194 | ), 1195 | 1196 | pub SetShortArrayRegion: unsafe extern "system" fn( 1197 | env: *mut JNIEnv, 1198 | array: jshortArray, 1199 | start: jsize, 1200 | len: jsize, 1201 | buf: *const jshort, 1202 | ), 1203 | 1204 | pub SetIntArrayRegion: unsafe extern "system" fn( 1205 | env: *mut JNIEnv, 1206 | array: jintArray, 1207 | start: jsize, 1208 | len: jsize, 1209 | buf: *const jint, 1210 | ), 1211 | 1212 | pub SetLongArrayRegion: unsafe extern "system" fn( 1213 | env: *mut JNIEnv, 1214 | array: jlongArray, 1215 | start: jsize, 1216 | len: jsize, 1217 | buf: *const jlong, 1218 | ), 1219 | 1220 | pub SetFloatArrayRegion: unsafe extern "system" fn( 1221 | env: *mut JNIEnv, 1222 | array: jfloatArray, 1223 | start: jsize, 1224 | len: jsize, 1225 | buf: *const jfloat, 1226 | ), 1227 | 1228 | pub SetDoubleArrayRegion: unsafe extern "system" fn( 1229 | env: *mut JNIEnv, 1230 | array: jdoubleArray, 1231 | start: jsize, 1232 | len: jsize, 1233 | buf: *const jdouble, 1234 | ), 1235 | 1236 | pub RegisterNatives: unsafe extern "system" fn( 1237 | env: *mut JNIEnv, 1238 | clazz: jclass, 1239 | methods: *const JNINativeMethod, 1240 | nMethods: jint, 1241 | ) -> jint, 1242 | 1243 | pub UnregisterNatives: unsafe extern "system" fn(env: *mut JNIEnv, clazz: jclass) -> jint, 1244 | pub MonitorEnter: unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject) -> jint, 1245 | pub MonitorExit: unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject) -> jint, 1246 | pub GetJavaVM: unsafe extern "system" fn(env: *mut JNIEnv, vm: *mut *mut JavaVM) -> jint, 1247 | #[jni_added("1.2")] 1248 | pub GetStringRegion: unsafe extern "system" fn( 1249 | env: *mut JNIEnv, 1250 | str: jstring, 1251 | start: jsize, 1252 | len: jsize, 1253 | buf: *mut jchar, 1254 | ), 1255 | 1256 | #[jni_added("1.2")] 1257 | pub GetStringUTFRegion: unsafe extern "system" fn( 1258 | env: *mut JNIEnv, 1259 | str: jstring, 1260 | start: jsize, 1261 | len: jsize, 1262 | buf: *mut c_char, 1263 | ), 1264 | 1265 | #[jni_added("1.2")] 1266 | pub GetPrimitiveArrayCritical: unsafe extern "system" fn( 1267 | env: *mut JNIEnv, 1268 | array: jarray, 1269 | isCopy: *mut jboolean, 1270 | ) -> *mut c_void, 1271 | 1272 | #[jni_added("1.2")] 1273 | pub ReleasePrimitiveArrayCritical: 1274 | unsafe extern "system" fn(env: *mut JNIEnv, array: jarray, carray: *mut c_void, mode: jint), 1275 | 1276 | #[jni_added("1.2")] 1277 | pub GetStringCritical: unsafe extern "system" fn( 1278 | env: *mut JNIEnv, 1279 | string: jstring, 1280 | isCopy: *mut jboolean, 1281 | ) -> *const jchar, 1282 | 1283 | #[jni_added("1.2")] 1284 | pub ReleaseStringCritical: 1285 | unsafe extern "system" fn(env: *mut JNIEnv, string: jstring, cstring: *const jchar), 1286 | #[jni_added("1.2")] 1287 | pub NewWeakGlobalRef: unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject) -> jweak, 1288 | #[jni_added("1.2")] 1289 | pub DeleteWeakGlobalRef: unsafe extern "system" fn(env: *mut JNIEnv, ref_: jweak), 1290 | #[jni_added("1.2")] 1291 | pub ExceptionCheck: unsafe extern "system" fn(env: *mut JNIEnv) -> jboolean, 1292 | #[jni_added("1.4")] 1293 | pub NewDirectByteBuffer: unsafe extern "system" fn( 1294 | env: *mut JNIEnv, 1295 | address: *mut c_void, 1296 | capacity: jlong, 1297 | ) -> jobject, 1298 | 1299 | #[jni_added("1.4")] 1300 | pub GetDirectBufferAddress: 1301 | unsafe extern "system" fn(env: *mut JNIEnv, buf: jobject) -> *mut c_void, 1302 | #[jni_added("1.4")] 1303 | pub GetDirectBufferCapacity: unsafe extern "system" fn(env: *mut JNIEnv, buf: jobject) -> jlong, 1304 | #[jni_added("1.6")] 1305 | pub GetObjectRefType: 1306 | unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject) -> jobjectRefType, 1307 | #[jni_added("9")] 1308 | pub GetModule: unsafe extern "system" fn(env: *mut JNIEnv, clazz: jclass) -> jobject, 1309 | 1310 | #[jni_added("19")] 1311 | pub IsVirtualThread: unsafe extern "system" fn(env: *mut JNIEnv, obj: jobject) -> jboolean, 1312 | } 1313 | 1314 | #[repr(C)] 1315 | #[derive(Copy, Debug)] 1316 | pub struct JNIEnv_ { 1317 | pub functions: *const JNINativeInterface_, 1318 | } 1319 | 1320 | impl Clone for JNIEnv_ { 1321 | fn clone(&self) -> Self { 1322 | *self 1323 | } 1324 | } 1325 | 1326 | #[repr(C)] 1327 | #[derive(Copy, Debug)] 1328 | pub struct JavaVMOption { 1329 | pub optionString: *mut c_char, 1330 | pub extraInfo: *mut c_void, 1331 | } 1332 | 1333 | impl Clone for JavaVMOption { 1334 | fn clone(&self) -> Self { 1335 | *self 1336 | } 1337 | } 1338 | 1339 | #[repr(C)] 1340 | #[derive(Copy, Debug)] 1341 | pub struct JavaVMInitArgs { 1342 | pub version: jint, 1343 | pub nOptions: jint, 1344 | pub options: *mut JavaVMOption, 1345 | pub ignoreUnrecognized: jboolean, 1346 | } 1347 | 1348 | impl Clone for JavaVMInitArgs { 1349 | fn clone(&self) -> Self { 1350 | *self 1351 | } 1352 | } 1353 | 1354 | #[repr(C)] 1355 | #[derive(Copy, Debug)] 1356 | pub struct JavaVMAttachArgs { 1357 | pub version: jint, 1358 | pub name: *mut c_char, 1359 | pub group: jobject, 1360 | } 1361 | 1362 | impl Clone for JavaVMAttachArgs { 1363 | fn clone(&self) -> Self { 1364 | *self 1365 | } 1366 | } 1367 | 1368 | #[repr(C)] 1369 | #[jni_to_union] 1370 | #[non_exhaustive] 1371 | #[derive(Copy, Clone)] 1372 | pub struct JNIInvokeInterface_ { 1373 | #[jni_added("reserved")] 1374 | pub reserved0: *mut c_void, 1375 | #[jni_added("reserved")] 1376 | pub reserved1: *mut c_void, 1377 | #[jni_added("reserved")] 1378 | pub reserved2: *mut c_void, 1379 | pub DestroyJavaVM: unsafe extern "system" fn(vm: *mut JavaVM) -> jint, 1380 | pub AttachCurrentThread: unsafe extern "system" fn( 1381 | vm: *mut JavaVM, 1382 | penv: *mut *mut c_void, 1383 | args: *mut c_void, 1384 | ) -> jint, 1385 | 1386 | pub DetachCurrentThread: unsafe extern "system" fn(vm: *mut JavaVM) -> jint, 1387 | 1388 | #[jni_added("1.2")] 1389 | pub GetEnv: 1390 | unsafe extern "system" fn(vm: *mut JavaVM, penv: *mut *mut c_void, version: jint) -> jint, 1391 | 1392 | #[jni_added("1.4")] 1393 | pub AttachCurrentThreadAsDaemon: unsafe extern "system" fn( 1394 | vm: *mut JavaVM, 1395 | penv: *mut *mut c_void, 1396 | args: *mut c_void, 1397 | ) -> jint, 1398 | } 1399 | 1400 | extern "system" { 1401 | pub fn JNI_GetDefaultJavaVMInitArgs(args: *mut c_void) -> jint; 1402 | pub fn JNI_CreateJavaVM( 1403 | pvm: *mut *mut JavaVM, 1404 | penv: *mut *mut c_void, 1405 | args: *mut c_void, 1406 | ) -> jint; 1407 | pub fn JNI_GetCreatedJavaVMs(vmBuf: *mut *mut JavaVM, bufLen: jsize, nVMs: *mut jsize) -> jint; 1408 | } 1409 | -------------------------------------------------------------------------------- /systest/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "systest" 3 | version = "0.2.0" 4 | authors = ["Steven Fackler "] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | jni-sys = { path = ".." } 9 | libc = "0.2" 10 | 11 | [build-dependencies] 12 | ctest2 = "0.4" 13 | 14 | [features] 15 | jni19 = [] 16 | jni20 = [] 17 | jni21 = [] -------------------------------------------------------------------------------- /systest/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::path::PathBuf; 3 | 4 | fn main() { 5 | let java_home = PathBuf::from(env::var_os("JAVA_HOME").unwrap()); 6 | let target = env::var("TARGET").unwrap(); 7 | let windows = target.contains("windows"); 8 | 9 | let (platform_dir, lib_dir) = if target.contains("linux") { 10 | ("linux", "jre/lib/amd64/server") 11 | } else if target.contains("windows") { 12 | ("win32", "lib") 13 | } else if target.contains("darwin") { 14 | ("darwin", "jre/lib/server") 15 | } else { 16 | panic!("unsupported target"); 17 | }; 18 | 19 | println!( 20 | "cargo:rustc-link-search=native={}", 21 | java_home.join(lib_dir).display() 22 | ); 23 | println!("cargo:rustc-link-lib=dylib=jvm"); 24 | 25 | // Increase the stack size on Windows otherwise the tests just overflow 26 | // the stack. 27 | if env::var("CARGO_CFG_TARGET_ENV").unwrap() == "msvc" { 28 | println!("cargo:rustc-link-arg=/stack:{}", 8 * 1024 * 1024); 29 | } 30 | 31 | let mut cfg = ctest2::TestGenerator::new(); 32 | 33 | let include_dir = java_home.join("include"); 34 | cfg.include(&include_dir) 35 | .include(include_dir.join(platform_dir)); 36 | 37 | cfg.skip_const(|s| { 38 | (!cfg!(feature = "jni19") && s == "JNI_VERSION_19") 39 | || (!cfg!(feature = "jni20") && s == "JNI_VERSION_20") 40 | || (!cfg!(feature = "jni21") && s == "JNI_VERSION_21") 41 | }); 42 | cfg.skip_type(|s| s == "va_list"); 43 | cfg.skip_field(|s, field| { 44 | (s == "jvalue" && field == "_data") 45 | || s == "JNINativeInterface_" 46 | || s == "JNIInvokeInterface_" // ctest2 isn't able to test these unions 47 | }); 48 | cfg.type_name(|s, is_struct, _is_union| { 49 | if is_struct && s.ends_with('_') { 50 | format!("struct {}", s) 51 | } else { 52 | s.to_string() 53 | } 54 | }); 55 | cfg.skip_signededness(|s| { 56 | matches!( 57 | s, 58 | "jfloat" 59 | | "jdouble" 60 | | "jobject" 61 | | "jclass" 62 | | "jstring" 63 | | "jarray" 64 | | "jbooleanArray" 65 | | "jbyteArray" 66 | | "jcharArray" 67 | | "jshortArray" 68 | | "jintArray" 69 | | "jlongArray" 70 | | "jfloatArray" 71 | | "jdoubleArray" 72 | | "jobjectArray" 73 | | "jweak" 74 | | "jthrowable" 75 | | "jfieldID" 76 | | "jmethodID" 77 | | "JNIEnv" 78 | | "JavaVM" 79 | ) 80 | }); 81 | cfg.skip_fn_ptrcheck(move |_name| { 82 | // dllimport weirdness? 83 | windows 84 | }); 85 | cfg.skip_roundtrip(|s| { 86 | s == "jboolean" || // We don't need to be able to roundtrip all possible u8 values for a jboolean, since only 0 are 1 are considered valid. 87 | s == "JNINativeInterface_" || s == "JNIInvokeInterface_" // ctest2 isn't able to test these unions 88 | }); 89 | cfg.header("jni.h").generate("../src/lib.rs", "all.rs"); 90 | } 91 | -------------------------------------------------------------------------------- /systest/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(bad_style, improper_ctypes)] 2 | #![allow(clippy::all)] 3 | 4 | extern crate jni_sys; 5 | extern crate libc; 6 | 7 | use jni_sys::*; 8 | 9 | include!(concat!(env!("OUT_DIR"), "/all.rs")); 10 | -------------------------------------------------------------------------------- /tests/jni-to-union.rs: -------------------------------------------------------------------------------- 1 | use jni_sys::{jint, JNIEnv, JNINativeInterface_}; 2 | use jni_sys_macros::jni_to_union; 3 | use std::os::raw::c_void; 4 | 5 | #[test] 6 | fn jni_to_union_trybuilds() { 7 | let t = trybuild::TestCases::new(); 8 | t.pass("tests/trybuild/01-jni-to-union-basic-pass.rs"); 9 | t.compile_fail("tests/trybuild/01-jni-fail-reserved-read.rs"); 10 | t.compile_fail("tests/trybuild/01-jni-fail-read-1-2-from-1-1.rs"); 11 | } 12 | 13 | #[test] 14 | fn jni_to_union() { 15 | #[repr(C)] 16 | #[jni_to_union] 17 | pub struct MyStruct { 18 | #[jni_added("reserved")] 19 | pub reserved0: *mut c_void, 20 | 21 | #[jni_added("1.1")] 22 | pub GetVersion: unsafe extern "system" fn(env: *mut JNIEnv) -> jint, 23 | 24 | #[jni_added("1.2")] 25 | pub FunctionA: unsafe extern "system" fn(env: *mut JNIEnv) -> jint, 26 | 27 | pub FunctionB: unsafe extern "system" fn(env: *mut JNIEnv) -> jint, 28 | 29 | #[jni_added("1.3")] 30 | pub FunctionC: unsafe extern "system" fn(env: *mut JNIEnv) -> jint, 31 | } 32 | 33 | assert_eq!( 34 | std::mem::size_of::(), 35 | std::mem::size_of::<*mut c_void>() * 5 36 | ); 37 | assert_eq!( 38 | std::mem::size_of::(), 39 | std::mem::size_of::<*mut c_void>() * 4 40 | ); 41 | } 42 | 43 | const NUM_JNI_ENV_MEMBERS: usize = 235; 44 | #[test] 45 | fn jni_env_union() { 46 | assert_eq!( 47 | std::mem::size_of::(), 48 | std::mem::size_of::<*mut c_void>() * NUM_JNI_ENV_MEMBERS 49 | ); 50 | } 51 | -------------------------------------------------------------------------------- /tests/trybuild/01-jni-fail-read-1-2-from-1-1.rs: -------------------------------------------------------------------------------- 1 | 2 | use jni_sys::JNINativeInterface_; 3 | 4 | pub fn main() { 5 | unsafe { 6 | let jni = std::mem::zeroed::(); 7 | let _1_2_function = jni.v1_1.FromReflectedMethod; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/trybuild/01-jni-fail-read-1-2-from-1-1.stderr: -------------------------------------------------------------------------------- 1 | error[E0609]: no field `FromReflectedMethod` on type `JNINativeInterface__1_1` 2 | --> tests/trybuild/01-jni-fail-read-1-2-from-1-1.rs:7:38 3 | | 4 | 7 | let _1_2_function = jni.v1_1.FromReflectedMethod; 5 | | ^^^^^^^^^^^^^^^^^^^ unknown field 6 | | 7 | = note: available fields are: `GetVersion`, `DefineClass`, `FindClass`, `GetSuperclass`, `IsAssignableFrom` ... and 203 others 8 | -------------------------------------------------------------------------------- /tests/trybuild/01-jni-fail-reserved-read.rs: -------------------------------------------------------------------------------- 1 | 2 | use jni_sys::JNINativeInterface_; 3 | 4 | pub fn main() { 5 | unsafe { 6 | let jni = std::mem::zeroed::(); 7 | let _reserved = jni.v1_1.reserved0; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/trybuild/01-jni-fail-reserved-read.stderr: -------------------------------------------------------------------------------- 1 | error[E0609]: no field `reserved0` on type `JNINativeInterface__1_1` 2 | --> tests/trybuild/01-jni-fail-reserved-read.rs:7:34 3 | | 4 | 7 | let _reserved = jni.v1_1.reserved0; 5 | | ^^^^^^^^^ unknown field 6 | | 7 | = note: available fields are: `GetVersion`, `DefineClass`, `FindClass`, `GetSuperclass`, `IsAssignableFrom` ... and 203 others 8 | -------------------------------------------------------------------------------- /tests/trybuild/01-jni-to-union-basic-pass.rs: -------------------------------------------------------------------------------- 1 | use jni_sys::{jint, JNIEnv}; 2 | use jni_sys_macros::jni_to_union; 3 | use std::os::raw::c_void; 4 | 5 | #[jni_to_union] 6 | pub struct MyStruct { 7 | #[jni_added("reserved")] 8 | pub reserved0: *mut c_void, 9 | 10 | #[jni_added("1.1")] 11 | pub GetVersion: unsafe extern "system" fn(env: *mut JNIEnv) -> jint, 12 | 13 | pub FunctionA: unsafe extern "system" fn(env: *mut JNIEnv) -> jint, 14 | 15 | #[jni_added("1.2")] 16 | pub FunctionB: unsafe extern "system" fn(env: *mut JNIEnv) -> jint, 17 | } 18 | 19 | pub fn main() { 20 | assert_eq!(std::mem::size_of::(), std::mem::size_of::<*mut c_void>() * 4); 21 | } 22 | --------------------------------------------------------------------------------