• Android JNI之C/C++层调用JAVA


    从C/C++层调用JAVA层代码步骤:

    1. 在JAVA类中创建java方法和本地方法

    public class TestNdk{
    int a;//本示例中将被修改的JAVA变量 Handler handler;
    public TestNdk(Handler handler){ this.handler = handler; setUp(); } public native void setUp();//本地方法 public native static int getStringFromNative();//本地方法 public int getA() { return a; } public native void setA(int a);//本地方法 public void notifyFiledChange(){//本示例中将被C/C++调用的JAVA方法 Message message = new Message(); Bundle bundle = new Bundle(); bundle.putInt("a",a); message.setData(bundle); message.what=1; handler.sendMessage(message); } static { System.loadLibrary("MyJni");//导入生成的链接库文件 } }

    2.在JNI文件夹下创建类对应的.h文件(可通过JAVAH命令生成该类的.h文件,就不赘述了),创建.cpp文件(用于编写C/C++层的代码)

    .h文件:

    #ifndef _Included_com_x_mp4player_TestNdk
    #define _Included_com_x_mp4player_TestNdk
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_x_mp4player_TestNdk
     * Method:    setUp
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_com_x_mp4player_TestNdk_setUp
      (JNIEnv *, jobject);
    
    /*
     * Class:     com_x_mp4player_TestNdk
     * Method:    setA
     * Signature: (I)V
     */
    JNIEXPORT void JNICALL Java_com_x_mp4player_TestNdk_setA
            (JNIEnv *env, jobject thiz,jint i);
    
    /*
     * Class:     com_x_mp4player_TestNdk
     * Method:    getStringFromNative
     * Signature: ()I
     */
    JNIEXPORT jint JNICALL Java_com_x_mp4player_TestNdk_getStringFromNative
      (JNIEnv *, jclass);
    
    #ifdef __cplusplus
    }
    #endif
    #endif

    .cpp文件

    #include <jni.h>
    #include <com_x_mp4player_TestNdk.h>
    
    jobject m_object;
    jmethodID m_mid;
    jfieldID m_fid;
    
    JNIEXPORT jint JNICALL Java_com_x_mp4player_TestNdk_getStringFromNative
            (JNIEnv *env, jclass cls) {
        return 1;
    }
    
    JNIEXPORT void JNICALL Java_com_x_mp4player_TestNdk_setUp
            (JNIEnv *env, jobject thiz) {
        jclass clazz = (*env).GetObjectClass(thiz);//获取该对象的类
        m_object = (*env).NewGlobalRef(thiz);//创建对象的本地变量
        m_mid =(*env).GetMethodID(clazz, "notifyFiledChange", "()V");//获取JAVA方法的ID
        m_fid = (*env).GetFieldID(clazz,"a","I");//获取java变量的ID
        return;
    }
    
    JNIEXPORT void JNICALL Java_com_x_mp4player_TestNdk_setA
            (JNIEnv *env, jobject thiz,jint i) {
        (*env).SetIntField( m_object, m_fid,i);
        (*env).CallVoidMethod(m_object,m_mid);
        return;
    }

    3.调用JAVA方法需要类的对象

    在C/C++层获取类的对象的方法有两种:

    • 通过JAVA层调用本地方法(如示例中的setUp()方法),在调用时,会传入对象jobject或者对象的类jclass

    JNIEXPORT void JNICALL Java_com_x_mp4player_TestNdk_setUp
            (JNIEnv *env, jobject thiz) {
        ...
        jclass clazz = (*env).GetObjectClass(thiz);//获取该对象的类
        ...
        return;
    }
    • 通过C/C++创建java对象

    方法如下:

    1.通过JAVA层的本地方法创建同类对象

    步骤:

    I.通过对象获取类

    II.通过类获取类的构造方法的ID

    III.基于方法ID和类,创建新对象

    JNIEXPORT void JNICALL JAVA_nativeMethod
            (JNIEnv *env, jobject thiz,jint i){
        ...
        jclass clazz = (*env).GetObjectClass(thiz);
        jmethodID mid = (*env).GetMethodID(clazz,"<init>","()V");
        jobject obj = (*env).NewObject(clazz,mid);
        ...
        return;
    }

    2.通过C/C++创建不同类对象

    步骤:

    I.通过FindClass方法获取需要的类

    II.通过类获取类的构造方法的ID

    III.基于方法ID和类,创建新对象

    JNIEXPORT void JNICALL JAVA_nativeMethod
            (JNIEnv *env, jobject thiz,jint i){
        ...
        jclass clazz = (*env).FindClass("com/x/test/Test");//参数为类路径
        jmethodID mid = (*env).GetMethodID(clazz,"<init>","()V");
        jobject obj = (*env).NewObject(clazz,mid);
        ...
        return;
    }

    3.通过C++直接创建

    4.调用java方法的步骤:

    1. 获取类的方法ID
    2. 基于对象和方法id调用JAVA方法

    • 示例中是java调用本地方法setUp后,调用本地方法setA(int i),在本地方法setA(int i)中调用JAVA方法notifyFiledChange()方法

    5.C/C++直接存取JAVA变量

    1. 获取对象的变量的ID
    2. 基于对象和变量id存取变量

  • 相关阅读:
    [洛谷 U68862] 奶牛滑迷宫 题解
    STL的妙用(二)——洛谷 P2073 送花
    平衡树 x 01-trie √
    最小生成树(大纲,待补全)
    单源最短路算法
    黑科技:如何提高整数域内高斯消元的精度和速度——高斯消元与辗转相除法的结合
    Scratch的入门笔记
    Ubuntu18.04安装Tensorflow
    Ubuntu18.04安装英伟达显卡驱动
    macOS下appstore提示未能完成该操作的解决办法
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/10605730.html
Copyright © 2020-2023  润新知