c 调用 java jni_java JNI 的实现(2)-java和C/C++的相互调用.

目录

概述

从第一篇

一,java代码:

我们稍微对类做了更改,如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 packagejuk.demo;2

3 public classJSay {4 //member/class field.

5 public static String country = "cn";6

7 public int age = 20;8

9 //native method.

10 public native voidchangeAge();11

12 public static native voidstaticSay();13

14 //member method.

15 public voidgetVoid() {16

17 }18

19 publicString getString() {20 return "json";21 }22

23 public intgetInt() {24 return 1;25 }26

27 private voidgetUnknown() {28

29 }30

31 public int[] getIntArray() {32 return new int[]{1,2};33 }34

35 //static method.

36 public static voidjavaStatic() {37 System.out.println(country + ", center china");;38 }39

40 static{41 System.loadLibrary("JNITestCCPP");42 }43

44

45 public static voidmain(String[] args) {46 //invoke native method.

47 JSay.staticSay();48

49 JSay jSay = newJSay();50 System.out.println("before invoke native,age=" +jSay.age);51 jSay.changeAge();52 System.out.println("after invoke native,age=" +jSay.age);53

54 }55

56 }

View Code

这次,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代码的关系:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 /*DO NOT EDIT THIS FILE - it is machine generated*/

2 #include "jni.h"

3 /*Header for class juk_demo_JSay*/

4

5 #ifndef _Included_juk_demo_JSay6 #define _Included_juk_demo_JSay

7 #ifdef __cplusplus8 extern "C"{9 #endif

10 /*

11 * Class: juk_demo_JSay12 * Method: changeAge13 * Signature: ()V14 */

15 JNIEXPORT voidJNICALL Java_juk_demo_JSay_changeAge16 (JNIEnv *, jobject);17

18 /*

19 * Class: juk_demo_JSay20 * Method: staticSay21 * Signature: ()V22 */

23 JNIEXPORT voidJNICALL Java_juk_demo_JSay_staticSay24 (JNIEnv *, jclass);25

26 #ifdef __cplusplus27 }28 #endif

29 #endif

View Code

我们发现,通过javah命令生成的C/C++.h头文件,不会在.h头文件中出现(这其实也是很合情理的,但是我们却可以通过java中的native方法对应的.h中的方法的参数'JNIEnv *'去获得java中所有的成员).

三,在C/C++中实现java的native方法(完整C/C++):

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 #include

2 #include "juk_demo_JSay.h"

3 using namespacestd;4

5 //3 ways to get jclass:

6 /*

7 1,(JNIEnv *)->FindClass(class-name),which find the class by the classpath.8 2,(JNIEnv *)->GetObjectClass(jobject).9 3,(JNIEnv *)->GetSuperclass(jobject).10 */

11

12 /*

13 * Class: juk_demo_JSay14 * Method: changeAge15 * Signature: ()V16 */

17 JNIEXPORT voidJNICALL Java_juk_demo_JSay_changeAge18 (JNIEnv *env, jobject obj) {19 jclass JSayClass = env->GetObjectClass(obj);20 jfieldID ageId = env->GetFieldID(JSayClass, "age", "I");21 //env->GetIntField(obj, ageId);

22 env->SetIntField(obj, ageId, 22); //set the age with a new value.

23 }24

25 /*

26 * Class: juk_demo_JSay27 * Method: staticSay28 * Signature: ()V29 */

30 JNIEXPORT voidJNICALL Java_juk_demo_JSay_staticSay31 (JNIEnv *env, jclass clz) {32 //jclass JSayClass = env->FindClass("juk.demo.JSay");33

34 //javaStatic method.35 //the third argument,can be fetch with 'javap' command.

36 jmethodID getStaticMethodId = env->GetStaticMethodID(clz, "javaStatic", "()V");37 env->CallStaticVoidMethod(clz, getStaticMethodId, NULL);38

39 //get age field.

40 /*jfieldID countryId = env->GetStaticFieldID(JSayClass, "country", "Ljava/lang/String;");41 env->GetStaticObjectField(JSayClass, countryId);*/

42 }

View Code

1,修改age,即Java_juk_demo_JSay_changeAge方法,我们首先要获得jclass对象(jclass对应于java中的Class对象),而jclass对象的获得可以根据3中方式:

1,(JNIEnv *)->FindClass(class-name),which find the classby the classpath.2,(JNIEnv *)->GetObjectClass(jobject).3,(JNIEnv *)->GetSuperclass(jobject).

然后可以通过(JNIEnv *)获得属性的ID,并修改.稍微注意的是'env->GetFieldID'方法中的第3个参数,是为了区别方法的重载问题,

Java VM Type Signatures

Type SignatureJava 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',即可得到对应的签名,如:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 Compiled from "JSay.java"

2 public classjuk.demo.JSay extends java.lang.Object{3 public staticjava.lang.String country;4 Signature: Ljava/lang/String;5 public intage;6 Signature: I7 publicjuk.demo.JSay();8 Signature: ()V9 public native voidchangeAge();10 Signature: ()V11 public static native voidstaticSay();12 Signature: ()V13 public voidgetVoid();14 Signature: ()V15 publicjava.lang.String getString();16 Signature: ()Ljava/lang/String;17 public intgetInt();18 Signature: ()I19 public int[] getIntArray();20 Signature: ()[I21 public static voidjavaStatic();22 Signature: ()V23 public static voidmain(java.lang.String[]);24 Signature: ([Ljava/lang/String;)V25 }

View Code

2,调用java中的'javaStatic'方法,和上面C/C+实现方法相似,不过由于在java源码中,native被定义成了类方法,所以不用获得jclass,而直接从参数获取.同理,通过(JNIEnv *)获得java中的javaStatic方法,并调用.

最后,我们再java主函数中进行测试,结果为:

cn, center china

before invoke native,age=20after invoke native,age=22

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值