Android NDK 学习之在C中调用Java的变量和静态变量
来源:互联网 发布:数据质量的重要性 编辑:程序博客网 时间:2024/06/18 18:52
本博客主要是在Ubuntu 下开发,且默认你已经安装了Eclipse,Android SDK, Android NDK, CDT插件。
在Eclipse中添加配置NDK,路径如下Eclipse->Window->Preferences->Android->NDK ,选择NDK的路径,然后Apply即可。
新建一个名为AndroidJNI_AccessField的Android工程,新建一个jni的文件夹,其目录下文件树列表如下:
├── jni
│ ├── accessfield
│ │ ├── accessfield_jni.c
│ │ ├── Android.mk
│ │ └── logger.h
│ ├── Android.mk
│ └── Application.mk
jni/Application.mk文件内容如下:
APP_ABI := all
jni/Android.mk,主要用来指定顺序执行所有子文件夹下面的makefile文件,内容如下:
include $(call all-subdir-makefiles)
jni/accessfield/Android.mk,主要用来指定需要编译出的动态库的名称,以及需要编译的源文件,内容如下:
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := accessfield_jniLOCAL_SRC_FILES := accessfield_jni.cLOCAL_LDLIBS := -lloginclude $(BUILD_SHARED_LIBRARY)
jni/accessfield/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/accessfield/objectarray_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/AccessField"/** * 返回成员实例域 */JNIEXPORT void JNICALL native_accessField(JNIEnv *env, jobject obj) { jfieldID fid; jstring jstr; const char *str; //在实力引用对象上得到类的引用 jclass cls = (*env)->GetObjectClass(env, obj); //从类的引用,成员域的名称,和成员域描述符来得到成员域(field)ID fid = (*env)->GetFieldID(env, cls, "mStr", "Ljava/lang/String;"); if (NULL == fid) { return ; } //获取传递对象引用和成员域ID获取实例域访问函数 jstr = (*env)->GetObjectField(env, obj, fid); //获取传递对象引用的字符 str = (*env)->GetStringUTFChars(env, jstr, NULL); if (NULL == str) { return ; } LOGI("mStr = %s \n", str); (*env)->ReleaseStringUTFChars(env, jstr, str); jstr = (*env)->NewStringUTF(env, "123"); if (NULL == jstr) { return ; } //替换掉获取到的实例对象的引用 (*env)->SetObjectField(env, obj, fid, jstr); //Caching at the Point of Use /*static jfieldID fid_s = NULL; jstring jstr; const char *str; jclass cls = (*env)->GetObjectClass(env, obj); if (NULL == fid_s) { fid_s = (*env)->GetFieldID(env, cls, "mStr", "Ljava/lang/String;"); if (NULL == fid_s) { return ; } } LOGI("In C \n"); jstr = (*env)->GetObjectField(env, obj, fid_s); str = (*env)->GetStringUTFChars(env, jstr, NULL); if (NULL == str) { return ; } LOGI("mStr = %s \n", str); (*env)->ReleaseStringUTFChars(env, jstr, str); jstr = (*env)->NewStringUTF(env, "123"); if (NULL == jstr) { return ; } (*env)->SetObjectField(env, obj, fid_s, jstr);*/}/** * 得到静态成员实例域 */JNIEXPORT void JNICALL native_staticAccessField(JNIEnv *env, jobject obj) { jfieldID fid; jint si; jclass cls = (*env)->GetObjectClass(env, obj); fid = (*env)->GetStaticFieldID(env, cls, "mSi", "I"); if (NULL == fid) { return ; } si = (*env)->GetStaticIntField(env, cls, fid); LOGI("mSi = %d \n", si); (*env)->SetStaticIntField(env, cls, fid, 200);}/** * Java和JNI函数绑定 */static JNINativeMethod method_table[] = { { "accessField", "()V", (void*) native_accessField }, { "staticAccessField", "()V", (void*) native_staticAccessField },};/** * 注册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_load(JNIEnv* env) { return registerNativeMethods(env, JNIREG_CLASS, method_table, NELEM(method_table));}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_load(env); //返回jni的版本 return JNI_VERSION_1_4;}
接着在Project中右键Android Tools->Add Native Support,最后java层调用如下:
package com.clarck.jni;public class AccessField { public String mStr; public static int mSi; public native void accessField(); public native void staticAccessField(); static { System.loadLibrary("accessfield_jni"); }}
package com.clarck.jni;import android.app.Activity;import android.os.Bundle;import android.util.Log;public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); AccessField accessField = new AccessField(); accessField.mStr = "abc"; accessField.accessField(); Log.d("Test", "mStr = " + accessField.mStr); accessField.mSi = 100; accessField.staticAccessField(); Log.d("Test", "mStr = " + accessField.mSi); }}
执行Ctrl+B执行编译,运行工程即可。
- Android NDK 学习之在C中调用Java的变量和静态变量
- android NDK 入门之在JNI中修改java中对象的成员变量的值
- java中静态变量和非静态变量的区别
- C语言再学习之:局部变量,局部静态变量,全局变量和全局静态变量的区别
- JNI/NDK开发指南(六)--C/C++访问Java实例变量和静态变量
- 基于 Android NDK 的学习之旅-----Java 调用C
- 基于 Android NDK 的学习之旅----- C调用Java
- 基于 Android NDK 的学习之旅-----Java 调用C
- 基于 Android NDK 的学习之旅----- C调用Java
- 基于 Android NDK 的学习之旅-----Java 调用C
- 基于 Android NDK 的学习之旅----- C调用Java
- 基于 Android NDK 的学习之旅----- C调用Java
- 基于 Android NDK 的学习之旅-----Java 调用C
- 基于 Android NDK 的学习之旅-----Java 调用C
- 基于 Android NDK 的学习之旅----- C调用Java
- 基于 Android NDK 的学习之旅----- C调用Java
- 基于 Android NDK 的学习之旅-----Java 调用C
- 基于 Android NDK 的学习之旅----- C调用Java
- 对n*n矩阵,以对角线为对称线,将对称元素相加并将结果存放在下三角元素中,右上角三角元素置0.例如,若n=4,有下列矩阵
- HTML5 之2__列表标记
- Android NDK 学习之接受Java传入Object数组
- OpenCV加载图像并建立窗口显示代码
- AIR 检查网络是否可用,URLMonitor.
- Android NDK 学习之在C中调用Java的变量和静态变量
- Qt使用QTextEdit进行文本编辑实现查找高亮
- 常用数学符号的 LaTeX 表示方法
- 差距产生动力
- postgis 建表插入数据sql
- 蓝桥杯 校外的树 线段树
- Android NDK 学习之调用Java函数
- MFC OnCmdMsg函数是干什么用的?
- DIV 和 CSS 网页布局总结