JNI(三)、java代码传递int、String、int[] 并 调用C 代码


熟悉开发JNI基本流程以后,我来尝试写一下传递多种数据类型的情况。包括int、String、int[ ] 类型。这次我把这些native方法放在一个类中。

定义本地接口方法:

package com.example.manzuo.jni;

public class JNIUtils {
	
	static {
		System.loadLibrary("Message");
	}

	public native String callC();
	//给C代码传递 多个参数
	public native int javaCallCSendInts(int i,int j);
	
	 // 给C代码传递字符 数据
	 //应用场景:把web 请求的url用jni返回,防止别人反编译后拿到url
	public native String javaCallCSendString(String params);
	
	//给C代码传递 整形数组
	//应用场景:图像,音频处理。
	public native int[] javaCallCSendIntArray(int[] arraydata);
	
	private JNIUtils(){}
	public static JNIUtils instance =  new JNIUtils();
	public static JNIUtils getInstance(){
		return instance;
	}
	
}

然后 编写对应的C代码的实现

#include <stdio.h>
#include <jni.h>
#include <string.h>


char*   Jstring2CStr(JNIEnv*   env,   jstring   jstr)
{
	 char*   rtn   =   NULL;
	 jclass   clsstring   =   (*env)->FindClass(env,"java/lang/String");
	 jstring   strencode   =   (*env)->NewStringUTF(env,"GB2312");
	 jmethodID   mid   =   (*env)->GetMethodID(env,clsstring,   "getBytes",   "(Ljava/lang/String;)[B");
	 jbyteArray   barr=   (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode); // String .getByte("GB2312");
	 jsize   alen   =   (*env)->GetArrayLength(env,barr);
	 jbyte*   ba   =   (*env)->GetByteArrayElements(env,barr,JNI_FALSE);
	 if(alen   >   0)
	 {
	  rtn   =   (char*)malloc(alen+1);         //"\0"
	  memcpy(rtn,ba,alen);
	  rtn[alen]=0;
	 }
	 (*env)->ReleaseByteArrayElements(env,barr,ba,0);  //
	 return rtn;
}


jstring Java_com_example_manzuo_jni_JNIUtils_callC(JNIEnv* env,jobject obj){

//	return **env.NewStringUTF(env,"message from C returned");
	return (*env)->NewStringUTF(env,"message from C returned");
}


//传递多个参数的情况:这个方法用来 计算两个数的和。
jint  Java_com_example_manzuo_jni_JNIUtils_javaCallCSendInts(JNIEnv * env, jobject object, jint x, jint y){

	// 由jni.h文件中定义得知:java中的int就是c语言中的int。
	return x+y;
}
//传递String 类型的情况:返回一个新的字符串“你好 xxx”.
//这里的str 是java中的String,  在C语言中不能直接操作str(java总的String)。怎么做呢?
// 把java语言中的字符串转换成C 语言中的 char数组,下面的Jstring2CStr方法 就是做这个工作。
jstring Java_com_example_manzuo_jni_JNIUtils_javaCallCSendString(JNIEnv * env, jobject object, jstring str){

	char* c = Jstring2CStr(env,str);
    char* hi = "Hi 你好 ";
    // 这个C语言中的函数 就是字符串拼接函数,注意对字符串需要引入string.h 头文件
    // 函数执行过后,第一个参数的值就已经被操作了,这里是c 变量,那么c的值就变了。

    strcat(c,hi);

    return (*env)->NewStringUTF(env,c);


}
//传递int[] 数组类型的情况: 对数组中的每个数字*2 。 在C语言中要处理java数组,(注意是java数组不是C的数组)需要知道 数组长度和 如何遍历数组。
//在jni.h头文件 中我找到了 如下定义
// 得到java数组长度
//		jsize       (*GetArrayLength)(JNIEnv*, jarray);
// 得到java传递过来的int数组,第三个参数表示是否对数组中的元素拷贝,传0、1都行。
//	    jint*       (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*); 遍历java数组元素
//注意:不能一上来直接用C语言操作,必须 转化为C语言的东西。再进行操作.
jintArray  Java_com_example_manzuo_jni_JNIUtils_javaCallCSendIntArray(JNIEnv * env, jobject object, jintArray jarray){

		int length = (*env)->GetArrayLength(env,jarray);
		//由于jint和int是一样的。所以用int* 接收.
		int* array = (*env)->GetIntArrayElements(env,jarray,0);
		int i=0;
		for(;i<length;i++){

			array[i] = array[i] * array[i];

		}
		return jarray;
}




注:在碰到要传递的其他类型时,也可以用这几种类型来实现,比如传递char  ,那么就可以用String来表示,要传递String [ ] ,可以考虑将数组中的数据转为一个

大的字符串,然后用String。总之简单就行。

-----------------------------------------------Android.mk----------------------------------------

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := Message
LOCAL_SRC_FILES := Message.c
include $(BUILD_SHARED_LIBRARY)

执行结果:以上调试均执行成功。



©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页