JNI 传递数据

1.通过JNI,java能够调用  C/C++函数,也能在C/C++ 里面调用 java 方法

  

Java Language Type
Native Type
Description
boolean
jboolean
unsigned 8 bits
byte
jbyte
signed 8 bits
char
jchar
unsigned 16 bits
short
jshort
signed 16 bits
int
jint
signed 32 bits
long
jlong
signed 64 bits
float
jfloat
32 bits
double
jdouble
64 bits


The jsize integer type is used to describe cardinal indices and sizes:

 typedef jint jsize;

//-----------------------------------------------------------------------------------------

java端:

		int sumResult = sum(10, 21);
		String sResult = sumStr("Dai", "Wuhanshi");
		Log.e("AAAA",""+sumResult);
		Log.e("AAAA",sResult);

    // 求和
    public native int sum(int a,int b);
    
    // 字符串连接
    public native String sumStr(String strA,String strB);

native端:

/*
 * Class:     com_example_mystore_MainActivity
 * Method:    sum
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_example_mystore_MainActivity_sum(
		JNIEnv * pJNIEnv, jobject pThis, jint a, jint b) {
	return a + b;
}

/*
 * Class:     com_example_mystore_MainActivity
 * Method:    sumStr
 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_mystore_MainActivity_sumStr(
		JNIEnv * pJNIEnv, jobject pThis, jstring a, jstring b) {
	const char* aString = (*pJNIEnv)->GetStringUTFChars(pJNIEnv, a, 0);
	const char* bString = (*pJNIEnv)->GetStringUTFChars(pJNIEnv, b, 0);

	char* buf[1024];
	strcpy(buf, aString);
	strcat(buf, bString);

	(*pJNIEnv)->ReleaseStringUTFChars(pJNIEnv, a, aString);
	(*pJNIEnv)->ReleaseStringUTFChars(pJNIEnv, b, bString);

	return (*pJNIEnv)->NewStringUTF(pJNIEnv, buf);
}

介绍了java端将String类型和int 类型作为参数传递到native端,

native端是如何进行处理的。

由于java程序中传过去的String对象在本地方法中对应的是jstring类型,jstring类型和c中的char*不同,所以如果你直接当做 char*使用的话,就会出错。因此在使用之前需要将jstring转换成为c/c++中的char*,这里使用JNIEnv的方法转换。

const char* aString = (*pJNIEnv)->GetStringUTFChars(pJNIEnv, a, 0);
这里其实只是得到a的一个copy.所以用完后,还需要通过 ReleaseStringUTFChars这方法进行释放

GetStringUTFChars 和 ReleaseStringUTFChars 这两方法需要成对出现.


//---------------------- 在native里面进行 抛异常

主要代码为:

package com.example.mystore;

public class MyException extends Exception {

	private String message;

	public MyException(String name) {
		super(name);
		message = name;
	}

	public String getMessageString() {
		return message;
	}
}


package com.example.mystore;

public class Dog {

	private String name;
	private int age;

	public Dog(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

}

public native Dog getDog() throws MyException;

		Dog newDog = null;
		try {
			newDog = getDog();
			Log.e("AAAA", newDog.getName() + ":" + newDog.getAge());
		} catch (MyException e) {
			Log.e("AAAA", e.getMessageString());
		}

现在再看native端的代码:

/*
 * Class:     com_example_mystore_MainActivity
 * Method:    getDog
 * Signature: ()Lcom/example/mystore/Dog;
 */
JNIEXPORT jobject JNICALL Java_com_example_mystore_MainActivity_getDog(
		JNIEnv * pJNIEnv, jobject pThis) {

	if (globalObject == NULL) {
		throwMyException(pJNIEnv);
		return NULL;
	}

	CCLog(TAG,"到这里了");

	return globalObject;
}

void throwMyException(JNIEnv * pJNIEnv) {
	jclass lClass = (*pJNIEnv)->FindClass(pJNIEnv,
			"com/example/mystore/MyException");

	if (lClass != NULL) {
		(*pJNIEnv)->ThrowNew(pJNIEnv, lClass, "没有发现aa啊!!!");
	}

	(*pJNIEnv)->DeleteLocalRef(pJNIEnv, lClass);
}

 在 native端,其实是通过 throwMyException 这个方法, 

然后,找到异常类,通过如下语句

(*pJNIEnv)->ThrowNew(pJNIEnv, lClass, "没有发现aa啊!!!");

抛出异常.

注意,在  throwMyException这方法里面,JNI里面的 Local引用需要手动删除.


//-----------------------------------------------------------------------------------

传递基本类型的数组

JNIEXPORT void JNICALL Java_com_example_mystore_MainActivity_saveIntArr(
		JNIEnv * pJNIEnv, jobject pThis, jintArray jay) {
	// 先得到数组的长度
	jsize lLength = (*pJNIEnv)->GetArrayLength(pJNIEnv, jay);

	// 分配内存
	int* lArray = (int*) malloc(sizeof(int) * lLength);

	//将传递过来的数据放入
	(*pJNIEnv)->GetIntArrayRegion(pJNIEnv, jay, 0, lLength, lArray);

	//需要检查是否出现异常
	if ((*pJNIEnv)->ExceptionCheck(pJNIEnv)) {
		free(lArray);
		return;
	}

	//将传递过来的int数组打印出来
	jint i = 0;
	for (i = 0; i < lLength; ++i) {
		//(*pJNIEnv)->GetIntArrayElements(pJNIEnv,jay,);
		CCLog("AAAA", "%d \n", lArray[i]);
	}

	free(lArray);
}

从native端传递基本类型数组到java端

JNIEXPORT jintArray JNICALL Java_com_example_mystore_MainActivity_getIntArray(
		JNIEnv * pJNIEnv, jobject pThis) {
	//我想返回 2,4,6,8组成的数组

	//  先创建
	jintArray lJavaArray = (*pJNIEnv)->NewIntArray(pJNIEnv, 4);
	if (lJavaArray == NULL) {
		return NULL;
	}

	int target[] = { 2, 4, 6, 8 };
	(*pJNIEnv)->SetIntArrayRegion(pJNIEnv, lJavaArray, 0, 4, target);
	return lJavaArray;
}

//----------------------

从java端传递对象数组到native端

JNIEXPORT void JNICALL Java_com_example_mystore_MainActivity_saveDogArr(
		JNIEnv * pJNIEnv, jobject pThis, jobjectArray joa) {
	//先得到个数
	jsize lLength = (*pJNIEnv)->GetArrayLength(pJNIEnv, joa);

	//分配内存
	jobject* lArray = (jobjectArray*) malloc(lLength * sizeof(jobject));

	//将传入的数据放入
	int i = 0;
	for (i = 0; i < lLength; ++i) {
		jobject obj = (*pJNIEnv)->GetObjectArrayElement(pJNIEnv, joa, i);
		lArray[i] = (*pJNIEnv)->NewGlobalRef(pJNIEnv, obj);
		(*pJNIEnv)->DeleteLocalRef(pJNIEnv, obj);
	}

	globalObjectArray = lArray;
	gLength = lLength;
}

从native端传递对象数组到java端

JNIEXPORT jobjectArray JNICALL Java_com_example_mystore_MainActivity_getDogArr(
		JNIEnv * pJNIEnv, jobject pThis) {
	// 先找到class
	jclass dogClass = (*pJNIEnv)->FindClass(pJNIEnv, "com/example/mystore/Dog");

	//检查是否找到dogclass
	if (dogClass == NULL) {
		CCLog("AAAA", "没有找到dogClass");
		return NULL;
	}

	jobjectArray joa = (*pJNIEnv)->NewObjectArray(pJNIEnv, gLength, dogClass,
			NULL);
	(*pJNIEnv)->DeleteLocalRef(pJNIEnv, dogClass);
	int i = 0;
	for (i = 0; i < gLength; ++i) {
		(*pJNIEnv)->SetObjectArrayElement(pJNIEnv, joa, i,
				globalObjectArray[i]);
		if ((*pJNIEnv)->ExceptionCheck(pJNIEnv)) {
			CCLog("AAAA", "[SetObjectArrayElement] 里面出现错误!!!");
			return NULL;
		}
	}
	return joa;
}

总结一下: 

1.从native端传递到java端的时候,一般都是通过(*pJNIEnv)->NewXXXXX(pJNIEnv,xxx);生成,然后再返回.

   方法里面 类似 

jclass dogClass = (*pJNIEnv)->FindClass(pJNIEnv, "com/example/mystore/Dog");
或者 
jobject obj = (*pJNIEnv)->GetObjectArrayElement(pJNIEnv, joa, i);
这样的调用,使用完毕后,需要将这样的局部使用 
(*pJNIEnv)->DeleteLocalRef(pJNIEnv, xxx);
引用进行删除.



2.native端如果需要保存java端传递过来的对象或者数据,native端需要自己管理好内存.


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值