JNI 簡單例子

☆綠茶☆發表於2013-10-31

原文:http://www.cnblogs.com/youxilua/archive/2011/09/16/2178554.html

1,先把c語言的編譯環境搭建好,windows下這裡使用mingw

1,mingw具體配置

配置環境變數: 
                         開啟:“我的電腦->屬性->高階->環境變數->系統變數”編輯如下系統變數: 
                         變數名                            變數值 
                         PATH                             C:\MinGW\bin; 
                         LIBRARY_PATH                C:\MinGW\lib 
                         C_INCLUDEDE_PATH        C:\MinGW\include 
                         CPLUS_INCLUDE_PATH      C:\MinGW\include\c++\3.4.2;C:\MinGW\include\c++\3.4.2\mingw32;C:\MinGW\include\c++\3.4.2\backward;C:\MinGW\include

 

碟符自己搞定吧…

image 

 

2,開始第一個JNI

1,JNI的原理圖

image

直接到官方教程那裡截的….

2,開始使用JNI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package kg.tom;
 
public class MyJni {
    //使用JNI的關鍵字native
    //這個關鍵字決定我們那些方法能在我們的C檔案中使用
    //只須宣告,不必實現
     public native void display();
     public native double sum(double x,double y);
      
    //這個是到時候呼叫我們寫好的C檔案
    //現在用不上
    //static {
    //  System.loadLibrary("sum");
    //}
     
     
    public static void main(String[] args) {
        //到時候測試用方法現在用不上
        //new MyJni().display();
        //System.out.println(new MyJni().sum(2.0, 3.0));
    }
}

 

然後,就是返回到我們的java基礎了…將我們寫好的類,轉換成標頭檔案

1,先把寫好的類轉換成.class檔案

image

2,把.class檔案轉換成標頭檔案,成功的話就會在src目錄下看到.h檔案了

 image

開啟後你會看到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class kg_tom_MyJni */
 
#ifndef _Included_kg_tom_MyJni
#define _Included_kg_tom_MyJni
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     kg_tom_MyJni
 * Method:    display
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_kg_tom_MyJni_display
  (JNIEnv *, jobject);
 
/*
 * Class:     kg_tom_MyJni
 * Method:    sum
 * Signature: (DD)D
 */
JNIEXPORT jdouble JNICALL Java_kg_tom_MyJni_sum
  (JNIEnv *, jobject, jdouble, jdouble);
 
#ifdef __cplusplus
}
#endif
#endif

native方法名稱轉換詳解:

英語原文 我的理解… 例子

the prefix Java_

轉換後的native方法全部以Java_為字首 Java_kg_tom_MyJni_display

a mangled fully-qualified class name

接著以類的全名標識(包名+類名) Java_kg_tom_MyJni_display
  • an underscore (“_”) separator
以下劃線為分隔符(“_”) Java_kg_tom_MyJni_display
mangled method name 最後就是方法的名稱 Java_kg_tom_MyJni_display
  • for overloaded native methods, two underscores (“__”) followed by the mangled argument signature
這個理解不能:直譯的話就是對已經讀取過的native方法,用雙下劃線(“__”)標註 沒找到

3,就是寫我們的C檔案了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//必須的標頭檔案jni.h
#include <jni.h>
//匯入我們需要實現的本地方法
#include "kg_tom_MyJni.h"
#include <stdio.h>
 
JNIEXPORT void JNICALL Java_kg_tom_MyJni_display
  (JNIEnv *env, jobject obj)
{
    printf("Hello World tom!!");
    return;
}
 
JNIEXPORT jdouble JNICALL Java_kg_tom_MyJni_sum
  (JNIEnv *env, jobject obj, jdouble a, jdouble b)
{
    return a + b;
}

 

4,windows下編譯成dll檔案,linux下編譯成so檔案.這裡只說windows下的

1,java基礎

找到我們的jdk資料夾,然後開啟其中的include資料夾,就會看到一些標頭檔案,看下關鍵的Jni.h標頭檔案在不在,在的話,繼續,不在

自行下載一個新的jdk…

2,把C檔案編譯成dll檔案

我們這裡使用mingw….你會用VC6也可以用VC6編譯…

gcc -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at   -Id:/java/include –Id:/java/include/win32   -shared -o sum.dll java_sum_native.c

命令 簡單介紹
-Wall -D_JNI_IMPLEMENTATION_ 把我們的C檔案編譯成dll
-Wl,--kill-at   因為mingw預設是用@來進行分隔,會導致JNI機制不能讀取,所以要刪掉.. 
mingw官網解釋
Id:/java/include –Id:/java/include/win32   匯入我們用的的jni需要的標頭檔案…碟符,資料夾自己修改
-shared -o 輸出配置,第一個引數為我們輸出的名字(隨便起),第二個引數為我們的C檔案(隨便起)
   

 

image

沒出什麼提示的話就是成功的了…

4,執行我們的JNI

1,用eclipse的話,我們把編譯好的dll放到專案根目錄,注意不是程式碼根目錄

1
2
3
4
5
6
7
8
9
10
//把剛才註釋的地方刪掉..
//這就是必須的,用來讀取我們寫好的C語言編譯好的dll,字尾是系統自己辨認…千萬不要自己寫
static {
        System.loadLibrary("sum");
    }
//mian方法中
//用底層c程式碼實現輸出..呵呵~~
new MyJni().display();
//用c計算會不會快點呢..呵呵~
System.out.println(new MyJni().sum(2.0, 3.0));

輸出結果

image

貌似java本身的輸出,優先順序比較高??

2,補充一下:

1,我們要執行我們編譯的C檔案,是與我們建立的類是必須一起存在,

例如:我把MyJni.java刪掉,然後另起一個Hello.java能不能直接呼叫dll中的方法呢?那是肯定不行的..因為,jni需要類名來進行查詢

 

 

相關文章