2016年7月4日 星期一

Java 透過 jni 聯結 c 動態程式庫

Java 可以呼叫由 c 寫成的原生副程式(.so). 載入的動態模組(.so)要放在 static 括弧內, 它只會載入一次,而要呼叫的副程式用關鍵字 static native  來宣告, 底下是在 linux 下編寫的程式:

         // callc.java
        class hello {
         private static native void nativeCall( ); //declare native  c function
           static {            System.loadLibrary("hello");   } // load  libhello.so
               public static void main(String[ ] args) {  //  main
      nativeCall( );     //  call native c function
             }
         }

使用 javac 編譯 JAVA 程式:

          javac callc.java

會產生 hello.class, 再用 javah 產生標頭檔

          javah hello

會產生 hello.h, 接著根據標頭檔的內容, 在程式宣告的地方, 將它複製過來, 再修改一下, 編寫 c 程式,並引入剛剛產生的標頭檔 hello.h:

              // native.c
             #include "hello.h"
             JNIEXPORT void JNICALL Java_hello_nativeCall  (JNIEnv *env, jclass jc) {
                 printf("Hello c\n");
             }

編譯 c 程式成動態程式庫, 並指定名稱(libhello.so), 將它放置到目前程式所在的目錄底下, JAVA 的標頭檔預(jni.h 及 jni_md.h)分別放在 $JAVA_HOME/include及$JAVA_HOME/include/linux底下, gcc 可以用 -I 指示讓它去找到, -shared 是產生動態程式庫, 另外還必須加上 -fPIC 指示:

     gcc -shared native.c -o libhello.so -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -fPIC

最後用 JVM 來執行程式 JAVA 程式, 須指定好 -Djava.library.path= 目錄, 讓 JVM 可以連結到該程式庫:

     java -Djava.library.path=./ hello


沒有留言: