详解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日

相关文章

  • Java编程中的vector类用法学习笔记

    Java编程中的Vector类用法学习笔记 Vector类概述 在Java中,Vector类是一种线程安全的动态数组,可以自动调整大小。它的用法类似于ArrayList,但是Vector是同步的,因此比ArrayList的访问开销更大。Vector实现了List接口,并且可以通过下标访问,插入和删除元素。 Vector类的基本用法 创建Vector对象 im…

    C 2023年5月22日
    00
  • C C++中exit(0)和exit(1)的区别

    下面我来为大家详细讲解一下 “C C++中exit(0)和exit(1)的区别”。 一、什么是exit? exit是C C++语言中定义在stdlib.h头文件中的函数,作用是退出程序并返回一个状态码给操作系统。常见的参数有0和1等,0表示程序成功结束,1则表示程序非正常结束。在程序中调用exit函数后,代码就会停止运行。 二、exit(0)和exit(1)…

    C 2023年5月10日
    00
  • C语言函数多个返回值方式

    C语言函数多个返回值方式 在C语言中,函数通常只能返回一个返回值。这可能会限制一些操作的实现,特别是在需要返回多个值的情况下。然而,C语言提供了多种方式来解决这个问题。 方式一:结构体 一种实现方式是通过使用结构体返回多个值。结构体通常定义了相​​关字段,而每个字段都可以看作是一个返回值。 typedef struct { int a; char b; fl…

    C 2023年5月23日
    00
  • C语言用指针支持栈

    C语言用指针支持栈的完整使用攻略 栈是一种常见的数据结构,在C语言中可以使用指针来支持栈。下面是用指针实现栈的完整使用攻略: 数据结构 栈是一种后进先出(LIFO)的数据结构,可以用数组或链表实现。这里我们使用数组实现栈。 定义栈结构体: #define MAXSIZE 10 // 栈的容量 typedef struct stack { int data[M…

    C 2023年5月9日
    00
  • C++实现大数相乘算法

    C++ 实现大数相乘算法 当我们需要计算两个超出计算机整数范围的大数相乘时,传统的计算方法已经无法满足需求,因此需要寻找一种适合大数相乘的算法。本文将介绍一种针对大数相乘的算法 – Karatsuba乘法,并使用C++语言进行实现。 Karatsuba 乘法的原理 Karatsuba 乘法的基本思想是将两个大数a和b分别划分为高位和低位,进而利用递归的方法将…

    C 2023年5月22日
    00
  • C++实现学生管理系统示例解析

    C++实现学生管理系统示例解析攻略 1. 系统介绍 学生管理系统是一种用于管理学生信息,包括学生基本信息、成绩、奖惩等信息的系统。C++实现学生管理系统需要用到文件操作、数据结构等知识,提供增删改查等基本功能。 2. 实现步骤 2.1. 设计数据结构 C++实现学生管理系统需要使用数据结构来存储学生信息,常见的数据结构有数组、链表、队列等。在此我们选择使用结…

    C 2023年5月24日
    00
  • MySQL处理JSON常见函数的使用

    下面是关于MySQL处理JSON常见函数的使用的完整攻略。 JSON类型介绍 在MySQL 5.7版本之后,MySQL开始支持JSON类型。JSON类型是一种结构化的数据类型,是一种轻量级的数据交换格式,便于人类阅读和编写,也易于机器解析和生成。JSON类型的值可以存储在JSON列中,也可以作为普通列或表达式的值使用。 处理JSON型列时的常见函数 MySQ…

    C 2023年5月23日
    00
  • CCleaner如何设置用户管理?CCleaner设置用户管理方法

    下面就详细讲解一下“CCleaner如何设置用户管理”的完整攻略,过程中包含两个示例说明。 CCleaner如何设置用户管理 什么是CCleaner用户管理? 首先我们需要了解一下什么是CCleaner用户管理。CCleaner是一款优秀的系统清理软件,用户管理功能是指在多用户的电脑上,针对不同的用户设置其个性化的清理选项。 CCleaner设置用户管理方法…

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