QtBindings

QtBindings

KMP bindings plugin for Qt.

EN | RU

QtBindings

A gradle plugin that generates Qt bindings for Kotlin code compiled into a C static or shared library. It helps to share business logic using Kotlin Multiplatform and create UI using Qt Quick (QML).

Supported KMP targets: linuxArm64, linuxX64.

Add QtBindings to the project

Add plugin to the build script and set up linux target(s) to compile static or shared library:

plugins {
    id("org.jetbrains.kotlin.multiplatform") version "2.1.10"
    id("com.google.devtools.ksp") version "2.1.10-1.0.29"
    id("ru.auroraos.kmp.qtbindings") version "0.1.0"
}

kotlin {
    val linuxTargets = listOf(linuxX64(), linuxArm64())

    linuxTargets.forEach { it ->
        it.binaries {
            staticLib("shared")
        }
    }
}

qtBindings {
    libName = "shared"
}

Note: The libName must match the name of the compiled static or dynamic library for the linux target.

Usage

Annotation QtExport can be applied to the top-level classes or function to create Qt bindings for them.

  • Export top-level Kotlin function
import ru.auroraos.kmp.qtbindings.QtExport

@QtExport
fun helloWorld() = println("Hello, World!")
Generated Qt function

The QtBindings plugin will generate this Qt function:

void helloWorld();
  • Export top-level Kotlin class
import ru.auroraos.kmp.qtbindings.QtExport

@QtExport
class Calculator() {
    fun sum(x: Int, y: Int) : Int = x + y
    fun multiply(x: Int, y: Int) : Int = x * y
}
Generated Qt class

The QtBindings plugin will generate this Qt class:

class Calculator
{
public:
    Calculator();
    Calculator(Calculator &&other);
    Calculator(libshared_kref_ru_auroraos_example_Calculator ptr);
    ~Calculator();

    Calculator &operator=(Calculator &&other);

    int sum(int x, int y) const;
    int multiply(int x, int y) const;

    libshared_kref_ru_auroraos_example_Calculator unsafeKotlinPointer() const;
private:
    libshared_kref_ru_auroraos_example_Calculator d_ptr;
};
  • Export suspend function
import kotlinx.coroutines.delay
import ru.auroraos.kmp.qtbindings.QtExport

@QtExport
suspend fun calculateAsync(x: Int, y: Int) : Int {
    delay(1000)
    return x + y
}
Generated Qt function that returns QFuture

The QtBindings plugin will generate this Qt function:

QFuture<int> calculateAsync(int x, int y);

Note: Generated Qt bindings (cpp and hpp files) are located in build/generated/ksp/[linuxTargetName]/[linuxMainSourceSetName]/resources

Do not forget to add the compiled C library for the Linux target to the Qt project to make the Qt bindings work.

Ways to use Qt bindings in a Qt project:

  • Compile static or shared library from the generated Qt bindings and add it to the project
  • Add the generated Qt binding source code to the project's build system (qmake, cmake, meson)

Mappings

Kotlin Qt (C++)
Primitives: Unit, Bool, Int, Long, etc void, bool, int, long long, etc
String QString
List, MutableList QList
suspend functions (coroutines) Functions that returns QFuture
Public top-level Kotlin function Public top-level Qt (C++) function
Public top-level Kotlin class Public top-level Qt (C++) class
data class Qt (C++) class with copy constructor, copy operator, getters and setters

Known limitations

  • Qt collections (QList) are copies of Kotlin ones. You need create a setter or special kotlin function that updates Kotlin list.
import ru.auroraos.kmp.qtbindings.QtExport

@QtExport
data class Example(val example: MutableList<String>)

For example, generated code for the Kotlin Example class:

class Example
{
public:
    Example(const QList<QString> &example);
    Example(const Example &other);
    Example(Example &&other);
    Example(libshared_kref_ru_auroraos_example_Example ptr);
    ~Example();

    Example &operator=(const Example &other);
    Example &operator=(Example &&other);

    QList<QString> getExample() const; // Returns copy of the Kotlin list
    void setExample(const QList<QString> &set); // Change Kotlin list

    libshared_kref_ru_auroraos_example_Example unsafeKotlinPointer() const;
private:
    libshared_kref_ru_auroraos_example_Example d_ptr;
};

getExample function will return COPY of Kotlin MutableList. You need to use setExample function to change its value in the Example class in the Kotlin side. After you have changed the value of the list using setExample, you will get the updated value in the getExample function.

  • Nested classes are not supported yet
  • Objects are not supported yet
  • Enums are not supported yet

How to build and publish locally

Prerequisites:

  • JDK 11
./gradlew publishToMavenLocal