简体   繁体   English

Kotlin多平台/本机与Objective-C框架的互操作性

[英]Kotlin multiplatform/native interoperability with Objective-C framework

I'm trying to call Swift/Objective-C code from Kotlin in a multiplatform project. 我试图在一个多平台项目中从Kotlin调用Swift / Objective-C代码。 There are no problems with calls to platform code. 调用平台代码没有问题。 But when I'm trying to call some library (or framework, not sure how it is properly called as I'm not an iOS dev) it fails. 但是当我试图调用某个库(或框架,不确定它是如何被正确调用,因为我不是iOS开发者)时它失败了。 Docs states that it is possible to call Objective-C code and Swift if it is properly exported: Docs声明如果正确导出,可以调用Objective-C代码和Swift:

Kotlin/Native provides bidirectional interoperability with Objective-C. Kotlin / Native提供与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). 如果正确导入到构建中,可以在Kotlin代码中使用Objective-C框架和库(默认情况下导入系统框架)。 See eg "Using cinterop" in Gradle plugin documentation. 请参阅Gradle插件文档中的“使用cinterop”。 A Swift library can be used in Kotlin code if its API is exported to Objective-C with @objc. 如果使用@objc将其API导出到Objective-C,则可以在Kotlin代码中使用Swift库。 Pure Swift modules are not yet supported. 尚不支持Pure Swift模块。

But it does not say anything about how can I import them properly. 但它没有说明如何正确导入它们。 It only point to gradle plugin description that describes old version of gradle plugin. 它仅指向描述旧版gradle插件的gradle插件描述 So it does not work for me. 所以它对我不起作用。 Finally I figured out something might be the way to import Objective-C code: 最后我想出了一些可能是导入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 runs without failures, but it does not import anything. 构建运行没有失败,但它不导入任何东西。 What am I doing wrong? 我究竟做错了什么? Is it possible to import such a lib at all? 是否有可能导入这样的lib?

UPD: UPD:

here I found an example of usage cinterop tool like this: 在这里我找到了一个使用cinterop工具的例子,如下所示:

cd samples/gitchurn
../../dist/bin/cinterop -def src/main/c_interop/libgit2.def \
 -compilerOpts -I/usr/local/include -o libgit2

It looks like cinterop tool should be in /dist/bin/ folder in my projects but there is no such folder. 看起来cinterop工具应该在我的项目中的/dist/bin/文件夹中,但是没有这样的文件夹。 Where do I get cinterop tool ? 我在哪里获得cinterop工具?

I ended up with this cinterops section in build.gradle 我最终在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"
                }
            }
        }
    }

end this .def file: 结束这个.def文件:

language = Objective-C
headers = FirebaseCore.h FirebaseDatabase.h

What's going on here? 这里发生了什么? Cocopods frameworks are placed in Pods directory in your Xcode project. Cocopods框架放在Xcode项目的Pods目录中。 Navigating this folder a bit, you'll find what you need. 稍微浏览此文件夹,您将找到所需内容。 I'm not sure if there is some standard but firebase place main header file in Public folder. 我不确定在Public文件夹中是否有一些标准但firebase放置主头文件。 And it contains references to other header files it needs... So you specify these file names in your .def file in the headers section. 它包含对其所需的其他头文件的引用...因此,您可以在头部分的.def文件中指定这些文件名。

Next, you need to specify where to look for these files and others referenced by them. 接下来,您需要指定查找这些文件的位置以及它们引用的其他文件。 You can do it in the .def file in includeDirs or in build.gradle file. 您可以在includeDirsbuild.gradle文件中的.def文件中build.gradle操作。 I prefer to use the build.gradle file as it can use variables. 我更喜欢使用build.gradle文件,因为它可以使用变量。 So you specify the path to these Public folders. 所以你指定的路径,这些Public文件夹。 (This is enough for kotlin to see library API, but in order to be able to run the app you need to compile and link this library...) (这足以让kotlin看到库API,但为了能够运行应用程序,您需要编译并链接此库...)

Then the compiler and linker need to know where library/framework is. 然后编译器和链接器需要知道库/框架的位置。 So you specify path to root folder of the framework in compilerOpts and linkerOpts prefixing them with -F if it is a framework or -L if it is a library. 因此,您在compilerOptslinkerOpts指定框架的根文件夹的路径,如果它是框架则为-F加前缀,如果是库,则为-L

It looks like you are going to use a cocoapods library. 看起来你打算使用cocoapods库。 Currently the Gradle plugin has no support for cocapods out of the box. 目前,Gradle插件不支持开箱即用的cocapods。 But may be a dependency on your library can be configured "manully". 但可能是对您的库的依赖可以配置为“manully”。 Could you please share a link to your project? 你能分享一下你项目的链接吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM