JNI设置C++与java的结合(2)
发布日期:2021-06-30 21:49:34 浏览次数:2 分类:技术文章

本文共 3905 字,大约阅读时间需要 13 分钟。

我们可以看到其中有四个函数声明, Java_完整类名_方法名完整类名包括了包名例如demo.Sample1是完整类名对应的这里就是demo_Sample1.

在注释中我们可以看到这样一个东西 Signature, 这个是方法的签名关于Signature, 下面通过一个表格来说明.

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数组, [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

 源代码下载: 

运行其中的build&run.bat文件即可如有错误请根据实际情况修改其中的一些参数.

DLL工程文件VC6.0VS2010: 

参考文献:

  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.

转载地址:https://loongembedded.blog.csdn.net/article/details/40948455 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:使用 /sys 文件系统访问 Linux 内核
下一篇:android 常用方法集合

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年04月12日 08时27分07秒