On 06/18/2017 08:10 PM, Steve Prior wrote:
> I've been playing more with the MQTT library for SWI-Prolog at
>
https://github.com/olsky/swi-mqtt-pack which does not appear
> to be actively maintained and have been able to publish and subscribe to
> MQTT messages. It looks like this repository bundles an old version of
> the mosquitto library which caused some problems with subscribe, but
> once I used an up to date library that problem went away - so far so good.
>
> One requirement I've got for my use of Prolog in my Smarthome system is
> to be able to pass binary blobs (actually images) around and I found
> this MQTT library doesn't work for that. Digging into the C code I've
> found that the author used PL_get_chars(topic, &mqtt_topic, CVT_WRITE |
> BUF_MALLOC) to copy from the term_t into the message buffer used for
> mosquitto - since PL_get_chars returns a null terminated string that's
> certainly not going to work for me. Since MQTT messages are binary
> blobs there should be another way.
Just replace that by PL_get_nchars() and you can represent blobs in
atoms, strings and lists of character codes. Just make sure all
`characters' are in the range 0..255. If one is higher it internally
switches to wide character arrays and it won't work any longer.
> To support the work I'm about to do I've forked the SWI MQTT pack on
> Github, my fork is at
https://github.com/sprior/swi-mqtt-pack. The
> code of interest is c/mqtt.c around lines 716-729. I know that binary
> blobs aren't explicitly supported by SWI-Prolog, but 10 years ago when I
> did this for CORBA Jan mentioned that Strings are internally stored as
> an array of unsigned chars, so binary data should actually work there,
> and it has - that's been working for 10 years! When I did it I wrote my
> code in C++, not C so it was a lot easier. The one problem I had at the
> time was how to determine the length of the char buffer, so I ended up
> doing it ont the Prolog side with string_length/2:
>
> filestore_storeFile(ServerMachine, Description, Mimetype, Contents):-
> string_length(Contents,Length),
> filestore_storeFile(ServerMachine, Description, Mimetype, Contents,
> Length).
So, see above. Might not have existed by then, but I doubt it. Just,
there is no C++ support for it. You can simply call the C API from
C++ though.
> filestore_storeFile was implemented in C++.
>
> So now with the MQTT code I'm looking at the code:
> where term_t payload;
> char* mqtt_payload;
> PL_get_chars(payload, &mqtt_payload, CVT_WRITE | BUF_MALLOC)
> mosq_rc = mosquitto_publish(m->mosq, &mid, mqtt_topic,
> strlen(mqtt_payload), mqtt_payload, qos, retain);
>
> Is it more correct to use
> int *PL_get_pointer*(term_t +t, void **ptr)
No no. PL_get_pointer() is only the inverse of PL_put_pointer(), which
allows storing a pointer as a Prolog integer. There is some logic in
there that changes the pointer representation such that it typically
becomes a small integer which is stored more efficiently in Prolog.
Its use is generally not encouraged these days.
> instead of PL_get_chars
> and is there any way to ask a term_t for its length to avoid the call to
> string_length in the Prolog wrapper?
See above.
Cheers --- Jan
> --
> You received this message because you are subscribed to the Google
> Groups "SWI-Prolog" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to
swi-prolog+...@googlegroups.com
> <mailto:
swi-prolog+...@googlegroups.com>.
> Visit this group at
https://groups.google.com/group/swi-prolog.
> For more options, visit
https://groups.google.com/d/optout.