java JNI 的实现(2)-java和C/C++的相互调用.
目录
二,稍微注意通过javah生成的'C/C++'.h头文件和源java代码的关系
三,在C/C++中实现java的native方法(完整C/C++)
1,修改age,即Java_juk_demo_JSay_changeAge方法
2,调用java中的'javaStatic'方法,和上面C/C+实现方法相似
概述
从第一篇java JNI 的实现(1)-又进一步加深对JVM实现的理解对JNI有了大致的理解之后,并知道JNI中java如何调用C/C++等,这篇文章我们进一步将JNI中,java和C/C++的相互调用.
一,java代码:
我们稍微对类做了更改,如下:
package juk.demo; public class JSay {
//member/class field.
public static String country = "cn"; public int age = 20; //native method.
public native void changeAge(); public static native void staticSay(); //member method.
public void getVoid() { } public String getString() {
return "json";
} public int getInt() {
return 1;
} private void getUnknown() { } public int[] getIntArray() {
return new int[]{1,2};
} //static method.
public static void javaStatic() {
System.out.println(country + ", center china");;
} static {
System.loadLibrary("JNITestCCPP");
} public static void main(String[] args) {
//invoke native method.
JSay.staticSay(); JSay jSay = new JSay();
System.out.println("before invoke native,age=" + jSay.age);
jSay.changeAge();
System.out.println("after invoke native,age=" + jSay.age); } }
这次,java代码有两个native方法(changeAge和staticSay),并且有许多成员和类的普通java方法(主要是研究通过javah产生的.h头文件和源java代码直接的关系),
我们这次的目的,一是在java中调用'changeAge' native方法的时候,在C/C++代码中对其对象的age属性进行更改(当然,一般成员变量都是封装的,这里只是为了测试);二是在java调用'staticSay' native方法的时候,在C/C++代码中,反过来调用java的'javaStatic'方法.
二,稍微注意通过javah生成的'C/C++'.h头文件和源java代码的关系:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class juk_demo_JSay */ #ifndef _Included_juk_demo_JSay
#define _Included_juk_demo_JSay
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: juk_demo_JSay
* Method: changeAge
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_juk_demo_JSay_changeAge
(JNIEnv *, jobject); /*
* Class: juk_demo_JSay
* Method: staticSay
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_juk_demo_JSay_staticSay
(JNIEnv *, jclass); #ifdef __cplusplus
}
#endif
#endif
我们发现,通过javah命令生成的C/C++.h头文件,不会在.h头文件中出现(这其实也是很合情理的,但是我们却可以通过java中的native方法对应的.h中的方法的参数'JNIEnv *'去获得java中所有的成员).
三,在C/C++中实现java的native方法(完整C/C++):
#include <iostream>
#include "juk_demo_JSay.h"
using namespace std; //3 ways to get jclass:
/*
1,(JNIEnv *)->FindClass(class-name),which find the class by the classpath.
2,(JNIEnv *)->GetObjectClass(jobject).
3,(JNIEnv *)->GetSuperclass(jobject).
*/ /*
* Class: juk_demo_JSay
* Method: changeAge
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_juk_demo_JSay_changeAge
(JNIEnv *env, jobject obj) {
jclass JSayClass = env->GetObjectClass(obj);
jfieldID ageId = env->GetFieldID(JSayClass, "age", "I");
//env->GetIntField(obj, ageId);
env->SetIntField(obj, ageId, ); //set the age with a new value.
} /*
* Class: juk_demo_JSay
* Method: staticSay
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_juk_demo_JSay_staticSay
(JNIEnv *env, jclass clz) {
//jclass JSayClass = env->FindClass("juk.demo.JSay"); //javaStatic method.
//the third argument,can be fetch with 'javap' command.
jmethodID getStaticMethodId = env->GetStaticMethodID(clz, "javaStatic", "()V");
env->CallStaticVoidMethod(clz, getStaticMethodId, NULL); //get age field.
/*jfieldID countryId = env->GetStaticFieldID(JSayClass, "country", "Ljava/lang/String;");
env->GetStaticObjectField(JSayClass, countryId);*/
}
1,修改age,即Java_juk_demo_JSay_changeAge方法,我们首先要获得jclass对象(jclass对应于java中的Class对象),而jclass对象的获得可以根据3中方式:
,(JNIEnv *)->FindClass(class-name),which find the class by the classpath.
,(JNIEnv *)->GetObjectClass(jobject).
,(JNIEnv *)->GetSuperclass(jobject).
然后可以通过(JNIEnv *)获得属性的ID,并修改.稍微注意的是'env->GetFieldID'方法中的第3个参数,是为了区别方法的重载问题,
如下表(来自oracle的Chapter 3: JNI Types and Data Structures)
Type Signature | Java Type |
---|---|
Z | boolean |
B | byte |
C | char |
S | short |
I | int |
J | long |
F | float |
D | double |
L fully-qualified-class ; | fully-qualified-class |
[ type | type[] |
( arg-types ) ret-type | method type |
sun为了方便我们程序员,写一个工具(即,jdk中的javap),而不用我们记忆那些类型签名,例如,我们可以在包含该java的class的目录上(通过命令行),输入 'javap -s -public juk.demo.JSay',即可得到对应的签名,如:
Compiled from "JSay.java"
public class juk.demo.JSay extends java.lang.Object{
public static java.lang.String country;
Signature: Ljava/lang/String;
public int age;
Signature: I
public juk.demo.JSay();
Signature: ()V
public native void changeAge();
Signature: ()V
public static native void staticSay();
Signature: ()V
public void getVoid();
Signature: ()V
public java.lang.String getString();
Signature: ()Ljava/lang/String;
public int getInt();
Signature: ()I
public int[] getIntArray();
Signature: ()[I
public static void javaStatic();
Signature: ()V
public static void main(java.lang.String[]);
Signature: ([Ljava/lang/String;)V
}
2,调用java中的'javaStatic'方法,和上面C/C+实现方法相似,不过由于在java源码中,native被定义成了类方法,所以不用获得jclass,而直接从参数获取.同理,通过(JNIEnv *)获得java中的javaStatic方法,并调用.
最后,我们再java主函数中进行测试,结果为:
cn, center china
before invoke native,age=
after invoke native,age=
java JNI 的实现(2)-java和C/C++的相互调用.的更多相关文章
- java JNI介绍
java JNI介绍 目录 java JNI介绍 1. Java调用C++代码 2.C++代码调用java代码 JNI是Java Native Interface的全称. oracle文档中是这样描述 ...
- 关于java jni编译javac javah的问题
这篇文章是在安卓教程网http://android.662p.com那边分享过来的,文章说得还不错的,希望能够帮到大家的学习. javac 编译class文件命令,需要注意的是当类B中import类 ...
- java + jni + mingw实例开发(基于命令行窗口模式)
java+ jni + mingw 参考网址: http://wenku.baidu.com/link?url=9aQ88d2ieO7IgKLlNhJi5d3mb3xwzbezLPzSIX3ixz4_ ...
- Jni中C++和Java的参数传递 参数对照
Jni中C++和Java的参数传递 如何使用JNI的一些基本方法和过程在网上多如牛毛,如果你对Jni不甚了解,不知道Jni是做什么的,如何建立一个基本的jni程序,或许可以参考下面下面这些文章:利用V ...
- Jni中C++和Java的参数传递
Jni中C++和Java的参数传递 如何使用JNI的一些基本方法和过程在网上多如牛毛,如果你对Jni不甚了解,不知道Jni是做什么的,如何建立一个基本的jni程序,或许可以参考下面下面这些文章:利用V ...
- 三、Android NDK编程预备之Java jni入门创建C/C++共享库
转自: http://www.eoeandroid.com/thread-264971-1-1.html 应网友回复,答应在两天前要出一篇创建C/C++共享库的,但由于清明节假期,跟朋友出去游玩,丢手 ...
- 二、Android NDK编程预备之Java jni入门Hello World
转自: http://www.eoeandroid.com/forum.php?mod=viewthread&tid=264543&fromuid=588695 昨天已经简要介绍了J ...
- 一、Android NDK编程预备之Java jni简介
转自: http://www.eoeandroid.com/thread-264384-1-1.html 游戏开发 视频教程 博客 淘帖 论坛›eoe·Android应用开发区›Androi ...
- Java JNI调用c语言的dll测试
最近复习C语言和java语言(10年没用了,温习一下),用JNI调用C语言的dll测试,以前没做过,在网上找了很多,总结如下: 环境:windows 10(64位) + JDK(32位,版本1.7.0 ...
随机推荐
- testservice小项目总结
关于自做小项目testservice的总结: 1.Activity与Service的绑定及之间的通信: 1)关于Activity和Service的生命周期的理解: 2)bindService方法中Se ...
- Linux bash重拾 2016-8-16
bash支持的引号: "" 双引号:弱引用,可以实现变量替换(变量会替换为值) [root@localhost ssh-6Xolw4LLAMwe]# echo "dire ...
- iOS页面间传值的方式 (Delegate/NSNotification/Block/NSUserDefault/单例)
iOS页面间传值的方式(Delegate/NSNotification/Block/NSUserDefault/单例) iOS页面间传值的方式(NSUserDefault/Delegate/NSN ...
- Xcode export/upload error: Your session has expired. Please log in-b
1.Xcode export/upload error: Your session has expired. Please log in 我在stack over flow上找到的答案: 一看pre ...
- 如何改变dreamweaver的编码方式
- Mifare S50与Mifare S70
转自http://blog.sina.com.cn/s/blog_9ed067ad0100zyjx.html Mifare S50和Mifare S70又常被称为Mifare Standard.Mif ...
- GIve Me A Welcome Hug!
类似于初来乍到,和大家打个招呼,并矫情的希望路人也能回赠我一个welcome hug. 到了这种园子那一定是做CS相关的了,一直以为如果能够坚持写技术博客,那一定会对自己的内力有十足的提升.借用一位前 ...
- UGUI穿透3D世界判断&&UGUI全事件监听
public bool isPointUI(){ PointerEventData eventDataCurrnt = new PointerEventData (EventSystem.curren ...
- 利用Asio搭建日志系统
Asio(http://think-async.com)官方示例中给出了一个比较初步的日志服务,主要代码在basic_logger.hpp.logger_service.hpp.logger_serv ...
- Ubuntu 启用root账户
设置分配很简单,只要为root设置一个root密码就行了: $ sudo passwd root 之后会提示要输入root用户的密码,连续输入root密码,再使用:$ su 就可以切换成超级管理员用户 ...