-
Notifications
You must be signed in to change notification settings - Fork 111
Initial JNI support #116
base: master
Are you sure you want to change the base?
Initial JNI support #116
Conversation
Example code using these JNI bindings can be seen in rust-windowing/glutin#822 |
//} | ||
|
||
#[repr(C)] | ||
pub struct JNINativeInterface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was simply copied from injected-glue/ffi.rs
static JNI_HANDLE : RefCell<JNIEnvHandle> = RefCell::new(JNIEnvHandle { jni_env: ptr::null_mut(), counter: 0 }); | ||
} | ||
|
||
pub fn attach_thread() -> JNIEnv { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Detaching a thread in JNI is immediate, so nested attach/detach pairs are a pain. I've added simple reference counting here, so every call can simply enclose their code in jni::attach_thread()
/jni::detach_thread()
pairs, and only the final call will actually detach the thread.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're providing a high-level interface, I think attach_thread
should return an RAII guard that automatically calls detach_thread
in its Drop
implementation.
/// This static variable will store the android_app* on creation, and set it back to 0 at | ||
/// destruction. | ||
/// Apart from this, the static is never written, so there is no risk of race condition. | ||
#[no_mangle] | ||
pub static mut ANDROID_APP: *mut ffi::android_app = 0 as *mut ffi::android_app; | ||
pub static mut CLASS_LOADER: ffi::jobject = 0 as ffi::jobject; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CLASS_LOADER
and ACTIVITY
need some documentation for what they are.
static JNI_HANDLE : RefCell<JNIEnvHandle> = RefCell::new(JNIEnvHandle { jni_env: ptr::null_mut(), counter: 0 }); | ||
} | ||
|
||
pub fn attach_thread() -> JNIEnv { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're providing a high-level interface, I think attach_thread
should return an RAII guard that automatically calls detach_thread
in its Drop
implementation.
Overall I think this needs some more high-level functions as well. But I'm not sure what the right border should be between the low-level bindings and a high-level wrapper, so this could eventually be done in a later PR. |
Here's a gist @sfackler made demonstrating a high-level API for JNI stuff: https://gist.github.com/sfackler/5c036006f8d58a1d38887ba014759f74 As I said in the previous comment, this might be out of scope of this PR but I thought I'd leave it somewhere for reference. |
Might also be worth depending on https://crates.io/crates/jni-sys to avoid needing to have a second copy in here. Happy to make any changes necessary on that end. |
@tomaka, what is your view on using @sfackler's jni-sys crate? Before I start addressing other feedback, it would be nice to decide if using jni-sys is on the table, and if we should add higher level wrappers to android-rs-glue, jni-sys, or some intermediate crate that wraps raw jni-sys in a nice, safe, Rust-y API. I agree that adding a higher level API (like But I'm also not sure this should be part of android-rs-glue. @sfackler I don't think any explicit changes are required from looking at your code for a brief moment. There are some differences in the JNI implementation of Android, but those mostly (as far as I've read - I'm no expert) relate to how the JNI API is used, not the API itself. |
An alternative approach would be to remove the JNI API from the This would mean that |
In my opinion this is the ideal design:
|
I can agree with that. I'll look into making the adaptations over the weekend, probably. The higher level JNI wrapper will probably take a longer time to complete. @sfackler Are you interested in creating a repo for the higher level wrapper, or should I? |
I probably don't have the time to build out the high level wrapper right now unfortunately, so you might want to get it started. |
Just a note that I have started on reworking this, but haven't found the time to finish it yet (because life). |
So ... what is the current state? The |
Why can't the |
I'm ok with exposing the JNI-related functions of the FFI, as long as they are contained within their own scope and don't require an external crate. |
@tomaka ... why? What's wrong about the |
Sorry, what I mean is that we should simply reexport the content of the jni-sys crate from our own crate, instead of exposing it in the API. |
Feedback welcome!