準備工作: 寫一個c語言的庫
-
CLion新建C靜態(tài)庫工程
simplelib.h
void hello(void);
char *getString(void);
simplelib.c
#include "simplelib.h"
#include <stdio.h>
void hello(void) {
printf("Hello, World!\n");
}
char *getString() {
return "string from c library";
}
-
編譯項目,得到libsimplelib.a文件
正式開始
- 新建Kotlin Native項目煤痕,我這里換了IDEA,CLion也可以
-
我們新建一個cinterop文件夾疗韵,將剛才項目中生成的靜態(tài)庫和頭文件拷貝過來
-
然后在src目錄中新建nativeInterop目錄,在里面新建cinterop目錄,在里面新建interop.def文件(這是gradle插件默認找.def文件的位置)
- 然后我們編輯.def文件,
libraryPaths = D:\\Workplace\\kotlin\\kandc\\interop\\
headers = D:\\Workplace\\kotlin\\kandc\\interop\\simplelib.h
staticLibraries = libsimplelib.a
- 同時編輯build.gradle耻卡,在kotlin->mingwX64中加入
compilations.main.cinterops { interop }
,下面是完整的build.gradle文件
plugins {
id 'kotlin-multiplatform' version '1.3.31'
}
repositories {
mavenCentral()
}
kotlin {
mingwX64("mingw") {
compilations.main.cinterops {
interop
}
binaries {
executable {
entryPoint = 'sample.main'
runTask?.args('')
}
}
}
sourceSets {
mingwMain {
}
mingwTest {
}
}
}
- 現(xiàn)在可以編譯項目了牲尺,老規(guī)矩,double ctrl幌蚊, 輸入gradle build谤碳,回車
- 編譯完成后可以發(fā)現(xiàn)project面板的External Libraries里面多了一項,這就是kotlin native根據(jù).def文件生成的溢豆,原始文件在build目錄中蜒简,現(xiàn)在我們可以在kotlin代碼里面調(diào)用c寫的靜態(tài)庫了
- 打開SampleMingw.kt,擼代碼
package sample
import interop.*
import kotlinx.cinterop.toKString
fun main() {
hello()
println(getString()?.toKString())
}
運行
-
老規(guī)矩漩仙,雙擊ctrl搓茬,跑起來
結果,有點奇怪這里是輸出順序是反的
- 試試命令行運行
和第一篇一樣队他,加上system("pause")
卷仑,就可以雙擊運行了
package sample
import interop.*
import kotlinx.cinterop.toKString
import platform.posix.system
fun main() {
hello()
println(getString()?.toKString())
system("pause")
}
說明
- 因為是靜態(tài)庫,庫就直接編譯到最后的可執(zhí)行文件中了
- simplelib中
getString()
函數(shù)返回的是char *類型麸折,這個在kotlin native中被映射為kotlinx.cinterop.CPointer<ByteVar>?
的可空類型锡凝,調(diào)用toKString()
將該類型轉換為kotlin中的String?
- 建立.def文件是為了使用kotlin native的
cinterop
命令將c語言的頭文件編譯成kotlin native可以識別的klib庫,這個kandc-cinterop-interop.klib就是cinterop
編譯出來的文件
這是0_interop.knm文件的內(nèi)容
// IntelliJ API Decompiler stub source generated from a class file
// Implementation of methods is not available
package interop
public fun getString(): kotlinx.cinterop.CPointer<kotlinx.cinterop.ByteVar /* = kotlinx.cinterop.ByteVarOf<kotlin.Byte> */>? { /* compiled code */ }
public fun hello(): kotlin.Unit { /* compiled code */ }
@kotlin.native.SymbolName private external fun kniBridge0(): kotlin.Unit { /* compiled code */ }
@kotlin.native.SymbolName private external fun kniBridge1(): kotlinx.cinterop.NativePtr /* = kotlin.native.internal.NativePtr */ { /* compiled code */ }
所以寫kotlin native代碼時就可以調(diào)用這些數(shù)據(jù)/函數(shù)了