Skip to content

Latest commit

 

History

History
157 lines (121 loc) · 4.57 KB

5.3预备知识-JNI C层访问java层.md

File metadata and controls

157 lines (121 loc) · 4.57 KB

6. C层访问Java类的field

java 层:

//成员变量
private int number = 88;
private String message = "Hello from Java";
//静态变量
private static double numberStatic = 1998.2;
//访问对象
private native void modifyVariable();

c 层:

JNIEXPORT void JNICALL Java_HelloJNI_modifyVariable(JNIEnv *env, jobject obj) {
    //0.获取到 jcalss
    jclass thisClass = env->GetObjectClass(obj);
  
    //1.获取到 filed 的 ID
    jfieldID numberId = env->GetFieldID(thisClass, "number", "I");
    if (nullptr == numberId) {
        return;
    }
    //2.根据 id 获取到 filed 
    jint number = env->GetIntField(obj, numberId);
    cout << "In C++, the number from java is " << number << endl;

    //3.给 filed 赋值
    number = 99;
    env->SetIntField(obj, numberId, number);

    //获取一个 String 成员变量,与获取 number 类似
    jfieldID messageId = env->GetFieldID(thisClass, "message", "Ljava/lang/String;");
    if(NULL == messageId) return;

    jstring message =  (jstring)env->GetObjectField(obj, messageId);

    const char* str = env->GetStringUTFChars(message, NULL);
    if(NULL == str) return;

    cout << "In C++, the message is " << str << endl;
    //内存清理
    env->ReleaseStringUTFChars(message, str);

    message = env->NewStringUTF("Hello from C++");
    if(NULL == message) return;

    env->SetObjectField(obj, messageId, message);

    //访问静态变量
    jfieldID staticNumberId = env->GetStaticFieldID(thisClass, "numberStatic", "D");
    if (nullptr == staticNumberId) {
        return;
    }
    jdouble number2 = env->GetStaticDoubleField(thisClass, staticNumberId);
    cout << "In C++, the static double is " << number2 << endl;

    number2 = 77.88;
    env->SetStaticDoubleField(thisClass, fidStaticNumber, number2);

}

GetFieldID 的最后一个参数是字段描述符:

描述符 含义
I int
B byte
S short
J long
F float
D double
C char
Z boolean
[I int[]
Ljava/lang/String String
[Ljava/lang/String String[]

7. C层调用Java层方法

java 层:

public class TestJNICallBackMethod{
    static {
        System.loadLibrary("myjni");
    }

    private native void nativeMethod();

    private void callback(){
        System.out.println("In Java");
    }

    private void callback(String message){
        System.out.println("In Java with " + message);
    }

    private double callbackAverage(int n1, int n2){
        return ((double)n1 + n2) / 2.0;
    }

    private static String callbackStatic(){
        return "From static Java method";
    }

    public static void main(String[] args){
        new TestJNICallBackMethod().nativeMethod();
    }
}

cpp 层:

#include "TestJNICallBackMethod.h"
#include <iostream>

using namespace std;

JNIEXPORT void JNICALL Java_TestJNICallBackMethod_nativeMethod(
    JNIEnv *env, jobject thisObj)
{
    jclass thisClass = env->GetObjectClass(thisObj);

    jmethodID midCallBack = env->GetMethodID(thisClass, "callback", "()V");
    if(NULL == midCallBack) return;
    cout << "In C++, call back Java's callback()\n";

    // Call back the method (which returns void), based on the Method ID
    env->CallVoidMethod(thisObj, midCallBack);

    jmethodID midCallBackStr = env->GetMethodID(thisClass, "callback", "(Ljava/lang/String;)V");
    if(NULL == midCallBackStr) return;
    cout << "In C++, call back Java's callback(String)\n";
    jstring message = env->NewStringUTF("Hello from C++");
    env->CallVoidMethod(thisObj, midCallBackStr, message);

    jmethodID midCallBackAverage = env->GetMethodID(thisClass, "callbackAverage", "(II)D");
    if(NULL == midCallBackAverage) return;
    jdouble average = env->CallDoubleMethod(thisObj, midCallBackAverage, 2, 3);
    cout << "In C++, the average is " << average << endl;

    jmethodID midCallBackStatic = env->GetStaticMethodID(thisClass, "callbackStatic", "()Ljava/lang/String;");
    if(NULL == midCallBackStatic) return;
    jstring resultJNIStr = (jstring)env->CallStaticObjectMethod(thisClass, midCallBackStatic);
    const char* resultStr = env->GetStringUTFChars(resultJNIStr, NULL);
    if(NULL == resultStr) return;
    cout << "In C++, the returned string is " << resultStr << endl;
    env->ReleaseStringUTFChars(resultJNIStr, resultStr);
}