Android NDK中数据类型传递使用

根据上一篇对应的数据类型关系,从这一篇开始一种一种的对应进行测试.工程的话还是用第一篇中的那个工程:

<1> : 先介绍整型 :

在工程lib包下新建DurianJniInteger.java的类型,添加内容如下:

/**  
* @Title: DurianJniInteger.java
* @Package com.durian.jnienv.lib
* @Description: TODO
* @author zhibao.liu from durian organization
* @date 2015-12-24 下午05:01:36
* @version V1.0  
*/
package com.durian.jnienv.lib;

/**
 * @ClassName: DurianJniInteger
 * @Description: TODO
 * @author zhibao.liu Freelancer
 * @email warden_sprite@foxmail.com
 * @date 2015-12-24 下午05:01:36
 *
 */
public class DurianJniInteger {

    public native int DurianAdd(int a,int b);
    public native int DurianDul(int a,int b);

}

做一个加号运算,做一个减号运算.

build 工程,生成class文件,然后在include.txt文件中修改,单独javah下面的一个就好了:

com.durian.jnienv.lib.DurianJniInteger

执行cmd命令:

javah -d jni -classpath bin/classes -jni @temp.txt


然后将生成.h文件名调整一下,当然建议大家不要调整,不然每次javah一次都要修改一次文件名,很逗逼的.


同时我调整了一些辅助文件到durianUtils.h中:

#include <jni.h>
/* Header for class com_durian_jnienv_lib_DurianJni */

#ifndef _Included_com_durian_jnienv_lib_DurianUtils
#define _Included_com_durian_jnienv_lib_DurianUtils
#ifdef __cplusplus
extern "C" {
#endif

#include <android/log.h>
#define LOG_TAG "durian"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__)

#ifdef __cplusplus
}
#endif
#endif

durianJniInteger.c 如下:

#include "durianJniInteger.h"
#include "durianUtils.h"

JNIEXPORT jint JNICALL Java_com_durian_jnienv_lib_DurianJniInteger_DurianAdd(JNIEnv *env, jobject jobj, jint a, jint b){

	int sum =(int)a+(int)b;
	LOGI("sum : %d from jni !",sum);
	return (jint)sum;

}

JNIEXPORT jint JNICALL Java_com_durian_jnienv_lib_DurianJniInteger_DurianDul(JNIEnv *env, jobject jobj, jint a, jint b){

	int dul =0;
	if(a>b){
		dul=(int)a-(int)b;
	}else{
		dul=(int)b-(int)a;
	}

	LOGI("dul : %d from jni !",dul);
	return (jint)dul;

}

durianJniInteger.h如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_durian_jnienv_lib_DurianJniInteger */

#ifndef _Included_com_durian_jnienv_lib_DurianJniInteger
#define _Included_com_durian_jnienv_lib_DurianJniInteger
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_durian_jnienv_lib_DurianJniInteger
 * Method:    DurianAdd
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_durian_jnienv_lib_DurianJniInteger_DurianAdd
  (JNIEnv *, jobject, jint, jint);

/*
 * Class:     com_durian_jnienv_lib_DurianJniInteger
 * Method:    DurianDul
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_durian_jnienv_lib_DurianJniInteger_DurianDul
  (JNIEnv *, jobject, jint, jint);

#ifdef __cplusplus
}
#endif
#endif

Android.mk中还需要将上面的c文件添加到编译中:

LOCAL_SRC_FILES += durianJniInteger.c

基本上准备就OK了,运行结果如下:

很容易验证就OK了.


下面在介绍字符串型:

同样在工程lib包下面添加DurianJniString.java,然后类似上面的编译方式,生成头文件,修改名称后durianJniString.h,并且新建durianJniString.c文件,内容如下:

DurianJniString.java :

/**  
* @Title: DurianJniString.java
* @Package com.durian.jnienv.lib
* @Description: TODO
* @author zhibao.liu from durian organization
* @date 2015-12-24 下午05:02:57
* @version V1.0  
*/
package com.durian.jnienv.lib;

/**
 * @ClassName: DurianJniString
 * @Description: TODO
 * @author zhibao.liu Freelancer
 * @email warden_sprite@foxmail.com
 * @date 2015-12-24 下午05:02:57
 *
 */
public class DurianJniString {

    public native void setInformation(String info);
    public native String getInformation();
    
}


不过需要添加一个java string转为jstring的函数放到durianUtils.c中,如果没有这个文件新建之:

#include<stdio.h>
#include<string.h>
#include "durianUtils.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); //new   char[alen+1]; "\0"
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    (*env)->ReleaseByteArrayElements(env, barr, ba, 0); //释放内存

    return rtn;
}


durianJniString.c 文件内容如下:

#include "durianJniString.h"
#include "durianUtils.h"
#include "durianUtils.c"

JNIEXPORT void JNICALL Java_com_durian_jnienv_lib_DurianJniString_setInformation(JNIEnv *env, jobject jobj, jstring msg){

	char* message;
	message=Jstring2CStr(env,msg);

	LOGI("message : %s log from jni !",message);

}

JNIEXPORT jstring JNICALL Java_com_durian_jnienv_lib_DurianJniString_getInformation(JNIEnv *env, jobject jobj){

	char* newstr = "return durian generall information from jni !";

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

}


并且同样在Android.mk文件中添加:

LOCAL_SRC_FILES += durianJniString.c

编译运行:

设置进去和返回都是OK的.


下面接着来扯一下布尔类型的传递.

同样新建一个DurianJniBoolean.java :

/**  
* @Title: DurianJniBoolean.java
* @Package com.durian.jnienv.lib
* @Description: TODO
* @author zhibao.liu from durian organization
* @date 2015-12-24 下午05:03:18
* @version V1.0  
*/
package com.durian.jnienv.lib;

/**
 * @ClassName: DurianJniBoolean
 * @Description: TODO
 * @author zhibao.liu Freelancer
 * @email warden_sprite@foxmail.com
 * @date 2015-12-24 下午05:03:18
 *
 */
public class DurianJniBoolean {

    public native void setBoolean(boolean lean);
    public native boolean getBoolean();
    
}

对应生成.h文件,我这里直接写出实现函数durianJniBoolean.c的文件:

#include "durianJniBoolean.h"
#include "durianUtils.h"

JNIEXPORT void JNICALL Java_com_durian_jnienv_lib_DurianJniBoolean_setBoolean(JNIEnv *env, jobject jobj, jboolean lean){

	if(lean==JNI_TRUE){
		LOGI("boolean : true log from jni !");
	}else{
		LOGI("boolean : false log from jni !");
	}

}

JNIEXPORT jboolean JNICALL Java_com_durian_jnienv_lib_DurianJniBoolean_getBoolean(JNIEnv *env, jobject jobj){

	LOGI("return boolean : true log from jni !");

	return JNI_TRUE;
}

build,运行结果:


下面是数组传递,主要介绍两种,一个整型(上一篇表单2中的其他类型一次类推),一个字符串型:

DurianJniArray.java :

/**  
* @Title: DurianJniArray.java
* @Package com.durian.jnienv.lib
* @Description: TODO
* @author zhibao.liu from durian organization
* @date 2015-12-25 上午09:52:02
* @version V1.0  
*/
package com.durian.jnienv.lib;

/**
 * @ClassName: DurianJniArray
 * @Description: TODO
 * @author zhibao.liu Freelancer
 * @email warden_sprite@foxmail.com
 * @date 2015-12-25 上午09:52:02
 *
 */
public class DurianJniArray {

    public native void setDurianStringArray(String[] array);
    public native String[] getDurianStringArray();
    
    public native void setDurianBooleanArray(Boolean[] array);
    public native Boolean[] getDurianBooleanArray();
    
    public native void setDurianIntegerArray(int[] array);
    public native int[] getDurianIntegerArray();
    
}

然后编译生成头文件,实现他的具体方法如下durianJniArray.c :

#include "durianJniArray.h"
#include "durianUtils.h"

JNIEXPORT void JNICALL Java_com_durian_jnienv_lib_DurianJniArray_setDurianStringArray(JNIEnv *env, jobject jobj, jobjectArray array) {

	int size=(*env)->GetArrayLength(env,array);
	int i=0;
	LOGI("array string : %d",size);
	for(i=0;i<size;i++) {
		jstring obja=(jstring)(*env)->GetObjectArrayElement(env,array,i);
		LOGI("array string : %s",(*env)->GetStringUTFChars(env,obja,NULL));
	}

}

JNIEXPORT jobjectArray JNICALL Java_com_durian_jnienv_lib_DurianJniArray_getDurianStringArray(
		JNIEnv *env, jobject jobj) {
	jstring str;
	jobjectArray ret;
	jsize len = 5;
	char* sa[] = { "Hello,", "world!", "JNI", "is", "fun" };
	int i = 0;

	ret = (*env)->NewObjectArray(env,len,(*env)->FindClass(env,"java/lang/String"),0);
	for(i=0;i<5;i++){
		str = (*env)->NewStringUTF(env,sa[i]);
		(*env)->SetObjectArrayElement(env,ret,i,str);
	}

	return ret;
}

JNIEXPORT void JNICALL Java_com_durian_jnienv_lib_DurianJniArray_setDurianBooleanArray(JNIEnv *env, jobject jobj, jobjectArray array) {

	jsize len = (*env)->GetArrayLength(env,array);
	int i=0;
	jboolean obja;

	for( i=0; i < len; i++ ){

		obja=(jboolean)(*env)->GetObjectArrayElement(env,array,i);
		if(obja==JNI_TRUE){
			LOGI( "array boolean = true");
		}else{
			LOGI( "array boolean = false");
		}

	}

}

JNIEXPORT jobjectArray JNICALL Java_com_durian_jnienv_lib_DurianJniArray_getDurianBooleanArray(
		JNIEnv *env, jobject jobj) {

	jboolean lean;
	jbooleanArray args;
	jsize len = 5;
	jboolean le[] = { 0, 0, 0, 0, 1 };
	int i = 0;

	jintArray arg=(*env)->NewBooleanArray(env,5);

	args = (*env)->NewObjectArray(env,len, (*env)->FindClass(env,"java/lang/Boolean"), 0);

	(*env)->SetBooleanArrayRegion(env,arg,0,5,le);

	return arg;

}

JNIEXPORT void JNICALL Java_com_durian_jnienv_lib_DurianJniArray_setDurianIntegerArray
(JNIEnv *env, jobject jobj, jintArray array) {

	jint *buf=(*env)->GetIntArrayElements(env,array,(jint)0);
	jsize len=(*env)->GetArrayLength(env,array);
	int i=0;

	for(i=0;i<len;i++) {
		LOGI( "array set int = %d", buf[i]);
	}

	(*env)->ReleaseIntArrayElements(env, array, buf, 0);

}

JNIEXPORT jintArray JNICALL Java_com_durian_jnienv_lib_DurianJniArray_getDurianIntegerArray(
		JNIEnv *env, jobject jobj) {

	jint dur;
	jobjectArray args;
	jintArray arg=(*env)->NewIntArray(env,5);
	jsize len = 5;
	jint du[5] = { 100, 101, 102, 103, 104 };
	LOGI( "array set int 123");

	int i = 0;
	args = (*env)->NewObjectArray(env,5, (*env)->FindClass(env,"[I"), NULL);
	LOGI( "array set int 235");
	(*env)->SetIntArrayRegion(env,arg,0,5,du);

	return arg;

}


修改Android中主类:

private DurianJniArray mDurianJniArray;
mDurianJniArray=new DurianJniArray();

运行程序:

mDurianJniArray.setDurianIntegerArray(new int[]{200,201,202,203});
                        int[] arrInt=mDurianJniArray.getDurianIntegerArray();
                        
                        for(int i=0;i<arrInt.length;i++){
                            Log.i(TAG,"arrInt["+i+"]="+arrInt[i]);
                        }
                        
                        mDurianJniArray.setDurianStringArray(new String[]{"zhi","bao","liu","name","company"});
                        
                        String msg[]=mDurianJniArray.getDurianStringArray();
                        for(int i=0;i<msg.length;i++){
                            Log.i(TAG,"arrString["+i+"]="+msg[i]);
                        }

很简单,然后看看运行结果:



这个程序其实就是对前面一片的实际操作.


有图有代码:

百度盘:

http://pan.baidu.com/s/1mhmiUGo
























  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值