美文网首页kotlin native 入门&进阶
kotlin-native03 调用c静态库

kotlin-native03 调用c静态库

作者: hohov | 来源:发表于2019-06-12 17:38 被阅读0次

    准备工作: 写一个c语言的库

    • CLion新建C静态库工程


      新建工程

    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文件夹,将刚才项目中生成的静态库和头文件拷贝过来


      拷贝头文件和静态库
    • 然后在src目录中新建nativeInterop目录,在里面新建cinterop目录,在里面新建interop.def文件(这是gradle插件默认找.def文件的位置)


      interop.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 {
            }
        }
    }
    
    • 现在可以编译项目了,老规矩,double ctrl, 输入gradle build,回车
    build
    • 编译完成后可以发现project面板的External Libraries里面多了一项,这就是kotlin native根据.def文件生成的,原始文件在build目录中,现在我们可以在kotlin代码里面调用c写的静态库了
    • 打开SampleMingw.kt,撸代码
    package sample
    
    import interop.*
    import kotlinx.cinterop.toKString
    
    fun main() {
        hello()
        println(getString()?.toKString())
    }
    

    运行

    • 老规矩,双击ctrl,跑起来


      gradle run

      结果,有点奇怪这里是输出顺序是反的


      结果
    编译后的程序
    • 试试命令行运行
    运行exe

    和第一篇一样,加上system("pause"),就可以双击运行了

    package sample
    
    import interop.*
    import kotlinx.cinterop.toKString
    import platform.posix.system
    
    fun main() {
        hello()
        println(getString()?.toKString())
        system("pause")
    }
    
    双击运行

    说明

    • 因为是静态库,库就直接编译到最后的可执行文件中了
    • simplelib中getString()函数返回的是char *类型,这个在kotlin native中被映射为kotlinx.cinterop.CPointer<ByteVar>?的可空类型,调用toKString()将该类型转换为kotlin中的String?
    • 建立.def文件是为了使用kotlin native的cinterop命令将c语言的头文件编译成kotlin native可以识别的klib库,这个kandc-cinterop-interop.klib就是cinterop编译出来的文件
      kandc-cinterop-interop.klib
      这是0_interop.knm文件的内容
    // 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代码时就可以调用这些数据/函数了

    相关文章

      网友评论

        本文标题:kotlin-native03 调用c静态库

        本文链接:https://www.haomeiwen.com/subject/fcslfctx.html