本博客主要是在Ubuntu 下开发,且默认你已经安装了Eclipse,Android SDK, Android NDK, CDT插件。

在Eclipse中添加配置NDK,路径如下Eclipse->Window->Preferences->Android->NDK ,选择NDK的路径,然后Apply即可。

新建一个名为AndroidJNI_Object的Android工程,新建一个jni的文件夹,其目录下文件树列表如下:

├── jni
│   ├── Android.mk
│   ├── Application.mk
│   └── object
│      ├── Android.mk
│      ├── logger.h
│      └── object_jni.c

jni/Application.mk文件内容如下:

APP_ABI := all

jni/Android.mk,主要用来指定顺序执行所有子文件夹下面的makefile文件,内容如下:

include $(call all-subdir-makefiles)

jni/object/Android.mk,主要用来指定需要编译出的动态库的名称,以及需要编译的源文件,内容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE     := object_jni
LOCAL_SRC_FILES := object_jni.c LOCAL_LDLIBS := -llog include $(BUILD_SHARED_LIBRARY)

jni/object/logger.h 主要用来在JNI层打印日志,内容如下:

#include <jni.h>
#include <android/log.h> /**
* 定义log标签
*/
#define TAG "jni_logger" /**
* 定义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__)

jni/object/object_jni.c,主要用来注册绑定java函数和native函数,以及java函数在c中相应函数的具体实现, 内容如下:

#include "logger.h"

#ifndef NULL
#define NULL ((void *) 0)
#endif /**
* 获取数组的大小
*/
#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) /**
* 指定要注册的类,对应的完整的java类名
*/
#define JNIREG_CLASS "com/clarck/jni/MainActivity"
#define JNIPAR_CLASS "com/clarck/jni/Person" struct PersonOffsets
{
jfieldID name;
jfieldID age;
jfieldID height;
} gPersonOffsets; typedef struct tagPerson
{
char mName[];
int mAge;
float mHeight;
} Person; static Person gPersons[] = {
{"clarck", , },
{"lilei", , },
{"hanmeimei", , },
}; #define GPERSON_NUM NELEM(gPersons) JNIEXPORT jint JNICALL native_object(JNIEnv *env, jobject clazz, jobject person, jint index) {
if ((int) index < || (int) index >= GPERSON_NUM)
return -; //将Person数组中的第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 ;
} static void nativeClassInit(JNIEnv *env) {
jclass personClass = (*env)->FindClass(env, JNIPAR_CLASS);
gPersonOffsets.name = (*env)->GetFieldID(env, personClass, "mName", "Ljava/lang/String;");
gPersonOffsets.age = (*env)->GetFieldID(env, personClass, "mAge", "I");
gPersonOffsets.height = (*env)->GetFieldID(env, personClass, "mHeight", "F");
} /**
* Java和JNI函数绑定
*/
static JNINativeMethod method_table[] = {
{ "getPersonInfoByIndex", "(Lcom/clarck/jni/Person;I)I", (void*) native_object },
}; /**
* 注册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) < ) {
return JNI_FALSE;
} return JNI_TRUE;
} /**
* 调用注册方法
*/
int register_ndk_load(JNIEnv* env) {
nativeClassInit(env);
return registerNativeMethods(env, JNIREG_CLASS, method_table,
NELEM(method_table));
} JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
jint result = -; if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return result;
} register_ndk_load(env); //返回jni的版本
return JNI_VERSION_1_4;
}

接着在Project中右键Android Tools->Add Native Support,最后java层调用如下:

package com.clarck.jni;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log; public class MainActivity extends Activity {
private Person mPerson = null; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); Log.d("Test", "onCreate");
mPerson = new Person();
for (int i = 0; i < 3; i++) {
getPersonInfoByIndex(mPerson, i);
Log.d("Test", "mPersion[" + i + "] -- " + mPerson);
}
} private native int getPersonInfoByIndex(Person person, int index); static {
System.loadLibrary("object_jni");
} }
package com.clarck.jni;

public class Person {
private String mName;
private int mAge;
private float mHeight; @Override
public String toString() {
return "mName: " + mName + ", mAge: " + mAge + ", mHeight: " + mHeight;
} }

运行结果如下:

04-15 15:37:30.916: D/Test(31477): onCreate
04-15 15:37:30.916: D/jni_logger(31477): native_object index-0 mName:clarck, mAge:25, mHeight:175.000000
04-15 15:37:30.916: D/Test(31477): mPersion[0] -- mName: clarck, mAge: 25, mHeight: 175.0
04-15 15:37:30.916: D/jni_logger(31477): native_object index-1 mName:lilei, mAge:30, mHeight:166.000000
04-15 15:37:30.916: D/Test(31477): mPersion[1] -- mName: lilei, mAge: 30, mHeight: 166.0
04-15 15:37:30.916: D/jni_logger(31477): native_object index-2 mName:hanmeimei, mAge:51, mHeight:172.000000
04-15 15:37:30.916: D/Test(31477): mPersion[2] -- mName: hanmeimei, mAge: 51, mHeight: 172.0

Android NDK 学习之传递类对象的更多相关文章

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

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

  2. Android 通过 Intent 传递类对象

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

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

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

  4. android通过 Intent 传递类对象

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

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

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

  6. Android JNI和NDK学习(09)--JNI实例二 传递类对象

    1 应用层代码 NdkParam.java是JNI函数的调用类,它的代码如下:   package com.skywang.ndk; import android.app.Activity; impo ...

  7. Android NDK 学习之在C中调用Java的变量和静态变量

    本博客主要是在Ubuntu 下开发,且默认你已经安装了Eclipse,Android SDK, Android NDK, CDT插件. 在Eclipse中添加配置NDK,路径如下Eclipse-> ...

  8. Android中数据的传递以及对象序列化

    Android中当两个Activity需要有信息交互的时候,可以使用Intent.具体来说: 发送单一类型数据: 发送方: String data = "Hello SecondActivi ...

  9. Android NDK 学习之调用Java函数

    本博客主要是在Ubuntu 下开发,且默认你已经安装了Eclipse,Android SDK, Android NDK, CDT插件. 在Eclipse中添加配置NDK,路径如下Eclipse-> ...

随机推荐

  1. GPU---并行计算利器

    转载请引用:GPU---并行计算利器 源于阿里巴巴CCO<猿来如此>分享 1 GPU是什么 如图1所示,这台PC机与普通PC机不同的是这里插了7张显卡,左下角是显卡,在中间的就是GPU芯片 ...

  2. java 数据类型

    java是一个静态类型的语言,所有的数据类型都是有类型的(强类型的语言),当一个变量名指定类型后不可再改变变量类型 数据类型包括基本数据类型和引用数据类型(除基本数据类型外的其他类型都是引用数据类型) ...

  3. paip.文件读写api php java python总结.txt

    paip.文件读写api php java python总结.txt 一.多种方式读文件内容.    1.按字节读取文件内容   以字节为单位读取文件,常用于读二进制文件,如图片.声音.影像等文件. ...

  4. paip.调试js 查看元素事件以及事件断点

    paip.调试js  查看元素事件以及事件断点 ff 26 +firebug 查看不出来.. 360 ,虽然也是chrome 基础,但是开发工具烂阿,也是显示不出来.. 作者Attilax  艾龙,  ...

  5. .NET Remoting学习笔记(二)激活方式

    目录 .NET Remoting学习笔记(一)概念 .NET Remoting学习笔记(二)激活方式 .NET Remoting学习笔记(三)信道 参考:百度百科  ♂风车车.Net 激活方式概念 在 ...

  6. 为ubuntu操作系统增加root用户

    1:当安装好虚拟机,安装好Ubuntu操作系统后,登陆的时候发现除了自己的设置的用户就是外来用户,其实Ubuntu中的root帐号默认是被禁用了的,所以登陆的时候没有这个账号,但是如果每次使用root ...

  7. animate.css

    这是个css3动画框架,现在很流行,在小动画效果有很多,使用的方式 <div class="animated bounce"></div> /*只要修改bo ...

  8. 查看Exchange邮件队列(queue)

    #加载Exchange管理模块 Add-PSSnapin Microsoft.Exchange.Management.PowerShell.snapin get-queue #查看队列 get-mes ...

  9. wordpress自动保存远程图片插件 DX-auto-save-images

    wordpress自动保存远程图片插件DX-auto-save-images 解决了保存文章就可以自动将远程图片保存到你的服务器上了. 具体操作步骤如下: 1.安装启用wordpress自动保存远程图 ...

  10. 【cocos2d-x 手游研发----目录】

    感谢大家一直支持我写这样一系列的博客,从中我自己也获益良多,cocos2d-x这样一款非常棒的引擎,是值得我们去学习和分享的,谈到分享,那我就把这套写了差不多一两个月的框架给大家开源下载,写的很一般, ...