I'm still busy trying to get MQTT (using Mosquitto MQTT) running for me in Scheme. I have the following code, and this works fine when compiling.
Note, that I have defined the `on_message` callback as external, so basically a C function in the end. This forces me to use this code compiled.
Ideally, in a next step, I'd like to put everything into a Chicken module in a way that will also be usable in the interpreter. Therefore my question:
What would I have to do to be able to use pure Scheme functions as callbacks here?
Any hint and help appreciated ...
;; csc -I /usr/include -L "-l mosquitto" mqtt.scm
(import (chicken memory))
(import (chicken blob))
(import bind)
(bind-rename/pattern "_" "-")
(bind* "struct mosquitto_message{
int mid;
char *topic;
void *payload;
int payloadlen;
int qos;
___bool retain;
};")
(bind* "int mosquitto_lib_init();")
(bind* "int mosquitto_lib_cleanup();")
(bind* "int mosquitto_lib_version(___out int *major,
___out int *minor,
___out int *revision);")
(bind* "struct mosquitto *mosquitto_new(const char *id,
___bool clean_session,
void *obj);")
(bind* "void mosquitto_destroy(struct mosquitto *mosq);")
(bind* "int mosquitto_connect(struct mosquitto *mosq,
const char *host,
int port,
int keepalive);")
(bind* "int mosquitto_publish(struct mosquitto *mosq,
___out int *mid,
const char *topic,
___length(payload) int payloadlen,
___blob payload /* const void *payload */,
int qos,
___bool retain);")
(bind* "___safe int mosquitto_loop(struct mosquitto *mosq, int timeout, int max_packets);")
(bind* "___safe int mosquitto_loop_forever(struct mosquitto * mosq, int timeout, int max_packets);")
(bind* "int mosquitto_subscribe(struct mosquitto *mosq,
int *mid,
const char *sub,
int qos);")
(bind* "int mosquitto_unsubscribe(struct mosquitto *mosq,
int *mid,
const char *sub);")
;; setting callbacks
(bind* "void mosquitto_connect_callback_set(struct mosquitto *mosq,
void (*on_connect)(struct mosquitto *, void *, int));")
;;(bind* "mosquitto_disconnect_callback_set")
;;(bind* "mosquitto_publish_callback_set")
;; NB: the last type of return value in the vallback is 'const struct *' according
;; to mosquitto.h; however, it seems impossible to encode this in the
;; Scheme callback function using combinations of 'c-pointer' and 'const'
(bind* "void mosquitto_message_callback_set(struct mosquitto *mosq,
void (*on_message)(struct mosquitto *,
void *,
struct mosquitto_message *));")
;;(bind* "mosquitto_subscribe_callback_set")
;;(bind* "mosquitto_unsubscribe_callback_set")
;;(bind* "mosquitto_log_callback_set")
(mosquitto-lib-init)
(display (mosquitto-lib-version))
;; on-connect callback
(define-external (on_connect ((c-pointer "struct mosquitto") mosq)
((c-pointer void) userdata)
(int returncode))
void
(begin
(display "connected to broker ... returncode: ")
(display returncode)
(newline)))
;; on-message callback
(define-external (on_message ((c-pointer "struct mosquitto") mosq)
((c-pointer void) userdata)
((c-pointer "struct mosquitto_message") msg))
void
(let* ((len (mosquitto-message-payloadlen msg))
(*payload (mosquitto-message-payload msg))
(payload (make-blob len))
(mid (mosquitto-message-mid msg))
(topic (mosquitto-message-topic msg))
(qos (mosquitto-message-qos msg))
(retain (mosquitto-message-retain msg))
;; int mid; char* topic; int qos; bool retain
)
(if (> len 0)
(move-memory! *payload payload len))
(display "Wow! ... there was a message!\n")
(display (blob->string payload)) (newline)
(display retain)
(newline)))
(let-values (((res major minor revision) (mosquitto-lib-version)))
(display major) (newline)
(display minor) (newline)
(display revision) (newline))
;; #f is equivalent to C's NULL
(define mqttc (mosquitto-new #f #t #f))
(display "mqtt client address\n")
(display mqttc) (newline)
(mosquitto-connect-callback-set mqttc #$on_connect)
(mosquitto-message-callback-set mqttc #$on_message)
(display "connect to broker\n")
(display (mosquitto-connect mqttc "localhost" 1883 60))
(newline)
(mosquitto-subscribe mqttc #f "greetings/#" 0)
(define payload (string->blob "gluck, gluck!"))
(mosquitto-publish mqttc "chicken/call" payload 0 #f)
(let loop ()
(mosquitto-loop mqttc -1 1)
(loop))
;;(mosquitto-loop-forever mqttc -1 1)
;; (mosquitto-loop mqttc -1 1)
(mosquitto-destroy mqttc)
(mosquitto-lib-cleanup)