原文: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
碟符自己搞定吧…
2,開始第一個JNI
1,JNI的原理圖
直接到官方教程那裡截的….
2,開始使用JNI
12345678910111213141516171819202122package
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檔案
2,把.class檔案轉換成標頭檔案,成功的話就會在src目錄下看到.h檔案了
開啟後你會看到
1234567891011121314151617181920212223242526272829/* 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檔案了
123456789101112131415161718//必須的標頭檔案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檔案(隨便起)
沒出什麼提示的話就是成功的了…
4,執行我們的JNI
1,用eclipse的話,我們把編譯好的dll放到專案根目錄,注意不是程式碼根目錄
12345678910//把剛才註釋的地方刪掉..
//這就是必須的,用來讀取我們寫好的C語言編譯好的dll,字尾是系統自己辨認…千萬不要自己寫
static
{
System.loadLibrary(
"sum"
);
}
//mian方法中
//用底層c程式碼實現輸出..呵呵~~
new
MyJni().display();
//用c計算會不會快點呢..呵呵~
System.out.println(
new
MyJni().sum(2.0, 3.0));
輸出結果
貌似java本身的輸出,優先順序比較高??
2,補充一下:
1,我們要執行我們編譯的C檔案,是與我們建立的類是必須一起存在,
例如:我把MyJni.java刪掉,然後另起一個Hello.java能不能直接呼叫dll中的方法呢?那是肯定不行的..因為,jni需要類名來進行查詢