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);
} /** env和obj参数详解:
* 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;
}
|
结果: |