Kotlin multiplatform/native interoperability with Objective-C framework

百般思念 提交于 2019-12-09 05:59:58

问题


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 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.

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:

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

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 ?


回答1:


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"
                }
            }
        }
    }

end this .def file:

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

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.

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...)

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.




回答2:


It looks like you are going to use a cocoapods library. Currently the Gradle plugin has no support for cocapods out of the box. But may be a dependency on your library can be configured "manully". Could you please share a link to your project?



来源:https://stackoverflow.com/questions/54005467/kotlin-multiplatform-native-interoperability-with-objective-c-framework

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!