1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use jni_sys::{JavaVM, JNIEnv};
use std::ptr;
use std::os::raw::c_void;

// =================================================================================================

/// A native thread's attachment to an embedded JVM.
/// There should be only exactly one `JvmAttachment` instance at the same time.
/// The thread is automatically detached when `JvmAttachment` goes out of scope (RAII).
pub struct JvmAttachment {

    /// The JNI environment.
    jni_environment: *mut JNIEnv,

    /// The JVM.
    jvm: *mut JavaVM,
}


impl JvmAttachment {

    ///
    pub fn new(jvm: *mut JavaVM) -> JvmAttachment {

        // Initialize the data.
        let mut jvm_attachment = JvmAttachment {
            jni_environment: ptr::null_mut(),
            jvm: jvm,
        };

        unsafe {
            // Try to attach the current native thread to an embedded JVM.
            let _ = (**jvm).AttachCurrentThread.unwrap()(
                jvm,
                (&mut jvm_attachment.jni_environment as *mut *mut JNIEnv) as *mut *mut c_void,
                ptr::null_mut(),
            );
        }

        // TODO: interpret the result

        jvm_attachment
    }

    ///
    pub fn jni_environment(&self) -> *mut JNIEnv {
        self.jni_environment
    }
}

// =================================================================================================

impl Drop for JvmAttachment {

    fn drop(&mut self) {

        unsafe {
            // Try to detach the current native thread from the embedded JVM.
            let _ = (**self.jvm).DetachCurrentThread.unwrap()(
                self.jvm,
            );

            // TODO: interpret the result
        }
    }
}

// =================================================================================================