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