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

来源:互联网 发布:兼职数据录入员招聘 编辑:程序博客网 时间:2024/06/16 18:00


熟悉开发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返回,防止别人反编译后拿到urlpublic 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 := MessageLOCAL_SRC_FILES := Message.cinclude $(BUILD_SHARED_LIBRARY)

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



0 0
原创粉丝点击