Rust JNIの原理

4658 ワード

1、Rust FFI
Rust言語自体はC言語インターフェースを提供し、ffiの形で直接Cライブラリの関数を呼び出すことができます。文法はこうです。
#[link(so/filename)]
extern "C" {
    fn foo() -> return_type;
}

#[repr(return_type)]
return type definition
JNIはJDKがJavaとC/C++の間で相互に呼び出すために提供しているもので、関数は全部libjvm.soに定義されています。Linuxシステムなら、実行します。
locate libjvm.so
このライブラリが見つかります。
2、Java Native Interface
JNIフルネームJava Native Interfaceは、JavaとC/C++の間の通信の仕組みを実現し、JavaからC/C++にアクセスでき、C/C++からJavaにアクセスすることもできます。
  • Javaは、C/C++にアクセスし、Javaでは、nativeキー宣言方法を通じて、外部C/C++ファイルによって実現される。jvmは外部ライブラリをロードして対応する方法を見つけます。Java宣言が完了した後、javacを通じてヘッダファイルが生成され、JDK 10以前のバージョンであれば、javahを通じてヘッダファイルが生成され、
  • javac foo.java -h <header_dir>
    関連するフィーチャーの更新記録はhttp://openjdk.java.net/projects/jdk/10/において、そのうち313条Remove the Native-Header Generation Tool (javah)Hello World Example
    Javaコード
    class HelloWorld {
        private native void print();
        public static void main(String[] args) {
            new HelloWorld().print();
        }
        static {
            System.loadLibrary("hello");
        }
    }
    C言語コード
    #include 
    #include 
    #include "HelloWorld.h"
    
    JNIEXPORT void JNICALL
    Java_HelloWorld_print(JNIEnv *env, jobject obj)
    {
        printf("Hello World
    "
    ); }
    Makefile
    .PHONY: all clean tar
    
    INC_DIR =
    INC_DIR += -I/usr/lib/jvm/java-10-oracle/include/
    INC_DIR += -I/usr/lib/jvm/java-10-oracle/include/linux
    
    all: libhello.so
    
    libhello.so: HelloWorld.o
        gcc -shared -o $@ $<
    
    %.o : %.c
        gcc $(INC_DIR) -c -fPIC $<
    
    clean:
        @rm -rf libhello.so *.o
    
    tar:
  • C/C++Javaにアクセスすると、上のexampleから2つのパラメータがあります。このJNIEnvとjobjectはJavaの定義に対応する方法とメンバーのすべての情報を含んでいます。libjvm.soでJNI_を提供しました。CreateJavaVM関数はJNIEncvを初期化するために使われています。プロトタイプJNI_CreateJavaVM(JNIInvokeInterface **, JNINativeInterface **, JavaVMInitArgs *)はJNIEnvを通じてJava中の方法とメンバーにアクセスできます。
  • 三、Rust JNI倉庫
    git clone https://github.com/benanders/rjni.git
    cd rjni; cargo build
    カードgo.tomlファイルにexampleを追加します。
    [[example]]
    name = "instance"
    path = "examples/instance.rs"
    
    [[example]]
    name = "field"
    path = "examples/field.rs"
    
    [[example]]
    name = "static"
    path = "examples/static.rs"
    
    [[example]]
    name = "static_field"
    path = "examples/static_field.rs"
    then use examples to test Rust JNI Crate
    export LIBRARY_PATH=/usr/lib/jvm/java-8-oracle/jre/lib/amd64/server/; cargo run --example instance