Kotlin native - Execute an executable
Asked Answered
K

3

7

I am trying to execute a command via bash, for example konanc.

In KotlinJVM this would just be using Runtime.getRuntime().exec("..."), or creating a Process using the ProcessBuilder, however, none of those classes are available in Kotlin-Native, as they are part of the Java libraries.

I tried searching for example code in the documentation and the kotlin-native GitHub repository, but haven't found anything.

Kokura answered 21/7, 2018 at 23:43 Comment(0)
R
4

tl;dr No, there is no standard process api for kotlin-native

Well the kotlin std for native is still under development, and i don't think process api will be there anytime soon.

However you could use interoperability with some C process library such as https://github.com/eidheim/tiny-process-library

How-to you will find here https://github.com/JetBrains/kotlin-native/blob/master/INTEROP.md

However there are also POSIX's exec/fork calls you could use to spawn and create new process and i think kotlin-native does include POSIX for linux/windows. https://github.com/JetBrains/kotlin-native/tree/master/platformLibs/src/platform see posix.def for platforms.

Example:

import platform.posix.*

fun main(arguments: Array<String>) {
    println("${arguments[0]}")
    execlp("touch", "touch", "${arguments[0]}")
}

Calling it with ./file <name> will create a file that is named after the parameter name in your current directory.

Robomb answered 22/7, 2018 at 0:0 Comment(4)
Thanks for the answer, i have provided a working example.Kokura
any code after execlp doesn't get executed, is there a workaround?Trigonal
println("Hello"), execlp("java", "/usr/bin/java", "-version"), println("Done") . ---- the program ends with printing 'Done'...Trigonal
Sorry, for the late answer, but I assume that's because execlp waits for the child process to exit. If the process is something like a browser for example, it'll probably block til the application is closed.Kokura
A
0

IMHO, this is the killer app for Kotlin native. And here is part of the solution using the standard Kotlin API; This solution still needs the buffering of the dir or date command output, but generally works on Windows yea!

import kotlin.native.OsFamily.*
import platform.posix.*

fun main(arguments: Array<String>) {
    println("running")
    if (arguments.size >= 1) {
        arguments.forEach { a -> println(a) }
    }
    val platform  = Platform
    val os = platform.osFamily
    println("os is " + os)
    when (os) {
        WINDOWS -> runWindows()
        else -> runUnix()
    }
}

fun runWindows() {
    val result = execlp("dir", "","")
    println("Ran on windows $result");
}

fun runUnix() {
    execlp("date", "","")
    println("Ran on UNIX")
}
Accuse answered 28/9, 2021 at 2:52 Comment(0)
A
0

Finally one that reads from the called process yea! Only tested on Windows, I will do unix (aka mac :) ) tomorrow.

import kotlin.native.OsFamily.*
import platform.posix.*
import kotlinx.cinterop.refTo
import kotlinx.cinterop.toKString

fun main(arguments: Array<String>) {
    println("running")
    if (arguments.size >= 1) {
        arguments.forEach { a -> println(a) }
    }
    val platform  = Platform
    val os = platform.osFamily
    println("os is " + os)
    when (os) {
        WINDOWS -> runWindows()
        else -> runUnix()
    }
}

fun runWindows() {
    val result = execl("dir", "","")
    //hmm emulate https://gist.github.com/a-cordier/33211eda92b8084a9e7e
    //https://www.youtube.com/watch?v=6xbLgZpOBi8
    val fp = _popen("dir", "r") ?: error("Failed to run command: dir")
    val buffer = ByteArray(4096)
    var counter = 0
    println("hmm")
    while (true) {
        val input = fgets(buffer.refTo(0), buffer.size, fp) ?: break
        print(input.toKString())
        //println(counter++)
    }
    println("Ran on windows $result");
}

fun runUnix() {
    execlp("date", "","")
    println("Ran on UNIX")
}
Accuse answered 30/9, 2021 at 2:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.