如何在 Kotlin 中的 Android Studio 中使用 cmake 构建的 C 库?

问题描述 投票:0回答:1

我正在尝试在使用 Kotlin 的 Android Studio 项目中使用使用 cmake 构建的 C 库。 到目前为止,我已经能够在 Android Studio 中安装 NDK 和 cmake,将 C 库的 CMakeLists.txt 文件包含在项目中并编译项目,以便我在其中看到 .so 文件。

但我不知道如何从 Kotlin 调用 C 库函数。 C 库头文件应该包含 jni.h 吗?如果是这样,我在哪里可以找到它?库 API 函数的签名应该是什么,以便 Android Studio 能够看到它们?如何在 Android Studio Kotlin 中使用这些?

我知道有很多文档,但它们确实很零散且令人困惑,其中大部分都指向 Kotlin Native 或 java。我希望能够提供用于定义库 API 的 C 头文件的清晰代码示例以及使用它的 Kotlin 文件。 我的意思是,我是在 .kt 文件中导入某些内容还是什么?

谢谢您,非常感谢您的帮助!

c kotlin android-studio cmake
1个回答
0
投票

我弄清楚了如何在 Koltin Android Studio 项目中使用使用 CMake 构建的共享 C 库:

  1. 在 Andoid Studio 中,将新的 cmake 共享库添加到您的 Kotlin 项目中 并指向库的 CMakeLists.txt

  2. 在 MainACtivity.kt 的顶部范围中声明 C 库函数,如下所示:

    外部乐趣 addNumbers(a:Int, b:Int) :Int

C库头文件中的函数名必须包含 很多与项目相关的前缀。如果您添加此外部声明,然后打开红色灯泡旁边的菜单,告诉您找不到此功能,Android Studio 会告诉您这些是什么。在那里,您将找到一个在 C 文件中创建函数的选项,因此执行此操作,它将具有完整的前缀名称。

  1. 一旦 cmake 构建的 C 库成为项目的一部分,您必须使用“构建”菜单中的“刷新链接的 C++ 项目”来刷新它。每当您更改 C 库源时都需要执行此操作。

  2. 然后你只需构建你的项目就可以开始了。

Android 在 https://github.com/android/ndk-samples 提供了超级有用的示例。

这些的主要收获是:

让我们创建并使用一个名为 doSomething 的 C 库。 它提供了两个公共函数,展示如何将数字和字符串参数传递给 并从 Kotlin 中的 C 库返回它们。 该项目的名称是 Greeting Card(是的,这是一个 Kotlin 教程项目)。

CMakeLists.txt

#you should always set this
cmake_minimum_required(VERSION 3.22)

project(doSomething VERSION 1.0.0 DESCRIPTION "An exercise to build a C library with CMake in Android Studio.")

add_library(doSomething SHARED src/doSomething.c )

set_target_properties(doSomething PROPERTIES VERSION ${PROJECT_VERSION})

# this is where the header file is
set_target_properties(doSomething PROPERTIES PUBLIC_HEADER include/doSomething.h)

# define include base dir for the sources
target_include_directories(doSomething PRIVATE include)
target_include_directories(doSomething PRIVATE src)

doSomething.h

/* Dont worry where the jni.h header comes from.
 * Android Studio takes care of that.
 */
#include <jni.h>

/* JNIEXPORT and JNICALL are magic words that just have to be there.
 * jint is the type of the returned value.
 * The full name of the function with all the prefixes
 * is generated by Android Studio as described above.
 */
JNIEXPORT jint JNICALL
Java_com_example_greetingcard_MainActivityKt_addNumbers(JNIEnv *env, jclass thiz, jint a, jint b);

JNIEXPORT jstring JNICALL
Java_com_example_greetingcard_MainActivityKt_flipString(JNIEnv *env, jclass thiz, jstring instr);

doSomething.c

#include "include/doSomething.h"

#include <stdio.h>
#include <string.h>

JNIEXPORT jint JNICALL
Java_com_example_greetingcard_MainActivityKt_addNumbers(JNIEnv *env, jobject thiz, jint a, jint b) {
    return a + b;
}

JNIEXPORT jstring JNICALL
Java_com_example_greetingcard_MainActivityKt_flipString(JNIEnv *env, jobject thiz, jstring instr) {
    char *str;
    jboolean isCopy;
// Get the string from the kotlin parameter
    str = (*env)->GetStringUTFChars(env, instr, &isCopy);
    size_t len = strlen( str );
    for( size_t i = 0; i < len / 2; ++i ) {
        char c = str[i];
        str[i] = str[ len - i - 1 ];
        str[ len - i - 1] = c;
    }
    return (*env)->NewStringUTF(env,str);
}

MainActivity.kt

在此文件的顶部范围(即不在 MainActivity 类内),声明 C 库中的函数:

external fun addNumbers( a:Int, b:Int) :Int
external fun flipString( instr: String ): String

然后您可以按照预期在 MainActivity.kt 文件中的任何位置使用它们:

println("If we add 1 + 2, we get ${addNumbers(1,2)}!")
println("Flip \"dog\" and get \"${flipString("dog")}\".")
© www.soinside.com 2019 - 2024. All rights reserved.