此文章寫於2015.02.03,發佈於網易博客,於2020.03.25遷移至此。
前言:記錄學習過程便於記憶。經過多次嘗試發現Java環境下的JNI調用與Andriod環境下的JNI調用有所不同,不知道是否正確。先記錄一下Java環境下的JNI調用。
先寫一個Java文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package com.example.myjni; public class MyJni { //使用JNI的關鍵字native,決定我們那些方法能在我們的C文件中使用,只須聲明,不必實現
public native void display(); public native double sum(double x,double y); //用來讀取我們寫好的C語言編譯好的dll,後綴是系統自己辨認 static { System.loadLibrary("myjni"); } public static void main(String[] args) { new MyJni().display(); System.out.println(new MyJni().sum(2.0, 3.0)); } }
|
把寫好的類轉換成.class文件
javac com\example\myjni\MyJni.java
把.class文件轉換成頭文件,成功的話就會在src目錄下看到.h文件了
javah com.example.myjni.MyJni
打開.h文件可以看到
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 com_example_myjni_MyJni */ #ifndef _Included_com_example_myjni_MyJni #define _Included_com_example_myjni_MyJni #ifdef __cplusplus extern "C" { #endif /* * Class: com_example_myjni_MyJni * Method: display * Signature: ()V */ JNIEXPORT void JNICALL Java_com_example_myjni_MyJni_display (JNIEnv *, jobject); /* * Class: com_example_myjni_MyJni * Method: sum * Signature: (DD)D */ JNIEXPORT jdouble JNICALL Java_com_example_myjni_MyJni_sum (JNIEnv *, jobject, jdouble, jdouble); #ifdef __cplusplus } #endif #endif
|
native方法名稱組成詳解:
Java_爲前綴 + 類的全名標識(包名+類名) + “_” + 方法名
寫與.h文件對應的.c文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include <jni.h> #include <stdio.h> #include "com_example_myjni_MyJni.h" JNIEXPORT void JNICALL Java_com_example_myjni_MyJni_display (JNIEnv *env, jobject obj) { printf("Hello MyJni!"); return; } JNIEXPORT jdouble JNICALL Java_com_example_myjni_MyJni_sum (JNIEnv *env, jobject obj, jdouble a, jdouble b) { return a + b; }
|
windows下編譯成dll文件,linux下編譯成so文件.這裏只講dll的,.so的以後嘗試了再說
首先查看我們的jdk文件夾,查看其include文件夾下是否存在Jni.h頭文件。在的話,繼續,否則重新安裝jdk。
使用mingw編譯.c文件(確保前面已經安裝了mingw)
gcc -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -I"C:\Program Files\Java\jdk1.6.0_45\include" -I"C:\Program Files\Java\jdk1.6.0_45\include\win32" -shared myjni.c -o myjni.dll
命令 | 簡單介紹 |
-Wall -D_JNI_IMPLEMENTATION_ | 把我們的C文件編譯成dll |
-Wl,--kill-at | 因爲mingw默認是用@來進行分隔,會導致JNI機制不能讀取,所以要刪掉.. mingw官網解釋 |
-I"C:\Program Files\Java\jdk1.6.0_45\include" -I"C:\Program Files\Java\jdk1.6.0_45\include\win32" | 導入我們用的的jni需要的頭文件…盤符,文件夾自己修改 |
-shared -o | 輸出配置,第一個參數爲我們輸出的名字(隨便起),第二個參數爲我們的C文件(隨便起) |
沒出什麼提示的話就是成功的了…
運行我們的JNI(用eclipse的話,我們把編譯好的dll放到項目根目錄,注意不是代碼根目錄)
輸出結果
貌似java本身的輸出,優先級比較高?