https://kotlinlang.org logo
n

napperley

11/30/2020, 1:13 AM
IntelliJ applies invalid syntax checking to a Kotlin source file in a Kotlin Native project (using the linuxX64 target) that uses a Kotlin Multiplatform library ( https://gitlab.com/napperley/kmqtt-client ). Both the library and the project use the same Kotlin version (1.4.20). There are no compilation/build issues with the project. When doing a Gradle refresh IntelliJ showed a popup window about the Kotlin Native library being incompatible which is incorrect.
a

Alexey Belkov [JB]

11/30/2020, 1:15 PM
@Artyom Degtyarev [JB] can you please take a look?
a

Artyom Degtyarev [JB]

11/30/2020, 1:16 PM
👀
Hello, @napperley! Please help me a little bit. As far as I can get, I should utilize kmqtt-client library from some simple Kotlin Native project. Is this library published somewhere, or I have to build and publish it locally? If so, please provide some instructions with listed prerequisites etc.
n

napperley

11/30/2020, 10:08 PM
I am about to provide some build information that uses Gradle Kotlin DSL. Presumably @Artyom Degtyarev [JB] is familiar with the DSL. In the repositories block a custom Maven repository will need to be added:
Copy code
maven {
        url = uri("<https://dl.bintray.com/digieng/development>")
    }
After adding the repository the dependency is added. In this case the dependency is applied to the linuxX64 target:
Copy code
linuxX64("linuxX64") {
        compilations.getByName("main") {
            dependencies {
                val kmqttClientVer = "0.2.1-dev"
                implementation("org.digieng:kmqtt-client:$kmqttClientVer")
            }
            cinterops.create("paho_mqtt") {
                val pahoMqttDir = "${System.getenv("HOME")}/paho_mqtt_c-1.3.7"
                val includeDir = "$pahoMqttDir/include"
                compilerOpts(includeDir)
                extraOpts("-libraryPath", "$pahoMqttDir/lib")
                includeDirs(includeDir)
            }
        }
        // ...
    }
With the library it is recommended to create a definition file called paho_mqtt.def, that is stored in src/nativeInterop/cinterop. Inside the def file add the following:
Copy code
headers = MQTTClient.h MQTTClientPersistence.h
headerFilter = MQTTClient.h MQTTClientPersistence.h
staticLibraries.linux = libpaho-mqtt3c.a

---
static inline MQTTClient_connectOptions* createMqttConnectionOptions() {
    MQTTClient_connectOptions* options = (MQTTClient_connectOptions*) malloc(sizeof(MQTTClient_connectOptions));
    options->struct_id[0] = 'M';
    options->struct_id[1] = 'Q';
    options->struct_id[2] = 'T';
    options->struct_id[3] = 'C';
    options->struct_version = 6;
    options->reliable = 1;
    options->will = NULL;
    options->username = NULL;
    options->password = NULL;
    options->retryInterval = 0;
    options->ssl = NULL;
    options->serverURIcount = 0;
    options->serverURIs = NULL;
    options->MQTTVersion = MQTTVERSION_DEFAULT;
    options->maxInflightMessages = -1;
    return options;
}

static inline MQTTClient_message* createMqttMessage() {
    MQTTClient_message* msg = (MQTTClient_message*) malloc(sizeof(MQTTClient_message));
    return msg;
}
With the library the MqttClient class is used to manage a MQTT connection with a Message Broker (eg RabbitMQ - https://www.rabbitmq.com/ ), handle publishing/subscribing, and manages callbacks to various events. Below is an example:
Copy code
fun main(args: Array<String>) {
val mqttHost = args.last().split(":").first()
    val mqttPort = args.last().split(":").last().toUInt()
    val mqttClient = MqttClient(brokerUrl = "tcp://$host:$port")
val mqttConnOptions = MqttConnectionOptions()
    mqttClient.deliveryCompleteHandler = { println("Published message.") }
mqttClient?.connect(mqttConnOptions)

val msg = MqttMessage(payload = "Hello World! :)")
while (true) {
    mqttClient.publish(topic = "/greeting", msg = msg)
}
}
One thing that I forgot to mention earlier is that the library requires Kotlin 1.4.20 to be used in the project due to Kotlin Native not having backwards compatibility (at the moment). Lack of backwards compatibility with Kotlin Native will cause a bit of pain, and seems to create big problems with tooling.