具有Objective-C框架的Kotlin多平台/本机互操作性 [英] Kotlin multiplatform/native interoperability with Objective-C framework

查看:134
本文介绍了具有Objective-C框架的Kotlin多平台/本机互操作性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to call Swift/Objective-C code from Kotlin in a multiplatform project. 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. Docs states that it is possible to call Objective-C code and Swift if it is properly exported:

Kotlin/Native提供与Objective-C的双向互操作性.如果正确导入到构建中,则可以在Kotlin代码中使用Objective-C框架和库(默认情况下会导入系统框架).参见例如Gradle插件文档中的使用cinterop".如果使用@objc将Swift库的API导出到Objective-C,则可以在Kotlin代码中使用Swift库.尚不支持Pure 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的旧版本.插入.因此它对我不起作用.最后,我发现了某种可能是导入Objective-C代码的方式:

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. So it does not work for me. Finally I figured out something might be the way to import Objective-C code:

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?

UPD:

此处我找到了用法示例cinterop这样的工具:

here I found an example of usage cinterop tool like this:

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

看来cinterop工具应该在我项目的/dist/bin/文件夹中,但是没有这样的文件夹.我在哪里可以得到cinterop工具?

It looks like cinterop tool should be in /dist/bin/ folder in my projects but there is no such folder. Where do I get cinterop tool ?

推荐答案

我在build.gradle

I ended up with this cinterops section in 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框架位于Xcode项目的Pods目录中.稍微浏览一下该文件夹,您将找到所需的内容.我不确定Public文件夹中是否有一些标准但firebase的主头文件.它包含对所需的其他头文件的引用...因此,您可以在头部分的.def文件中指定这些文件名.

What's going on here? Cocopods frameworks are placed in Pods directory in your Xcode project. 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. And it contains references to other header files it needs... So you specify these file names in your .def file in the headers section.

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

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. I prefer to use the build.gradle file as it can use variables. So you specify the path to these Public folders. (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...)

然后,编译器和链接器需要知道库/框架在哪里.因此,您可以在compilerOpts中指定框架根文件夹的路径,并在linkerOpts中以-F为前缀,如果是框架,则以-L为前缀.

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.

这篇关于具有Objective-C框架的Kotlin多平台/本机互操作性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆