Android JNI学习笔记(四)-数据类型映射以及native调用java

1. 前言

前几篇学习了jni开发的基本流程、动态注册native函数以及相关编译文件的编写,咱们也算是知道了jni开发,但是还不够,今天咱们来学习下,java和jni的数据类型映射(说白了就是对应关系),以及如何在jni层调用java层的一些东西。偷偷告诉你们,这些全在jni.h文件里。

2. 数据类型映射

首先是我们的基本数据类型,其关系如下表描述这样。

上面关系的相关代码在jni.h的44-51行,如下

typedef unsigned char   jboolean;       /* unsigned 8 bits */
typedef signed char     jbyte;          /* signed 8 bits */
typedef unsigned short  jchar;          /* unsigned 16 bits */
typedef short           jshort;         /* signed 16 bits */
typedef int             jint;           /* signed 32 bits */
typedef long long       jlong;          /* signed 64 bits */
typedef float           jfloat;         /* 32-bit IEEE 754 */
typedef double          jdouble;        /* 64-bit IEEE 754 */

而jni层的引用类型则是下面这个样子。

对于这些引用类型,c++和c的实现是不一样的。如果是c++的话,所有引用类型派生自 jobject,如果使用 C 语言编写的话,所有引用类型使用 jobject,其它引用类型使用 typedef 重新定义。同样代码也在jni.h中。这里只给出c++继承结构的部分。

class _jobject {};
class _jclass : public _jobject {};
class _jstring : public _jobject {};
class _jarray : public _jobject {};
class _jobjectArray : public _jarray {};
class _jbooleanArray : public _jarray {};
class _jbyteArray : public _jarray {};
class _jcharArray : public _jarray {};
class _jshortArray : public _jarray {};
class _jintArray : public _jarray {};
class _jlongArray : public _jarray {};
class _jfloatArray : public _jarray {};
class _jdoubleArray : public _jarray {};
class _jthrowable : public _jobject {};

3. native 如何调用c

我们这里的调用包括许多方面,如:

  • 调用静态方法
  • 调用实例方法
  • 获取字段值
  • 修改字段值
  • 构造对象
  • 等等

而要实现上面的一些功能,同样要依靠jni.h的JNINativeInterface这个结构体,这里有很多很多的方法,供我们使用来实现native 调用java层的功能。而调用的流程是这样的:

  • 根据全限定名在jvm中找到想要的类
  • 从jclass中获取到method、或者field
  • 执行获取值、修改值、调用方法或者其他的操作
  • 释放局部引用

举个调用静态方法的例子看看。

void callJavaStatic(JNIEnv *env,jobject jobj){
  char* str = "call from c++";

  jclass clazz = env->FindClass("com/example/cmake_demo/MainActivity");
  if (clazz == NULL) {
    LOGE("class is null");
    return;
  }

  jmethodID method = env->GetStaticMethodID(clazz,"javaStaticMethod","(Ljava/lang/String;)V");
  if (method == NULL) {
    LOGE("not find method");
  }

  jstring  jstr = env->NewStringUTF(str);
  env->CallStaticVoidMethod(clazz,method,jstr);
  env->DeleteLocalRef(clazz);
  env->DeleteLocalRef(jstr);
}

3.1 如何找到类

很简单,我们可以通过FindClass方法去查找类。

jclass clazz = env->FindClass("com/example/cmake_demo/MainActivity");

3.2 如何获取方法、或者字段

大致为以下四种方法

 env->GetxxxField()
 env->GetStaticxxxField()
 env->GetMethodID()
 env->GetxxxMethodID()

上面没有列出参数,但是仍然很明白,这里就不多说了。

3.3 如何调用方法

这里呢。大致分为以下四种:

  env->CallXXXMethod();
  env->CallxxxMethodA();
  env->CallxxxMethodV();
  env->CallNonvirtualBooleanMethod()

同样,我这里没给出方法的参数,同学们自己看jni.h吧

  • 调用方法(这里的方法可能使静态的、也可能是非静态的)
  • 和上面的区别就在于对应的java层参数,在这里以数组的形式传进入
  • 和1的区别就是,以v(矢量?)的形式传进去,这里我也不是很理解,希望知道的同学指点下。
  • 调用构造函数初始化一个对象,这个,马上说道。

3.4 如何修改字段的值

相信到这里,大家猜都能猜出来,set 么,这里我就不叨叨了。

3.5 如何构造一个对象出来

有些情况下我们是需要构造出java层的对象的,那么如何构造呢,我们有两种办法。

  • NewObject方法
  • CallNonvirtualxxMethod

先说第一种,NewObject方法,除了要求jclass参数之外,还要求jmethodid,以及java称构造方法对应的参数。其他两个还好,关键是这个jmethodID,这个在获取的时候,方法名固定是< init >(md语法的原因,注意尖括号之间没有空格),别问为什么。

在来说说第二种,第二中使用时这样的

  jobject  jo = env->AllocObject(clazz);
  env->CallNonvirtualVoidMethod(jo,clazz,jmethodId,arg )
  • 第一行代码 创建未初始化的对象,并分配内存
  • 第二行代码,调用init那个方法(构造方法)进行初始化,注意,只能初始化一次。

4. 总结

现在我们明白了jni 和 java的数据类型映射关系,以及在jni层调用java层的方法。

时间: 2024-10-04 08:30:59

Android JNI学习笔记(四)-数据类型映射以及native调用java的相关文章

Android JNI 学习笔记

JNI  是 Java Native Interface(Java 本地接口).JNI不是Android 专有的东西,他是从Java继承来的.但是 对于Android来说JNI至关重要,Android 作为一种嵌入式操作系统,有大量和驱动.硬件相关的功能都是用C/C++来实现的.可以说在Android中不管应用级还是系统级的开发都离不开JNI. Java语言的执行,离不开JVM,因此当需要在Java层中调用C/C++层时,需要先告诉JVM那个方法代表本地函数,伊基在哪里能找到这个函数,反之也一样

Android JNI学习笔记(三)-编译文件Android.mk、Application.mk 与camke

1. 前言 在android2.2中,加入了cmake编译,而以前都是用Android.mk.Application.mk的,今天就来记录下,他们的配置选项. 2. Android.mk Android.mk在jni目录下,用于描述构建系统的源文件以及 shared libraries .文件格式如下: 以LOCAL_PATH变量开始 LOCAL_PATH := $(call my-dir) 紧接着是CLEAR_VARS变量 include $(CLEAR_VARS) 接下来LOCAL_MODU

疯狂Android讲义 - 学习笔记(四)

Android应用通常有多个Activity,多个Activity组成Activity栈,当前活动的Activity位于栈顶.Activity相当于Java Web开发的Servlet.当Activity处于Android应用运行时,同样受系统控制.有生命周期. 4.1 建立.配置和使用Activity 4.1.1 Activity 建立自己的Activity需要集成Activity基类,在不同的应用场景,有时也能集成Activity的子类. Activity间接或直接继承了Context.Co

Android学习笔记四:添加Source

问题描述 Source not foundThe JAR file D:\.....\sdk\platforms\android-20\android.jar has no source attachment. 问题原因及解决办法 1. 使用SDK Manager下载最新版本的Sources for Android SDK 一般文件下载目录默认在SDK下的sources文件中即 \adt-bundle-windows-x86_64-20130522\sdk\sources\android-20

【Android开发学习笔记】【第四课】基础控件的学习

通过一个简单的例子来学习下面几种控件: 1.TextView:简单的文本显示控件 2.EditText:可以编辑的文本框 3.Button:按钮 4.Menu:这里指的是系统的Menu 5.Toast:消息提示控件,类似于MFc的tip(不知道理解的对不对) 顺便用到上一次学习的多个Activity之间传递数据的技术,来做一个小的计算乘法的case 步骤: (1)主Activity 和显示结果的 Activity 都采用线性布局,下面是布局文件的源代码: <LinearLayout xmlns:

Android NDK学习笔记(一) 为什么要用NDK?

NDK是什么 NDK是Native Development Kit的简称,即本地开发工具包.通过NDK,Android允许开发人员使用本地代码语言(例如C/C++)来完成应用的部分(甚至全部)功能.注意:由于翻译原因,有些地方也把Native翻译为"原生". NDK是SDK的一个补充,可以帮助你做这些事情: 生成可以在ARM CPU,Android 1.5(及以上)平台运行的JNI兼容的共享库. 将生成的共享库放置在应用程序项目路径的合适位置,使其能自动地添加进你最终的(和经过签名的)

Android Animation学习笔记

关于动画的实现,Android提供了Animation,在Android SDK介绍了2种Animation模式: 1. Tween Animation:通过对场景里的对象不断做图像变换(平移.缩放.旋转)产生动画效果,即是一种渐变动画: 2. Frame Animation:顺序播放事先做好的图像,是一种画面转换动画. 动画类型 下面先来看看Android提供的动画类型.Android的animation由四种类型组成 在XML文件中: alpha        渐变透明度动画效果 scale

java/android 设计模式学习笔记(10)---建造者模式

这篇博客我们来介绍一下建造者模式(Builder Pattern),建造者模式又被称为生成器模式,是创造性模式之一,与工厂方法模式和抽象工厂模式不同,后两者的目的是为了实现多态性,而 Builder 模式的目的则是为了将对象的构建与展示分离.Builder 模式是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部构建细节的情况下,可以更精细地控制对象的构造流程.一个复杂的对象有大量的组成部分,比如汽车它有车轮.方向盘.发动机.以及各种各样的小零件,要将这些部件装配成一辆汽车,这个装配过

Android:日常学习笔记(8)———探究UI开发(5)

Android:日常学习笔记(8)---探究UI开发(5) ListView控件的使用 ListView的简单用法 public class MainActivity extends AppCompatActivity { private String[] data={"Apple","Banana","Orange","Watermelon","Pear","Grape","