首頁 > 網際網路

Java通過-jni呼叫c語言

2019-12-10 17:08:03

在Ubuntu14.04中通過Java呼叫c語言

1

(1)首先編寫一個簡單的Java程式。public class TestJNI {??????? static{??????????? System.loadLibrary("diaoyong");? //程式在載入時,自動載入libdiaoyong.so庫??????? ????}???????? public native void set(int value);? ????//宣告原生函數。注意要新增native關鍵字?? ?????public native int get();??????? public static void main(String[] args) {?????????? ??TestJ
NI test=new TestJNI();???????????? test.set(1);???????????? System.out.println(test.get());??????? ??????????}} ?????
?????}} ?????

2

(2)用javac編譯TestJNI.java檔案生成TestJNI.class檔案


3

(3)用javah帶-jni引數編譯TestJNI.class檔案生成TestJNI.h檔案。該檔案中定義了c的函數原型。在實現c函數的時候需要。


4

(4)生成的TestJNI.h檔案如下:/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class TestJNI */#ifndef _Included_TestJNI#define _Included_TestJNI#ifdef __cplusplusextern "C" {#endif/*?* Class:???? TestJNI?* Method:??? set?* Signature: (I)V?*/JNIEXPORT void JNICALL Java_TestJNI_set(JNIEnv
*, jobject, jint);/*?* Class:???? TestJNI?* Method:??? get?* Signature: ()I?*/JNIEXPORT jint JNICALL Java_TestJNI_get(JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif?????? 這裡JNIEXPORT和JNICALL都是JNI的關鍵字,表示此函數是要被JNI呼叫的。而jint是以JNI為中介使Java的int型別與原生的int溝通的一種型別,我們可以視而不見,就當做int使用。函數的名稱是Java_再加上Java程式的package路徑再加函數名組成的。引數中, 我們也只需要關心在Java程式中存在的引數,至於JNIEnv*和jclass我們一般沒有必要去碰它。
va_TestJNI_get(JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif?????? 這裡JNIEXPORT和JNICALL都是JNI的關鍵字,表示此函數是要被JNI呼叫的。而jint是以JNI為中介使Java的int型別與原生的int溝通的一種型別,我們可以視而不見,就當做int使用。函數的名稱是Java_再加上Java程式的package路徑再加函數名組成的。引數中, 我們也只需要關心在Java程式中存在的引數,至於JNIEnv*和jclass我們一般沒有必要去碰它。

5

(5)編寫c語言去實現這些方法,一個簡單的程式碼如下:??????? #include <stdio.h>???????? #include "TestJNI.h"???????? int i=0;???????? JNIEXPORT void JNICALL Java_TestJNI_set (JNIEnv * env, jobject obj, jint j)???????? {??????????? i=j*888;???????? }? ?????????? ??? JNIEXPORT jint JNICALL Java_TestJNI_get (JNIEnv * env, jobject obj)??????
?? {????????? printf("ok!You have successfully passed the Java call cn");????????? return i;???????? }??
?

6

(6)生成物件檔案TestJNI.o。(注意:這裡面的路徑/usr/lib/jvm/java/是JDk安裝的路徑,所以大家應根據自己的JDK路徑設定。Jni_md.h和Jni.h分別在JDK的/include/linux與/include/目錄下。)-Wall:開啟警告開關。-fPIC:表示編譯為位置獨立的程式碼,不用此選項的話編譯後的程式碼是位置相關的所以動態載入時是通過程式碼拷貝的方式來滿足不同進程的需要,而不能達到真正程式碼段共用的目的。


7

(7)生成動態連結庫libdiaoyong.so檔案,(注意:動態連結庫的名字必須是 lib*.so,因為編譯器查詢動態連線庫時有隱含的命名規則,即在給出的名字前面加上lib,後面加上.so來確定庫的名稱。這裡是libdiaoyong.so對應於Java程式裡的diaoyong) 選項 -rdynamic 用來通知連結器將所有符號新增到動態符號表中。-shared指編譯後會連結成共用物件。


8

(8)設定環境變數,我看了網上大多都是修改/home/使用者目錄/下的.bash_profile檔案,但有的機器上沒有這個檔案,那麼就去建立一個就行了。而我的方法直接在/home/使用者目錄/下的.bashrc檔案(也就是我們設定環境變數的檔案)進行設定。上面兩種方法的設定內容是一樣的,如下:

                  export LD_LIBRARY_PATH=./

下面我就以我的方法為例做詳細操作。

先進入到/home/使用者目錄/下,用ls –al命令(可用於檢視隱藏檔案)檢視.bashrc檔案。


9

然後用vi編輯器或gedit編輯器開啟.bashrc檔案。


10

輸入紅線框中內容:(注意.bashrc檔案裡面有好多環境變數設定不要隨意更動)LD_LIBRARY_PATH:這個環境變數指示動態連線器可以裝載動態庫的路徑。


11

讓.bashrc中設定立即載入


12

(9)執行Java程式,實現去呼叫c語言。(注意:一定要回到Java檔案所在目錄執行,不然會找不到檔案)。



IT145.com E-mail:sddin#qq.com