I wanted to send/receive MQTT messages from Perl. For various reasons (MQTT 5 support, TLS) I don't want to use existing Perl libraries. So I tried to create XS bindings to Paho MQTT C Library. I somehow adapted provided example to link Perl module to Paho library using relly basic Perl XS:
#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <MQTTClient.h>
#define CLIENTID "ExampleClientPub"
#define QOS 1
#define TIMEOUT 10000L
MODULE = paho PACKAGE = paho
int
mqtt_connect_and_send (server_address, username, topic, payload)
char * server_address
char * username
char * topic
char * payload
CODE:
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_message msg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
int rc;
/* connect to server */
MQTTClient_create(&client, server_address, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.username = username;
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
/* didn't connect */
die("Failed to connect, return code %d", rc);
}
/* fill in message data and send it */
msg.payload = payload;
msg.payloadlen = strlen(payload);
msg.qos = QOS;
msg.retained = 0;
MQTTClient_publishMessage(client, topic, &msg, &token);
rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
/* shutdown connection */
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
if (rc != MQTTCLIENT_SUCCESS) {
/* didn't send the message */
die("Failed to send message, return code %d", rc);
}
RETVAL = 1;
OUTPUT:
RETVAL
This is working OK. But now I want to split function mqtt_connect_and_send
to 3 functions: mqtt_connect
, mqtt_send_message
, mqtt_disconnect
. And my question is - how to do this? How to create a handle (client
in my case) in XS in one function, return it to Perl to somehow store it in a scalar and use that handle in ahother XS function to be used to send more messages? I want to be able to do this in Perl:
my $client = paho::mqtt_connect($server_spec, $username, $password, $more_opts);
$success = paho::mqtt_send($client, $data, $message_opts);
# ... more of mqtt_send's
paho::mqtt_disconnect($server)
I tried to set RETVAL RETVAL = &client
or mXPUSHu(&client)
but that I didn't get anywhere with that. Can you point me to some example how to get client
to Perl and then back to XS to be used again?
Thank you.