被回调的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,3,data);
env->CallStaticVoidMethod(clz,methodId,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);
关于更多的函数签名相关内容,可参考上篇日志。
CSDN同步发布地址
网友评论