前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JNI接口操作实践(二)

JNI接口操作实践(二)

作者头像
用户4148957
发布2022-06-14 09:08:42
5220
发布2022-06-14 09:08:42
举报
文章被收录于专栏:C/C++与音视频

前面介绍了JNI的基本规范以及JNI的接口的生成过程。本文通过一个jni_test 应用实践操作JNI的接口各种典型应用。

    jni_test从jni的字符串,数组,基本类型,自定义类,C回调java静态方法,C回调Java的实例方法,C访问Java的静态变量,C访问Java的实例变量,Java传内存数据给C,C传内存数据给Java 共10个demo演示jni各种典型应用场景。

一、UI设计

通过修改active_main.xml(为了简单起见采用相对布局),或者直接使用design工具拖动布局(先拖一个layout线下布局,再在该布局上排上控件,类似MFC的UI设计原理),UI效果如下。

                                   jni_test的UI界面

二、JIN接口的定义

Java JNI接口声明如下:

代码语言:javascript
复制
public native String stringFromJNI(String src);
public native String CallbackFuncTest();
public native int CallbackClassTest();
public native int CallbackStaticVarTest();
public native int CallbackVarTest(TestNative obj);
public native int add(int x,int y);
public native int [] updateArray(int [] src,int len);
public native void passmem2C(int [] src,int len);
public native int [] getmem2C();

 三、在native层jni实现如下:

代码语言:javascript
复制
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_jni_1test_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */,
        jstring src) {
    std::string hello = "Hello3 from C++";
    const char* native_string = env->GetStringUTFChars(src, NULL);
    std::string temp(native_string);
    std::string dst = hello+temp;
    env->ReleaseStringUTFChars(src, native_string);
    return env->NewStringUTF(dst.c_str());
}
//回调java 静态的方法
extern "C" JNIEXPORT jstring Java_com_example_jni_1test_MainActivity_CallbackFuncTest(
        JNIEnv* env,
jobject /* this */ ){
    jclass mJclass;
    jstring mJstring;
    jmethodID mJStaticmethodID;
    //1.从classpath路径下搜索ClassMethod这个类,并返回该类的Class对象
    int i = 0;
    mJclass = env->FindClass("com/example/jni_test/TestNative"); //JNIEnv*, const char*
    if (mJclass == NULL) {
        LOGI("test","callJavaStaticMethod==>>mJclass==NULL==>>%s", "");
        return env->NewStringUTF("CallbackTest is failed");
    }
    // 2、从clazz类中查找callStaticMethod方法
    mJStaticmethodID = env->GetStaticMethodID(mJclass,
                                              "settext",
                                              "(Ljava/lang/String;)V"); //JNIEnv*, jclass, const char*, const char*
    if (mJStaticmethodID == NULL) {
        LOGI("test","=====>>>can not foud callStaticMethod");
        return env->NewStringUTF("CallbackFuncTest is failed");
    }
    mJstring= env->NewStringUTF("settext is now");
    env->CallStaticVoidMethod(mJclass, mJStaticmethodID, mJstring);
    // 删除局部引用
    env->DeleteLocalRef(mJstring);
    env->DeleteLocalRef(mJclass);
    return env->NewStringUTF("CallbackFuncTest is now");

}
//回调java中的类
extern "C" JNIEXPORT jint Java_com_example_jni_1test_MainActivity_CallbackClassTest(
        JNIEnv* env,
        jobject /* this */ ) {
    jclass mJclass = NULL;
    jmethodID jmethodID_Construct; //构造方法ID
    jmethodID jmethodID_Method_Instance; //方法的ID
    jmethodID jmethodID_Method_Instance2; //方法的ID
    jobject jobjectMyClass; //类的实例
    //1、从classpath路径下搜索ClassMethod这个类,并返回该类的Class对象
    mJclass = env->FindClass("com/example/jni_test/TestNative");
    if (mJclass == NULL) {
        printf("====FindClass  not found \n");
        return 0;
    }
    // 2、获取类的默认构造方法ID
    jmethodID_Construct = env->GetMethodID(mJclass, "<init>", "(I)V");
    if (jmethodID_Construct == NULL) {
        printf("GetMethodID not found ==>>jmethodID_Construct");
        return 0;
    }
    // 3、查找实例方法的ID
    jmethodID_Method_Instance = env->GetMethodID(mJclass,
                                                 "setnum", "(I)V");
    if (jmethodID_Method_Instance == NULL) {
        return 0;
    }
    // 4、创建该类的实例  调用无参构造方法  如果其它构造方法,后面可传参数
    jobjectMyClass = env->NewObject(mJclass, jmethodID_Construct,100); //JNIEnv*, jclass, jmethodID, ...
    if (jobjectMyClass == NULL) {
        return 0;
    }
    // 5、调用对象的实例方法

    env->CallVoidMethod(jobjectMyClass, jmethodID_Method_Instance,
                        100); //JNIEnv*, jobject, jmethodID, ...
    // 3、查找实例方法的ID
    jmethodID_Method_Instance2 = env->GetMethodID(mJclass,
                                                 "getnum", "()I");
    if (jmethodID_Method_Instance2 == NULL) {
        return 0;
    }
    int ret;
    ret=env->CallIntMethod(jobjectMyClass, jmethodID_Method_Instance2); //JNIEnv*, jobject, jmethodID, ...

    // 删除局部引用
    env->DeleteLocalRef(jobjectMyClass);
    return ret;
}
//回调java中的类中静态变量
extern "C" JNIEXPORT jint Java_com_example_jni_1test_MainActivity_CallbackStaticVarTest(
        JNIEnv* env,
        jobject /* this */ ) {
    jclass clazz;
    jfieldID fid;
   int test;

    //1.获取ClassField类的Class引用
    clazz = env->FindClass("com/example/jni_test/TestNative");
    if (clazz == NULL) { // 错误处理
        return 0;
    }
    //2.获取ClassField类静态变量test的属性ID
    fid = env->GetStaticFieldID(clazz, "iVar", "I");
    if (fid == NULL) {
        return 0;
    }

    // 3.获取静态变量test的值


    test = env->GetStaticIntField(
            clazz,
            fid);
    LOGI("test","test = %d\n", test);
    // 4.修改静态变量num的值
    jint ret = 55;
    env->SetStaticIntField(clazz, fid, ret);
    test = env->GetStaticIntField(
            clazz,
            fid);
    // 删除属部引用
    env->DeleteLocalRef(clazz);
    return test;
}
extern "C" JNIEXPORT int Java_com_example_jni_1test_MainActivity_CallbackVarTest(
        JNIEnv* env,
        jobject /* this */,jobject obj) {
    jclass clazz;
    jfieldID fid;
    jstring j_str;
    jstring j_newStr;
    const char *c_str = NULL;
    // 1.获取AccessField类的Class引用
    clazz = env->GetObjectClass(obj);
    if (clazz == NULL) {
        return 0;
    }
    // 2. 获取AccessField类实例变量str的属性ID
    fid = env->GetFieldID(clazz, "str", "Ljava/lang/String;");
    if (clazz == NULL) {
        return 0;
    }
    // 3. 获取实例变量str的值
    j_str = static_cast<jstring>(env->GetObjectField(obj, fid)); //JNIEnv*, jobject, jfieldID
    if (j_str == NULL) {
        return 0;
    }
    // 4. 将unicode编码的java字符串转换成C风格字符串
    c_str = env->GetStringUTFChars(j_str, NULL); //JNIEnv*, jstring, jboolean*
    if (c_str == NULL) {
        return 0;
    }
    LOGI("test","In C--->ClassField.str = %s\n", c_str);
    env->ReleaseStringUTFChars(j_str, c_str); //JNIEnv*, jstring, const char*
    // 5. 修改实例变量str的值
    j_newStr = env->NewStringUTF("This is new String");
    if (j_newStr == NULL) {
        return 0;
    }
    env->SetObjectField(obj, fid, j_newStr); //JNIEnv*, jobject, jfieldID, jobject

    // 6.删除局部引用
    env->DeleteLocalRef(clazz); //JNIEnv*, jobject
    env->DeleteLocalRef(j_str); //JNIEnv*, jobject
    env->DeleteLocalRef(j_newStr); //JNIEnv*, jobject
    //env->DeleteLocalRef(env,fid);//JNIEnv*, jobject  返回的非object,不能使用 DeleteLocalRef
    //使用NewObject就会返回创建出来的实例的局部引用 可  DeleteLocalRef
    return 1;
}

extern "C" JNIEXPORT jint JNICALL Java_com_example_jni_1test_MainActivity_add
        (JNIEnv *env, jobject, jint x, jint y){
    int x1 =  x;
    int y1 = y;
    int sum = (x1+y1)*200;
    __android_log_print(ANDROID_LOG_DEBUG,"test","hello5 world");
    LOGD("test","hello sum is %d",sum);
    //printf("hello3 world");
   // std::cout<<"hello4 world"<<std::endl;
    return sum;
}
extern "C" JNIEXPORT jintArray JNICALL Java_com_example_jni_1test_MainActivity_updateArray
        (JNIEnv *env, jobject, jintArray src,jint len)
{
    jintArray dst;
    jint *cPArray = env->GetIntArrayElements(src, NULL);
    if (cPArray == NULL) {
        return 0; // JVM复制原始数据到缓冲区失败
    }
  //  jint i;
    for(int i=0;i<len;i++)
    {
        cPArray[i]=cPArray[i]+100;
        LOGD("test","cPArray %d",cPArray[i]);
    }
    //给java层返回数组方式1
    int cInts[len]; //定义一个数组
    for (int i = 0; i < len; i++) {
        cInts[i] = cPArray[i];
    }
    dst = env->NewIntArray(len);
    if (dst == NULL) {
        return NULL; /* out of memory error thrown */
    }
    //move from the temp structure to the java structure  将native数组转换为java层数组
    env->SetIntArrayRegion(dst, 0, sizeof(cInts) / sizeof(cInts[0]),
                           cInts);
    env->ReleaseIntArrayElements(src, cPArray, 0); // 释放可能复制的缓冲区
    return dst;
}
extern "C" JNIEXPORT void JNICALL Java_com_example_jni_1test_MainActivity_passmem2C
        (JNIEnv *env, jobject, jintArray src,jint len) {

    jintArray dst;
    int *cPArray = env->GetIntArrayElements(src, NULL);
    if (cPArray == NULL) {
        return ; // JVM复制原始数据到缓冲区失败
    }
    for(int i=0;i<len;i++)
    {
        *(cPArray+i)=i;
        LOGD("test","cPArray %d",  *(cPArray+i));
    }
    env->ReleaseIntArrayElements(src, cPArray, 0); // 释放可能复制的缓冲区
}
extern "C" JNIEXPORT jintArray JNICALL Java_com_example_jni_1test_MainActivity_getmem2C
        (JNIEnv *env, jobject){
    jintArray dst;
   int *p = (int *)malloc(10);
   if(!p)
   {
       LOGD("test","malloc is failed");
   }
    for(int i=0;i<10;i++)
    {
        *(p+i)=i;
        LOGD("test","navtive cPArray %d",  *(p+i));
    }
    dst = env->NewIntArray(10);
    if (dst == NULL) {
        return NULL; /* out of memory error thrown */
    }
    //move from the temp structure to the java structure  将native数组转换为java层数组
    env->SetIntArrayRegion(dst, 0, 10,p);
    return dst;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-08-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档