Jni Native를 통한 Rust 함수 호출
Posted: September 25, 2015 Filed under: Code, FOSS, Tokamak Project | Tags: jni, rust, Tajo Leave a comment회사 허락을 맡아 홀로 프로젝트를 하나 시작했다. 큰 그림은 일부 컴포넌트를 Rust로 구현하고 컴포넌트간 연결은 rpc로 하는 것인데 아직 Rust 로 rpc 구현을 하기에 시간이 더 필요하다. 임시적인 수단으로 JNI를 통해 기존 컴포넌트에 연결을 하려고 한다.
그 외 프로젝트에 자세한 이야기는 나중에 설명하고 위 목적으로 Stackoverflow 에서 참고하고 https://github.com/Monnoroch/RustJni 를 참고해서 JNI를 테스트를 해봤다.
C 바인딩이 쉬운것은 Rust의 장점 중 하나인데 JNI 바인딩 역시 순조로웠다. 방법은 우선 아래와 같이 native 함수 인터페이스를 작성하고
| public class NativeInvoke { | |
| public static native void procedure(); | |
| public static native void stringArg(String str); | |
| public static native String returnString(); | |
| } |
아래와 같이 Rust 코드를 작성하면 된다.
| #![crate_type="dylib"] | |
| #![feature(libc)] | |
| #![allow(non_camel_case_types)] | |
| #![allow(non_snake_case)] | |
| #![allow(unused_variables)] | |
| extern crate libc; | |
| extern crate jni; | |
| use libc::c_void; | |
| use std::ptr; | |
| use jni::native::*; | |
| use jni::helper::*; | |
| #[no_mangle] | |
| pub extern fn Java_org_github_hyunsik_NativeInvoke_procedure(jre: *mut JNIEnv, | |
| class: *const c_void) { | |
| println!("Invoked native method, jre: {:p}, class: {:p}", jre, class); | |
| unsafe { | |
| let v = ((**jre).GetVersion)(jre); | |
| println!(">> version: {:?}", v); | |
| } | |
| } | |
| #[no_mangle] | |
| pub extern fn Java_org_github_hyunsik_NativeInvoke_stringArg(jre: *mut JNIEnv, | |
| class: *const c_void, name: jstring) { | |
| unsafe { | |
| let string = ((**jre).GetStringUTFChars)(jre, name, ptr::null_mut()); | |
| println!("{}", chars_to_str(string)); | |
| ((**jre).ReleaseStringUTFChars)(jre, name, string); | |
| } | |
| } | |
| #[no_mangle] | |
| pub extern fn Java_org_github_hyunsik_NativeInvoke_returnString(jre: *mut JNIEnv, | |
| class: *const c_void) -> jstring { | |
| unsafe { | |
| return str_to_jstring(jre, "jni native"); | |
| } | |
| } |
이게 전부다. 위에서 사용된 chars_to_str와 str_to_jstring 는 아래 github repository에 있다.
https://github.com/hyunsik/jni-rs/blob/master/src/helper.rs
위 repository 는 https://github.com/Monnoroch/RustJni를 fork 해서 JNI 뿐 아니라 JNI 프로그램 작성 중에 반복되는 코드들에 대한 유틸리티 함수들을 추가할 계획이다.
그리고 아래는 JNI Native + Rust 를 위한 템플릿 프로젝트이다.
https://github.com/hyunsik/rust-jni-template