android jni 总复习(转载)
本文全文转载自:http://www.cnblogs.com/shuqingstudy/p/4909089.html,非常感谢
package com.test.androidjni; import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView; public class MainActivity extends Activity {
private static final String DEBUGTAG = "NATIVE";
private String myString;
private static int si=0;
private static String helloString = "What's your name"; //对基本数据类型的访问
private native String GetNativeString(String str);//访问字串
private native int SumArray(int [] ar, int length);//传一个数组的长度
private native int SumArrayA(int [] ar);//不传长度
private native int SumArray2D(int [][]ar2d);//传一个二维数组,返回一个长度
private native int [][] ModifyArray2d(int [][]ar2d);//传入一个二维数组,返回一个二维数组 //这一部分是对成员和方法的访问
private native void AccessField();//访问静态成员
private native void AccessMethod(); private native void signature(String str1, int i,byte b,char c,boolean bl,long l,double d,float f,short sh); /**
* 对于加动.so库做一点说明
* System.loadLibrary 这个方法默认去system/lib去找这个.so库,
* 再到data/data/com.test.androidjin/lib/目录下找。本应数据存放的目录下
* 我们可以通过eclipse上的ddms去查看。前提是把调试的机器联上,
* 动态库的名称是:lib前缀+库名+.so后缀。此函数不要前缀,也不要后缀,只要包名,否则找不到
* 但是我们在这个apk的libs/armeabi/目录下要用libmyjni.so这个全名.
* 另外还有一个加载库的函数
* System.load 这个函数是传入全路径名.这样就可以到指定的路径加载了
* System.load(/system/lib/libXXX.so);注意访问目录的权限问题 ,这个与linux的目录访问权限一样的.
* 有时候我们在使用第三访.so库是,找不到库,但明明库已加打包进了。这里我们要看它的本地方法是在
* 那个java包下的那个类中声明的,比如这个apk的native方法是在
* com.test.androidjni包的MainActivity 这个类中声明的。生成的native函数都有
* Java_com_test_androidjni_MainActivity_这个前缀.我们可以根据第三访.so的函数接口的前缀
* 建立相应的包和类名,然后就可以正确加载了。这里与前面讲的找库的路径是刚好相互应证了。
*
*/
static{
System.loadLibrary("myjni");
} @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//字符串操作
String retStr = GetNativeString("Please give me A String");
Log.d(DEBUGTAG, retStr);
if(null != retStr){
TextView t = (TextView)findViewById(R.id.nativeString);
t.setText(retStr);
} //传入一维数组,累计和,并修改了第0,第1个数组元素的值
int arr[] =new int[]{1,2,3,4,5,6,7};
Integer value = SumArrayA(arr);
TextView t = (TextView)findViewById(R.id.nativeArray);
t.setText(value.toString());
Log.d(DEBUGTAG, "arr[0] = "+ arr[0]+" arr[1]"+arr[1]); //访问二维数组,累计和,
int arr2d[][] = {{1,1,5,5},{2,2,2,2,}};//new int[2][4];
int sum = SumArray2D(arr2d);
Log.d(DEBUGTAG, "len = " + sum); //访问二维数组,并返回一个二维数组,且修改了传入二维数组的元素
int arr2dA[][] = null;
int sumV = 0;
arr2dA = ModifyArray2d(arr2d);
for(int i=0;i<2;i++)
{
for(int j=0;j<4;j++)
{
sumV += arr2dA[i][j];
}
}
Log.d(DEBUGTAG, "sumV = " + sumV); //c中访问java域和方法
this.myString = "Android Java String";
this.AccessField();
Log.d(DEBUGTAG, "after modify by native myString = " + myString);
Log.d(DEBUGTAG, "after modify by native si = " + si);
Log.d(DEBUGTAG, "after modify by native helloString = " + helloString);
//c中调用java中的方法
this.AccessMethod();
}
private void callback(String strFromNative,int i,byte b,char c,boolean bl,long l,double d,float f,short sh){
Log.d(DEBUGTAG,"CALL FROM NATIVE:"+strFromNative +i+b+c+bl+l+d+f+sh);
}
private static String callStaticBack(){
return "What's your name ";
} } MainActivity.java
MainActivity.java
#include <string.h>
#include <jni.h>
#include "com_test_androidjni_MainActivity.h"
/*
* @学习使用jni字串函数 JNIEnv 是一个结构体,下面列出的是这个结构体的部分函数指针,还有很多其他的
*
* unicode16编码,字串符没有结束符'\0',
* jstring (*NewString)(JNIEnv*, const jchar*, jsize);//最后一个参数表示jchar* 内存长度
* jsize (*GetStringLength)(JNIEnv*, jstring);
* const jchar* (*GetStringChars)(JNIEnv*, jstring, jboolean*);
* void (*ReleaseStringChars)(JNIEnv*, jstring, const jchar*);
* void (*GetStringRegion)(JNIEnv*, jstring, jsize, jsize, jchar*);
*
* utf8编码,得到的字串是有结束符'\0'的
* jstring (*NewStringUTF)(JNIEnv*, const char*);
* jsize (*GetStringUTFLength)(JNIEnv*, jstring);
* const char* (*GetStringUTFChars)(JNIEnv*, jstring, jboolean*);
* void (*ReleaseStringUTFChars)(JNIEnv*, jstring, const char*);
* void (*GetStringUTFRegion)(JNIEnv*, jstring, jsize, jsize, char*);
*
* 获取直接指向jstring的地址,因此没有编码区别。这一对函数中,不能有阻塞操作
* 这对函数之间,不能有任何对jni的操作,因此这对函数,一般较少用。
* const jchar* (*GetStringCritical)(JNIEnv*, jstring, jboolean*);
* void (*ReleaseStringCritical)(JNIEnv*, jstring, const jchar*);
*
*/
jstring JNICALL Java_com_test_androidjni_MainActivity_GetNativeString(
JNIEnv *env, jobject obj, jstring str) {
const char * pStr;
const char* pUTF8Str = "From jni String";
char outbuff[128] = { 0 }; //获取传入字串中的所有字串
pStr = (*env)->GetStringUTFChars(env, str, NULL);
if (pStr == NULL)
return NULL;
strcat(outbuff, pStr);
(*env)->ReleaseStringUTFChars(env, str, pStr); //这里要释放,否则内存泄漏
strcat(outbuff, "/"); //加一个分隔符
//从传入字串第三个位置开始,获取4个,到字串尾
(*env)->GetStringUTFRegion(env, str, 3, 4, outbuff + strlen(outbuff));
strcat(outbuff, "/"); //加一个分隔符
strcat(outbuff, pUTF8Str); //联接一个本地字串
//从buff中构建一个jstring返回给java,这个新构建的字串由虚拟机负责回收
return (*env)->NewStringUTF(env, outbuff);
}
/**
* 访问基本数组类型
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); 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*); 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); void (*GetBooleanArrayRegion)(JNIEnv*, jbooleanArray,jsize, jsize, jboolean*);
void (*GetByteArrayRegion)(JNIEnv*, jbyteArray,jsize, jsize, jbyte*);
void (*GetCharArrayRegion)(JNIEnv*, jcharArray,jsize, jsize, jchar*);
void (*GetShortArrayRegion)(JNIEnv*, jshortArray,jsize, jsize, jshort*);
void (*GetIntArrayRegion)(JNIEnv*, jintArray,jsize, jsize, jint*);
void (*GetLongArrayRegion)(JNIEnv*, jlongArray,jsize, jsize, jlong*);
void (*GetFloatArrayRegion)(JNIEnv*, jfloatArray,jsize, jsize, jfloat*);
void (*GetDoubleArrayRegion)(JNIEnv*, jdoubleArray,jsize, jsize, jdouble*); spec shows these without const; some jni.h do, some don't
void (*SetBooleanArrayRegion)(JNIEnv*, jbooleanArray,jsize, jsize, const jboolean*);
void (*SetByteArrayRegion)(JNIEnv*, jbyteArray,jsize, jsize, const jbyte*);
void (*SetCharArrayRegion)(JNIEnv*, jcharArray,jsize, jsize, const jchar*);
void (*SetShortArrayRegion)(JNIEnv*, jshortArray,jsize, jsize, const jshort*);
void (*SetIntArrayRegion)(JNIEnv*, jintArray,jsize, jsize, const jint*);
void (*SetLongArrayRegion)(JNIEnv*, jlongArray,jsize, jsize, const jlong*);
void (*SetFloatArrayRegion)(JNIEnv*, jfloatArray,jsize, jsize, const jfloat*);
void (*SetDoubleArrayRegion)(JNIEnv*, jdoubleArray,jsize, jsize, const jdouble*);
*
*
*这里可以求得任意数组大小的,累计合
*/
JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray(
JNIEnv *env, jobject obj, jintArray arr, jint length) {
int i, sum = 0;
jint* pOutbuf = NULL;
if (length > 0)
pOutbuf = (jint*) malloc(length * sizeof(jint));
else
return 0;
(*env)->GetIntArrayRegion(env, arr, 0, length, pOutbuf);
for (i = 0; i < 10; i++)
sum += pOutbuf[i];
free(pOutbuf);
pOutbuf = NULL; return sum;
}
/*
*
* ReleaseIntArrayElements
* 第三个参数就是决定更新与否的。
* 取值 零(0) 时,更新数组并释放所有元素;
* 取值 JNI_COMMIT 时,更新但不释放所有元素;
* 取值 JNI_ABORT 时,不作更新但释放所有元素;
* #define JNI_COMMIT 1 // copy content, do not free buffer
* #define JNI_ABORT 2 // free buffer w/o copying back ^/
* //获取数组长度,注意jarray是指所有类型j<类型>array
* typedef jarray jintArray //其他的jbyteArray或jfloatArray都是jarray.
* jsize (*GetArrayLength)(JNIEnv*, jarray);
*/
JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArrayA(
JNIEnv *env, jobject obj, jintArray arr) {
int i,j, sum = 0;
jint* buf;
j = (*env)->GetArrayLength(env,arr);
//另外,这里返回的值,是jint*,不是const jint*,也就是说可以对其中的值进行修改
buf = (*env)->GetIntArrayElements(env, arr, NULL);//这一句其实也告java内存回收器,不要回收arr数组的内存,或者不要整理内存
//如果回收器,回收和整理内存,那么我们在c中,访问的地址就可能错了
for (i = 0; i < j; i++)//这里是求合
sum += buf[i];
//现在我们来修改一下buf中的元素,看看返回后,会不会把buf中的值,更新到java中的arr里去
buf[0] = 100;
buf[1] = 200; (*env)->ReleaseIntArrayElements(env, arr, buf, 0);//调用这个方法,告诉java内存回收器,我忆用完了arr,,现在可以回收arr的内存了
return sum;
}
/**
* 要点:演示对传入二维数组的访问
* 功能:计算二维数组的和
* NewObjectArray( env,len,jcIntArray,NULL );
* 参数2:是要创建的元数个数
* 参数3:是要创建的元素的类型
* 参数4:是创建时的初值,可以传空
*/
JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray2D
(JNIEnv *env, jobject obj, jobjectArray arr2D)
{
int len = 0,length = 0;
int i,j,sum=0;
jarray jaIntArray;
jintArray jiaTmpIntArray;
jobjectArray joaReturnInt2DArray;//定义一个数组指针,到时候返回用
jclass jcIntArray;
jboolean jbIsCopy = JNI_FALSE; len = (*env)->GetArrayLength( env, arr2D );//获取第一维的元数长度
jaIntArray = (*env)->GetObjectArrayElement(env, arr2D, 0);//获取第0个元素 ,它是一个一维数组首地址
length = (*env)->GetArrayLength( env, jaIntArray );//获取一维数组的长度 jcIntArray = (*env)->FindClass( env, "[I" );//得到一个一维数组的引用
joaReturnInt2DArray = (*env)->NewObjectArray( env,len,jcIntArray,NULL );//创建len个jcIntArray. for(i=0;i<len;i++)
{
jint *piSrc,*piDes; jaIntArray = (*env)->GetObjectArrayElement(env, arr2D, i);//void*指针
jiaTmpIntArray = (*env)->NewIntArray( env, length );//void*指针,元素个数是length piSrc = (*env)->GetIntArrayElements( env,jaIntArray,&jbIsCopy );//这里还是获取首地址,得到的是jin*类型的了
piDes = (*env)->GetIntArrayElements( env,jiaTmpIntArray,&jbIsCopy );//这里还是获取首地址,得到的是jin*类型的了 for(j=0;j<length;j++)
{
piDes[j] = piSrc[j];//把传入数组的值,赋给新创建的数组
sum +=piDes[j];//通过新创建数的值。累计
} (*env)->ReleaseIntArrayElements( env,jaIntArray,piSrc,0 );//对应的释放函数
(*env)->ReleaseIntArrayElements( env,jiaTmpIntArray,piDes,0 );//对应的释放函数 (*env)->SetObjectArrayElement( env, joaReturnInt2DArray, i, jiaTmpIntArray );//将新建的一维数组,做为二维数组的元素
(*env)->DeleteLocalRef( env, jiaTmpIntArray );//删掉这个引用.
} (*env)->DeleteLocalRef( env, joaReturnInt2DArray );//释放整个创建的二维数组 return sum;
}
/*
* 要点:
* 1:访问传入的二维数组
* 2:创建一个新的二维数组
* 3:修改传入的二维数组的值
* 4:返回一个二维数组对象给java调用端
*/
JNIEXPORT jobjectArray JNICALL Java_com_test_androidjni_MainActivity_ModifyArray2d
(JNIEnv *env, jobject obj, jobjectArray arr2D)
{
int len = 0,length = 0;
int i,j,sum=0;
jarray jaIntArray;
jintArray jiaTmpIntArray;
jobjectArray joaReturnInt2DArray;//定义一个数组指针,到时候返回用
jclass jcIntArray;
jboolean jbIsCopy = JNI_FALSE; len = (*env)->GetArrayLength( env, arr2D );//获取第一维的元数长度
jaIntArray = (*env)->GetObjectArrayElement(env, arr2D, 0);//获取第0个元素 ,它是一个一维数组首地址
length = (*env)->GetArrayLength( env, jaIntArray );//获取一维数组的长度 jcIntArray = (*env)->FindClass( env, "[I" );//得到一个一维数组的引用
joaReturnInt2DArray = (*env)->NewObjectArray( env,len,jcIntArray,NULL );//创建len个jcIntArray. for(i=0;i<len;i++)
{
jint *piSrc,*piDes; jaIntArray = (*env)->GetObjectArrayElement(env, arr2D, i);//void*指针
jiaTmpIntArray = (*env)->NewIntArray( env, length );//void*指针,元素个数是length piSrc = (*env)->GetIntArrayElements( env,jaIntArray,&jbIsCopy );//这里还是获取首地址,得到的是jin*类型的了
piDes = (*env)->GetIntArrayElements( env,jiaTmpIntArray,&jbIsCopy );//这里还是获取首地址,得到的是jin*类型的了 for(j=0;j<length;j++)
{
piDes[j] = piSrc[j];//把传入数组的值,赋给新创建的数组
sum +=piDes[j];//通过新创建数的值。累计
piDes[j] = 5;//修改传入数组的值
} (*env)->ReleaseIntArrayElements( env,jaIntArray,piSrc,0 );//对应的释放函数
(*env)->ReleaseIntArrayElements( env,jiaTmpIntArray,piDes,0 );//对应的释放函数 (*env)->SetObjectArrayElement( env, joaReturnInt2DArray, i, jiaTmpIntArray );//将新建的一维数组,做为二维数组的元素
(*env)->DeleteLocalRef( env, jiaTmpIntArray );//删掉这个引用.
} // (*env)->DeleteLocalRef( env, joaReturnInt2DArray );//释放整个创建的二维数组 return joaReturnInt2DArray;
}
/**
* 访问java中的成员[通用的逻辑]
* 注意:访问的是java中非静态成员,非静态成员是属于对象的.另外还要访问静态成员,静态成员属于类
* 步骤:
* 1:先找到对象的类
* 2:根据成员的名称和类型,获取该成员的id引用
* 3:根据id引用,获取该成员的域引用
* 4:根据域引用再得到具体的内容
*
*/
JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessField
(JNIEnv *env, jobject obj)
{
jclass cls;//void*指针
jfieldID fid;//抽象的结构体指针
jstring jstr;//void*指针
jint value;
const char* str; cls = (*env)->GetObjectClass(env,obj);//得到类的引用
fid = (*env)->GetFieldID(env, cls, "myString", "Ljava/lang/String;");//得到成员id的引用
if( fid == NULL ){//检测根据给定的信息是否找到了id,
return ;
}
jstr = (*env)->GetObjectField(env, obj, fid);//得到对象的引用
str = (*env)->GetStringUTFChars(env, jstr, NULL);//从对象引用中得到内容
if( str == NULL ){
return ;
}
//printf(" c.s = "%s"\n", str ) ;
(*env)->ReleaseStringUTFChars(env, jstr, str);//更新或释放,不过最好用SetObjectField来操作。
jstr = (*env)->NewStringUTF(env, "accedfild");//创建一个新的字串,这个是用java的方法创建的
if( jstr == NULL ){
return ;
}
//用jstr,更新obj对象的fid域.
(*env)->SetObjectField(env, obj, fid, jstr);//设置域对象 //===============访问int静态成员=======================
fid = (*env)->GetStaticFieldID(env,cls,"si","I");
if(NULL == fid)
return;
value = (*env)->GetStaticIntField(env, cls, fid);//注意第二个参数是类,不是对象,因为是静态成员
value = 100;
(*env)->SetStaticIntField(env, cls, fid, 100);
//===============访问String静态成员=======================
fid = (*env)->GetStaticFieldID(env, cls, "helloString", "Ljava/lang/String;");
jstr = (*env)->GetStaticObjectField(env, cls, fid);//注意第二个参数是类,不是对象,因为是静态成员
str = (*env)->GetStringUTFChars(env, jstr, NULL);
//可以对str做一些处理
(*env)->ReleaseStringUTFChars(env, jstr, str);
jstr = (*env)->NewStringUTF(env, "static string");
(*env)->SetStaticObjectField(env, cls, fid, jstr);//注意第二个参数是类,不是对象,因为是静态成员 return;
}
/*
* 访问java中的方法
* 并传递了所有java中的数据类型,对象类型除外
*
*
*/
JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessMethod
(JNIEnv *env, jobject obj)
{
jclass cls;
jmethodID mid;
const char *str = "hello call back";
jstring jstr; jboolean z = 1;
jbyte b = 0xff;
jchar c = 'c';
jshort s = 60;
jint i = 100;
jlong j = 568978523;
jfloat f = 125643.22222;
jdouble d = 123456789.12654789;
//jobject l = ; cls = (*env)->GetObjectClass(env,obj);//得到类的引用 //从静态方法中得到str,再传回给callback方法
mid = (*env)->GetStaticMethodID(env, cls,"callStaticBack","()Ljava/lang/String;");
jstr = (*env)->CallStaticObjectMethod(env,cls,mid); mid = (*env)->GetMethodID(env, cls, "callback", "(Ljava/lang/String;IBCZJDFS)V"); if (mid == NULL) {
return; /* method not found */
}
//printf("In C\n"); //jstr = (*env)->NewStringUTF(env, str);
(*env)->CallVoidMethod(env, obj, mid,jstr,i,b,c,z,j,d,f,s); } myjni.c
jni.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_test_androidjni_MainActivity */ #ifndef _Included_com_test_androidjni_MainActivity
#define _Included_com_test_androidjni_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_test_androidjni_MainActivity
* Method: GetNativeString
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_test_androidjni_MainActivity_GetNativeString
(JNIEnv *, jobject, jstring); /*
* Class: com_test_androidjni_MainActivity
* Method: SumArray
* Signature: ([II)I
*/
JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray
(JNIEnv *, jobject, jintArray, jint); /*
* Class: com_test_androidjni_MainActivity
* Method: SumArrayA
* Signature: ([I)I
*/
JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArrayA
(JNIEnv *, jobject, jintArray); /*
* Class: com_test_androidjni_MainActivity
* Method: SumArray2D
* Signature: ([[I)I
*/
JNIEXPORT jint JNICALL Java_com_test_androidjni_MainActivity_SumArray2D
(JNIEnv *, jobject, jobjectArray); /*
* Class: com_test_androidjni_MainActivity
* Method: ModifyArray2d
* Signature: ([[I)[[I
*/
JNIEXPORT jobjectArray JNICALL Java_com_test_androidjni_MainActivity_ModifyArray2d
(JNIEnv *, jobject, jobjectArray); /*
* Class: com_test_androidjni_MainActivity
* Method: AccessField
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessField
(JNIEnv *, jobject); /*
* Class: com_test_androidjni_MainActivity
* Method: AccessMethod
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_AccessMethod
(JNIEnv *, jobject); /*
* Class: com_test_androidjni_MainActivity
* Method: signature
* Signature: (Ljava/lang/String;IBCZJDFS)V
*/
JNIEXPORT void JNICALL Java_com_test_androidjni_MainActivity_signature
(JNIEnv *, jobject, jstring, jint, jbyte, jchar, jboolean, jlong, jdouble, jfloat, jshort); #ifdef __cplusplus
}
#endif
#endif com_test_androidjni_MainActivity.h
com_test_androidjni_MainActivity.h
jni.h 这个头文件在android-ndk包中的platroms/具体的api包的inlcude中。
关于android jni编程,java与c,c++之间数据的传递都在jni.h这个头文件中.根据类型结构,可知为什么不可以在c中,直接访问java传入的jstring或一些其他类型
它们的类若是void*的,那么就无法访问了。因为我们不知道它在内存的布局,占几个字节,也就无法访问。这就是所谓不透明类型。另外对于c++里面访问java,实
际是对c的封装.
我们注意一下jni.h中
#if defined(__cplusplus)//这里表示是c++用的
typedef _JNIEnv JNIEnv;//这是native方法的第一个参数
typedef _JavaVM JavaVM;//这个是虚拟机
#else
typedef const struct JNINativeInterface* JNIEnv;
typedef const struct JNIInvokeInterface* JavaVM;
#endif struct JNINativeInterface{ //具体内容省略, //它们都是一些函数指针,这个结构体,每个native方法的第一个参数JNIEnv env 就是它自己 }; 另外注意一下 //这两个方法,是由java虚拟机调用的,它传入一个vm,通过vm我们可以得到JNIEnv,通过JNIEnv我们可以得到
//java与c,c++之间的交互接口。 JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved);
JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved);
面这些代码,是对<JNI编程指南> 前4章方法的汇总.也总结了许多网友的代码,并对其做了一些修改,加入了自己的理解。
private static final String DEBUGTAG = "NATIVE";
private String myString;
private static int si=0;
private static String helloString = "What's your name"; //对基本数据类型的访问
private native String GetNativeString(String str);//访问字串
private native int SumArray(int [] ar, int length);//传一个数组的长度
private native int SumArrayA(int [] ar);//不传长度
private native int SumArray2D(int [][]ar2d);//传一个二维数组,返回一个长度
private native int [][] ModifyArray2d(int [][]ar2d);//传入一个二维数组,返回一个二维数组 //这一部分是对成员和方法的访问
private native void AccessField();//访问静态成员
private native void AccessMethod();
//这个方法是为了生成一个包括所有基本类型的方法签名,请查看头文件
private native void signature(String str1, int i,byte b,char c,boolean bl,long l,double d,float f,short sh);
自己体会:
学习了这么多天的jni终于要结束了,不知道怎么总结,这5篇博客和这位NB的博主的文章算是对其做一个总结吧,当需要
改变C语言的算法时,直接在操作区修改即可,配置NDK,导入include可以问Java/android调用C,当然是JNI借口了,提供更快速的平台工具
加油,下一个内容!
android jni 总复习(转载)的更多相关文章
- [转载]—— Android JNI知识点
Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) 内部运行的 ...
- [ 转载 ] Android JNI(一)——NDK与JNI基础
Android JNI(一)——NDK与JNI基础 隔壁老李头 关注 4.4 2018.05.09 17:15* 字数 5481 阅读 11468评论 8喜欢 140 本系列文章如下: Androi ...
- Android JNI学习(四)——JNI的常用方法的中文API
本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...
- android JNI调用(转)
Android jni开发资料--NDK环境搭建 android开发人员注意了 谷歌改良了ndk的开发流程,对于Windows环境下NDK的开发,如果使用的NDK是r7之前的版本,必须要安装Cygwi ...
- Android JNI之JAVA与C++对象建立对称关联(JNI优化设计,确保JNI调用的稳定性)
转载请声明:原文转自:http://www.cnblogs.com/xiezie/p/5930503.html Android JNI之JAVA与C++对象建立对称关联 1.JAVA对象持有C++对象 ...
- Android JNI 获取应用程序签名
使用Android JNI 获取应用程序签名. 获取基础上生成自己的签名password,这可以防止别人反编译找到自己的源代码password. jstring Java_com_masonsdk_j ...
- android JNI 简单demo(2)它JNI demo 写
android JNI 简单demo(2)它JNI demo 写 一.搭建Cygwin 环境:http://blog.csdn.net/androidolblog/article/details/25 ...
- 基于NDK的Android防破解& Android防破解 【转载】
两篇防破解文章转载 基于NDK的Android防破解:http://blog.csdn.net/bugrunner/article/details/8634585 Android防破解:http:// ...
- Android JNI学习(五)——Demo演示
本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...
随机推荐
- 远离DoS攻击 Windows Server 2016发布DNS政策
Windows Server 2016的网络功能虽然没有获得像Docker容器和Nano Server同等重要的关注,但是管理员们应该了解的是,新的域名系统(Domain Name ...
- 18、手把手教你Extjs5(十八)模块记录的拖放删除、拖放复制新增
网页当中的拖放(drag-drop)是比较有趣的操作,extjs5中很好的封装了拖放的动作,也有各种类来支持,但是要学好“拖放”这个东西真是很难,特别是象我这样英语不好的人,看不太懂官网上的说明,做一 ...
- 《C程序设计语言》读书笔记----习题1-20
练习1-20:编写程序detab,将输入中的制表符替换成适当数目的空格,使得空格充满到下一个制表符终止位的地方,.假设制表符终止位的位置时固定的,比如每隔n列就会出现一个终止位. 这里要理解“制表符” ...
- iOS 生产证书 分类: ios相关 app相关 2015-05-22 14:49 175人阅读 评论(0) 收藏
首先登陆https://developer.apple.com(99美元账号) 选择iOS Developer program 板块下的 Certificates,Identifiers & ...
- Memcached源码分析之slabs.c
#include "memcached.h" #include <sys/stat.h> #include <sys/socket.h> #include ...
- stm32 DMA数据搬运 [操作寄存器+库函数](转)
源:stm32 DMA数据搬运 [操作寄存器+库函数] DMA(Direct Memory Access)常译为“存储器直接存取”.早在Intel的8086平台上就有了DMA应用了. ...
- mysql5.7创建账户并授权
CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'mypass'; GRANT ALL ON db1.* TO 'jeffrey'@'localhost ...
- 深入理解yield(转)
yield的英文单词意思是生产,刚接触Python的时候感到非常困惑,一直没弄明白yield的用法.只是粗略的知道yield可以用来为一个函数返回值塞数据,比如下面的例子: def addlist(a ...
- tap是什么意思
分光是数据通过光纤传输:分路是数据通过网线传输.粗浅的说,Tap的概念类似于“三通”的意思,即原来的流量正常通行,同时分一股出来供监测设备分析使用. 其实这只是最简单的Tap的概念,目前的技术发展已经 ...
- Mybatis学习(8)逆向工程
什么是逆向工程: mybaits需要程序员自己编写sql语句,mybatis官方提供逆向工程 可以针对单表自动生成mybatis执行所需要的代码(mapper.java,mapper.xml.po.. ...