{"id":21736116,"url":"https://github.com/hexedtech/jni-toolbox","last_synced_at":"2025-04-13T01:53:44.503Z","repository":{"id":257789568,"uuid":"860934051","full_name":"hexedtech/jni-toolbox","owner":"hexedtech","description":"easily write JNI extern functions with native Rust types","archived":false,"fork":false,"pushed_at":"2024-10-12T20:28:04.000Z","size":101,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"dev","last_synced_at":"2025-04-13T01:52:55.720Z","etag":null,"topics":["ffi","java","jni","proc-macro","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hexedtech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-21T14:58:02.000Z","updated_at":"2025-03-21T00:52:05.000Z","dependencies_parsed_at":"2024-09-21T16:18:57.155Z","dependency_job_id":"b35de4f7-d2cf-45ef-b7ef-3b29e7e0ec8d","html_url":"https://github.com/hexedtech/jni-toolbox","commit_stats":null,"previous_names":["hexedtech/jni-toolbox","hexedtech/jni-macro"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexedtech%2Fjni-toolbox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexedtech%2Fjni-toolbox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexedtech%2Fjni-toolbox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hexedtech%2Fjni-toolbox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hexedtech","download_url":"https://codeload.github.com/hexedtech/jni-toolbox/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248654052,"owners_count":21140235,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ffi","java","jni","proc-macro","rust"],"created_at":"2024-11-26T05:17:00.695Z","updated_at":"2025-04-13T01:53:44.455Z","avatar_url":"https://github.com/hexedtech.png","language":"Rust","readme":"# jni-toolbox\n[![Actions Status](https://github.com/hexedtech/jni-toolbox/actions/workflows/test.yml/badge.svg)](https://github.com/hexedtech/jni-toolbox/actions)\n[![Crates.io Version](https://img.shields.io/crates/v/jni-toolbox)](https://crates.io/crates/jni-toolbox)\n[![docs.rs](https://img.shields.io/docsrs/jni-toolbox)](https://docs.rs/jni-toolbox)\n\nThis is a simple crate built around [jni-rs](https://github.com/jni-rs/jni-rs) to automatically generate JNI-compatible extern functions.\n\nIt also wraps functions returning `Result\u003c\u003e`, making short-circuiting easy.\n\n## Usage\nJust specify package and class on your function, and done!\n\n```rust\n#[jni_toolbox::jni(package = \"your.package.path\", class = \"ContainerClass\")]\nfn your_function_name(arg: String) -\u003e Result\u003cVec\u003cString\u003e, String\u003e {\n  Ok(arg.split('/').map(|x| x.to_string()).collect())\n}\n```\n\n### Conversions\nEvery type that is meant to be sent to Java must implement `IntoJavaObject` (or, unlikely, `IntoJavaPrimitive`); every type that is meant to be\nreceived from Java must implement `FromJava`. Most primitives and a few common types should already be implemented.\n\n```rust\nimpl\u003c'j\u003e IntoJavaObject for MyClass {\n  type T = jni::objects::JObject\u003c'j\u003e\n  fn into_java(self, env: \u0026mut jni::JNIEnv\u003c'j\u003e) -\u003e Result\u003cSelf::T, jni::errors::Error\u003e {\n    let hello = env.new_string(\"world\")?;\n    // TODO!!\n  }\n}\n```\n\n### Pointers\nNote that, while it is possible to pass raw pointers to the JVM, it is not safe by default and must be done with extreme care.\n\n### Exceptions\nErrors are thrown automatically when a `Result` is an error. For your errors to work, you must implement the `JniToolboxError` trait for your errors,\n(which just returns the path to your Java error class) and then make a Java error wrapper which can be constructed with a single string argument.\n\nFunctions returning `Result`s will automatically have their return value unwrapped and, if is an err, throw an exception and return early.\n\n```rust\nimpl JniToolboxError for MyError {\n  fn jclass(\u0026self) -\u003e String {\n    \"my/package/some/MyError\".to_string()\n  }\n}\n```\n\n```java\npackage my.package.some;\npublic class MyError extends Throwable {\n  public MyError(String x) {\n    // TODO\n  }\n}\n```\n\nTo throw simple exceptions, it's possible to use the `exception` attribute. Pass the exception's fully qualified name (must have a constructor\nthat takes in a single `String` argument).\n\n### Examples\nThe following function:\n```rust\n#[jni(package = \"mp.code\", class = \"Client\", ptr)]\nfn connect(config: Config) -\u003e Result\u003cClient, ConnectionError\u003e {\n  super::tokio().block_on(Client::connect(config))\n}\n```\n\ngenerates a matching expanded function invoking it:\n\n```rust\nfn connect(config: Config) -\u003e Result\u003cClient, ConnectionError\u003e {\n  super::tokio().block_on(Client::connect(config))\n}\n\n#[no_mangle]\n#[allow(unused_unit)]\npub extern \"system\" fn Java_mp_code_Client_connect\u003c'local\u003e(\n  mut env: jni::JNIEnv\u003c'local\u003e,\n  _class: jni::objects::JClass\u003c'local\u003e,\n  config: \u003cConfig as jni_toolbox::FromJava\u003c'local\u003e\u003e::From,\n) -\u003e \u003cClient as jni_toolbox::IntoJava\u003c'local\u003e\u003e::Ret {\n  use jni_toolbox::{FromJava, IntoJava, JniToolboxError};\n  let config_new = match jni_toolbox::from_java_static::\u003cConfig\u003e(\u0026mut env, config) {\n    Ok(x) =\u003e x,\n    Err(e) =\u003e {\n      let _ = env.throw_new(e.jclass(), format!(\"{e:?}\"));\n      return std::ptr::null_mut();\n    }\n  };\n  let result = connect(config_new);\n  let ret = match result {\n    Ok(x) =\u003e x,\n    Err(e) =\u003e match env.find_class(e.jclass()) {\n      Err(e) =\u003e panic!(\"error throwing Java exception -- failed resolving error class: {e}\"),\n      Ok(class) =\u003e match env.new_string(format!(\"{e:?}\")) {\n        Err(e) =\u003e panic!(\"error throwing Java exception --  failed creating error string: {e}\"),\n        Ok(msg) =\u003e match env.new_object(class, \"(Ljava/lang/String;)V\", \u0026[jni::objects::JValueGen::Object(\u0026msg)]) {\n          Err(e) =\u003e panic!(\"error throwing Java exception -- failed creating object: {e}\"));\n          Ok(obj) =\u003e match env.throw(jni::objects::JThrowable::from(obj)) {\n            Err(e) =\u003e panic!(\"error throwing Java exception -- failed throwing: {e}\"),\n            Ok(_) =\u003e return std::ptr::null_mut(),\n          },\n        },\n      },\n    },\n  };\n  match ret.into_java(\u0026mut env) {\n    Ok(fin) =\u003e fin,\n    Err(e) =\u003e {\n      let _ = env.throw_new(e.jclass(), format!(\"{e:?}\"));\n      std::ptr::null_mut()\n    }\n  }\n}\n```\n\n## Status\nThis crate is early and intended mostly to maintain [`codemp`](https://github.com/hexedtech/codemp)'s Java bindings, so things not used\nthere may be missing or slightly broken. However, the crate is also quite small and only runs at compile time, so trying it out in your\nown project should not be a problem.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhexedtech%2Fjni-toolbox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhexedtech%2Fjni-toolbox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhexedtech%2Fjni-toolbox/lists"}