Android NDK - JNI 回调Java函数注意事项

被回调的Java静态函数中有数组参数

假设有如下Java函数待被JNI调用,但是由于Cpp中的数组和java中的数组是属于不同的数据类型,因此是无法直接传递的。
按照经验,极可能会在JNI中将基本数据类型数组直接传入,但这会报错。
因此传递之前,一定要C++中的数组进行本地化转换。

//Java 函数
package com.test.jni;
public class TestFunc{
    public static void testFunc(float vals[]){
        //...
    }
}

//JNI函数回调片段
jclass clz = jenv->FindClass("com/test/jni/TestFunc");
jmethodID methodId = env->GetMethodID(clz,"TestFunc","([F)V");
float[] data = new float[]{1.f,2.f};
//!!错误示例!!
env->CallStaticVoidMethod(clz,methodId,data);
//正确用例
jfloatArray array = env->NewFloatArray(2);
//参数1:待赋值数组;参数2:赋值起始位置;参数3:赋值长度;参数4:数据源
env->SetFloatArrayRegion(array,0,2,data);
env->CallStaticVoidMethod(clz,methodId,array);
//最后别忘记释放内存
env->ReleaseFloatArrayElements(array , (jfloat*) data , 0);
env->DeleteLocalRef(array);

如上例所示,由于C++中的数组与Java中存在差异,所以一定要在本地进行转换之后才能使用。同时,对于基本数据类型(int,float,double等),是可以直接传递的;当然,对待cpp中的string类型,也是不能直接传递的;

被回调的Java静态函数中有String 参数

由于CPP和java中的string/String是不同的,无法直接传递,举个栗子:

//Java 函数
package com.test.jni;
public class TestFunc{
    public static void testFunc(String str){
        //...
    }
}

//JNI函数回调片段
jclass clz = jenv->FindClass("com/test/jni/TestFunc");
jmethodID methodId = env->GetMethodID(clz,"TestFunc","(Ljava/lang/String;)V");
string data = "test";
//!!错误示例!!
env->CallStaticVoidMethod(clz,methodId,data);
//正确用例
jstring jstring1 = jenv->NewStringUTF(data.c_str());
env->CallStaticVoidMethod(clz,methodId,jstring1);

对于其他基本数据类型就可以直接传递。

对于非静态函数调用

在实际使用场景中,除了静态函数之外,更多的可能还有实例化方法,对于实例化函数的调用,我们势必需要持有一个实例化的引用才可以,所以就涉及本地化实例化操作。
举个栗子:

//Java 函数
package com.test.jni;
public class TestFunc{
    public TestFunc(){
    }
    
    public void testFunc(String str){
        //...
    }
}

//JNI函数回调片段
jclass clz = jenv->FindClass("com/test/jni/TestFunc");
//获取构造参数,多个构造参数根据函数签名确定
jmethodID methodIdConstructor = jenv->GetMethodID(clz, "<init>", "()V");
//通过调用构造函数创建本地化实例
jobject jobjClz = jenv->NewObject(clz, methodIdConstructor);
jmethodID methodId = env->GetMethodID(clz,"TestFunc","(Ljava/lang/String;)V");
//然后便可以调用实例化的方法
string data = "test";
jstring jstring1 = jenv->NewStringUTF(data.c_str());
env->CallVoidMethod(jobjClz,methodId,jstring1);

关于更多的函数签名相关内容,可参考上篇日志。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值