Android JNI和NDK学习(09)--JNI实例二 传递类对象

1 应用层代码

NdkParam.java是JNI函数的调用类,它的代码如下:

package com.skywang.ndk;import android.app.Activity;import android.os.Bundle;import android.util.Log;public class NdkParam extends Activity {    public static final String TAG="skywang--NdkParam";    /** Called when the activity is first created. */    private Person person=null;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);                Log.d(TAG, "on create.");        person = new Person();        for (int i=0; i<3; i++) {            getPersonInfoByIndex(person, i);            Log.d(TAG, "person["+i+"] -- "+person);        }    }        // jni中注册的方法    private native int getPersonInfoByIndex(Person person, int index);    static {        // 加载本地libndk_load.so库文件        System.loadLibrary("ndk_param");    }}

Person.java是用来在Java和JNI之间传递的数据类,它的代码如下:

package com.skywang.ndk;public class Person {        private String  mName;                         private int     mAge;    private float   mHeight;        public String toString(){        return "mName:"+mName+", mAge:"+mAge+", mHeight:"+mHeight;    }}

2 JNI层代码

ndk_param.c是实现并注册JNI的文件,它的代码如下:

#include <stdlib.h>#include <string.h>#include <stdio.h>#include <jni.h>#include <assert.h>// 获取数组的大小# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))// 指定要注册的类,对应完整的java类名#define JNIREG_CLASS "com/skywang/ndk/NdkParam"#define JNIPAR_CLASS "com/skywang/ndk/Person"// 引入log头文件#include <android/log.h>  // log标签#define  TAG    "hello_param"// 定义info信息#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)// 定义debug信息#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)// 定义error信息#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)// jfieldID结构体,用于保存类“Person.java”的filedIDstruct PersonOffsets{    jfieldID    name;    jfieldID    age;    jfieldID    height;} gPersonOffsets;// 与“Person.java”对应的结构体,用于保存数据,并将数据赋值给Person.java的成员typedef struct tagPerson{    char    mName[10];    int     mAge;    float   mHeight;}Person;// 定义了3个Personstatic Person gPersons[] = {    {"skywang", 25, 175},    {"eman"   , 30, 166},    {"Dan"    , 51, 172},};#define GPERSON_NUM NELEM(gPersons)/*  * 根据index获取Person信息。 * 参数说明: *         env : JNI 接口指针。 *        claszz : Java 类对象。 *        person : 输入参数,java对象 *        index : 输入参数,序列号。 */JNIEXPORT jint JNICALL getPersonInfoByIndex(JNIEnv *env, jobject clazz, jobject person, jint index){    // 若index无效,则直接返回-1。    if ((int)index<0 || (int)index>=GPERSON_NUM)        return -1;    // 将Person数组(gPersons)中的第index个成员赋值给pPerson指针    Person *pPerson = &gPersons[index];    // 设置java对象person的mName    jstring name = (*env)->NewStringUTF(env, pPerson->mName);    (*env)->SetObjectField(env, person, gPersonOffsets.name, name);    // 设置java对象person的mAge    (*env)->SetIntField(env, person, gPersonOffsets.age, pPerson->mAge);    // 设置java对象person的mHeight    (*env)->SetFloatField(env, person, gPersonOffsets.height, pPerson->mHeight);    LOGD("%s index-%d  mName:%s, mAge:%d, mHeight:%f\n",             __func__, index, pPerson->mName, pPerson->mAge, pPerson->mHeight);    return 0;}// 初始化函数,用于获取Java中各个成员对应的fieldID。static void nativeClassInit (JNIEnv *env){       jclass personClass = (*env)->FindClass(env, JNIPAR_CLASS);           // 获取Person的mName成员对应的FieldID,并保存到gPersonOffsets中    gPersonOffsets.name     = (*env)->GetFieldID(env, personClass, "mName"  , "Ljava/lang/String;");            // 获取Person的mAge成员对应的FieldID,并保存到gPersonOffsets中    gPersonOffsets.age      = (*env)->GetFieldID(env, personClass, "mAge"   , "I");    // 获取Person的mHeight成员对应的FieldID,并保存到gPersonOffsets中    gPersonOffsets.height   = (*env)->GetFieldID(env, personClass, "mHeight", "F");}// Java和JNI函数的绑定表static JNINativeMethod method_table[] = {    { "getPersonInfoByIndex", "(Lcom/skywang/ndk/Person;I)I", (void*)getPersonInfoByIndex },//绑定};// 注册native方法到java中static int registerNativeMethods(JNIEnv* env, const char* className,        JNINativeMethod* gMethods, int numMethods){    jclass clazz;    clazz = (*env)->FindClass(env, className);    if (clazz == NULL) {        return JNI_FALSE;    }    if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {        return JNI_FALSE;    }    return JNI_TRUE;}int register_ndk_param(JNIEnv *env){    nativeClassInit(env);    // 调用注册方法    return registerNativeMethods(env, JNIREG_CLASS,            method_table, NELEM(method_table));}// JNI_OnLoad在jni注册时,会被回调执行。JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved){    JNIEnv* env = NULL;    jint result = -1;     if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {        return result;    }       register_ndk_param(env);    // 返回jni的版本    return JNI_VERSION_1_4;}

Android.mk的代码如下:

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE    := ndk_paramLOCAL_SRC_FILES := ndk_param.c# 添加对log库的支持LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llog#  若生成static的.a,只需添加 LOCAL_LDLIBS:=-llog include $(BUILD_SHARED_LIBRARY)LOCAL_PATH := $(call my-dir)

3 运行工程

logcat信息如下:

D/skywang--NdkParam: on create.D/hello_param: getPersonInfoByIndex index-0  mName:skywang, mAge:25, mHeight:175.000000D/skywang--NdkParam: person[0] -- mName:skywang, mAge:25, mHeight:175.0D/hello_param: getPersonInfoByIndex index-1  mName:eman, mAge:30, mHeight:166.000000D/skywang--NdkParam: person[1] -- mName:eman, mAge:30, mHeight:166.0D/hello_param: getPersonInfoByIndex index-2  mName:Dan, mAge:51, mHeight:172.000000D/skywang--NdkParam: person[2] -- mName:Dan, mAge:51, mHeight:172.0

点击下载:“源代码

更多相关文章

  1. Android(java)学习笔记113:Android编写代码调用Vibrator震动功能,按
  2. android 源代码错误
  3. Android sqlite 数据库在java代码中的增删改查
  4. Android 通过intent 传递对象
  5. android代码实现按钮自旋转
  6. Android中MAC地址获取代码
  7. 服务器向Android写一个对象

随机推荐

  1. Android应用开发——TextView控件属性列
  2. android通过adb设置以太网共享
  3. [置顶] android四大组件之intent
  4. Android调用shell脚本并获得输出
  5. Android数据库操作
  6. (4.1.21.4)Android(安卓)Handler 异步消息
  7. Android内存管理-SoftReference的使用
  8. Android应用程序线程消息循环模型分析
  9. Android(安卓)应用程序之间数据共享—Con
  10. Android(安卓)Studio 无设备打包与有设备