我们可以看到其中有四个函数声明, 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()这个方法, 是用来在Java和C之间转换字符串的, 因为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, 我们知道struct在C++中和class的功能是几乎一样的,
struct也可以用来定义类, 所以env在C++中是个类对象的指针.

编译和运行

这里使用的是微软编译器, 编译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.0和VS2010的: 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.

JNI设置C++与java的结合(2)的更多相关文章

  1. Android中关于JNI 的学习(三)在JNI层訪问Java端对象

    前面两篇文章简介了JNI层跟Java层的一些相应关系,包含方法名,数据类型和方法名称等,相信在理论层面.可以非常好地帮助我们去了解JNI在Native本地开发中的作用,对JNI的一些概念也有了一个初步 ...

  2. Jni中C++和Java的参数传递 参数对照

    Jni中C++和Java的参数传递 如何使用JNI的一些基本方法和过程在网上多如牛毛,如果你对Jni不甚了解,不知道Jni是做什么的,如何建立一个基本的jni程序,或许可以参考下面下面这些文章:利用V ...

  3. Jni中C++和Java的参数传递

    Jni中C++和Java的参数传递 如何使用JNI的一些基本方法和过程在网上多如牛毛,如果你对Jni不甚了解,不知道Jni是做什么的,如何建立一个基本的jni程序,或许可以参考下面下面这些文章:利用V ...

  4. Jni中C++和Java的参数传递(转)

    如何使用JNI的一些基本方法和过程在网上多如牛毛,如果你对Jni不甚了解,不知道Jni是做什么的,如何建立一个基本的jni程序,或许可以参考下面下面这些文章:利用VC++6.0实现JNI的最简单的例子 ...

  5. Android JNI c/c++调用java 无需新建虚拟机

    近期通过研究SDL源码 得出android JNI  c/c++调用java 无需新建虚拟机: 具体步骤如下 第一步获得:两个参数 JNIEnv和jclass void Java_com_Test_A ...

  6. Linux上设置开机启动Java程序

    在Linux上设置开机启动Java程序,例如:test.jar 在Linux上启动Java程序的命令: nohup java -jar test.jar >/dev/>& & ...

  7. Android JNI中C和JAVA代码之间的互相调用

    关于Android studio中使用NDK/JNI环境和入门:http://blog.csdn.net/quan648997767/article/details/64923143 1. C代码回调 ...

  8. JNI中C调用Java方法

    背景需求 我们需要在JNI的C代码调用Java代码.实现原理:使用JNI提供的反射借口来反射得到Java方法,进行调用. JNI关键方法讲解. 1. 在同一个类中,调用其他方法 JNIEXPORT v ...

  9. JNI字段描述符-Java Native Interface Field Descriptors

    一.JNI字段描述符 "[I" ---  int[] "[[[D" --- double[][][] 如果以一个L开头的描述符,就是类描述符,它后紧跟着类的字符 ...

随机推荐

  1. linux下内存的统计和内存泄露类问题的定位

    在产品的开发中,通过对当前系统消耗内存总量的统计,可以对产品所需内存总量进行精确的评估,从而选择合适的内存芯片与大小,降低产品的成本.在遇到内存泄露类问题时,经常会对此束手无策,本文通过对proc下进 ...

  2. intel-hadoop/HiBench流程分析----以贝叶斯算法为例

    1.HiBench算法简介 Hibench 包含9个典型的hadoop负载(micro benchmarks,hdfs benchmarks,web search bench marks,machin ...

  3. Android开发之手把手教你写ButterKnife框架(二)

    欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/52664112 本文出自:[余志强的博客] 上一篇博客Android开 ...

  4. Unity角色残影特效

    残影特效在网上有很多例子,比如这个,我参考着自己整合了一下,算是整合了一个比较完整且特别简单易用的出来,只需要一个脚本挂上去无需任何设定就能用. 这里只针对SkinnedMeshRenderer的网格 ...

  5. Gazebo機器人仿真學習探索筆記(七)连接ROS

    中文稍后补充,先上官方原版教程.ROS Kinetic 搭配 Gazebo 7 附件----官方教程 Tutorial: ROS integration overview As of Gazebo 1 ...

  6. 凸函数与Jensen不等式

    这个是在凸优化里面看的,在EM算法中看有用到,所以用latex写了篇回忆用的小短文,现在不会把latex产生的pdf怎么转变成放到这里的内容. 所以我选择直接贴图. 这个pdf可以在我的资源里找到.  ...

  7. JBOSS EAP 6 系列四 EJB实现——调用(贯穿始终的模块)

    本文主要介绍在JBOSS EAP 6.2(或者JBOSS AS7)中模块是如何贯穿EJB实现的始终.延续上一博文<认识模块的使用>的话题继续聊JBOSS做为模块申明式容器的这一特性在EJB ...

  8. Download all Apple open source OS X files at once

    While it is well known that Mac OS X contains open source code, how to access and download that sour ...

  9. 【Unity Shaders】ShadowGun系列之二——雾和体积光

    写在前面 体积光,这个名称是God Rays的中文翻译,感觉不是很形象.God Rays其实是Crepuscular rays在图形学中的说法,而Crepuscular rays的意思是云隙光.曙光. ...

  10. 【java集合框架源码剖析系列】java源码剖析之java集合中的折半插入排序算法

    注:关于排序算法,博主写过[数据结构排序算法系列]数据结构八大排序算法,基本上把所有的排序算法都详细的讲解过,而之所以单独将java集合中的排序算法拿出来讲解,是因为在阿里巴巴内推面试的时候面试官问过 ...