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); //" " 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)
执行结果:以上调试均执行成功。
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: 字符串面试题(三)— 把一个字符串的大写字母放到字符串的后面
- 下一篇: 关于java数组的扩容问题