前言:在上一篇博客中介绍了jni的基本数据类型,本博客就要介绍些j访问ava对象的非静态属性和静态属性!
-----------分割线----------
我们先来看下对象的类型:
再来看一下java签名 每个java属性方法都有其对应的属性签名
上面的表只有一部分签名,如果发现你的方法没有签名需要自己在dos下查看:打开dos窗口 打开工程木…./src/bin/目录下 然后输入javap -s -p 包名.类名
---------------分割线------------
访问非静态属性通过jni更改属性的值:
java代码:
package com.fly;
public class TestJni {
// 创建一个非静态属性
String str = "hello";
public static void main(String[] args) {
TestJni tj = new TestJni();
System.out.println("--C没修改前:-->>" + tj.str);
// 进入c去修改
tj.jniCall();
System.out.println("--C没修改后:-->>" + tj.str);
}
// 访问java静态属性并且修改为 hello world
public native void jniCall();
// 加载动态库
static {
System.loadLibrary("JNI");
}
}
然后查找属性签名:
c头文件.h中:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class com_fly_TestJni */
#ifndef _Included_com_fly_TestJni
#define _Included_com_fly_TestJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_fly_TestJni
* Method: getCStringStatic
* Signature: ()Ljava/lang/String;
*/
//非静态的
JNIEXPORT jint JNICALL Java_com_fly_TestJni_jniCall
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
c源文件代码中:
#include"com_fly_TestJni.h"
JNIEXPORT jint JNICALL Java_com_fly_TestJni_jniCall
(JNIEnv *env, jobject jobj){
//获取jonj的class本例当中就是DemoJniBaseType的class对象
jclass cls = (*env)->GetObjectClass(env, jobj);
// 函数原型:jfieldID (JNICALL *GetFieldID)(JNIEnv *env, jclass clazz, const char *name, const char *sig);
// 第一个参数 不需要解释
// 第二个参数 属性所在对象的class本例当中就是TestJni的class对象
// 第三个参数 属性变量名字
// 第四个参数 属性签名
// 返回属性变量的id 在用id得到变量引用
jfieldID file_id = (*env)->GetFieldID(env, cls, "str", "Ljava/lang/String;");
//函数原型:jobject (JNICALL *GetObjectField)(JNIEnv *env, jobject obj, jfieldID fieldID);
//第一个参数 ..
//第二个参数 属性id
//返回 属性变量引用
jstring string = (*env)->GetObjectField(env, jobj, file_id);
//函数原型:const char* (JNICALL *GetStringUTFChars)(JNIEnv *env, jstring str, jboolean *isCopy);
//第一个参数...
//第二个参数 属性变量引用
//第三个参数 建议传入NULL 特别强调:调用此方法时内部会决定是否拷贝java属性变量的指针引用
// 如果拷贝了那么第三个参数 字面量就是true 反知
char * cchar = (*env)->GetStringUTFChars(env, string, NULL);
//printf("得到来自java的字符串%s",cchar);
////jstring(JNICALL *NewStringUTF)
// //(JNIEnv *env, const char *utf);
jstring newjstring = (*env)->NewStringUTF(env, "hello world");
//函数原型:void (JNICALL *SetObjectField)(JNIEnv *env, jobject obj, jfieldID fieldID, jobject val);
//第一个参数
//第二个参数 属性所在对象
//第三个参数 属性id
//第四个参数 赋值
//设置对象属性数值
(*env)->SetObjectField(env, jobj, file_id, newjstring);
//释放GetStringUTFChars 所拷贝java变量引用
//在取得字符串后,当已经不再之用,需要通过ReleaseStringChars、ReleaseStringUTFChars来释放拷贝所用的内存或释放Java的String对象的引用
(*env)->ReleaseStringChars(env, string, cchar);
}
最后生成dll文件复制到java项目的更目录中,运行:
--------分割线--------
访问静态属性通过jni更改属性的值:
java代码:
package com.fly;
public class TestJni {
// 创建一个静态属性
public static String str = "static hello";
public native static void callStaticStr();
public static void main(String[] args) {
callStaticStr();
System.out.println(str);
}
// 加载动态库
static {
System.loadLibrary("JNI");
}
}
C代码#include"com_fly_TestJni.h"
JNIEXPORT jint JNICALL Java_com_fly_TestJni_callStaticStr
(JNIEnv *env, jclass jcs){
//函数原型:jfieldID(JNICALL *GetStaticFieldID)(JNIEnv *env, jclass clazz, const char *name, const char *sig);
//第一个参数
//第二个参数 静态属性对应类的class
//第三个参数 静态属性名字
//第四个参数 属性签名
//返回 属性id
jfieldID field = (*env)->GetStaticFieldID(env, jcs, "str", "Ljava/lang/String;");
//函数原型jobject(JNICALL *GetStaticObjectField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
//第一个参数
//第二个参数 对应静态变量对应类的class
//第三个参数 静态属性的id
//返回对应object属性
jstring fields = (*env)->GetStaticObjectField(env, jcs, field);
printf("come from java string%s", (*env)->GetStringUTFChars(env, fields, NULL));
jstring restring = (*env)->NewStringUTF(env, "static hello world");
//函数原型void (JNICALL *SetStaticObjectField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value);
(*env)->SetStaticObjectField(env, jcs, field, restring);
}
运行:
--------完---------