kotlin - Kotlin 与 Objective-C 框架的多平台/原生互操作性
问题描述
我正在尝试在多平台项目中从 Kotlin 调用 Swift/Objective-C 代码。调用平台代码没有问题。但是,当我尝试调用某个库(或框架,由于我不是 iOS 开发人员而不确定如何正确调用它)时,它会失败。文档指出,如果正确导出,可以调用 Objective-C 代码和 Swift:
Kotlin/Native 提供与 Objective-C 的双向互操作性。如果将 Objective-C 框架和库正确导入构建(默认导入系统框架),则可以在 Kotlin 代码中使用 Objective-C 框架和库。请参阅 Gradle 插件文档中的“使用 cinterop”。如果使用 @objc 将 Swift 库的 API 导出到 Objective-C,则可以在 Kotlin 代码中使用 Swift 库。尚不支持纯 Swift 模块。
但它没有说明如何正确导入它们。它仅指向描述旧版本 gradle 插件的 gradle插件描述。所以它对我不起作用。最后我想出了一些可能是导入Objective-C代码的方法:
fromPreset(presets.iosX64, 'ios') {
compilations.main.outputKinds('FRAMEWORK')
compilations.main {
cinterops {
firebase {
def pods = '${System.getProperty("user.home")}/Projects/kmpp/iosApp/Pods/'
includeDirs '${pods}Firebase/CoreOnly/Sources',
'${pods}FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers'
}
}
}
}
构建运行没有失败,但它不导入任何东西。我究竟做错了什么?是否可以导入这样的库?
升级版:
在这里,cinterop
我找到了一个这样的使用工具示例:
cd samples/gitchurn
../../dist/bin/cinterop -def src/main/c_interop/libgit2.def \
-compilerOpts -I/usr/local/include -o libgit2
看起来cinterop
工具应该/dist/bin/
在我的项目的文件夹中,但没有这样的文件夹。我在哪里获得cinterop
工具?
解决方案
cinterops
我在 build.gradle 中结束了这一部分
fromPreset(presets.iosX64, 'ios') {
// This preset is for iPhone emulator
// Switch here to presets.iosArm64 (or iosArm32) to build library for iPhone device
compilations.main {
outputKinds('FRAMEWORK')
cinterops {
firebase {
defFile "$projectDir/src/iosMain/cinterop/firebase.def"
includeDirs {
allHeaders "$projectDir/../iosApp/Pods/FirebaseCore/Firebase/Core/Public",
"$projectDir/../iosApp/Pods/FirebaseDatabase/Firebase/Database/Public"
}
compilerOpts "-F$projectDir/../iosApp/Pods/Firebase -F$projectDir/../iosApp/Pods/FirebaseCore -F$projectDir/../iosApp/Pods/FirebaseDatabase"
linkerOpts "-F$projectDir/../iosApp/Pods/Firebase -F$projectDir/../iosApp/Pods/FirebaseCore -F$projectDir/../iosApp/Pods/FirebaseDatabase"
}
}
}
}
结束这个.def
文件:
language = Objective-C
headers = FirebaseCore.h FirebaseDatabase.h
这里发生了什么?Cocopods 框架放置在Pods
Xcode 项目的目录中。稍微浏览一下这个文件夹,你会找到你需要的。我不确定文件夹中是否有一些标准但firebase的主要头文件Public
。它包含对它需要的其他头文件的引用......所以你在你的.def
文件的 headers 部分中指定这些文件名。
接下来,您需要指定在何处查找这些文件以及它们引用的其他文件。您可以在.def
文件中includeDirs
或build.gradle
文件中执行此操作。我更喜欢使用 build.gradle 文件,因为它可以使用变量。因此,您指定这些Public
文件夹的路径。(这足以让 kotlin 看到库 API,但是为了能够运行应用程序,您需要编译和链接这个库......)
然后编译器和链接器需要知道库/框架在哪里。因此,您可以指定框架根文件夹的路径,compilerOpts
并在它们是框架还是库时为其linkerOpts
添加前缀。-F
-L
推荐阅读
- react-native - 不变违规:本机模块不能为空
- php - 当列名仅在 where 子句中指定时 MySQL 更新所有行
- docker - AKS,拉取 docker 映像失败并出现错误:未找到标记为“最新”的清单
- r - 从 R 中的列表绘制散点图
- vhdl - VHDL 转 Verilog
- compression - 霍夫曼编码可以压缩哪些类型的文件?
- node.js - 将 Node.JS express API 应用部署到 Azure 应用服务
- snowflake-cloud-data-platform - 雪花卸载喙文件成太多小文件
- reactjs - 应用多个动态过滤器
- r - 为什么我在 lapply 函数中的“对比度”中出现错误?