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学习笔记之TabHost
  2. Android(安卓)Studio获取SHA1值
  3. Android的第三个应用---短信发送器
  4. Android(安卓)程序获取、设置铃声、音量、静音、扬声器
  5. 《Android》Lesson21-广播+SharedPreferences
  6. android accessibility
  7. android編譯內核模塊
  8. 在SQLite数据库中获取新插入数据自增长的ID值(传智播客笔记)
  9. 类和 Json对象

随机推荐

  1. 转:android listView 继承ListActivity的
  2. Android SDK安装Android4.0“冰激淋三明
  3. Android(安卓)系统属性的设置查询
  4. 【Android(安卓)Training - 03】使用Frag
  5. Android DexClassLoader动态加载类文件
  6. Android 快速开发框架:推荐10个框架:afina
  7. Android:AIDL进程之间的通信
  8. Android 中LayoutInflater(布局加载器)源码
  9. Android自定制Toast显示外观
  10. Android 全景框架了解