zoukankan      html  css  js  c++  java
  • AndroidStudio2.2 cMake方式创建jni工程

    关于CMake:从androidStudio2.2版本开始,可以用cmake方式创建jni工程。


    打开androidStudio之后按照以下步骤:
    1)File-New-New Project , 注意勾选支持c++。然后一路next一直到finish。

     


    2)我这里出现一个编译问题;(如果没遇到这个问题,跳过此步骤)

     

    这个是因为新创建的工程,没有默认的NDK配置;配一下即可。操作如下:
    右键工程名,选open Module Setting 打开这个:

    然后注意红色标记。配置好你的NDK路径,我用的是14b这个版本。
    点OK,然后androidStudio会自动编译。

    3)观察一下自动生成的这些代码;

    这里有一个自动生成的MainActivity.java 红色标记的地方,就是调用的JNI。
    下面的System.loadLibrary就是加载名为native-lib.so的引擎文件(cmake方式下,在工程中看不到这个文件,但是编译出来的apk是有的)
    上面的native方法,就是在java代码中声明,jni层有这么一个方法的实现。
    左边画圈圈的 ,点一下(或者鼠标放在方法名上面,按住ctrl,点鼠标左键),就能直接索引到cpp文件中,这个方法的具体实现。如下图。

     


    第一次看到这个文件可能有点陌生,下面贴出重要代码的注解;

    #include <jni.h>
    #include <string>
    
    extern "C" //这一句,表示,按照C的方式去编译,如果不加这句,可能导致找不到这个方法
    JNIEXPORT jstring JNICALL //这一句,表示,返回值是一个java的string,至于JNIEXPORT ,JNICALL都是JNI的语法
    Java_test_hank_com_jni1011_MainActivity_stringFromJNI( // 这句,表示这个是实现JAVA类中的一个方法,java类的全名是test.hank.com.
    //jni1011.MainActivity,方法名为stringFromJNI
    JNIEnv *env,//指针对象
    jobject /* this */) {
    std::string hello = "Hello from C++";//创建string 对象,std::的写法,std是c++标准库,两个冒号之后,加上string,是说这个类是c++标准库内的string类。用这个类来创建一个string对象
    return env->NewStringUTF(hello.c_str());//返回值 ,由于env是指针对象,所以要用->来调用方法,NewStringUTF() 构建一个UTF编码的字符串
    }

    运行工程,就能看到界面中间显示一行字符串“Hello from C++”;这行字符串明显来自jni层。
    android给我们创建示例工程的时候,只告诉我们怎么用java调用jni。但是jni回调java的过程,需要我们手动修改代码。

    4)手动修改代码,来实现jni层调用c++层的代码;
    1-新建一个java类:JavaCaller.java ,并创建一个方法,表示这个就是让jni层去调用的方法。

     


    2-jni调用java某个对象的方法,也要遵循面向对象的方式,必须有该对象的引用才行。所以我们要先传递一个对象到jni层。
    看代码。
    在java层,新建一个native方法,setJavaObject,参数为JavaCaller类的一个对象。

     


    鼠标放在方法名上,按住alt+enter,就会提示,创建一个jni方法,作为这个native的实现。
    选择创建该方法,(这里有个坑,自动生成的这个方法,没有extern "C" 导致编译通不过,大概原因就是加了extern "C",就表示用c的方式去编译,jni对接的应该还是c,所以要加上extern "C")
    然后写代码调用这个setJavaObject方法。
    接下来继续进入jni层,这里,我们的目的是jni层调用java类的某个方法。
    所以,要在jni中写代码来使用传递进来的这个java对象。
    代码如下,有每个步骤的详细注解:

    这样的话,调用过程就执行完毕了。
    执行代码,就会发现,日志中有这一行。
    10-11 04:23:51.112 4254-4254/test.hank.com.jni1011 D/hankzhou: param:这里能不能放中文? - param2:真的可以放中文耶

    这个就是我们在JavaCaller.java test方法中打印的日志。说明,jni回调java的方法成功。

    至此,AndroidStudio - cMake方式开发jni的示例就完成了。
    但是,有两点需要说明一下。
    1)java的类型 转化为jni的类型存在有规律的转化(观察一下java层的native方法,以及jni层的c方法,两者的参数列表。有关联,但是写法大不相同)

     


    很抽象?那么看图吧。
    这是java的:

     

    这是jni的:

     

    jni前面的两个是干啥的暂时不知,但是很明显能看到3个参数都是string,到了jni这里,就变成了jstring,这就是所谓写法上的转化。

    2) jni回调java对象的某个方法,也是有类型转换的;

    还是看图:
    java的方法:


    jni中用反射创建该方法:

     


    这里的实参,test 是方法名,保持一致。
    形参以及返回值,必须完全对应,这里就有一个类型转换了。
    先看最后这个V,对应test方法的返回值void。
    前面的两个 Ljava/lang/String; 对应两个string。(多个参数,分号分隔)
    这里是void和string,那么如果是其他类型呢?参见了上面的表格。

     

    以上就是cMake方式开发jni的入门级指导。更复杂的,以后再写。


  • 相关阅读:
    A1132 Cut Integer (20分)
    A1131 Subway Map (30分)
    A1130 Infix Expression (25分)
    A1129 Recommendation System (25分)
    A1128 N Queens Puzzle (20分)
    arm指令集
    韦东山视频地址
    汇编知识
    emacs 使用教程
    ip
  • 原文地址:https://www.cnblogs.com/hankzhouAndroid/p/7650253.html
Copyright © 2011-2022 走看看