简体   繁体   English

从多平台 kotlin 项目访问 C/C++ 库

[英]Access C/C++ lib from a multiplatform kotlin project

For the first time, I'm using Android Studio to build a multiplatform project.我第一次使用 Android Studio 构建多平台项目。 I have created an Android app module that uses the multiplatform lib on Android.我创建了一个 Android 应用程序模块,它在 Android 上使用多平台库。 I have also used XCode to build an iOS app that uses the multiplatform lib on iOS.我还使用 XCode 构建了一个在 iOS 上使用多平台库的 iOS 应用程序。 Everything works fine and I'm able to use the expect fun that is implemented by different actual fun for Android and iOS.一切正常,我能够使用由 Android 和 iOS 的不同actual fun实现的expect fun

I have also created a library in C++ that exposes a C interface.我还在 C++ 中创建了一个公开 C 接口的库。

#ifndef PINGLIB_LIBRARY_H
#define PINGLIB_LIBRARY_H

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
    long long elapsed;
} PingInfo;

typedef void (*PingCallback)(PingInfo pingInfo);
typedef struct
{
    PingCallback pingUpdate;
} PingObserver;

void* ping(const char * url, const PingCallback *pingCallback);
void subscribe(void* pingOperation);
void unsubscribe(void* pingOperation);

#ifdef __cplusplus
}
#endif

#endif //PINGLIB_LIBRARY_H

I use CLion to build the C++ code.我使用 CLion 来构建 C++ 代码。 I have created a .def file that I use to build the library using cinterop .我创建了一个.def文件,用于使用cinterop构建库。

package = com.exercise.pinglib
headers = PingLibrary.h
linkerOpts.linux = -L/usr/lib/x86_64-linux-gnu
compilerOpts = -std=c99 -I/Users/username/myproject/ping/ping/header
staticLibraries = libping.a
libraryPaths = /opt/local/lib /Users/username/myproject/ping/cmake-build-debug

libping.a is the library created building the C++ code. libping.a是为构建 C++ 代码而创建的库。 It is created in the folder /Users/username/myproject/ping/cmake-build-debug它在文件夹/Users/username/myproject/ping/cmake-build-debug

When I run the command cinterop -def ping.def -o ping , it creates the klib file and a folder containing a manifest.properties file a natives subfolder containing a cstubs.bc file and a kotlin subfolder with a .kt file.当我运行命令cinterop -def ping.def -o ping ,它会创建klib文件,并包含一个文件夹manifest.properties提交natives子文件夹包含cstubs.bc文件和kotlin一个子文件夹.kt文件。

ping.klib
-ping-build
    manifest.properties
    -natives
        cstubs.bc
    -kotlin
        -com
            -exercise
                -pinglib
                    pinglib.kt

How can I use the library created by cinterop in my kotlin-multiplatform project?如何在我的 kotlin-multiplatform 项目中使用cinterop创建的库?

I have found different ways to import it but I did not find any complete description of how to do it.我找到了不同的导入方法,但没有找到有关如何操作的完整说明。 Here they say that I can use something like:在这里他们说我可以使用类似的东西:

    implementation files("ping.klib")

I did it for the iOS project but I still don't know how to access the kotlin classes neither on Android nor on iOS.我是为 iOS 项目做的,但我仍然不知道如何在 Android 和 iOS 上访问 kotlin 类。

This is my build.gradle这是我的build.gradle

apply plugin: 'com.android.library'
apply plugin: 'kotlin-multiplatform'

android {
    compileSdkVersion 28
    defaultConfig {
        minSdkVersion 15
    }
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}
kotlin {
    targets {
        final def iOSTarget = System.getenv('SDK_NAME')?.startsWith('iphoneos') ? presets.iosArm64 : presets.iosX64
        fromPreset(iOSTarget, 'ios') {
            binaries {
                framework('shared')
            }
        }
        fromPreset(presets.android, 'android')
    }
    sourceSets {
        // for common code
        commonMain.dependencies {
            api 'org.jetbrains.kotlin:kotlin-stdlib-common'
        }
        androidMain.dependencies {
            api 'org.jetbrains.kotlin:kotlin-stdlib'
        }
        iosMain.dependencies {
            implementation files("ping.klib")
        }
    }
}
configurations {
    compileClasspath
}

task packForXCode(type: Sync) {
    final File frameworkDir = new File(buildDir, "xcode-frameworks")
    final String mode = project.findProperty("XCODE_CONFIGURATION")?.toUpperCase() ?: 'DEBUG'
    final def framework = kotlin.targets.ios.binaries.getFramework("shared", mode)
    inputs.property "mode", mode
    dependsOn framework.linkTask
    from { framework.outputFile.parentFile }
    into frameworkDir
    doLast {
        new File(frameworkDir, 'gradlew').with {
            text = "#!/bin/bash\nexport 'JAVA_HOME=${System.getProperty("java.home")}'\ncd '${rootProject.rootDir}'\n./gradlew \$@\n"
            setExecutable(true)
        }
    }
}
tasks.build.dependsOn packForXCode

EDIT I have changed the question because, initially, I thought that cinterop was not creating the klib library but it was just a mistake: I was looking in the ping-build folder but the file is outside that folder.编辑我改变了问题,因为最初,我认为cinterop没有创建 klib 库,但这只是一个错误:我正在查看ping-build文件夹,但该文件在该文件夹之外。 So I resolved half of the question.所以我解决了一半的问题。

EDIT2 I have added the build.script EDIT2我添加了build.script

I'm glad to see that everything is fine with the KLIB, now about the library use.我很高兴看到 KLIB 一切正常,现在关于图书馆的使用。
First of all, I have to mention that this library can be utilized only by Kotlin/Native compiler, meaning it will be available for some targets(see list here ).首先,我不得不提到这个库只能由 Kotlin/Native 编译器使用,这意味着它可以用于某些目标(请参阅此处的列表)。 Then, if you're going to include C library use into an MPP project, it is always better to produce bindings via the Gradle script.然后,如果您要将 C 库的使用包含到 MPP 项目中,最好通过 Gradle 脚本生成绑定。 It can be done inside of a target, see this doc for example.它可以在目标内部完成,例如参见文档。 For your iOS target it should be like:对于您的 iOS 目标,它应该是这样的:

kotlin {
    iosX64 {  // Replace with a target you need.
        compilations.getByName("main") {
            val ping by cinterops.creating {
                defFile(project.file("ping.def"))
                packageName("c.ping")
            }
        }
    }
}

This snippet will add cinterop task to your Gradle, and provide module to include like import c.ping.* inside of the corresponding Kotlin files.此代码段将向您的 Gradle 添加 cinterop 任务,并提供模块以将import c.ping.*包含在相应的 Kotlin 文件中。

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

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