前言
关于JNI/NDK的博客,开发指南等网上都有很多资源,而且这篇博客的主要内容是关于集合对象的互传,所以就不再介绍了。
附上一个开发指南开发指南链接。
#Java层传递集合对象到Native层
在java层新建一个简单的类
public class Test {
private int a;
static int num = 1;
public Test (){
this.a= num;
num ++;
}
}
在MainActivity中声明native方法,并把集合作为方法参数传递到native层
public class MainActivity extends AppCompatActivity {
ArrayList<Test> list;
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = (TextView) findViewById(R.id.sample_text);
//创建三个Test实例对象
list = new ArrayList<>();
list.add(new Test ());
list.add(new Test ());
list.add(new Test ());
tv.setText(stringFromJNI(list));
}
public native String stringFromJNI(ArrayList<Test> list);
}
编写native-lib.cpp
#include <jni.h>
extern "C" JNIEXPORT jint
JNICALL
Java_com_example_a7w4kkq2_ndkdemo_MainActivity_stringFromJNI(
JNIEnv *env,
jobject jobject1,jobject jobject) {
//获取ArrayList的class
jclass list_cls = env->GetObjectClass(jobject);
//获得ArrayList的get方法,获取其中的对象,这里要注意签名
jmethodID jmethodID1 = env->GetMethodID(list_cls,"get","(I)Ljava/lang/Object;");
jmethodID jmethodID2 = env->GetMethodID(list_cls,"size","()I");
//释放jclass的资源
env->DeleteLocalRef(list_cls);
//获得Test,以便得到其中的成员变量a
jclass test_cls = env->FindClass("com/example/a7w4kkq2/ndkdemo/Test");
jfieldID jfieldID1 = env->GetFieldID(test_cls,"a","I");
env->DeleteLocalRef(test_cls);
int sum = 0;
int size = env->CallIntMethod(jobject,jmethodID2);
for (int i = 0; i < size; ++i) {
//在jni.h中typedef _jobject* jobject;
//获得ArrayList中的第i个元素
//CallObjectMethod()中的第一个参数为调用方法的对象,第二个参数为方法签名,接下来依次为传入方法的参数
jobject test = env->CallObjectMethod(jobject,jmethodID1,i);
sum = sum + env->GetIntField(test,jfieldID1);
//释放jobject的资源
env->DeleteLocalRef(test);
}
return sum;
}
需要注意的是,在jni中除了基本类型不需要手动释放,引用数据类型jclass,jobect,jintArray 等都需要手动释放。