1 应用层代码

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

 
  1. package com.skywang.ndk;
  2.  
  3. import android.app.Activity;
  4. import android.os.Bundle;
  5. import android.util.Log;
  6.  
  7. public class NdkParam extends Activity {
  8. public static final String TAG="skywang--NdkParam";
  9. /** Called when the activity is first created. */
  10. private Person person=null;
  11. @Override
  12. public void onCreate(Bundle savedInstanceState) {
  13. super.onCreate(savedInstanceState);
  14. setContentView(R.layout.main);
  15.  
  16. Log.d(TAG, "on create.");
  17. person = new Person();
  18. for (int i=0; i<3; i++) {
  19. getPersonInfoByIndex(person, i);
  20. Log.d(TAG, "person["+i+"] -- "+person);
  21. }
  22. }
  23.  
  24. // jni中注册的方法
  25. private native int getPersonInfoByIndex(Person person, int index);
  26.  
  27. static {
  28. // 加载本地libndk_load.so库文件
  29. System.loadLibrary("ndk_param");
  30. }
  31. }
 

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

 
  1. package com.skywang.ndk;
  2.  
  3. public class Person {
  4.  
  5. private String mName;
  6. private int mAge;
  7. private float mHeight;
  8.  
  9. public String toString(){
  10. return "mName:"+mName+", mAge:"+mAge+", mHeight:"+mHeight;
  11. }
  12.  
  13. }
 

2 JNI层代码

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

 
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <jni.h>
  5. #include <assert.h>
  6.  
  7. // 获取数组的大小
  8. # define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
  9. // 指定要注册的类,对应完整的java类名
  10. #define JNIREG_CLASS "com/skywang/ndk/NdkParam"
  11. #define JNIPAR_CLASS "com/skywang/ndk/Person"
  12.  
  13. // 引入log头文件
  14. #include <android/log.h>
  15.  
  16. // log标签
  17. #define TAG "hello_param"
  18. // 定义info信息
  19. #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)
  20. // 定义debug信息
  21. #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
  22. // 定义error信息
  23. #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)
  24.  
  25. // jfieldID结构体,用于保存类“Person.java”的filedID
  26. struct PersonOffsets
  27. {
  28. jfieldID name;
  29. jfieldID age;
  30. jfieldID height;
  31. } gPersonOffsets;
  32.  
  33. // 与“Person.java”对应的结构体,用于保存数据,并将数据赋值给Person.java的成员
  34. typedef struct tagPerson
  35. {
  36. char mName[10];
  37. int mAge;
  38. float mHeight;
  39. }Person;
  40.  
  41. // 定义了3个Person
  42. static Person gPersons[] = {
  43. {"skywang", 25, 175},
  44. {"eman" , 30, 166},
  45. {"Dan" , 51, 172},
  46. };
  47. #define GPERSON_NUM NELEM(gPersons)
  48.  
  49. /*
  50. * 根据index获取Person信息。
  51. * 参数说明:
  52. * env : JNI 接口指针。
  53. * claszz : Java 类对象。
  54. * person : 输入参数,java对象
  55. * index : 输入参数,序列号。
  56. */
  57. JNIEXPORT jint JNICALL
  58. getPersonInfoByIndex(JNIEnv *env, jobject clazz, jobject person, jint index)
  59. {
  60.  
  61. // 若index无效,则直接返回-1。
  62. if ((int)index<0 || (int)index>=GPERSON_NUM)
  63. return -1;
  64.  
  65. // 将Person数组(gPersons)中的第index个成员赋值给pPerson指针
  66. Person *pPerson = &gPersons[index];
  67.  
  68. // 设置java对象person的mName
  69. jstring name = (*env)->NewStringUTF(env, pPerson->mName);
  70. (*env)->SetObjectField(env, person, gPersonOffsets.name, name);
  71. // 设置java对象person的mAge
  72. (*env)->SetIntField(env, person, gPersonOffsets.age, pPerson->mAge);
  73. // 设置java对象person的mHeight
  74. (*env)->SetFloatField(env, person, gPersonOffsets.height, pPerson->mHeight);
  75.  
  76. LOGD("%s index-%d mName:%s, mAge:%d, mHeight:%f\n",
  77. __func__, index, pPerson->mName, pPerson->mAge, pPerson->mHeight);
  78.  
  79. return 0;
  80. }
  81.  
  82. // 初始化函数,用于获取Java中各个成员对应的fieldID。
  83. static void nativeClassInit (JNIEnv *env)
  84. {
  85. jclass personClass = (*env)->FindClass(env, JNIPAR_CLASS);
  86. // 获取Person的mName成员对应的FieldID,并保存到gPersonOffsets中
  87. gPersonOffsets.name = (*env)->GetFieldID(env, personClass, "mName" , "Ljava/lang/String;");
  88. // 获取Person的mAge成员对应的FieldID,并保存到gPersonOffsets中
  89. gPersonOffsets.age = (*env)->GetFieldID(env, personClass, "mAge" , "I");
  90. // 获取Person的mHeight成员对应的FieldID,并保存到gPersonOffsets中
  91. gPersonOffsets.height = (*env)->GetFieldID(env, personClass, "mHeight", "F");
  92. }
  93.  
  94. // Java和JNI函数的绑定表
  95. static JNINativeMethod method_table[] = {
  96. { "getPersonInfoByIndex", "(Lcom/skywang/ndk/Person;I)I", (void*)getPersonInfoByIndex },//绑定
  97. };
  98.  
  99. // 注册native方法到java中
  100. static int registerNativeMethods(JNIEnv* env, const char* className,
  101. JNINativeMethod* gMethods, int numMethods)
  102. {
  103. jclass clazz;
  104. clazz = (*env)->FindClass(env, className);
  105. if (clazz == NULL) {
  106. return JNI_FALSE;
  107. }
  108. if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {
  109. return JNI_FALSE;
  110. }
  111.  
  112. return JNI_TRUE;
  113. }
  114.  
  115. int register_ndk_param(JNIEnv *env)
  116. {
  117. nativeClassInit(env);
  118. // 调用注册方法
  119. return registerNativeMethods(env, JNIREG_CLASS,
  120. method_table, NELEM(method_table));
  121. }
  122.  
  123. // JNI_OnLoad在jni注册时,会被回调执行。
  124. JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
  125. {
  126. JNIEnv* env = NULL;
  127. jint result = -1;
  128.  
  129. if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
  130. return result;
  131. }
  132.  
  133. register_ndk_param(env);
  134.  
  135. // 返回jni的版本
  136. return JNI_VERSION_1_4;
  137. }
 

Android.mk的代码如下:

 
  1. LOCAL_PATH := $(call my-dir)
  2.  
  3. include $(CLEAR_VARS)
  4.  
  5. LOCAL_MODULE := ndk_param
  6. LOCAL_SRC_FILES := ndk_param.c
  7. # 添加对log库的支持
  8. LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llog
  9. # 若生成static的.a,只需添加 LOCAL_LDLIBS:=-llog
  10.  
  11. include $(BUILD_SHARED_LIBRARY)
  12.  
  13. LOCAL_PATH := $(call my-dir)
 

3 运行工程

logcat信息如下:

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

点击下载:“源代码

Android JNI和NDK学习(09)--JNI实例二 传递类对象的更多相关文章

  1. Android JNI和NDK学习(06)--JNI的数据类型(转)

    本文转自:http://www.cnblogs.com/skywang12345/archive/2013/05/23/3094037.html 本文介绍JNI的数据类型.NDK中关于JNI数据类型的 ...

  2. Android JNI和NDK学习(05)--JNI真机调试(转)

    本文转自: http://www.cnblogs.com/skywang12345/archive/2013/05/23/3094250.html 本文主要介绍如何将JNI导入到真机进行调试.下面以M ...

  3. Android JNI和NDK学习(04)--NDK调试方法(转)

    本文转自:http://www.cnblogs.com/skywang12345/archive/2013/05/23/3092812.html 本文主要介绍在ndk中添加log的方法.然后,我们就可 ...

  4. Android JNI和NDK学习(03)--动态方式实现JNI(转)

    本文转自:http://www.cnblogs.com/skywang12345/archive/2013/05/23/3092491.html 前面总结了静态实现JNI的方法,本文介绍如何动态实现J ...

  5. Android 通过 Intent 传递类对象或list对象

    (转:http://www.cnblogs.com/shaocm/archive/2013/01/08/2851248.html) Android中Intent传递类对象提供了两种方式一种是 通过实现 ...

  6. Android 通过 Intent 传递类对象

    Android中Intent传递类对象提供了两种方式一种是 通过实现Serializable接口传递对象,一种是通过实现Parcelable接口传递对象. 要求被传递的对象必须实现上述2种接口中的一种 ...

  7. Android 开发笔记——通过 Intent 传递类对象

    Android中Intent传递类对象提供了两种方式一种是 通过实现Serializable接口传递对象,一种是通过实现Parcelable接口传递对象. 要求被传递的对象必须实现上述2种接口中的一种 ...

  8. android通过 Intent 传递类对象

    Android中Intent传递类对象提供了两种方式一种是 通过实现Serializable接口传递对象,一种是通过实现Parcelable接口传递对象. 要求被传递的对象必须实现上述2种接口中的一种 ...

  9. Android中Intent传递类对象的方法一(Serializable)

    Activity之间通过Intent传递值,支持基本数据类型和String对象及它们的数组对象byte.byte[].char.char[].boolean.boolean[].short.short ...

随机推荐

  1. jquery-jquery异步提交表单插件

    使用jquery.form可以异步提交文件或者表单,下面的代码演示了如何提交文件 http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js <s ...

  2. 安卓版微信自带浏览器和IE6浏览器ajax请求abort错误处理

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46419567 给页面元素绑定了一个click事件用来触发ajax请求.在安卓微信自 ...

  3. 修改YOLO使其显示自定义类别

    基本参考自这篇文章(http://blog.csdn.net/ma3252788/article/details/74659230),主要用来记录下自己遇到的问题 根据@赤战约风 的帖子做如下修改可以 ...

  4. ThinkPHP5.0最最最最最简单实例

    ThinkPHP5.0最最最最最简单实例 一.效果图 二.操作步骤 1.用mysql数据库建立数据库 2.按照ThinkPHP官网的指示装好ThinkPHP5.0 tp5里面的目录结构如下: 3.配置 ...

  5. ThinkPHP5.0框架开发--第6章 TP5.0 请求和响应

    ThinkPHP5.0框架开发--第6章 TP5.0 请求和响应 第6章 TP5.0 请求和响应 ===================================== 上次复习 1.新建控制器 ...

  6. ubuntu 搜狗输入法的安装

    本文主要解决的是,通过安装搜狗网站提供的*.deb安装文件,使用ctrl+shift/space无法切换搜狗输入法的问题. 搜狗输入法 for linux:搜狗输入法 for linux,这还不算完: ...

  7. 2.windows下安装git

    转自:https://blog.csdn.net/lvkelly/article/details/54666868

  8. BZOJ 4636 (动态开节点)线段树

    思路: 偷懒 懒得离散化 搞了个动态开节点的线段树 (其实是一样的--..) 注意会有a=b的情况 要判掉 //By SiriusRen #include <cstdio> #includ ...

  9. (转载)7个去伪存真的JavaScript面试题

    7个去伪存真的JavaScript面试题 上周,我发表了<C#程序员的7个面试问题>.这次我要说的是如何淘汰那些滥竽充数的JavaScript程序员. 作者:小峰来源:码农网|2015-0 ...

  10. javascript 精确加减乘除

    最近一个项目中要使用 JS 实现自动计算的功能,本以为只是实现简单的加.减.乘.除就可以了,于是三下五除二做完了. 正当我窃喜的时候,发现问题了... 进行一些浮点数运算时,计算结果都是让我大跌眼镜啊 ...