你是否想過在Java程式中使用C或C 的功能?你是否知道JNI是什麼,以及它如何讓你在Linux下實現跨語言程式設計?如果你對這些問題有興趣,那麼本文就是為你準備的。本文將介紹JNI的基本概念,以及如何在Linux下使用JNI呼叫C/C 程式碼的步驟和範例。
public class Hello { static { try { // 此处即为本地方法所在链接库名 System.loadLibrary("hello"); } catch(UnsatisfiedLinkError e) { System.err.println( "Cannot load hello library:\n " + e.toString() ); } } public Hello() { } // 声明的本地方法 public native void SayHello(String strName); }
這裡有兩個注意事項:
首先:為要使用的每個本機方法編寫本機方法聲明,只是必須指定 native 關鍵字,如下所示:
public native void SayHello(String strName);
其次:必須明確地載入本機程式碼庫。我們需在類別的靜態區塊中載入這個函式庫(靜態函式庫在類別載入時候就會呼叫)
現在我們來編輯hello.java以產生hello.class檔。
#要為上述定義的類別產生 Java 本機介面頭文件,需使用 javah,Java 編譯器的 javah 功能將根據 Hello 類別產生必要的聲明,此命令將產生 Hello.h 檔案
產生的 Hello.h 檔案 內容如下所示:
#include /* Header for class Hello */ #ifndef _Included_Hello #define _Included_Hello #ifdef __cplusplus extern "C" { #endif /* * Class: Hello * Method: SayHello * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_Hello_SayHello (JNIEnv *, jobject, jstring); #ifdef __cplusplus } #endif #endif
內容如下:
#include "Hello.h" #include // 与 Hello.h 中函数声明相同 JNIEXPORT void JNICALL Java_Hello_SayHello (JNIEnv * env, jobject arg, jstring instring) { // 从 instring 字符串取得指向字符串 UTF 编码的指针 const jbyte *str = (const jbyte *)env->GetStringUTFChars( instring, JNI_FALSE ); printf("Hello,%s\n",str); // 通知虚拟机本地代码不再需要通过 str 访问 Java 字符串。 env->ReleaseStringUTFChars( instring, (const char *)str ); return; }
這裡有三個參數,下面要講一下參數用法:
(1)所有的 JNI 呼叫都使用了 JNIEnv * 類型的指針,習慣上在 CPP 檔案中將這個變數定義為 evn,它是任意一個本地方法的第一個參數。 env 指標指向一個函數指標表,在 VC 中可以直接用”->”操作符存取其中的函數。
(2)jobject 指向在此 Java 程式碼中實例化的 Java 物件 LocalFunction 的一個句柄,相當於 this 指標。
(3)第三個參數就是本地呼叫中有 Java 程式傳進的參數,本例只有一個 String 型參數。對於字串型參數,因為在本機程式碼中無法直接讀取 Java 字串,而必須將其轉換為 C /C 字串或 Unicode。
#使用 GCC 時 , 必須通知編譯器在何處查找此 Java 本地方法的支援文件,並且明確通知編譯器生成位置無關的程式碼,在我的環境中按如下程序編譯:
gcc -I/home/jbuilder/jdk1.3.1/include -I/home/jbuilder/jdk1.3.1/include/linux -fPIC -c Hello.c
產生 Hello.o
gcc -shared -Wl,-soname,libhello.so -o libhello.so Hello.o
產生 libhello.so(這就是linux下動態連結函式庫的檔名格式,就像windows下是.dll檔後綴名類似)
最後通知動態連結程式此共用檔案的路徑。
export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH
#將以下原始碼存為 A.java:
import Hello; import java.util.*; public class A { public static void main(String argv[]) { A a = new A(); } public A() { Hello h = new Hello(); // 调用本地方法 h.SayHello("Hello world"); } }
用 javac 編譯A.java,產生A.class
向執行普通 Java 程式一樣使用 java A,我們會看到在螢幕上出現 Hello world。
透過本文,你應該對JNI有了一個初步的了解,以及如何在Linux下使用JNI呼叫C/C 程式碼的方法。 JNI是一個強大且靈活的工具,它可以讓你在Java程式中利用C/C 的優勢,或是在C/C 程式中利用Java的優勢。當然,JNI也有一些缺點,例如效能損耗,記憶體洩漏,錯誤處理等。因此,在使用JNI時,你需要注意一些細節和規範,以確保程式碼的正確性和安全性。希望這篇文章能對你有所幫助,如果你有任何疑問或建議,請在評論區留言。
以上是如何在Linux下使用JNI呼叫C/C++程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!