JNI设置C++与java的结合(2)
我们可以看到其中有四个函数声明, 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数组, |
|
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
参考文献:
Scott Stricker, 用 JNI 进行 Java 编程,
http://www.ibm.com/developerworks/cn/education/java/j-jni/section2.htmlJDK 6u30 docs, Java Native Interface Specification, Chapter 3 JNI Types and Data Structures, Type Signatures.
JNI设置C++与java的结合(2)的更多相关文章
- Android中关于JNI 的学习(三)在JNI层訪问Java端对象
前面两篇文章简介了JNI层跟Java层的一些相应关系,包含方法名,数据类型和方法名称等,相信在理论层面.可以非常好地帮助我们去了解JNI在Native本地开发中的作用,对JNI的一些概念也有了一个初步 ...
- Jni中C++和Java的参数传递 参数对照
Jni中C++和Java的参数传递 如何使用JNI的一些基本方法和过程在网上多如牛毛,如果你对Jni不甚了解,不知道Jni是做什么的,如何建立一个基本的jni程序,或许可以参考下面下面这些文章:利用V ...
- Jni中C++和Java的参数传递
Jni中C++和Java的参数传递 如何使用JNI的一些基本方法和过程在网上多如牛毛,如果你对Jni不甚了解,不知道Jni是做什么的,如何建立一个基本的jni程序,或许可以参考下面下面这些文章:利用V ...
- Jni中C++和Java的参数传递(转)
如何使用JNI的一些基本方法和过程在网上多如牛毛,如果你对Jni不甚了解,不知道Jni是做什么的,如何建立一个基本的jni程序,或许可以参考下面下面这些文章:利用VC++6.0实现JNI的最简单的例子 ...
- Android JNI c/c++调用java 无需新建虚拟机
近期通过研究SDL源码 得出android JNI c/c++调用java 无需新建虚拟机: 具体步骤如下 第一步获得:两个参数 JNIEnv和jclass void Java_com_Test_A ...
- Linux上设置开机启动Java程序
在Linux上设置开机启动Java程序,例如:test.jar 在Linux上启动Java程序的命令: nohup java -jar test.jar >/dev/>& & ...
- Android JNI中C和JAVA代码之间的互相调用
关于Android studio中使用NDK/JNI环境和入门:http://blog.csdn.net/quan648997767/article/details/64923143 1. C代码回调 ...
- JNI中C调用Java方法
背景需求 我们需要在JNI的C代码调用Java代码.实现原理:使用JNI提供的反射借口来反射得到Java方法,进行调用. JNI关键方法讲解. 1. 在同一个类中,调用其他方法 JNIEXPORT v ...
- JNI字段描述符-Java Native Interface Field Descriptors
一.JNI字段描述符 "[I" --- int[] "[[[D" --- double[][][] 如果以一个L开头的描述符,就是类描述符,它后紧跟着类的字符 ...
随机推荐
- Unity3d导出Recast geomset.txt
Unity3d导出Recast geomset.txt (金庆的专栏) Recast Demo 输入需要 geomset.txt 文件来指定区域类型. 以ObjExporter.cs为基础,编写Uni ...
- ORACLE数据库管理常用查询语句
/*查看表空间的名称及大小*/ SELECT t.tablespace_name, round(SUM(bytes / (1024 * 1024)), 0) ts_size FROM dba_tabl ...
- EBS各个应用简称
模块全称 Banking Center 模块简称 FPT 服务器目录 FPT_TOP Billing Connect CUE CUE_TOP CADView-3D DDD DDD_TOP CPG ...
- java虚拟机 jvm 栈数据区
java栈帧还是需要一些数据支持常量池的解析.正常方法的返回和异常的处理.大部分的java字节码指令需要进行常量池的访问,在栈帧数据区中保存着访问常量池的指针,方便程序访问java常量池.如下图所示: ...
- 迎战大数据-Oracle篇
来自:http://www.cnblogs.com/wenllsz/archive/2012/11/16/2774205.html 了解大数据带来的机遇: 透视架构与工具: 开源节流,获得竞争优势. ...
- spark shuffle
Spark Shuffle 1. Shuffle相关 当Map的输出结果要被Reduce使用时,输出结果需要按key哈希,并且分发到每一个Reducer上去,这个过程就是shuffle.由于shuff ...
- JavaScript介绍-javaScript学习之旅(一)
javaScript简介 1.javaScript是互联网上最流行的脚本语言,这门可用于web和html,更可广泛用于服务器端,pc端,移动端. 2.javaScript脚本语言: javaScrip ...
- Dynamics CRM2011/2013 删除个人视图
这里以2013为例,2011同理.个人视图的功能很人性化,可以设置自己常看数据列表形式而不会去影响别人,但创建容易怎么删除还真不一定能找得到地,具体见下方截图.
- A*寻路算法入门(六)
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...
- UITableView大总结(上)
1.UITableView继承UIScrollView. 2.实例一城市列表思路: 步骤一:创建UITableView.UITableView样式为组 步骤二:设置UITableView的数据源方法. ...