[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Chicken-users] FFI and callbacks -- in Scheme?!

From: Christoph Lange
Subject: [Chicken-users] FFI and callbacks -- in Scheme?!
Date: Mon, 13 May 2019 11:07:07 +0200

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")
(display (mosquitto-lib-version))
;; on-connect callback
(define-external (on_connect ((c-pointer "struct mosquitto") mosq)
             ((c-pointer void) userdata) 
             (int returncode))
   (display "connected to broker ... returncode: ")
   (display returncode)
;; on-message callback
(define-external (on_message ((c-pointer "struct mosquitto") mosq)
     ((c-pointer void) userdata)
     ((c-pointer "struct mosquitto_message") msg))
  (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)
(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))
(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)
;;(mosquitto-loop-forever mqttc -1 1)
;; (mosquitto-loop mqttc -1 1)
(mosquitto-destroy mqttc)

Christoph Lange
Lotsarnas Väg 8
430 83 Vrångö

reply via email to

[Prev in Thread] Current Thread [Next in Thread]