[jni] 07_java传递数据给c

Android 4.0

java传递数据给c

对于char,java中占用两个字节,而c语言中占用一个字节,所以要将java中的char当做String来处理
步骤:1、创建java类DataProvider,里面定义4个native方法:
package cn.zengfansheng.datapass;
public class DataProvider {
    /**
     * 1、把两个java中的int传递给c语言, c语言处理完毕后,把相加的结果返回给java
     * @param x 
     * @param y
     * @return
     */
    public native int add(int x, int y);
    /**
     * 2、把java中的string传递给c语言, c语言获取到java中的string之后 ,在string后面添加 一个hello 字符串
     * @param s
     * @return
     */
    public native String sayHelloInC(String s);
    /**
     * 3、把java中的一个int数组 传递给c语言,c语言处理完毕这个java数组 
     * 把int数组中的每一个元素+10 ;
     * 然后把结果返回给java
     * @param iNum
     * @return
     */
    public native int[] intMethod(int[] iNum);
    
    /**
     * 4、静态的,将两个数相减
     * @param x 被减数
     * @param y 减数
     * @return 被减的结果
     */
    public static native int sub(int x ,int y);
}
2、然后使用javah生成头文件,然后拷贝头文件.h,建立Android.mk文件,
3、然后建立c代码,实现功能
#include <stdio.h>
#include <jni.h>
#include <malloc.h>
#include <android/log.h>
#include "cn_zengfansheng_datapass_DataProvider.h"
#define LOG_TAG "System.out.c" //在LogCat上打印出来的Tag
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)

//0、工具类:返回值 char* 这个代表char数组的首地址
//Jstring2CStr 把java中的jstring的类型转化成一个c语言中的char 字符串
char* Jstring2CStr(JNIEnv* env, jstring jstr) {
    char* rtn = NULL;
    jclass clsstring = (*env)->FindClass(env, "java/lang/String"); //String
    jstring strencode = (*env)->NewStringUTF(env, "GB2312"); // 得到一个java字符串 "GB2312"
    jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes",
            "(Ljava/lang/String;)[B"); //[ String.getBytes("gb2312");
    jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid,
            strencode); // String .getByte("GB2312");
    jsize alen = (*env)->GetArrayLength(env, barr); // byte数组的长度
    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;
}

//1、把两个java中的int传递给c语言, c语言处理完毕后,把相加的结果返回给java
JNIEXPORT jint JNICALL Java_cn_zengfansheng_datapass_DataProvider_add(
        JNIEnv * env, jobject obj, jint x, jint y) {
    LOGD("x=%d", x);
    LOGD("y=%d", y);
    return x + y;
}

//2、把java中的string传递给c语言, c语言获取到java中的string之后 ,在string后面添加 一个hello字符串
JNIEXPORT jstring JNICALL Java_cn_zengfansheng_datapass_DataProvider_sayHelloInC(
        JNIEnv * env, jobject obj, jstring jstr) {

    //1、获取从java传递进来的String数组,s的首地址(//在c语言中 是没有java的String)
    char* cstr = Jstring2CStr(env, jstr);
    LOGD("cstr=%s", cstr);
    char* arr = " hello\0";  //char* 是不可变的,在数据空间,char arr[]是可变的,在堆栈空间
    //char arr[7] = { ' ', 'h', 'e', 'l', 'l', 'o', '\0' };// c语言中的字符串 都是以'/0' 作为结尾
    //两者都可以实现功能

    //2、将该数组增加一个hello字符串
    strcat(cstr, arr);
    LOGD("new cstr=%s", cstr);
    return (*env)->NewStringUTF(env, cstr);
}

/** envobj参数详解:
  * env java 虚拟机 结构体c实现的指针 包含的有很多jni方法
  * jobject obj 代表的是调用这个c代码的java对象 代表的是DataProider的对象
  */

//3、把java中的一个int数组 传递给c语言,c语言处理完毕这个java数组
JNIEXPORT jintArray JNICALL Java_cn_zengfansheng_datapass_DataProvider_intMethod(
        JNIEnv * env, jobject obj, jintArray arr) {

    //1、获取从java传递进来的int数组
    //jsize (*GetArrayLength)(JNIEnv*, jarray);
    int size = (*env)->GetArrayLength(env, arr);
    LOGD("c arr size =%d", size);    //不要将,写成+

    //2、遍历每一个元素,然后增加10
    // jint*   (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);//第三个参数,基本没用
    int* intarr = (*env)->GetIntArrayElements(env, arr, 0);
    int i = 0;
    for (; i < size; i++) {
        LOGD("c intarr[%d]=%d", i, intarr[i]
        *(intarr + i) += 10;
    }

    //  void   (*ReleaseIntArrayElements)(JNIEnv*, jintArray,jint*, jint);
    //    (*env)->ReleaseIntArrayElements(env,arr,intarr,0); // c语言释放掉 刚才申请的内存空间
    return arr;    //不能return intarr
}

/**
 * 代表的是调用c代码 的class类
 * jclass DataProvider  类
 */

// 4、静态的,将两个数相减
JNIEXPORT jint JNICALL Java_cn_zengfansheng_datapass_DataProvider_sub(
        JNIEnv * env, jclass cla, jint x, jint y) {
    LOGD("x=%d", x);
    LOGD("y=%d", y);
    return x - y;
}
结果: