Coder Social home page Coder Social logo

Comments (4)

paxbun avatar paxbun commented on June 9, 2024

BTW, I'm using JNA and JNI in the same dynamic library; at first, I modified the template so System.loadLibrary is invoked right after Native.loadLibrary is called, but later, I kept the template as original and directly accessed to JNI_GetCreatedJavaVMs to get the current process's JavaVM.

from uniffi-rs.

coolbluewater avatar coolbluewater commented on June 9, 2024

Hi @paxbun, I also would like to pass JNI objects from Kotlin to Rust.
Do you have a fork of uniffi that implements this?

from uniffi-rs.

paxbun avatar paxbun commented on June 9, 2024

@coolbluewater No, I didn't have any time to work on this... If you want features like this but have to pass few objects, you can just System.loadLibrary the same library and pass the JNI objects. I have an example for you: https://github.com/paxbun/GraphicsTest/blob/6ab7e5d8cdc2864653d91f6d7fa77924c27815d5/rust/src/lib.rs#L16-L39

This example passes android.view.Surface via JNI and UIView via a C function, and does the other things using UniFFI. Feel free to ask me about the example :)

Note that this example also uses the KMM UniFFI bindgen mentioned in my first comment, so you have to build the plugin manually, which is not merged to main yet. Clone the branch of the following PR: https://gitlab.com/trixnity/uniffi-kotlin-multiplatform-bindings/-/merge_requests/39 You can build it with ./gradlew :build-logic:gradle-plugin:publishToMavenLocal.

This plugin configures almost every environment variable you'd need, but I haven't tested it on Windows or Linux. Please let me know if you have any trouble building that plugin or the example!

I'm going to make a POC of this at least by July.

from uniffi-rs.

paxbun avatar paxbun commented on June 9, 2024

I've been continuously investigating safer API design for this, but the existence of JNIEnv always brings me to something ugly or unsafe, which is thread-local but always required for practical use. This is the least ugly design I've come up with:

We need to put JNIEnv into a polymorphic object, which returns the underlying JNIEnv when called from a JVM and does nothing when called from other environments, such as Swift or Python. Since JNA does not support putting JNIEnv in a structure and modifying JNA to support it also does not make sense in the Java world, if we need to do this, the polymorphic object creation must be done on the Rust side, specifically in the scaffold.

For example, if a UniFFI function has a PlatformObject parameter, the scaffold for that function may look like this:

#[uniffi::export]
fn foo<'a>(env: uniffi::Env<'a>, platform_object: uniffi::PlatformObject) { ... }

pub unsafe extern "C" fn uniffi_my_package_fn_foo(
  env_identifier: u128,
  env: *const ::std::ffi::c_void,
  platform_object: *const ::std::ffi::c_void,
  call_status: &mut ::uniffi::RustCallStatus,
) {
  uniffi::rust_call(
    call_status,
    || {
      let env = uniffi::Env::new_unchecked(env_identifier, env);
      let platform_object = uniffi::PlatformObject::new_unchecked(platform_object);
      my_package::foo(env, platform_object);
    },
  );
}

and the Kotlin binding can call this function like uniffi_my_package_fn_foo(UNIFFI_IDENTIFIER_JAVA, JNIEnv.current, platformObject) and the others like uniffi_my_package_fn_foo(OTHER_IDENTIFIER, nullptr, platformObject).

Since env now has the identifier, functions like is_objc or is_java are all in uniffi::Env, not uniffi::PlatformObject.

#[uniffi::export]
fn foo<'a>(env: uniffi::Env<'a>, platform_object: uniffi::PlatformObject) {
  if env.is_java() {
    let platform_object = platform_object.into_inner() as jni_sys::object;
    ...
  }
}

But as you can see, this design forces the user to add an additional parameter when using a specific type of parameter, a new constraint that has never been in previous versions.

from uniffi-rs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.