如何使用JNI的一些基本方法和過程在網(wǎng)上多如牛毛,如果你對Jni不甚了解,不知道Jni是做什么的,如何建立一個(gè)基本的jni程序,或許可以參考下面下面這些文章:
利用VC++6.0實(shí)現(xiàn)JNI的最簡單的例子
JNI入門教程之HelloWorld篇
SUN JNI Tutorial
這 些資料的例子中,大多數(shù)只是輸入一些簡單的參數(shù),獲取沒有參數(shù)。而在實(shí)際的使用過程中,往往需要對參數(shù)進(jìn)行處理轉(zhuǎn)換。才可以被C/C++程序識別。比如我 們在C++中有一個(gè)結(jié)構(gòu)(Struct)DiskInfo ,需要傳遞一個(gè)類似于DiskInfo *pDiskInfo的參數(shù),類似于在C++這樣參數(shù)如何傳遞到Java中呢?下面我們就來討論C++到Java中方法的一些常見參數(shù)的轉(zhuǎn)換:
定義Native Java類:
如果你習(xí)慣了使用JNI,你就不會(huì)覺得它難了。既然本地方法是由其他語言實(shí)現(xiàn)的,它們在Java中沒有函數(shù)體。但是,所有本地代碼必須用本地關(guān)鍵詞聲明,成為Java類的成員。假設(shè)我們在C++中有這么一個(gè)結(jié)構(gòu),它用來描述硬盤信息:





那么我們需要在Java中定義一個(gè)類來與之匹配,聲明可以寫成這樣:







在這個(gè)類中,申明一些Native的本地方法,來測試方法參數(shù)的傳遞,分別定義了一些函數(shù),用來傳遞結(jié)構(gòu)或者結(jié)構(gòu)數(shù)組,具體定義如下面代碼:


















編譯生成C/C++頭文件
定義好了Java類之后,接下來就要寫本地代碼。本地方法符號提供一個(gè)滿足約定的頭文件,使用
Java工具Javah
可以很容易地創(chuàng)建它而不用手動(dòng)去創(chuàng)建。你對Java的class文件使用javah命令,就會(huì)為你生成一個(gè)對應(yīng)的C/C++頭文件。
1、在控制臺下進(jìn)入工作路徑,本工程路徑為:E:\work\java\workspace\JavaJni。
2、運(yùn)行javah 命令:javah -classpath E:\work\java\workspace\JavaJni com.sundy.jnidemo ChangeMethodFromJni
本文生成的C/C++頭文件名為: com_sundy_jnidemo_ChangeMethodFromJni.h
在C/C++中實(shí)現(xiàn)本地方法
生成C/C++頭文件之后,你就需要寫頭文件對應(yīng)的本地方法。注意:所有的本地方法的第一個(gè)參數(shù)都是指向
JNIEnv
結(jié)構(gòu)的。這個(gè)結(jié)構(gòu)是用來調(diào)用JNI函數(shù)的。第二個(gè)參數(shù)jclass的意義,要看方法是不是靜態(tài)的(static)或者實(shí)例(Instance)的。前者,jclass代表一個(gè)類對象的引用,而后者是被調(diào)用的方法所屬對象的引用。
返回值和參數(shù)類型 根據(jù)等價(jià)約定映射到本地C/C++類型,如表 JNI類型映射 所示。有些類型,在本地代碼中可直接使用,而其他類型只有通過JNI調(diào)用操作。
表A
Java 類型 | 本地類型 | 描述 |
boolean | jboolean | C/C++8位整型 |
byte | jbyte | C/C++帶符號的8位整型 |
char | jchar | C/C++無符號的16位整型 |
short | jshort | C/C++帶符號的16位整型 |
int | jint | C/C++帶符號的32位整型 |
long | jlong | C/C++帶符號的64位整型e |
float | jfloat | C/C++32位浮點(diǎn)型 |
double | jdouble | C/C++64位浮點(diǎn)型 |
Object | jobject | 任何Java對象,或者沒有對應(yīng)java類型的對象 |
Class | jclass | Class對象 |
String | jstring | 字符串對象 |
Object[] | jobjectArray | 任何對象的數(shù)組 |
boolean[] | jbooleanArray | 布爾型數(shù)組 |
byte[] | jbyteArray | 比特型數(shù)組 |
char[] | jcharArray | 字符型數(shù)組 |
short[] | jshortArray | 短整型數(shù)組 |
int[] | jintArray | 整型數(shù)組 |
long[] | jlongArray | 長整型數(shù)組 |
float[] | jfloatArray | 浮點(diǎn)型數(shù)組 |
double[] | jdoubleArray | 雙浮點(diǎn)型數(shù)組 |
※
JNI類型映射
使用數(shù)組:
JNI通過JNIEnv提供的操作Java數(shù)組的功能。它提供了兩個(gè)函數(shù):一個(gè)是操作java的簡單型數(shù)組的,另一個(gè)是操作對象類型數(shù)組的。
因?yàn)樗俣鹊脑颍唵晤愋偷臄?shù)組作為指向本地類型的指針暴露給本地代碼。因此,它們能作為常規(guī)的數(shù)組存取。這個(gè)指針是指向?qū)嶋H的Java數(shù)組或者Java數(shù)組的拷貝的指針。另外,數(shù)組的布置保證匹配本地類型。
為了存取Java簡單類型的數(shù)組,你就要要使用 GetXXXArrayElements 函數(shù)(見 表 B ),XXX代表了數(shù)組的類型。這個(gè)函數(shù)把Java數(shù)組看成參數(shù),返回一個(gè)指向?qū)?yīng)的本地類型的數(shù)組的指針。
表B
函數(shù) | Java 數(shù)組類型 | 本地類型 |
GetBooleanArrayElements | jbooleanArray | jboolean |
GetByteArrayElements | jbyteArray | jbyte |
GetCharArrayElements | jcharArray | jchar |
GetShortArrayElements | jshortArray | jshort |
GetIntArrayElements | jintArray | jint |
GetLongArrayElements | jlongArray | jlong |
GetFloatArrayElements | jfloatArray | jfloat |
GetDoubleArrayElements | jdoubleArray | jdouble |
JNI數(shù)組存取函數(shù)
當(dāng)你對數(shù)組的存取完成后,要確保調(diào)用相應(yīng)的 ReleaseXXXArrayElements 函數(shù),參數(shù)是對應(yīng)Java數(shù)組和 GetXXXArrayElements 返回的指針。如果必要的話,這個(gè)釋放函數(shù)會(huì)復(fù)制你做的任何變化(這樣它們就反射到j(luò)ava數(shù)組),然后釋放所有相關(guān)的資源。
為了使用java對象的數(shù)組,你必須使用
GetObjectArrayElement
函數(shù)和
SetObjectArrayElement
函數(shù),分別去get,set數(shù)組的元素。
GetArrayLength
函數(shù)會(huì)返回?cái)?shù)組的長度。
使用對象
JNI提供的另外一個(gè)功能是在本地代碼中使用Java對象。通過使用合適的JNI函數(shù),你可以創(chuàng)建 Java對象,get、set 靜態(tài)(static)和實(shí)例(instance)的域,調(diào)用靜態(tài)(static)和實(shí)例(instance)函數(shù)。JNI通過ID識別域和方法,一個(gè)域或 方法的ID是任何處理域和方法的函數(shù)的必須參數(shù)。
表C 列出了用以得到靜態(tài)(static)和實(shí)例(instance)的域與方法的JNI函數(shù)。每個(gè)函數(shù)接受(作為參數(shù))域或方法的類,它們的名稱,符號和它們對應(yīng)返回的 jfieldID 或 jmethodID 。
表C
函數(shù) | 描述 |
GetFieldID | 得到一個(gè)實(shí)例的域的ID |
GetStaticFieldID | 得到一個(gè)靜態(tài)的域的ID |
GetMethodID | 得到一個(gè)實(shí)例的方法的ID |
GetStaticMethodID | 得到一個(gè)靜態(tài)方法的ID |
※域和方法的函數(shù)
如果你有了一個(gè)類的實(shí)例,它就可以通過方法 GetObjectClass 得到,或者如果你沒有這個(gè)類的實(shí)例,可以通過 FindClass 得到。符號是從域的類型或者方法的參數(shù),返回值得到字符串,如 表 D 所示。
表D
Java 類型 | 符號 |
boolean | Z |
byte | B |
char | C |
short | S |
int | I |
long | L |
float | F |
double | D |
void | V |
objects對象 | Lfully-qualified-class-name;L類名 |
Arrays數(shù)組 | [array-type [數(shù)組類型 |
methods方法 | (argument-types)return-type(參數(shù)類型)返回類型 |
※確定域和方法的符號
下面我們來看看,如果通過使用數(shù)組和對象,從C++中的獲取到Java中的DiskInfo 類對象,并返回一個(gè)DiskInfo數(shù)組:











































全部的C/C++方法實(shí)現(xiàn)代碼如下:















































































































- 2011-01-26 17:03
- 瀏覽 273
- 評論(0)
- 相關(guān)推薦
發(fā)表評論
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

評論