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”的filedID
- struct PersonOffsets
- {
- jfieldID name;
- jfieldID age;
- jfieldID height;
- } gPersonOffsets;
- // 与“Person.java”对应的结构体,用于保存数据,并将数据赋值给Person.java的成员
- typedef struct tagPerson
- {
- char mName[10];
- int mAge;
- float mHeight;
- }Person;
- // 定义了3个Person
- static 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_param
- LOCAL_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.000000
- D/skywang--NdkParam: person[0] -- mName:skywang, mAge:25, mHeight:175.0
- D/hello_param: getPersonInfoByIndex index-1 mName:eman, mAge:30, mHeight:166.000000
- D/skywang--NdkParam: person[1] -- mName:eman, mAge:30, mHeight:166.0
- D/hello_param: getPersonInfoByIndex index-2 mName:Dan, mAge:51, mHeight:172.000000
- D/skywang--NdkParam: person[2] -- mName:Dan, mAge:51, mHeight:172.0
点击下载:“源代码”
Android JNI和NDK学习(09)--JNI实例二 传递类对象的更多相关文章
- Android JNI和NDK学习(06)--JNI的数据类型(转)
本文转自:http://www.cnblogs.com/skywang12345/archive/2013/05/23/3094037.html 本文介绍JNI的数据类型.NDK中关于JNI数据类型的 ...
- Android JNI和NDK学习(05)--JNI真机调试(转)
本文转自: http://www.cnblogs.com/skywang12345/archive/2013/05/23/3094250.html 本文主要介绍如何将JNI导入到真机进行调试.下面以M ...
- Android JNI和NDK学习(04)--NDK调试方法(转)
本文转自:http://www.cnblogs.com/skywang12345/archive/2013/05/23/3092812.html 本文主要介绍在ndk中添加log的方法.然后,我们就可 ...
- Android JNI和NDK学习(03)--动态方式实现JNI(转)
本文转自:http://www.cnblogs.com/skywang12345/archive/2013/05/23/3092491.html 前面总结了静态实现JNI的方法,本文介绍如何动态实现J ...
- Android 通过 Intent 传递类对象或list对象
(转:http://www.cnblogs.com/shaocm/archive/2013/01/08/2851248.html) Android中Intent传递类对象提供了两种方式一种是 通过实现 ...
- Android 通过 Intent 传递类对象
Android中Intent传递类对象提供了两种方式一种是 通过实现Serializable接口传递对象,一种是通过实现Parcelable接口传递对象. 要求被传递的对象必须实现上述2种接口中的一种 ...
- Android 开发笔记——通过 Intent 传递类对象
Android中Intent传递类对象提供了两种方式一种是 通过实现Serializable接口传递对象,一种是通过实现Parcelable接口传递对象. 要求被传递的对象必须实现上述2种接口中的一种 ...
- android通过 Intent 传递类对象
Android中Intent传递类对象提供了两种方式一种是 通过实现Serializable接口传递对象,一种是通过实现Parcelable接口传递对象. 要求被传递的对象必须实现上述2种接口中的一种 ...
- Android中Intent传递类对象的方法一(Serializable)
Activity之间通过Intent传递值,支持基本数据类型和String对象及它们的数组对象byte.byte[].char.char[].boolean.boolean[].short.short ...
随机推荐
- jquery-jquery异步提交表单插件
使用jquery.form可以异步提交文件或者表单,下面的代码演示了如何提交文件 http://apps.bdimg.com/libs/jquery/2.1.1/jquery.min.js <s ...
- 安卓版微信自带浏览器和IE6浏览器ajax请求abort错误处理
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46419567 给页面元素绑定了一个click事件用来触发ajax请求.在安卓微信自 ...
- 修改YOLO使其显示自定义类别
基本参考自这篇文章(http://blog.csdn.net/ma3252788/article/details/74659230),主要用来记录下自己遇到的问题 根据@赤战约风 的帖子做如下修改可以 ...
- ThinkPHP5.0最最最最最简单实例
ThinkPHP5.0最最最最最简单实例 一.效果图 二.操作步骤 1.用mysql数据库建立数据库 2.按照ThinkPHP官网的指示装好ThinkPHP5.0 tp5里面的目录结构如下: 3.配置 ...
- ThinkPHP5.0框架开发--第6章 TP5.0 请求和响应
ThinkPHP5.0框架开发--第6章 TP5.0 请求和响应 第6章 TP5.0 请求和响应 ===================================== 上次复习 1.新建控制器 ...
- ubuntu 搜狗输入法的安装
本文主要解决的是,通过安装搜狗网站提供的*.deb安装文件,使用ctrl+shift/space无法切换搜狗输入法的问题. 搜狗输入法 for linux:搜狗输入法 for linux,这还不算完: ...
- 2.windows下安装git
转自:https://blog.csdn.net/lvkelly/article/details/54666868
- BZOJ 4636 (动态开节点)线段树
思路: 偷懒 懒得离散化 搞了个动态开节点的线段树 (其实是一样的--..) 注意会有a=b的情况 要判掉 //By SiriusRen #include <cstdio> #includ ...
- (转载)7个去伪存真的JavaScript面试题
7个去伪存真的JavaScript面试题 上周,我发表了<C#程序员的7个面试问题>.这次我要说的是如何淘汰那些滥竽充数的JavaScript程序员. 作者:小峰来源:码农网|2015-0 ...
- javascript 精确加减乘除
最近一个项目中要使用 JS 实现自动计算的功能,本以为只是实现简单的加.减.乘.除就可以了,于是三下五除二做完了. 正当我窃喜的时候,发现问题了... 进行一些浮点数运算时,计算结果都是让我大跌眼镜啊 ...