详解Android studio ndk配置cmake开发native C

下面是详解Android Studio NDK配置CMake开发Native C的完整攻略。

一、前置条件

在进行此项操作前,先确保以下环境已准备好:

  1. Android Studio
  2. NDK(可以在 Android Studio 中下载)
  3. CMake

二、配置 CMake

CMake 是一个开源程序,它可以管理代码的编译过程。在 Android Studio 中使用 CMake 可以轻松配置 C/C++ 代码的编译过程。我们需要先配置 CMake,从而实现使用 CMake 开发 Native 代码。

(一)在 Android Studio 中配置 CMake

  1. 打开 Android Studio。
  2. 打开您的 Android 项目。
  3. 如果还没有,可以添加一个 cpp 文件。右键点击您的项目的 app/src/main 目录 ,选择 New > C++/JNI > C++ File。
  4. 在C++文件中输入一些代码,以便 Cmake 和 NDK 可以查看配置情况。例如:

```c++
#include
#include
#include

#define LOG_TAG "HelloWorld"
#define LOGI(...) android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS)

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_hellojni_MainActivity_stringFromJNI(JNIEnv env,
jobject /
this */) {
std::string hello = "Hello from C++";
LOGI("I am the hello-jni-javatest!");
return env->NewStringUTF(hello.c_str());
}
```

这是一个简单的 hello world 的 C++ 文件,它可以把字符串传递给调用该函数的 Java 代码。

  1. 打开 CMakeLists.txt 文件,它在您的项目的 /app/CMakeLists.txt 目录下。该文件控制 CMake 的配置过程。在文件中输入以下代码:

```
cmake_minimum_required(VERSION 3.4.1)

# set up shared library
add_library(hello-jni SHARED
hello-jni.cpp)

find_library(log-lib log)

# linking shared library to log library
target_link_libraries(hello-jni ${log-lib})
```

此代码片段告诉 CMake 创建一个名为“hello-jni”的共享库,并将其与 hello-jni.cpp 源代码链接。此文件还告诉 CMake 链接该库与 Android 的 log 库。

(二)在 Android Studio 中生成应用程序

  1. 选择 Build > Make Project,Android Studio 将使用 CMake 编译您的项目。
  2. 使用 Build > Rebuild Project 将重新生成项目,以确保更改已应用。

三、配置 和 实现 NDK

在了解了如何配置 CMake 之后,我们现在可以继续设置 NDK 来生成本机代码。此操作需要打开项目中的 build.gradle 文件。

  1. 在应用程序级别的 build.gradle 文件中添加以下块。此块指定您要使用的 CMake 版本并告诉 Android Studio 您是否要构建本机代码:

externalNativeBuild {
cmake {
version "3.10.2"
path "CMakeLists.txt"
}
}

  1. 接下来,添加以下两个 NDK 环境变量以应用程序级别的 build.gradle 文件中:

```
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {
cppFlags "-fexceptions"
}
}
}

 //配合之前添加的CMake块以使用CMake构建并传递信息
 externalNativeBuild {
    cmake {
        version "3.10.2"
        path "CMakeLists.txt"
    }
 }

 //添加NDK路径,注意替换为自己的NDK路径
 ndk {
    platformVersion 27
    abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86','x86_64'
    defualtConfig.ndk {
        abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86','x86_64'
    }
    //注意替换为自己的NDK路径
    path "C:\\Users\\Administrator\\AppData\\Local\\Android\\Sdk\\ndk-bundle"
}

}
```

  1. 现在,使用以下语句将您的 hello-jni 应用程序从 Java 调用你设置的本机语言 C++ 文件:

String outputString = null;
// /data/data/[package]/lib
File libraryFile = context.getDir("lib", Context.MODE_PRIVATE);
System.loadLibrary("hello-jni");
HelloJni helloJni = new HelloJni();
outputString = helloJni.stringFromJNI();

到这里,配置 CMake 和 NDK 的过程就已经完成了。接下来,让我们通过两个示例来更好地理解。

四、示例说明

示例1:整数加法运算

1.添加 native 方法:

需在你的 MainActivity.java 文件中,添加通过 native 关键字定义的 add 方法,该方法接受两个整数参数并返回它们的和。

package com.example.ndkespresso;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    static {
        System.loadLibrary("native-lib");
    }

    private native int add(int a, int b);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        int x = 4;
        int y = 6;

        int sum = add(x, y);
        Log.d(TAG, "Sum of " + x + " and " + y + " is: " + sum);
    }
}

2.添加本机代码 CPP:

接下来,我们需要实现 add 方法的本机代码。在您的 Android 项目中,在您的 cpp 文件中添加以下代码片段:

extern "C"
JNIEXPORT jint JNICALL
Java_com_example_ndkespresso_MainActivity_add(JNIEnv *env, jobject object, jint a, jint b) {

    return a+b;

}

现在,编译和运行应用,你将在控制台中看到你添加的日志打印出合计值。

示例2:基本算法-冒泡排序算法

1.添加 native 方法:

需在你的 MainActivity.java 中添加通过 native 关键字定义的 sort 方法。该方法将接受一个 int 数组和 int 数组的长度作为参数,并按升序对数组进行排序。

   package com.example.ndkespresso;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;

import java.util.Arrays;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    static {
        System.loadLibrary("native-lib");
    }

    private native int[] sort(int[] unsorted, int length);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        int arr[] = {1, 60, 90, 77, 99, 1, 200, 400};

        Log.d(TAG, "Initial Array : " + Arrays.toString(arr));

        int sortedArr[] = sort(arr, arr.length);

        Log.d(TAG, "Sorted Array : " + Arrays.toString(sortedArr));
    }
}

2.添加本机代码 CPP:

接下来,添加本机代码以对传递的整数数组进行排序。您可以使用 c++ 冒泡排序来实现此目的。

在您的 Android 项目中,在您的 cpp 文件中添加以下代码片段:

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

extern "C"
JNIEXPORT jintArray JNICALL
Java_com_example_ndkespresso_MainActivity_sort(JNIEnv *env, jobject thiz, jintArray unsorted,
                                                jint length) {
    std::vector<int> vec;

    jint *array = env->GetIntArrayElements(unsorted, nullptr);
    if (array) {
        for (int i = 0; i < length; i++) {
            vec.push_back(array[i]);
        }
    }
    env->ReleaseIntArrayElements(unsorted, array, JNI_ABORT);

    // sorted vector using standard library
    std::sort(vec.begin(), vec.end());

    jintArray result = env->NewIntArray(length);
    if (result == nullptr) {
        return nullptr; /* out of memory error thrown */
    }

    jint *nativeArray = env->GetIntArrayElements(result, nullptr);
    if (nativeArray == nullptr) {
        return nullptr; /* out of memory error thrown */
    }

    // copy vector to native array
    for (int i = 0, n = vec.size(); i < n; i++) {
        nativeArray[i] = vec[i];
    }

    env->ReleaseIntArrayElements(result, nativeArray, 0); // release 'resultArray'
    return result; // return the jni array
}

现在,编译和运行应用程序,您将在控制台中看到您打印的排序数组。

到这里,我们就成功地完成了 Android Studio NDK配置CMake开发native C的完整攻略,希望能对您有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解Android studio ndk配置cmake开发native C - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • C 循环

    当我们需要重复执行某些特定的代码时,循环结构便发挥了重要作用。在 C 语言中,循环语句主要有三种,分别是 for 循环、while 循环和 do…while 循环。下面详细讲解这三种循环语句的使用攻略。 for 循环 for 循环的语法如下: for (初始化表达式; 条件表达式; 更新表达式) { // 待执行的语句 } 其中,初始化表达式只会在循环开…

    C 2023年5月10日
    00
  • C语言中如何实现单链表删除指定结点

    实现单链表的删除指定结点,需要进行以下几个步骤: 首先判断需要删除的结点是不是链表的头结点,因为头结点是没有前驱结点的,所以需要特殊处理。 然后遍历链表查找需要删除的结点,查找时需要保存当前结点和前驱结点,以便完成删除操作。 找到需要删除的结点后,将前驱结点的next指针指向需要删除结点的下一个结点,从而完成删除操作。 以下是C语言实现单链表删除指定结点的完…

    C 2023年5月23日
    00
  • C语言实现UDP通信

    下面是C语言实现UDP通信的完整攻略。 1. 确定需要使用的库和头文件 首先需要引入的头文件有: #include <stdio.h> //标准输入输出库 #include <stdlib.h> //标准库 #include <string.h> //字符串处理库 #include <unistd.h> //U…

    C 2023年5月23日
    00
  • 如何在C++中实现按位存取

    在C++中,我们可以使用位运算符实现按位存取操作,包括位与、位或、异或、左移、右移等。 使用位与操作实现按位存取 位与操作符 & 可以用来获取一个数字的特定位。假设我们要获取数字 5 的二进制表示中的第二位,可以将其与二进制表示为 00000100 的数字进行位与运算。代码示例如下: int num = 5; int bit = 1 <<…

    C 2023年5月23日
    00
  • js实现div模拟模态对话框展现URL内容

    实现DIV模拟模态对话框展现URL内容的过程需要以下几个步骤: 创建一个DIV模拟对话框的框架,包括头部标题和关闭按钮。在这个DIV中,使用一个名为“content”的子DIV作为展示内容的容器。 使用JavaScript编写代码来获取指定URL的内容,并将内容插入到“content”子DIV中。可以使用AJAX技术获取URL内容。 将DIV模拟对话框显示在…

    C 2023年5月23日
    00
  • Swift如何调用Objective-C的可变参数函数详解

    那么首先我们需要了解的是Objective-C中的可变参数函数的使用方式和Swift对其的调用方式。 在Objective-C中,可变参数函数通常使用va_list和va_start、va_arg、va_end等宏来进行参数的处理。其中 va_start宏接受可变参数函数的参数列表以及可变参数的最后一个非变长参数,在获取可变参数时,需要使用 va_arg宏进…

    C 2023年5月23日
    00
  • Vue.js实现的计算器功能完整示例

    下面我会详细讲解Vue.js实现的计算器功能完整示例的攻略。 准备工作 在开始实现计算器之前,需要在HTML文件中引入Vue.js和一个CSS文件。 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Vue C…

    C 2023年5月22日
    00
  • Objective-C计时器NSTimer学习笔记

    没问题。下面是 “Objective-C计时器NSTimer学习笔记” 的完整攻略: 一、NSTimer概述 NSTimer 是 Foundation 框架提供的一个类,用来实现定时器的功能。使用 NSTimer 可以在程序中实现类似闹铃、计时器等功能。 二、NSTimer使用方法 2.1 创建对象 NSTimer *timer = [NSTimer sch…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部