7.3.3.2.1 从 C 映射原始数据类型 – 教程
4 分钟阅读
原文链接: https://kotlinlang.org/docs/mapping-primitive-data-types-from-c.html
7.3.3.2.1 从 C 映射原始数据类型 – 教程
注意: C 库导入处于 Beta 阶段。由 cinterop 工具从 C 库生成的所有 Kotlin 声明都应带有
@ExperimentalForeignApi注解。随 Kotlin/Native 提供的原生平台库(例如 Foundation、UIKit 和 POSIX)只对部分 API 要求选择启用。
我们来探索哪些 C 数据类型在 Kotlin/Native 中可见(以及反向的情况),并考察 Kotlin/Native 与多平台 Gradle 构建中与 C 互操作相关的高级用例。
在本教程中,你将:
你可以使用命令行直接生成 Kotlin 库,也可以通过脚本文件(例如 .sh 或 .bat 文件)来完成。不过,对于包含数百个文件和库的较大项目,这种方式扩展性不好。使用构建系统可以下载并缓存 Kotlin/Native 编译器二进制文件及其传递依赖的库,并负责运行编译器和测试,从而简化整个过程。Kotlin/Native 可以通过 Kotlin Multiplatform 插件使用 Gradle 构建系统。
C 语言中的类型
C 编程语言具有以下数据类型:
- 基本类型:
char, int, float, double,可带signed, unsigned, short, long修饰符 - 结构体、联合体、数组
- 指针
- 函数指针
还有一些更具体的类型:
C 语言中还有以下类型限定符:const、volatile、restrict、atomic。
我们来看看哪些 C 数据类型在 Kotlin 中可见。
创建 C 库
在本教程中,你不会创建 lib.c 源文件,只有在你想要编译并运行 C 库时才需要它。对于这个设置,你只需要一个 .h 头文件,这是运行 cinterop 工具所必需的。
cinterop 工具会为每组 .h 文件生成一个 Kotlin/Native 库(一个 .klib 文件)。生成的库有助于把 Kotlin/Native 到 C 的调用桥接起来。它包含与 .h 文件中定义相对应的 Kotlin 声明。
要创建 C 库:
- 为你的未来项目创建一个空文件夹。
- 在其中创建一个包含以下内容的
lib.h文件,以了解 C 函数如何映射到 Kotlin:
| |
该文件没有 extern "C" 块,本示例不需要它,但如果你使用 C++ 和重载函数,则可能需要。更多细节请参阅这个 Stackoverflow 讨论串。
- 创建包含以下内容的
lib.def定义文件:
| |
- 把宏或其他 C 定义包含进 cinterop 工具生成的代码中可能会很有帮助。这样方法体也会被编译并完整包含在二进制文件中。借助这一特性,你无需 C 编译器就能创建一个可运行的示例。
为此,请在新的 interop.def 文件中、--- 分隔符之后为 lib.h 文件中的 C 函数添加实现:
| |
interop.def 文件提供了编译、运行或在 IDE 中打开该应用所需的一切。
创建 Kotlin/Native 项目
提示: 关于详细的第一步以及如何创建新的 Kotlin/Native 项目并在 IntelliJ IDEA 中打开它,请参阅 Kotlin/Native 入门教程。
要创建项目文件:
- 在你的项目文件夹中,创建一个包含以下内容的
build.gradle(.kts)Gradle 构建文件:
Kotlin
| |
Groovy
| |
该工程文件把 C 互操作配置为一个额外的构建步骤。请查看 Multiplatform Gradle DSL 参考以了解配置它的不同方式。
- 把你的
interop.def、lib.h和lib.def文件移动到src/nativeInterop/cinterop目录中。 - 创建
src/nativeMain/kotlin目录。按照 Gradle 关于使用约定而非配置的建议,所有源文件都应放在这里。
默认情况下,来自 C 的所有符号都被导入到 interop 包中。
- 在
src/nativeMain/kotlin中,创建一个包含以下内容的hello.kt桩文件:
| |
在了解了 C 原始类型声明从 Kotlin 一侧看是什么样子之后,你稍后会补全这些代码。
检查为 C 库生成的 Kotlin API
我们来看看 C 原始类型如何映射到 Kotlin/Native,并相应地更新示例项目。
使用 IntelliJ IDEA 的转到声明命令(Cmd + B/Ctrl + B)导航到为 C 函数生成的以下 API:
| |
除 char 类型之外,C 类型都是直接映射的;char 映射为 kotlin.Byte,因为它通常是 8 位有符号值:
| C | Kotlin |
| char | kotlin.Byte | | unsigned char | kotlin.UByte | | short | kotlin.Short | | unsigned short | kotlin.UShort | | int | kotlin.Int | | unsigned int | kotlin.UInt | | long long | kotlin.Long | | unsigned long long | kotlin.ULong | | float | kotlin.Float | | double | kotlin.Double |
更新 Kotlin 代码
现在你已经看到了 C 定义,可以更新你的 Kotlin 代码了。hello.kt 文件中的最终代码可能如下所示:
| |
要验证一切是否按预期工作,请在你的 IDE 中运行 runDebugExecutable<YourTargetName> Gradle 任务,或在终端中使用控制台命令,例如:
| |
下一步
在本系列的下一部分中,你将了解结构体和联合体类型如何在 Kotlin 与 C 之间映射:
另请参阅
在与 C 互操作文档中了解更多内容,其中涵盖了更多高级场景。