JNI 玩转Java基本属性和对象
前景知识
Java,JNI,C++三者的关系
JNI是中转站,C++想要操作Java的数据,首先得第一条就是让JNI获取到Java的数据,也就是JAVA把数据传递给JNI,JNI经过一些列的处理,再传递给C++,
C++想把数据传递给Java,同样也需要通过JNI进行中转.Java与C++是相互分离的,不进行直接的交互
JNI和Java属性对应关系
Java | JNI |
---|---|
int | jint |
String | jstring |
boolean | jboolean |
byte | jbyte |
float | jfloat |
double | jdouble |
签名
Java | 签名 |
---|---|
int | I |
boolean | Z |
byte | B |
float | F |
double | D |
Lang | J |
String | Ljava/lan/string; |
object | Lxxx/xxx/xxx; |
前期准备文件
public class Student
{ private final static String TAG = Student.class.getSimpleName();
public String name="杰克逊";
public int age=18;
public static int id = 0;
public String getName() {
return name;
}
public void setName(String name) {
Log.d(TAG, "Java setName name:" + name);
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
Log.d(TAG, "Java setAge age:" + age);
this.age = age;
}
public static void showInfo(String info) {
Log.d(TAG, "showInfo info:" + info);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Java的基本属性
在Java中有一个这样的方法
public native void testArrayAction(jobject student, int[] ints, String[] strs);
与之对应的C++方法是这样的
extern "C"//按照C标准进行编译
JNIEXPORT void JNICALL
Java_com_json_testjni2_MainActivity_testArrayAction//方法名
(JNIEnv *env, jobject thiz, jint count,jstring text_info, jintArray ints,jobjectArray strs)
{}
我们的目的就是,操作传递过来的参数
extern "C"//按照C标准进行编译
JNIEXPORT void JNICALL
Java_com_json_testjni2_MainActivity_testArrayAction//方法名
(JNIEnv *env, jobject thiz, jint count,jstring text_info, jintArray ints,jobjectArray strs)
{
//操作属性
//获取Student的Class
jclass studentClass = env->GetObjectClass(student);
//获取属性名 第一个参数是类名,第二个参数是属性名,第三个参数是签名
jfieldID nameId = env->GetFieldID(studentClass, "name", "Ljava/lang/String;");
//获取属性值
jstring j_name = static_cast<jstring>(env->GetObjectField(student, nameId));
//把JNI字符串转换成C++类型
char *c_name = const_cast<char *>(env->GetStringUTFChars(j_name, NULL));
LOGI("我是 string 类型参数 %s", str);//打印 这是一个宏定义 #define TAG "jason" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)
//设置name值
//把字符串转换成JNI类型
jstring j_string = env->NewStringUTF("迈巴赫");
//设置属性字符串 第一个参数是JNI类型的对象名,第二个阐述属性Id,第三个参数是Value
env->SetObjectField(student, nameId, j_string);
//操作方法
//调用setName方法
//获取方法Id 第一个参数:类名,第二个参数:方法名,第三个参数:方法签名
jmethodID setName = env->GetMethodID(studentClass, "setName", "(Ljava/lang/String;)V");
jstring j_string = env->NewStringUTF("冯家振");
env->CallVoidMethod(studentObject, setName, j_string); //调用没有返回值得方法
//调用 getName
jmethodID getName = env->GetMethodID(studentClass, "getName", "()Ljava/lang/String;");
jstring name = static_cast<jstring >(env->CallObjectMethod(studentObject, getName));
char *c_name = const_cast<char *>(env->GetStringUTFChars(name, NULL));
LOGI("我是 getName 参数 %s", c_name);
//调用静态属性并赋值
//获取静态属性ID
jfieldID j_staticFieldId=env->GetStaticFieldID(studentClass,"id","I");
//获取值
jint j_int = env->GetStaticIntField(studentClass, j_staticFieldId);
LOGI("我是 int 类型参数 %d", j_int);
//设置值
env->SetStaticIntField(studentClass, j_staticFieldId, 10);
//调用静态方法
jmethodID showInfo = env->GetStaticMethodID(studentClass, "showInfo", "(Ljava/lang/String;)V");
jstring info = env->NewStringUTF("冯家振");
env->CallStaticVoidMethod(studentClass, showInfo, info);
}
创建Java对象
extern "C"
JNIEXPORT void JNICALL
Java_com_json_testjni2_MainActivity_insertObject(JNIEnv *env, jobject thiz) {
// TODO: implement insertObject()
const char *studentPath = "com/json/testjni2/Student";
jclass studentClass = env->FindClass(studentPath);
//Alloc 只实例化对象,不会调用构造函数
jobject studentObject=env->AllocObject(studentClass);
jmethodID setName = env->GetMethodID(studentClass, "setName", "(Ljava/lang/String;)V");
jstring j_string = env->NewStringUTF("冯家振");
env->CallVoidMethod(studentObject, setName, j_string);
jmethodID getName = env->GetMethodID(studentClass, "getName", "()Ljava/lang/String;");
jstring name = static_cast<jstring >(env->CallObjectMethod(studentObject, getName));
char *c_name = const_cast<char *>(env->GetStringUTFChars(name, NULL));
LOGI("我是 getName 参数 %s", c_name);
}