[英]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.