Kotlin multiplatform/native 与 Objective-C 框架的互操作性

Kotlin multiplatform/native interoperability with Objective-C framework

我正在尝试在多平台项目中从 Kotlin 调用 Swift/Objective-C 代码。调用平台代码没有问题。但是,当我尝试调用某个库(或框架,不确定如何正确调用它,因为我不是 iOS 开发人员)时,它失败了。 Docs 声明可以调用 Objective-C 代码和 Swift 如果正确导出:

Kotlin/Native provides bidirectional interoperability with Objective-C. Objective-C frameworks and libraries can be used in Kotlin code if properly imported to the build (system frameworks are imported by default). See e.g. "Using cinterop" in Gradle plugin documentation. A Swift library can be used in Kotlin code if its API is exported to Objective-C with @objc. Pure Swift modules are not yet supported.

但它没有说明如何正确导入它们。它只指向描述旧版本 gradle 插件的 gradle plugin description。所以它对我不起作用。最后我想通了一些可能是导入 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'
                }
            }
        }
    }

Build 运行没有失败,但它没有导入任何东西。我究竟做错了什么?是否可以完全导入这样的库?

更新:

here 我找到了一个使用 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 工具?

看来您要使用 cocoapods 库。目前 Gradle 插件不支持开箱即用的 Cocapods。但是可能是依赖你的库可以配置"manully"。你能分享一个 link 到你的项目吗?

我在 build.gradle

中完成了这个 cinterops 部分
    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 框架位于 Xcode 项目的 Pods 目录中。浏览一下这个文件夹,你会找到你需要的。我不确定 Public 文件夹中是否有一些标准但 firebase 放置主 header 文件。它包含对它需要的其他 header 文件的引用...因此您在 headers 部分的 .def 文件中指定这些文件名。

接下来,您需要指定在何处查找这些文件以及它们引用的其他文件。您可以在 includeDirsbuild.gradle 文件中的 .def 文件中执行此操作。我更喜欢使用 build.gradle 文件,因为它可以使用变量。因此,您指定了这些 Public 文件夹的路径。 (这足以让 kotlin 查看库 API,但是为了能够 运行 您需要编译的应用程序和 link 这个库...)

然后编译器和 linker 需要知道 library/framework 在哪里。因此,您在 compilerOptslinkerOpts 中指定框架根文件夹的路径,如果它是框架,则在它们前面加上 -F 前缀,如果它是库,则在它们前面加上 -L 前缀。