Android NDK:JNI开发之Java调用C、C++方法:Hello word

首先下载好对应的NDK,解压目录配置到Android Studio项目下的local.properties:

ndk.dir=C\:\\Users\\aibo\\AppData\\Local\\Android\\Sdk\\ndk-bundle
sdk.dir=C\:\\Users\\aibo\\AppData\\Local\\Android\\Sdk

方式一:

新建项目时选择最后一个C++项目:

然后创建出来的项目就直接可以运行了,出来的文字就是调用c++方法得到的Hello from C++。具体解释请往下看。


方式二:

针对在创建项目时没有想到现在会用到JNI的情况。就是已有项目了。

配置比较复杂,这里用最简单粗暴的方法:通过方式一新建出来的项目,复制里面的关键文件到自己的项目下:

  1. 复制cpp目录以及下面的两个文件到对应目录下。

  2. 复制build,gradle里面的externalNativeBuild代码过去:

其实内容里面东西也不多,列出来吧:

CMakeLists.txt

(如果需要修改,就修改native-lib,或者在它的下面添加你自己的C或C++文件的名称)

cmake_minimum_required(VERSION 3.4.1)
add_library( 
        native-lib
        SHARED
        native-lib.cpp)
find_library( # Sets the name of the path variable.
        log-lib
        log)
target_link_libraries( 
        native-lib
        ${log-lib})

native-lib.cpp

(可以把里面的这个方法去掉,再自己写方法,下面会解释如何写)

#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_com_xaehu_jnidemo_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

build.gradle中需要添加的代码:

externalNativeBuild {
    cmake {
        path "src/main/cpp/CMakeLists.txt"
    }
}

封装实现和解释:

1、创建一个JNI工具类,作为java调用C的桥梁:

public class JniTool {
    static {
        System.loadLibrary("native-lib");
    }
    public static native String sayHello();
}

注意native关键字,表示这个方法是调用jni的方法。

2、然后这个sayHello方法是调用C里的,但是我们没有创建,所以这里会报红。我们的AS工具再这里按提示的话,他会提醒我们创建C的方法:

3、回车,它就会在native-lib.cpp文件里自动创建该方法代码:

#include <jni.h>
JNIEXPORT jstring JNICALL
Java_com_xaehu_jnitest_JniTool_sayHello(JNIEnv *env, jclass type) {

    // TODO

    return (*env)->NewStringUTF(env, returnValue);
}

说明几点:

  1. #include <jni.h>是固定的。
  2. JNIEXPORT jstring JNICALL:主要是中间这个jstring表示该方法返回String类型,同理,int类型就是jint。具体类型可ctrl点进去看。
  3. 其实这个返回值和我们定义java方法也差不多,我们也可以把这行去掉,然后把下面的方法名写成 jstring Java_com_xaehu_jnitest_JniTool_sayHello(JNIEnv *env, jclass type)是同样效果
  4. 方法名那么那么长Java_com_xaehu_jnitest_JniTool_sayHello(JNIEnv *env, jclass type),我们拆分一下:Java_包名_类名_方法名(JNIEnv *env, jclass type[,其他参数])。包名中间用下划线隔开。
  5. 返回值中returnValue我们在下面定义,就是要给java返回的String值
  6. C/C++中没有String类型,用char*

再举个栗子,计算两个数字相加:

android代码:

public static native String numberAdd(int a,int b);

C/C++代码:

#include <jni.h>
jint Java_com_xaehu_jnitest_JniTool_numberAdd(JNIEnv *env, jclass type,jint a,jint b) {
    return a + b;
}

就是这么简单。

发布了60 篇原创文章 · 获赞 13 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_35584878/article/details/100555433