gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 07:23:29 29 4
gpt4 key购买 nike

我第一次使用 Android Studio 构建一个多平台项目。我创建了一个在 Android 上使用多平台库的 Android 应用程序模块。
我还使用 XCode 构建了一个在 iOS 上使用多平台库的 iOS 应用程序。
一切正常,我可以使用 expect fun由不同的 actual fun 实现适用于 Android 和 iOS。

我还在 C++ 中创建了一个库,它公开了一个 C 接口(interface)。

#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

我使用 CLion 来构建 C++ 代码。
我创建了一个 .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是为构建 C++ 代码而创建的库。它是在文件夹 /Users/username/myproject/ping/cmake-build-debug 中创建的。

当我运行命令 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

如何使用 cinterop 创建的库在我的 kotlin-multiplatform 项目中?

我找到了不同的方法来导入它,但我没有找到任何关于如何做到这一点的完整描述。
Here他们说我可以使用类似的东西:
    implementation files("ping.klib")

我是为 iOS 项目做的,但我仍然不知道如何在 Android 和 iOS 上访问 kotlin 类。

这是我的 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

编辑
我改变了这个问题,因为最初我认为 cinterop没有创建 klib 库,但这只是一个错误:我正在查看 ping-build文件夹,但文件在该文件夹之外。所以我解决了一半的问题。

编辑2
我添加了 build.script

最佳答案

我很高兴看到 KLIB 一切正常,现在关于图书馆的使用。首先,我必须提到这个库只能被 Kotlin/Native 编译器使用,这意味着它可以用于某些目标(见列表 here)。然后,如果您要将 C 库使用包含到 MPP 项目中,最好通过 Gradle 脚本生成绑定(bind)。它可以在目标内部完成,参见 this例如文档。对于您的 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")
}
}
}
}

此代码段会将 cinterop 任务添加到您的 Gradle,并提供要包含的模块,例如 import c.ping.*在相应的 Kotlin 文件中。

关于android - 从多平台 kotlin 项目访问 C/C++ 库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60692146/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com