java中如何使用JNI調用C++寫的函數

來源:互聯網
上載者:User

JAVA以其跨平台的特性深受人們喜愛,而又正由於它的跨平台的目的,使得它和本地機器的各種內部聯絡變得很少,約束了它的功能。解決JAVA對本地操作的一種方法就是JNI。  
   
  JAVA通過JNI調用本地方法,而本地方法是以庫檔案的形式存放的(在WINDOWS平台上是DLL檔案形式,在UNIX機器上是SO檔案形式)。通過調用本地的庫檔案的內部方法,使JAVA可以實現和本地機器的緊密聯絡,調用系統級的各介面方法。  
   
  簡單介紹及應用如下:  
   
  一、JAVA中所需要做的工作  
   
  在JAVA程式中,首先需要在類中聲明所調用的庫名稱,如下:  
   
  static   {  
   
  System.loadLibrary(“testdll”);  
   
  }  
   
  在這裡,庫的副檔名字可以不用寫出來,究竟是DLL還是SO,由系統自己判斷。  
   
  還需要對將要調用的方法做本地聲明,關鍵字為native。並且只需要聲明,而不需要具體實現。如下:  
   
  public   native   static   void   set(int   i);  
   
  public   native   static   int   get();  
   
  然後編譯該JAVA程式檔案,產生CLASS,再用JAVAH命令,JNI就會產生C/C++的標頭檔。  
   
   
   
  例如程式testdll.java,內容為:  
   
  public   class   testdll  
   
  {  
   
  static  
   
  {  
   
  System.loadLibrary("testdll");  
   
  }  
   
   
   
  public   native   static   int   get();  
   
  public   native   static   void   set(int   i);  
   
   
   
  public   static   void   main(String[]   args)  
   
  {  
   
  testdll   test   =   new   testdll();  
   
  test.set(10);  
   
  System.out.println(test.get());  
   
  }  
   
  }  
   
  用javac   testdll.java編譯它,會產生testdll.class。  
   
  再用javah   testdll,則會在目前的目錄下產生testdll.h檔案,這個檔案需要被C/C++程式調用來產生所需的庫檔案。  
   
   
   
  二、C/C++中所需要做的工作  
   
  對於已產生的.h標頭檔,C/C++所需要做的,就是把它的各個方法具體的實現。然後編譯串連成庫檔案即可。再把庫檔案拷貝到JAVA程式的路徑下面,就可以用JAVA調用C/C++所實現的功能了。  
   
   
   
  接上例子。我們先看一下testdll.h檔案的內容:  
   
  /*   DO   NOT   EDIT   THIS   FILE   -   it   is   machine   generated   */  
   
  #include    
   
  /*   Header   for   class   testdll   */  
   
   
   
  #ifndef   _Included_testdll  
   
  #define   _Included_testdll  
   
  #ifdef   __cplusplus  
   
  extern   "C"   {  
   
  #endif  
   
  /*  
   
  *   Class:   testdll  
   
  *   Method:   get  
   
  *   Signature:   ()I  
   
  */  
   
  JNIEXPORT   jint   JNICALL   Java_testdll_get  
   
  (JNIEnv   *,   jclass);  
   
   
   
  /*  
   
  *   Class:   testdll  
   
  *   Method:   set  
   
  *   Signature:   (I)V  
   
  */  
   
  JNIEXPORT   void   JNICALL   Java_testdll_set  
   
  (JNIEnv   *,   jclass,   jint);  
   
   
   
  #ifdef   __cplusplus  
   
  }  
   
  #endif  
   
  #endif  
   
  在具體實現的時候,我們只關心兩個函數原型  
   
  JNIEXPORT   jint   JNICALL   Java_testdll_get   (JNIEnv   *,   jclass);  
   
  和  
   
  JNIEXPORT   void   JNICALL   Java_testdll_set   (JNIEnv   *,   jclass,   jint);  
   
  這裡JNIEXPORT和JNICALL都是JNI的關鍵字,表示此函數是要被JNI調用的。而jint是以JNI為中介使JAVA的int類型與本地的int溝通的一種類型,我們可以視而不見,就當做int使用。函數的名稱是JAVA_再加上java程式的package路徑再加函數名組成的。參數中,我們也只需要關心在JAVA程式中存在的參數,至於JNIEnv*和jclass我們一般沒有必要去碰它。  
   
  好,下面我們用testdll.cpp檔案具體實現這兩個函數:  
   
  #include   "testdll.h"  
   
  int   i   =   0;  
   
  JNIEXPORT   jint   JNICALL   Java_testdll_get   (JNIEnv   *,   jclass)  
   
  {  
   
  return   i;  
   
  }  
   
  JNIEXPORT   void   JNICALL   Java_testdll_set   (JNIEnv   *,   jclass,   jint   j)  
   
  {  
   
  i   =   j;  
   
  }  
  編譯串連成庫檔案,本例是在WINDOWS下做的,產生的是DLL檔案。並且名稱要與JAVA中需要調用的一致,這裡就是testdll.dll   
        對於在VC6.0中,可以開啟VC++6.0,建立->; 工程 ->; win32 Dynamic-Link Library .在嚮導中選擇空工程。
       把剛才javah產生的那個標頭檔加入工程 .然後 檔案->;建立->;textFile 自己做一個
.cpp檔案.實現自己的native函數.

       對於在visual stdio 2005中,可以建立一個WIN32的空項目,下一步中選擇DLL和空項目。然後把上面的testdll.h和testdll.cpp加進去,編譯就可以產生testdll.dll檔案

      通常情況下,VC的編譯器會找不到jni.h和jni_md.h標頭檔,這兩個標頭檔可以在JDK目錄下的include下找到。vc6.0也有可能找不到cl.exe這個編譯器,可以上網下載後再設定環境變數就可以了。通常這個編譯器會在VC目錄下的vc/bin目錄下可以找到的。
  把testdll.dll拷貝到testdll.class的目錄下,java   testdll運行它,就可以觀察到結果了 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.