Я хотел отправлять/получать сообщения MQTT из Perl. По разным причинам (поддержка MQTT 5, TLS) я не хочу использовать существующие библиотеки Perl. Поэтому я попытался создать привязки XS к Paho MQTT C Library а>. Я каким-то образом адаптировал приведенный пример, чтобы связать модуль Perl с Библиотека Paho, использующая базовый 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
Это работает нормально. Но теперь я хочу разделить функцию mqtt_connect_and_send
на 3 функции: mqtt_connect
, mqtt_send_message
, mqtt_disconnect
. И у меня вопрос - как это сделать? Как создать дескриптор (в моем случае client
) в XS в одной функции, вернуть его в Perl, чтобы каким-то образом сохранить его в скаляре и использовать этот дескриптор в другой функции XS для отправки большего количества сообщений? Я хочу иметь возможность сделать это в 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)
Я пытался установить RETVAL RETVAL = &client
или mXPUSHu(&client)
, но ничего не добился. Можете ли вы указать мне на какой-нибудь пример, как перевести client
в Perl, а затем обратно в XS для повторного использования?
Спасибо.
client
имеет автоматическое хранилище (в основном, в стеке), что означает, что доступ к нему возможен только во время выполнения функции. Вам нужно будет динамически выделить его. - person ikegami   schedule 29.07.2020client = (MQTTClient *) malloc(sizeof(MQTTClient));
...использование...free(client);
? Деструктор: Часть Perl я понимаю. Я просто не знаю, как перевести этотclient
из XS в Perl. Возврат через RETVAL? Прагмы нижнего регистра: Первоначально в моем доказательстве концепции я использовал однобуквенную букву «p» в качестве имени :) Изменится в пригодной для использования версии. - person ico   schedule 29.07.2020server_address
? Укажите некоторые значения, которые мы можем протестировать. - person Håkon Hægland   schedule 29.07.2020make
d. Затем я создал пакет для своего Slackware Linux и установил библиотеки в/usr/lib64
, а заголовки в/usr/include
. Простой тестовый исходный код компилируется и работает нормально. - person ico   schedule 30.07.2020$rv = paho::mqtt_connect_and_send("tcp://127.0.0.1:1883","username","topic",scalar(localtime));
E.g. У меня есть локальный сервер MQTT (mosquitto), работающий по петле. Я начал с простого TCP, без паролей. Когда мои привязки Perl станут пригодными для использования, я, конечно же, перейду на TLS, ACL и установку mosquitto нашей компании. - person ico   schedule 30.07.2020cd paho.mqtt.c; make; cd build/output
, а затем сохранил пример синхронного клиента вclient.c
. Скомпилировал:gcc -I../../src -L. -lpaho-mqtt3c -o client client.c
и запустил:LD_LIBRARY_PATH=. ./client
. Может быть, это можно было бы сделать и для тестирования XS... - person ico   schedule 30.07.2020perl
, может не сработать. Если вы собираетесь выпустить это на CPAN, вы можете подумать о создании копии специально для Perl. IIRC, XML::LibXML делает это (но я думаю, что это библиотека C++). Некоторые примеры, вероятно, можно найти в Alien::* - person ikegami   schedule 31.07.2020