學習——>JNI設置C++與java的結合(2)

咱們能夠看到其中有四個函數聲明, Java_完整類名_方法名, 完整類名包括了包名, 例如demo.Sample1是完整類名, 對應的這裏就是demo_Sample1.html

在註釋中咱們能夠看到這樣一個東西 Signature, 這個是方法的簽名. 關於Signature, 下面經過一個表格來講明.java

java類型編程

Signature數組

備註函數

booleanui

Z編碼


bytespa

B指針


charorm

C


short

S


int

I


long

L


float

F


double

D


void

V


object

L/分割的完整類名

例如: Ljava/lang/String表示String類型

Array

[簽名

例如: [I表示int數組, [Ljava/lang/String表示String數組

Method

(參數簽名)返回類型簽名

例如: ([I)I表示參數類型爲int數組, 返回int類型的方法

上面頭文件的第一個函數聲明

JNIEXPORT jint JNICALL Java_Sample1_intMethod (JNIEnv *, jobject, jint);

註釋中的簽名是 Signature: (I)I

在每一個函數的參數列表中都有JNIEnv * jobject兩個參數, 這兩個參數稍候說明.

實現頭文件中的函數

可使用C語言來實現, 也可使用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(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()這個方法, 是用來在JavaC之間轉換字符串的, 由於Java自己都使用了雙字節的字符, C語言自己都是單字節的字符, 因此須要進行轉換.

JNIEnv *是每一個函數都有的參數, 它包含了不少有用的方法, 使用起來相似Java的反射, 也提供了這樣一個編碼轉換的函數.

GetStringUTFChars()NewStringUTF(), 第一個是從UTF8轉換爲C的編碼格式, 第二個是根據C的字符串返回一個UTF8字符串.

ReleaseStringUTFChars()是用來釋放對象的, Java中有虛擬機進行垃圾回收, 可是在C語言中, 這些對象必須手動回收. 不然可能形成內存泄漏.

函數的名字一眼看到就能夠猜出功能, jni.h中的大部分函數名都是這樣.

若是是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;

}

 

上述兩端代碼很是類似, 只有一個不一樣點

C代碼: (*env)->GetStringUTFChars(env, string, 0);

C++代碼: env->GetStringUTFChars(string, 0);

C語言中使用的是結構體的函數指針, 而在C++中使用的仍是struct, 咱們知道structC++中和class的功能是幾乎同樣的, struct也能夠用來定義類, 因此envC++中是個類對象的指針.

編譯和運行

這裏使用的是微軟編譯器, 編譯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

運行

>java Sample1

注意: 64位版本的JDK可能會在運行時報錯:

java.lang.UnsatisfiedLinkError: ...Sample1.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform

若是您有這樣的錯誤, 請使用32位的JDK來從新運行.

運行結果以下:

intMethod: 25

booleanMethod: false

stringMethod: JAVA

intArrayMethod: 36

 源代碼下載: Sample1.zip

運行其中的build&run.bat文件便可, 若有錯誤請根據實際狀況修改其中的一些參數.

DLL工程文件VC6.0VS2010: VC6.0&VS2010.zip

參考文獻:

  1. Scott Stricker, JNI 進行 Java 編程,      http://www.ibm.com/developerworks/cn/education/java/j-jni/section2.html

  2. JDK 6u30 docs, Java Native      Interface Specification, Chapter 3 JNI Types and Data Structures, Type      Signatures.

相關文章
相關標籤/搜索