android jni C++ java 相互调用
最近回顾下android jni相关接口使用,现在总结一下相关接口,希望对初学者有所帮助。
1. jni 层数据 与java层的数据结构对应关系
这个表的对应关系一定要对住,否则会出现一些莫名其秒的错误。
2. jni层 的 方法对应的 关系
基本有两种方式对应,第一种是给予javah 后边跟一些参数,把java包里的接口生成一些头文件然后在去编写代码。
第二种通过映射的方式去书写接口,我比较喜欢第二种方式,本文着重讲解第二种情况。
首先构造 java接口
public class Tool {
Bitmap mSrcBitmap = null;
private long add(long a, long b)
{
return a + b;
}
private long CreatBitmap(int width, int height, int data[]){
if (width < 0 || height < 0 || data == null)
return -1;
mSrcBitmap = Bitmap.createBitmap(data, width, height, Bitmap.Config.ARGB_8888);
if (mSrcBitmap == null)
return -1;
return 0;
}
public native long nativeAdd(long a, long b);
public native void nativeTest( );
public native long nativeCreatBitmap(int width, int height, int[]data);
// 加载 JNI 库文件;
static {
System.loadLibrary("tool");
}
}
然后处理jni 处理对应的接口
1)构造映射数组
JNINativeMethod gMethods[] = {
{ "native_add", "(JJ)J;", (void*)jni_add },//绑定
{ "nativeTest", "()V", (void*)Java_util_Tool_nativeTest },//绑定
{ "nativeAdd", "(JJ)J", (void*)jni_add },
{ "nativeCreatBitmap", "(II[I)J", (void*)jni_CreateBitmap },
};
2) 书写上边对应的方法
JNIEXPORT jlong JNICALL jni_add(JNIEnv *env, jobject cls, jlong a, jlong b)
{
jclass clazz = env->FindClass((char *)JNIREG_CLASS);
jmethodID add = env->GetMethodID(clazz, "add", "(JJ)J");
return env->CallLongMethod(cls, add, a, b);
}
JNIEXPORT jlong JNICALL jni_CreateBitmap(JNIEnv *env, jobject cls,int width, int height, jintArray data)
{
jclass clazz = env->FindClass((char *)JNIREG_CLASS);
jmethodID CreateBitmap = env->GetMethodID(clazz, "CreatBitmap", "(II[I)J");
//申明一个object数组
jintArray array = 0;
int *pData = (int *)malloc(width * height * sizeof(int));
//新建object数组
array = (env)->NewIntArray(width * height);
pData[0] = 1;
pData[1] = 2;
pData[2] = 3;
env->SetIntArrayRegion(array, 0, width * height, pData);
return env->CallLongMethod(cls, CreateBitmap, width, height, array);
}
JNIEXPORT void JNICALL Java_util_Tool_nativeTest(JNIEnv *env, jobject clazz)
{
jclass Bitmap = env->FindClass("android.graphic.Bitmap");
return;
}
3) 加载jni接口
/* * Register several native methods for one class. */ jint Register_JNI(JNIEnv * env, char* className, JNINativeMethod* methods, jint methodsCnt) { jclass clazz = env->FindClass(className); if (clazz == NULL) { return -1; } jint res = env->RegisterNatives(clazz, methods, methodsCnt); if (res < 0) { env->DeleteLocalRef(clazz); return -1; } env->DeleteLocalRef(clazz); return 0; } /* * Set some test stuff up. * * Returns the JNI version on success, -1 on failure. */ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint result = -1; if (vm->GetEnv( (void**) &env, JNI_VERSION_1_6) != JNI_OK) { return -1; } assert(env != NULL); if (Register_JNI(env, JNIREG_CLASS, gMethods, sizeof(gMethods) / sizeof(gMethods[0]))) return JNI_FALSE; /* success -- return valid version number */ result = JNI_VERSION_1_6; return result; }
4) 释放接口jint Unregister_JNI(JNIEnv* env, char* className) { jclass clazz = env->FindClass(className); if (NULL == clazz) { return JNI_ERR; } env->UnregisterNatives(clazz); env->DeleteLocalRef(clazz); return JNI_OK; } JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) { JNIEnv* env = NULL; if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) { return; } Unregister_JNI(env, JNIREG_CLASS); }
这样就完成上边java与jni对应关系。另外分享几个其他博客对这方面介绍也挺好的。
讲解c++ 数据结构与 java数据结构关系
http://www.cnblogs.com/daniel-shen/archive/2006/10/16/530587.html
http://zhiweiofli.iteye.com/blog/1830321
jni接口中文解释
http://www.ceeger.com/Script/AndroidJNI/AndroidJNI.CallLongMethod.html
源代码:http://download.youkuaiyun.com/download/c553110519/10049211