Android JNI Getting Started

Reference: the Java JNI to interact with CC ++ programming

AndroidStudio use JNI to achieve Log log , we implemented a simple Java调用C++的方法example, took in the realization of a more complex interaction of Java and C ++.

Java call C ++

In the definition of the native methods MainActivity.java addTest01, and invokes the method corresponding to the incoming values, as follows:

Here Insert Picture Description

Java native-lib.cpp received in the incoming value, and conversion, the output value corresponding to the print log.
Here Insert Picture Description
Output results are as follows:
Here Insert Picture Description

It can be seen from the above output, java array in which a value has changed, because the memory address directly modify the values ​​in the C ++ as follows:

Here Insert Picture Description

C ++ calling Java

We define a Student class, attribute values ​​corresponding to the print process in the set, and defines a static method myStaticMethod, as follows:
Here Insert Picture Description
Here Insert Picture Description

Methods test03 method set to Student's age and name attribute values, and call the method of putStudent native, then we need to call in C ++, Java Student in and modify the value of the age and name of.
Here Insert Picture Description

Here Insert Picture Description
You can see in the output, we not only call methods Student is in C ++, the name and age also modify the property value.

javap -s acquisition method signature

For the following method signature we can generate by javap -s
Here Insert Picture Description

Find the following directory
Here Insert Picture Description
to open the command line
Here Insert Picture Description
, type:javap -s com.hongx.jni.Student

Here Insert Picture Description

Paste the code

package com.hongx.jni;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    String TAG = "Hongx";
    static {
        System.loadLibrary("native-lib");
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView tv = findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
          //test01();
//        test02();
        test03();
    }
    public native String stringFromJNI();
    public native void test01();
    public native void addTest01(int number, String text, int[] intArray, String[] array);
    public native void putStudent(Student student);
    
    public void test03() {
        Student student = new Student();
        student.age = 98;
        student.name = "雄霸";
        putStudent(student);
    }
    public void test02() {
        int[] ints = {1,2,3,4,5,6};
        String[] strings = {"李小龙", "李连杰"};
        addTest01(9527, "李元霸", ints, strings);
        for (int anInt : ints) {
            Log.d(TAG, "test02: " + anInt);
        }
    }
}
package com.hongx.jni;

import android.util.Log;

public class Student {
    private final static String TAG = Student.class.getSimpleName();
    public String name;
    public int age;
    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;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    public static void myStaticMethod() {
        Log.d(TAG, "myStaticMethod: ");
    }
}
#include <jni.h>
#include <string>
#include <android/log.h>

#define TAG "Hongx"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)

extern "C" JNIEXPORT jstring JNICALL
Java_com_hongx_jni_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}
extern "C" // 支持C语言的代码
JNIEXPORT // Linux 和 Windows jni.h 内部定义全部都不一样,此宏代表我要暴露出去的标准形式定义
// 例如:在Windows中,对外暴露的标准就规定了,所以函数必须是Windows系统规则定义的

void JNICALL // Linux 和 Windows jni.h 内部定义全部都不一样,此宏代表 当前函数 压栈规则(行参规则)
// 例如:Windows中:代表函数压栈 从右 到 左边
Java_com_hongx_jni_MainActivity_test01(JNIEnv *env, jobject thiz) {
    LOGD("test01");
}

extern "C"
JNIEXPORT void JNICALL
Java_com_hongx_jni_MainActivity_addTest01(JNIEnv *env,  // Java虚拟机 自动携带过来的,就是为了 让我们可以使用JNI的API
                                          jobject thiz, // java中的 MainActivity 这个实例
                                          jint number,jstring text,jintArray int_array,jobjectArray string_array) {
    // C领域中         JNI领域中          Java领域中
    // int             jint             int
    // const char *    jstring          String
    int my_number = number;
    LOGD("my_number: %d\n", my_number);
    // 参数二:第一重意思:是否在内部完成Copy操作,NULL==0 false,  第二重意思:要给他一个值,让内部可以转起来,这个值,随意
    const char *my_text = env->GetStringUTFChars(text, NULL);
    LOGD("my_text: %s\n", my_text);
    // 回收 GetStringUTFChars
    env->ReleaseStringUTFChars(text, my_text);
    // 打印Int数组
    // jint* GetIntArrayElements(jintArray array, jboolean* isCopy)
    jint *my_int_array = env->GetIntArrayElements(int_array, NULL);
    // jsize GetArrayLength(jarray array)
    jsize intsize = env->GetArrayLength(int_array);
    for (int i = 0; i < intsize; ++i) {
        int result = *(my_int_array + i);
        *(my_int_array + i) += 1000;
        LOGD("遍历IntArray里面的值:%d\n", result);
    }
    // 回收
    env->ReleaseIntArrayElements(int_array, my_int_array, 0); // 0代表要刷新
    // 打印String数组
    jsize jsize1 = env->GetArrayLength(string_array);
    for (int i = 0; i < jsize1; i++) {
        jobject jobject1 = env->GetObjectArrayElement(string_array, i);
        jstring jstring1 = static_cast<jstring>(jobject1);
        const char *itemStr = env->GetStringUTFChars(jstring1, NULL);
        LOGD("遍历String Array 里面的值:%s\n", itemStr);
        env->ReleaseStringUTFChars(jstring1, itemStr);   // 回收
    }
}
extern "C"
JNIEXPORT void JNICALL
Java_com_hongx_jni_MainActivity_putStudent(JNIEnv *env,
                                           jobject thiz,
                                           jobject student) {
    // C领域中         JNI领域中          Java领域中
    //                jclass            class
    //                jmethodID         Method
    // 1.获取字节码
    const char * student_clss_str = "com/hongx/jni/Student";
    jclass student_class = env->FindClass(student_clss_str);
    // 2.拿到方法对象
    const char * sig = "(Ljava/lang/String;)V"; // 方法签名  javap -s 全类名 必须在.class下
    jmethodID  setName = env->GetMethodID(student_class, "setName", sig);
    sig = "(I)V";
    jmethodID setAge = env->GetMethodID(student_class, "setAge", sig);
    sig = "()V";
    jmethodID myStaticMethod = env->GetStaticMethodID(student_class, "myStaticMethod", sig);
    // 3.调用对象
    const char * str = "AAAAAAAA";
    jstring str2 = env->NewStringUTF(str);
    env->CallVoidMethod(student, setName, str2);
    env->CallVoidMethod(student, setAge, 888);
    env->CallStaticVoidMethod(student_class, myStaticMethod);
    env->DeleteLocalRef(student_class); // 回收
    env->DeleteLocalRef(student); // 回收
}
Published 446 original articles · won praise 67 · views 240 000 +

Guess you like

Origin blog.csdn.net/hongxue8888/article/details/105110516