Android NDK开发(二)数组
来源:互联网 发布:阿里云服务器好用吗 编辑:程序博客网 时间:2024/05/22 03:49
在这篇文章里记录一下C语言操作java数组的相关方法,通过一个简单的程序实现:在c语言里使用java生成的数组,在java里使用c语言生成的数组。
数据类型对应关系
首先我们来看一下,c语言和java语言里数据类型是如何对应的
// 基本类型typedef unsigned char jboolean; /* unsigned 8 bits */typedef signed char jbyte; /* signed 8 bits */typedef unsigned short jchar; /* unsigned 16 bits */typedef short jshort; /* signed 16 bits */typedef int jint; /* signed 32 bits */typedef long long jlong; /* signed 64 bits */typedef float jfloat; /* 32-bit IEEE 754 */typedef double jdouble; /* 64-bit IEEE 754 */typedef jint jsize;// 对象类型typedef void* jobject;typedef jobject jclass;typedef jobject jstring;typedef jobject jarray;typedef jarray jobjectArray;typedef jarray jbooleanArray;typedef jarray jbyteArray;typedef jarray jcharArray;typedef jarray jshortArray;typedef jarray jintArray;typedef jarray jlongArray;typedef jarray jfloatArray;typedef jarray jdoubleArray;typedef jobject jthrowable;typedef jobject jweak;
这里只截取与C语言有关的部分,如果想查看全部对应关系,请参考${ndk_dir}/platforms/android-14/arch-arm/usr/include/jni.h
相关方法
1、生成数组
jobjectArray (*NewObjectArray)(JNIEnv*, jsize, jclass, jobject); // 参数第四个参数用来初始化数组(All elements are initially set to initialElement.) jbooleanArray (*NewBooleanArray)(JNIEnv*, jsize); jbyteArray (*NewByteArray)(JNIEnv*, jsize); jcharArray (*NewCharArray)(JNIEnv*, jsize); jshortArray (*NewShortArray)(JNIEnv*, jsize); jintArray (*NewIntArray)(JNIEnv*, jsize); jlongArray (*NewLongArray)(JNIEnv*, jsize); jfloatArray (*NewFloatArray)(JNIEnv*, jsize); jdoubleArray (*NewDoubleArray)(JNIEnv*, jsize);
2、 获取长度
jsize (*GetArrayLength)(JNIEnv*, jarray);
3、获取数组里的内容
3、1、对象类型的数组
jobject (*GetObjectArrayElement)(JNIEnv*, jobjectArray, jsize);// 最后一个参数是要获取的对象在数组里的下标
3、2、基本类型数组
jboolean* (*GetBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*); jbyte* (*GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*); jchar* (*GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*); jshort* (*GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*); jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*); jlong* (*GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*); jfloat* (*GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*); jdouble* (*GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*);
A family of functions that returns the body of the primitive array. The result is valid until the corresponding ReleaseArrayElements() function is called. Since the returned array may be a copy of the Java array, changes made to the returned array will not necessarily be reflected in the original array until ReleaseArrayElements() is called.
If isCopy is not NULL, then *isCopy is set to JNI_TRUE if a copy is made; or it is set to JNI_FALSE if no copy is made.
PS:第三个参数:JNI_TRUE或者JNI_FALSE或者0
PS:如果我们调用这些方法时没有把数组赋值一份,用完后也需要调用对应的ReleaseArrayElements方法释放资源,否则会内存泄漏。
4、给数组赋值
4、1、对象类型
void (*SetObjectArrayElement)(JNIEnv*, jobjectArray, jsize, jobject);
4、2、基本数据类型
void (*ReleaseBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*, jint); void (*ReleaseByteArrayElements)(JNIEnv*, jbyteArray, jbyte*, jint); void (*ReleaseCharArrayElements)(JNIEnv*, jcharArray, jchar*, jint); void (*ReleaseShortArrayElements)(JNIEnv*, jshortArray, jshort*, jint); void (*ReleaseIntArrayElements)(JNIEnv*, jintArray, jint*, jint); void (*ReleaseLongArrayElements)(JNIEnv*, jlongArray, jlong*, jint); void (*ReleaseFloatArrayElements)(JNIEnv*, jfloatArray, jfloat*, jint); void (*ReleaseDoubleArrayElements)(JNIEnv*, jdoubleArray, jdouble*, jint);
最后一个参数:
0——-copy back the content and free the elems buffer
JNI_COMMIT——-copy back the content but do not free the elems buffer
JNI_ABORT——-free the buffer without copying back the possible changes
如果有其他参数不明白什么意思,可以参考http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/functions.html#wp9502
sample
–
1、新建项目,添加native修饰的方法
public class MainActivity extends Activity { public native int[] testArray(byte[] array); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); }}
2、在命令行,cd 到src目录下,执行命令
3、在项目跟目录下创建jni文件夹,把第二步生成的net_qingtian_array_MainActivity.h头文件拷贝在该目录下。
4、 在jni目录下新建一个c代码源文件,叫array.c,在array.c里把net_qingtian_array_MainActivity.h头文件里的方法给实现了
#include "net_qingtian_array_MainActivity.h"#include <android/log.h>JNIEXPORT jintArray JNICALL Java_net_qingtian_array_MainActivity_testArray (JNIEnv * env, jobject obj, jbyteArray _jbyteArray){ // 获取数组长度 jsize length = (*env)->GetArrayLength(env, _jbyteArray); __android_log_print(ANDROID_LOG_INFO, "qingtian", "byte数组长度:%d", length); // 获取c语言的数组 jbyte* _bytes = (*env)->GetByteArrayElements(env, _jbyteArray, JNI_FALSE); // 打印数组 int i = 0; for(i = 0 ; i < length ; i ++){ __android_log_print(ANDROID_LOG_INFO, "qingtian", "byte数组第%d个值:%d", i, _bytes[i]); } // 释放byte数组资源 (*env)->ReleaseByteArrayElements(env, _jbyteArray, _bytes, 0); // 生成jint数组,长度为传递进来的数组的两倍 jsize newLength = length * 2; jintArray _jintArray = (*env)->NewIntArray(env, newLength); // 获取jintArray对应的本地数组 jint* _jints = (*env)->GetIntArrayElements(env, _jintArray, JNI_FALSE); // 赋值 for(i = 0 ; i < newLength ; i ++){ _jints[i] = 20 + i; } // 释放int数组资源 (*env)->ReleaseIntArrayElements(env, _jintArray, _jints, 0); // 返回int数组 return _jintArray;}
5、 在jni下编写Android.mk,这是和编译打包有关系的脚本文件
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)# 对应打包成函数库的名字LOCAL_MODULE := array# 对应c代码的文件LOCAL_SRC_FILES := array.cLOCAL_LDLIBS += -lloginclude $(BUILD_SHARED_LIBRARY)
6、编译共享库。在linux环境下切换到项目根目录(cygwin),执行ndk-build命令。
7、在java方法里添加调用native方法的代码
public class MainActivity extends Activity { static { System.loadLibrary("array"); } public native int[] testArray(byte[] array); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); byte[] bytes = new byte[]{0, 1, 2}; int[] ints = testArray(bytes); Log.d("qingtian", "int数组的长度是:"+ints.length); for(int i = 0 ; i < ints.length ; i ++){ Log.d("qingtian", String.format("int数组第%d个值:%d", i, ints[i])); } }}
8、运行项目。
最后
–
祝大家元旦快乐。
- Android NDK开发(二)数组
- android ndk开发二
- Android NDK 开发之(二) 牛刀小试
- Android NDK 开发之(二) 牛刀小试
- Android NDK开发学习(二)
- Android——NDK开发(二)
- Android学习笔记-NDK开发(二)
- Android NDK开发 。Java层与Jni层的数组传递(二)
- Android NDK开发技巧二
- Android NDK开发技巧二
- Android NDK开发技巧二
- Android NDK开发技巧二
- Android NDK开发技巧二
- Android NDK 开发教程二
- android开发之绝对安全(二) NDK开发
- Android开发篇(二)-- JNI 与 NDK开发
- Android-NDK开发之基础--Android NDK开发技巧二
- Android-NDK开发之基础--Android NDK开发技巧二
- php【基础学习十六】多个构造方法
- JTS(Geometry) 空间数据模型的构建
- linux 调试用到知识点
- jQuery子窗体取得父窗体元素的方法
- Linux初学者成为高手的学习步骤和建议【新人必看】
- Android NDK开发(二)数组
- android进阶-题目总结(进行中)
- io操作
- iOS 开始页面实现
- Android中Dialog实现自定义弹出对话框
- weblogic调整服务console时间和系统时间一致
- [leetcode] 6. ZigZag Conversion 解题报告
- jQuery 双击事件(dblclick)时,不触发单击事件(click)
- 使用灵雀云免费docker修建梯子