JNI设置C++与java的结合(2)
我們可以看到其中有四個(gè)函數(shù)聲明, Java_完整類名_方法名,?完整類名包括了包名,?例如demo.Sample1是完整類名,?對(duì)應(yīng)的這里就是demo_Sample1.
在注釋中我們可以看到這樣一個(gè)東西?Signature,?這個(gè)是方法的簽名.?關(guān)于Signature,?下面通過一個(gè)表格來說明.
| java類型 | Signature | 備注 |
| boolean | Z | |
| byte | B | |
| char | C | |
| short | S | |
| int | I | |
| long | L | |
| float | F | |
| double | D | |
| void | V | |
| object | L用/分割的完整類名 | 例如: Ljava/lang/String表示String類型 |
| Array | [簽名 | 例如: [I表示int數(shù)組, [Ljava/lang/String表示String數(shù)組 |
| Method | (參數(shù)簽名)返回類型簽名 | 例如: ([I)I表示參數(shù)類型為int數(shù)組,?返回int類型的方法 |
上面頭文件的第一個(gè)函數(shù)聲明
JNIEXPORT jint JNICALL Java_Sample1_intMethod (JNIEnv *, jobject, jint);
注釋中的簽名是?Signature: (I)I
在每個(gè)函數(shù)的參數(shù)列表中都有JNIEnv *和?jobject兩個(gè)參數(shù),?這兩個(gè)參數(shù)稍候說明.
實(shí)現(xiàn)頭文件中的函數(shù)
可以使用C語言來實(shí)現(xiàn),?也可以使用C++來實(shí)現(xiàn),?下面先說說C語言的實(shí)現(xiàn).
| 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 30 31 32 33 34 35 36 37 38 39 | #include "Sample1.h" #include <string.h> ? JNIEXPORT jint JNICALL Java_Sample1_intMethod ??(JNIEnv *env, jobject obj, jint num) { ????return?num * num; } ? JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod ??(JNIEnv *env, jobject obj, jboolean ? boolean) { ????return?!boolean; } ? JNIEXPORT jstring JNICALL Java_Sample1_stringMethod ??(JNIEnv *env, jobject obj, jstring string) { ????const?char* str = (*env)->GetStringUTFChars(env, ? string, 0); ????char?cap[128]; ????strcpy(cap, str); ????(*env)->ReleaseStringUTFChars(env, ? string, 0); ????return?(*env)->NewStringUTF(env, ? strupr(cap)); } ? JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod ??(JNIEnv *env, jobject obj, jintArray array) { ????int?i, sum = 0; ????jsize len = ? (*env)->GetArrayLength(env, array); ????jint *body = ? (*env)->GetIntArrayElements(env, array, 0); ????? ????for?(i = 0; i < len; ? ++i) ????{ ????????sum += ? body[i]; ????} ????(*env)->ReleaseIntArrayElements(env, ? array, body, 0); ????return?sum; } |
(*env)->GetStringUTFChars()這個(gè)方法,?是用來在Java和C之間轉(zhuǎn)換字符串的,?因?yàn)?/span>Java本身都使用了雙字節(jié)的字符,?而C語言本身都是單字節(jié)的字符,?所以需要進(jìn)行轉(zhuǎn)換.
JNIEnv *是每個(gè)函數(shù)都有的參數(shù),?它包含了很多有用的方法,?使用起來類似Java的反射,?也提供了這樣一個(gè)編碼轉(zhuǎn)換的函數(shù).
GetStringUTFChars()和NewStringUTF(),?第一個(gè)是從UTF8轉(zhuǎn)換為C的編碼格式,?第二個(gè)是根據(jù)C的字符串返回一個(gè)UTF8字符串.
ReleaseStringUTFChars()是用來釋放對(duì)象的,?在Java中有虛擬機(jī)進(jìn)行垃圾回收,?但是在C語言中,?這些對(duì)象必須手動(dòng)回收.?否則可能造成內(nèi)存泄漏.
函數(shù)的名字一眼看到就可以猜出功能, jni.h中的大部分函數(shù)名都是這樣.
如果是C++的話,?這段代碼該怎么寫?
下面是C++的代碼
| 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 30 31 32 33 34 35 36 37 38 39 | #include "Sample1.h" #include <string.h> ? JNIEXPORT jint JNICALL Java_Sample1_intMethod ??(JNIEnv *env, jobject obj, jint num) { ????return?num * num; } ? JNIEXPORT jboolean JNICALL Java_Sample1_booleanMethod ??(JNIEnv *env, jobject obj, jboolean ? boolean) { ????return?!boolean; } ? JNIEXPORT jstring JNICALL Java_Sample1_stringMethod ??(JNIEnv *env, jobject obj, jstring string) { ????const?char* str = env->GetStringUTFChars(string, ? 0); ????char?cap[128]; ????strcpy(cap, str); ????env->ReleaseStringUTFChars(string, ? 0); ????return?env->NewStringUTF(strupr(cap)); } ? JNIEXPORT jint JNICALL Java_Sample1_intArrayMethod ??(JNIEnv *env, jobject obj, jintArray array) { ????int?i, sum = 0; ????jsize len = ? env->GetArrayLength(array); ????jint *body = ? env->GetIntArrayElements(array, 0); ????? ????for?(i = 0; i < len; ? ++i) ????{ ????????sum += ? body[i]; ????} ????env->ReleaseIntArrayElements(array, ? body, 0); ????return?sum; } |
?
上述兩端代碼非常相似,?只有一個(gè)不同點(diǎn)
C代碼: (*env)->GetStringUTFChars(env, string, 0);
C++代碼: env->GetStringUTFChars(string, 0);
C語言中使用的是結(jié)構(gòu)體的函數(shù)指針,?而在C++中使用的還是struct,?我們知道struct在C++中和class的功能是幾乎一樣的, struct也可以用來定義類,?所以env在C++中是個(gè)類對(duì)象的指針.
編譯和運(yùn)行
這里使用的是微軟編譯器,?編譯C語言版的dll
>cl -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -LD Sample1.c -FeSample1.dll
編譯C++版本的dll
>cl -I%JAVA_HOME%\include -I%JAVA_HOME%\include\win32 -LD Sample1.cpp -FeSample1.dll
運(yùn)行
>java Sample1
注意:?64位版本的JDK可能會(huì)在運(yùn)行時(shí)報(bào)錯(cuò):
java.lang.UnsatisfiedLinkError: ...Sample1.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
如果您有這樣的錯(cuò)誤,?請(qǐng)使用32位的JDK來重新運(yùn)行.
運(yùn)行結(jié)果如下:
| intMethod: 25 booleanMethod: false stringMethod: JAVA intArrayMethod: 36 |
?源代碼下載:?Sample1.zip
運(yùn)行其中的build&run.bat文件即可,?如有錯(cuò)誤請(qǐng)根據(jù)實(shí)際情況修改其中的一些參數(shù).
DLL工程文件VC6.0和VS2010的:?VC6.0&VS2010.zip
參考文獻(xiàn):
Scott Stricker,?用?JNI?進(jìn)行?Java?編程, ? ? ?http://www.ibm.com/developerworks/cn/education/java/j-jni/section2.html
JDK 6u30 docs, Java Native ? ? ?Interface Specification, Chapter 3 JNI Types and Data Structures, Type ? ? ?Signatures.
總結(jié)
以上是生活随笔為你收集整理的JNI设置C++与java的结合(2)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android 常用方法集合
- 下一篇: MTK Android添加驱动模块