Kotlin external 关键字
最后修改于 2025 年 4 月 19 日
Kotlin 的 external
关键字实现了与原生代码的互操作性。 它标记了在 Kotlin 之外实现的声明。 本教程通过实际例子深入探讨了 external
关键字。
基本定义
Kotlin 中的 external
关键字表示声明是在特定于平台的代码中实现的。 它用于 JNI (Java Native Interface) 和 JavaScript 互操作性。 实际的实现必须在外部提供。
基本 external 函数
external
最简单的用法是声明一个在原生代码中实现的函数。 函数体被省略,因为它是在外部提供的。
package com.zetcode external fun helloFromNative() fun main() { helloFromNative() }
在这里,我们声明一个没有实现的 external
函数。 实际的原生代码将用 C/C++ 编写,并通过 JNI 链接。 Kotlin 代码可以像调用任何其他函数一样调用它。
使用 JNI 的 external
在使用 JNI 时,external
标记在 C/C++ 中实现的函数。 函数名称必须遵循 JNI 命名约定才能正确链接。
package com.zetcode external fun nativeAdd(a: Int, b: Int): Int fun main() { System.loadLibrary("nativeLib") val sum = nativeAdd(5, 7) println("Sum from native: $sum") }
此示例显示了一个将两个整数相加的原生函数。 对应的 C 函数将被命名为 Java_com_zetcode_JNIFunction_nativeAdd
。 在调用原生函数之前,会加载库。
external 属性
属性也可以标记为 external
。 getter 和 setter 必须在原生代码中实现。 这对于访问原生状态很有用。
package com.zetcode external var nativeCounter: Int fun main() { System.loadLibrary("nativeLib") nativeCounter = 10 println("Counter value: $nativeCounter") }
在这里,我们声明一个由原生代码支持的 external
属性。 原生实现必须同时提供 getter 和 setter 函数。 该属性的行为类似于常规的 Kotlin 属性。
external 类
整个类可以标记为 external
。 这种类的所有成员也必须是 external
。 这对于 JNI 包装器很常见。
package com.zetcode external class NativeMath { fun add(a: Int, b: Int): Int fun subtract(a: Int, b: Int): Int } fun main() { System.loadLibrary("nativeLib") val math = NativeMath() println("5 + 3 = ${math.add(5, 3)}") println("5 - 3 = ${math.subtract(5, 3)}") }
这个 external
类声明了在原生代码中实现的方法。 原生实现必须提供所有声明的方法。 该类可以像任何常规的 Kotlin 类一样使用。
JavaScript 互操作
当目标是 JavaScript 时,external
用于从 Kotlin 代码访问 JavaScript API。 声明直接映射到 JavaScript 对象。
package com.zetcode external fun alert(message: String) external val document: dynamic fun main() { alert("Hello from Kotlin/JS!") document.getElementById("demo").innerHTML = "Updated" }
在 Kotlin/JS 中,external
声明映射到 JavaScript API。 这里我们声明了 alert
函数和 document
对象。 dynamic
类型允许灵活访问 JavaScript 属性。
external 伴生对象
伴生对象可以标记为 external
,以便为静态方法提供原生实现。 这对于实用程序函数很有用。
package com.zetcode class NativeUtils { companion object { external fun getSystemTime(): Long } } fun main() { System.loadLibrary("nativeLib") val time = NativeUtils.getSystemTime() println("System time: $time") }
此示例显示了一个 external
伴生对象函数。 原生实现将是一个静态 JNI 函数。 该函数通过伴生对象像静态方法一样被调用。
使用平台库的 external
external
关键字可以与特定于平台的库一起使用。 此示例演示了访问 Windows API 函数。
package com.zetcode external fun MessageBoxA( hWnd: Int, text: String, caption: String, uType: Int ): Int fun main() { System.loadLibrary("user32") MessageBoxA(0, "Hello from Kotlin", "Message", 0) }
在这里,我们将 Windows MessageBoxA
API 声明为 external
。 该函数从 user32.dll 加载。 这演示了 Kotlin 中的特定于平台的互操作性。
external 的最佳实践
- 谨慎使用: 仅在互操作性必要时使用
external
。 - 彻底记录: 清楚地记录原生要求和调用约定。
- 处理错误: 为原生调用实现正确的错误处理。
- 考虑替代方案: 在使用原生代码之前评估 Kotlin 多平台库。
- 彻底测试: 原生代码可能导致崩溃 - 进行广泛的测试。
来源
本教程深入探讨了 Kotlin 的 external
关键字,展示了它在 JNI、JavaScript 和平台互操作性中的应用。 我们探讨了各种场景,包括函数、属性、类和伴生对象。 正确使用 external
可以实现强大的原生集成。
作者
列出 所有 Kotlin 教程。