Android NDK 学习之传递类对象
本博客主要是在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 学习之传递类对象的更多相关文章
- 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 ...
- Android JNI和NDK学习(09)--JNI实例二 传递类对象
1 应用层代码 NdkParam.java是JNI函数的调用类,它的代码如下: package com.skywang.ndk; import android.app.Activity; impo ...
- Android NDK 学习之在C中调用Java的变量和静态变量
本博客主要是在Ubuntu 下开发,且默认你已经安装了Eclipse,Android SDK, Android NDK, CDT插件. 在Eclipse中添加配置NDK,路径如下Eclipse-> ...
- Android中数据的传递以及对象序列化
Android中当两个Activity需要有信息交互的时候,可以使用Intent.具体来说: 发送单一类型数据: 发送方: String data = "Hello SecondActivi ...
- Android NDK 学习之调用Java函数
本博客主要是在Ubuntu 下开发,且默认你已经安装了Eclipse,Android SDK, Android NDK, CDT插件. 在Eclipse中添加配置NDK,路径如下Eclipse-> ...
随机推荐
- 我的fckeditor实践
一开始我不懂这个ConnectorServlet是何用处,后来发现是专门用于文件上传的,因为fckeditor默认是不支持这个功能的. ConnectorServlet: /* * FCKeditor ...
- Ubuntu下postgresql安装
第一步:在Ubuntu下安装Postgresql 1.使用 apt-get install 安装 zhang@ubuntu:~/protgresql#sudo apt ...
- 大姨吗向左,美柚向右,女性健康APP路在何方?
日前,中国IT研究中心发布了<2016Q3中国女性健康管理APP市场研究报告>,报告显示大姨吗与美柚占据了整个行业的绝对优势,大姨吗的行业用户覆盖率最高,美柚则在月活用户数方面领先. 不过 ...
- 不能返回函数内部new分配的内存的引用
以前在开发电子秤接口动态库时,曾尝试在用于获取重量的函数外面定义一个字符串指针,然后作为参数传入函数内部,然后在函数内部new,用来输出函数执行过程中发生的错误.但是总是出错,没有找到原因,后来无意中 ...
- Android 使用Fragment界面向下跳转并一级级返回
http://www.cnblogs.com/_ymw/p/4227862.html 1.首先贴上项目结构图: 2.先添加一个接口文件BackHandledInterface.java,定义一个set ...
- 斐波那契数列(Fibonacci)递归和非递归实现
序列前9项为:0, 1, 1, 2, 3, 5, 8, 13, 21 要注意非递归的话就是那一个变量帮助存储当前下一项的值,然后依次挪动两个指针往下即可 注意如果n太大 会溢出 ...
- android 开发 简单的页面布局
package com.example.test; import android.app.Activity; import android.os.Bundle; import android.view ...
- Xcode中iPhone iPad模拟器调整大小的方法
Xcode中调试iPad程序默认的iPad模拟器非常小,如何方法iPad模拟器的显示尺寸呢? 选中iOS模拟器,在“Window -> 缩放比例”中就可以调整了. 快捷键: Command + ...
- Python中的字典排序
我想将 b = {'a':234,'b':1,'c':2,'e':2387} 分别按照key和value进行排序,该怎样办呢? Python中比较常用的排序有两个函数, 一.定义 (1)一个是List ...
- android 虚线
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http: ...