你好,JNI

239 阅读3分钟

第二天

c中获取java的属性,并修改属性;c调用java中的方法

一、公共成员属性

1、首先java层定义native方法 以及调用方法

package com.sohubill.ndkstudy;



public class Study1 {
	static {
		System.load("G:\\NDKProjcet\\NdkJni\\x64\\Debug\\NdkJni.dll");
	}
	
	public String mName = "bill";
	public native void changeName();
	
	public static void main(String[] args) {
		Study1 study = new Study1();
		System.out.println("java中原来的name = "+study.mName);
		study.changeName();
		System.out.println("经过navtice改变后的名字"+study.mName);
	}
	
}

2、头文件添加方法

#include "jni.h"

#ifndef _Included_com_sohubill_ndkstudy_Study1
#define _Included_com_sohubill_ndkstudy_Study1
#ifdef __cplusplus
extern "C" {
#endif


JNIEXPORT void JNICALL Java_com_sohubill_ndkstudy_Study1_changeName
(JNIEnv*, jobject);


#ifdef __cplusplus
}
#endif
#endif

3、c文件实现方法

#include "com_sohubill_ndkstudy_Study1.h"

JNIEXPORT void JNICALL Java_com_sohubill_ndkstudy_Study1_changeName
(JNIEnv* env, jobject jobj) {

	//3、需要得到jclass需要用到GetObjectClass方法,参数是(JNIEnv *env, jclass jobj);
	jclass j_class = (*env)->GetObjectClass(env, jobj);

	//2、需要得到jfieldID需要用到GetFieldID方法,参数是(JNIEnv *env, jclass clazz, const char *name, const char *sig);
	//	由此可知需要获取jclass *sig是方法签名,Java中类签名规则是L+类全名(.改成/)+; int 是I,float是F等
	jfieldID j_fieldID = (*env)->GetFieldID(env, j_class, "mName", "Ljava/lang/String;");

	//1、需要得到java中的String元素需要用到*env中 GetObjectField方法,参数是 (JNIEnv *env, jobject obj, jfieldID fieldID);
	//	由此可知需要获得jfieldID;
	jstring j_str = (*env)->GetObjectField(env, jobj, j_fieldID);
	char* c_str = (*env)->GetStringUTFChars(env, j_str, NULL);
	printf("c中得到的java字符串是:%s", c_str);

	//4、修改java中的属性
	jstring j_newStr = (*env)->NewStringUTF(env, "jack");
	(*env)->SetObjectField(env, jobj, j_fieldID, j_newStr);
	//5、j_str没有使用了,需要释放资源。j_newStr会返回给java层,还在使用不能释放内存.
	(*env)->ReleaseStringUTFChars(env, j_str, c_str);
}

运行结果是:

java中原来的name = bill
经过navtice改变后的名字jack
c中得到的java字符串是:bill

二、公共静态属性

1、java 定义静态变量和native静态方法,并调用方法

package com.sohubill.ndkstudy;

public class Study1 {
	static {
		System.load("G:\\NDKProjcet\\NdkJni\\x64\\Debug\\NdkJni.dll");
	}

	public static int age = 30;
	public static native void changeAge();
	
	public static void main(String[] args) {
		System.out.println("java中原来的name = "+age);
		changeAge();
		System.out.println("经过navtice改变后的名字"+age);
	}
	
}

2、头文件添加对应的方法。这里是静态方法参数不是jboject 是jclass

#include "jni.h"

#ifndef _Included_com_sohubill_ndkstudy_Study1
#define _Included_com_sohubill_ndkstudy_Study1
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_com_sohubill_ndkstudy_Study1_changeAge
(JNIEnv*, jclass);


#ifdef __cplusplus
}
#endif
#endif

3、c文件实现方法

#include "com_sohubill_ndkstudy_Study1.h"

JNIEXPORT void JNICALL Java_com_sohubill_ndkstudy_Study1_changeAge
(JNIEnv* env, jclass jclass) {
	//2、需要得到jfieldID需要用到GetFieldID方法,参数是(JNIEnv *env, jclass clazz, const char *name, const char *sig);
	//	由此可知需要获取jclass *sig是方法签名,Java中类签名规则是L+类全名(.改成/)+; int 是I,float是F等
	jfieldID j_fieldID = (*env)->GetStaticFieldID(env, jclass, "age", "I");

	//1、需要得到java中的静态int元素需要用到*env中 GetStaticIntField方法,参数是 (JNIEnv *env, jclass clazz, jfieldID fieldID);
	//	由此可知需要获得jfieldID;
	jint j_age = (*env)->GetStaticIntField(env, jclass, j_fieldID);
	printf("c中得到的java整数是:%d", j_age);
	j_age = j_age + 15;
	//3、修改java中的属性
	(*env)->SetStaticIntField(env,jclass , j_fieldID, j_age);

}

三、c中调用java中的静态方法

1、java 定义一个方法以及实现,定义一个native方法,在c中实现这个navive访问java中的方法

package com.sohubill.ndkstudy;



public class Study1 {
	static {
		System.load("G:\\NDKProjcet\\NdkJni\\x64\\Debug\\NdkJni.dll");
	}
	
	public static int add(int x,int y) {
		return x+y;
	}
	public static native int useJavaMethod();
	
	public static void main(String[] args) {
		int res = useJavaMethod();
		System.out.println("c中调用java的add方法并传入参数12,13,运行结果是:"+res);
	}
}

2、头文件添加对应的方法。这里是静态方法参数不是jboject 是jclass

#include "jni.h"
#ifndef _Included_com_sohubill_ndkstudy_Study1
#define _Included_com_sohubill_ndkstudy_Study1
#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jint JNICALL Java_com_sohubill_ndkstudy_Study1_useJavaMethod
(JNIEnv*, jclass);


#ifdef __cplusplus
}
#endif
#endif

3、c文件实现方法

#include "com_sohubill_ndkstudy_Study1.h"

JNIEXPORT jint JNICALL Java_com_sohubill_ndkstudy_Study1_useJavaMethod
(JNIEnv* env, jclass jclass) {

	//2、利用 GetStaticMethodID获取jmethodID 参数时(JNIEnv *env, jclass clazz, const char *name, const char *sig);
	// *sig是方法签名 规则是【(参数...)返回值类型】比如 int XXX(int,int)则是(II)I void XXX(double,int)则是(DI)V
	jmethodID j_methodID =(*env)->GetStaticMethodID(env,jclass,"add","(II)I");

	//1、利用 CallStaticIntMethod 调用java中的静态方法, 参数(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
	//   需要获取jmethodID
	jint j_res = (*env)->CallStaticIntMethod(env, jclass, j_methodID, 12, 13);
	return j_res;
}

四、c中调用java的成员方法与静态方法类似。只是jclass换成jobject