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 ...
随机推荐
- IntelliJ IDEA 初始化项目时No Java SDK Found
IntelliJ IDEA 初始化项目时No Java SDK Found 自己在Project SDK后面的New按钮进行JDK的添加:
- php扩展之 pdo_mysql.so
总结:新搭编译安装的 nginx+php+mysql环境,执行之前开发的项目遇到了没有安装pdo的问题 1.进入到php5的源代码包里面,ext以下.找到pdo_mysql目录 首先运行:/usr/l ...
- bzoj1218: [HNOI2003]激光炸弹(DP二维前缀和)
1218: [HNOI2003]激光炸弹 题目:传送门 题解: 一道经典题目啊... 为了更好的操作...把整个坐标系向右上角移动,从(1,1)开始 那么f[i][j]统计一下以(i,j)作为右上角, ...
- zzulioj--1711--漂洋过海来看你(dfs+vector)
1711: 漂洋过海来看你 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 89 Solved: 33 SubmitStatusWeb Board D ...
- angular4(2-2)angular脚手架引入第三方类库(swiper)
试了好多方法,npm install 方法失败了,下载到本地是可以使用的: 将swiper文件放到assets文件下: 项目目录下:(命令行) 因为ts并不能准确识别js语法,所以需要用ts中的int ...
- [jzoj 5930] [NOIP2018模拟10.26】山花 解题报告 (质因数分类)
题目链接: http://172.16.0.132/senior/#contest/show/2538/2 题目: 小S决定从某一个节点$u$开始对其子树中与$u$距离小于$K$的节点代表的花树进行采 ...
- ImageUtils
JavaSE package com.easystructure.utils.system; import java.awt.Color; import java.awt.Font; import j ...
- HD-ACM算法专攻系列(13)——How Many Fibs?
问题描述: 源码: import java.math.BigInteger; import java.util.*; public class Main { //主函数 public static v ...
- java中return在Try-Catch中的执行顺序
我们知道return会结束此方法并返回指定值.以及在Try-catch-finally中无论try代码块中有没有异常finally中的代码时都会被执行的.但是如果return包含在try-catch- ...
- 乌班图 之 apt命令 及 VMware共享文件夹
apt是Advanced Packaging Tool ,是Ubuntu下的一个安装包管理工具 大部分软件的安装.更新.卸载 都是利用apt命令来实现 直接在终端输入apt即可查阅命令的帮助信息 常用 ...