首頁  >  文章  >  系統教程  >  如何在Linux下使用JNI呼叫C/C++程式碼

如何在Linux下使用JNI呼叫C/C++程式碼

PHPz
PHPz轉載
2024-02-13 15:30:041018瀏覽

你是否想過在Java程式中使用C或C 的功能?你是否知道JNI是什麼,以及它如何讓你在Linux下實現跨語言程式設計?如果你對這些問題有興趣,那麼本文就是為你準備的。本文將介紹JNI的基本概念,以及如何在Linux下使用JNI呼叫C/C 程式碼的步驟和範例。

如何在Linux下使用JNI呼叫C/C++程式碼

#定義一個 Java 類別 — Hello類別

 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

在與 Hello.h 相同的路徑下建立一個 CPP 檔案 Hello.cpp

內容如下:

#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

寫一個簡單的 Java 程式來測試我們的本機方法

#將以下原始碼存為 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中文網其他相關文章!

陳述:
本文轉載於:lxlinux.net。如有侵權,請聯絡admin@php.cn刪除