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实例二 传递类对象的更多相关文章

  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. 面试书上一些题目的整理:O(n)复杂度排序年龄 & 青蛙跳台阶

    可以按照年龄的个数,设置99个桶,然后桶内处理. 青蛙跳台阶,每次1阶或者2阶,就是fib数 如果每次1到n阶,那么归纳法可得,是2^(n-1) 另外1*2 覆盖 2*n个矩阵的问题,仍然是Fib数. ...

  2. CC2540/CC2541 : Set the Peripheral Being Advertising while It is Being Connected

    There is possible to set your CC254X be scanable when it is in connection. But, based on my test,the ...

  3. HTML打开摄像头,进行拍照上传

    html代码 <%@ page language="java" contentType="text/html; charset=utf-8" pageEn ...

  4. Java生成验证码_转

    为了防止用户恶意,或者使用软件外挂提交一些内容,就得用验证码来阻止,虽然这个会影响用户体验,但为了避免一些问题很多网站都使用了验证码;今天下午参考文档弄了一个验证码,这里分享一下;这是一个web工程, ...

  5. Windows下本机简易监控系统搭建(Telegraf+Influxdb+Grafana)--转

    原文地址:http://www.cnblogs.com/liugh/p/6683488.html 一.文件准备 1.1 文件名称 telegraf-1.2.1_windows_amd64.zip in ...

  6. 新疆大学(新大)OJ xju 1010: 四个年级 C++ STL map 将4层循环优化成2层循环可解

    1010: 四个年级 时间限制: 3 Sec  内存限制: 128 MB 题目描述 为了加强全体软件学院的同学的较量,学院想让ACM协会设计一次活动让所以软件学院的同学都加入,并且要实现高年级和低年级 ...

  7. 使用python进行分页操作

    class getPage: """通过这个类 获取 开始和结束点""" def __init__(self,page): try: sel ...

  8. 贰、js的基础(二)类型转换

    JS 数据类型转换 方法主要有三种 转换函数.强制类型转换.利用js变量弱类型转换. 1. 转换函数: js提供了parseInt()和parseFloat()两个转换函数.前者把值转换成整数,后者把 ...

  9. checkbox控制显示隐藏

    显示文本框<input type = "checkbox" id="checkbox" onclick="on_hide();"/&g ...

  10. ListNode的python 实现

    class Node(object): def __init__(self): self.val = None self.next = None class Node_handle(): def __ ...