|
8 months ago | |
---|---|---|
.github/workflows | 8 months ago | |
test | 3 years ago | |
.gitignore | 6 years ago | |
CHANGELOG.md | 1 year ago | |
EXPLAIN.md | 5 years ago | |
LICENSE | 8 months ago | |
Makefile | 1 year ago | |
README.md | 8 months ago | |
build.sh | 5 years ago | |
module.l | 8 months ago | |
nanomsg.l | 8 months ago | |
test.l | 3 years ago |
Nanomsg FFI bindings for PicoLisp.
The following protocols are supported:
v17.12+
v20.6.29
, see test runsTo learn more about PicoLisp and this Nanomsg library, please read the EXPLAIN.md document.
This binding relies on the Official Nanomsg C Library, compiled as a shared library.
make
to pull and compile the Official Nanomsg C Library.nanomsg.l
in your projectOnce compiled, the shared library is symlinked as:
.lib/libnanomsg.so -> .modules/nanomsg/HEAD/libnanomsg.so
The nanomsg.l
file searches for .lib/libnanomsg.so
, relative to its current directory.
To keep everything updated, type:
git pull && make clean && make
Only the following functions are considered public
:
protocol-bind
: bind a REP, PUB, BUS, PAIR, PULL, or SURVEYOR
socket (inproc, ipc, tcp)protocol-connect
: connect to a REQ, SUB, BUS, PAIR, PUSH, RESPONDENT
socket (inproc, ipc, tcp)end-sock
: shutdown and close a socketmsg-recv
: receive a message (blocking/non-blocking)msg-send
: send a message (blocking/non-blocking)subscribe
: subscribe to a PUB/SUB
topicunsubscribe
: unsubscribe from a PUB/SUB
topicNote: These functions are not namespace local symbols, which means they would redefine symbols with the same name in the
'pico
namespace.
When an error occurs, 'InternalError
is thrown, along with the error (error type in car
, message in cdr
). The error will also be returned by the (catch)
expression. Ensure your (catch)
ends with NIL
.
pil +
(load "nanomsg.l")
(let Error
(catch 'InternalError
(protocol-bind "REP" "tcpz://127.0.0.1:5560" "AF_SP_RAW")
(prinl "you shouldn't see this") NIL)
(when Error (println @)) )
-> (NanomsgError . "Protocol not supported")
pil +
(load "nanomsg.l")
(unless (fork)
(let Sockpair
(protocol-bind "REP" "tcp://127.0.0.1:5560")
(prinl (msg-recv (car Sockpair)))
(msg-send (car Sockpair) "Yep I can see it!" T) # non-blocking
(end-sock Sockpair) )
(bye) )
# => Can you see this?
pil +
(load "nanomsg.l")
(unless (fork)
(let Sockpair
(protocol-connect "REQ" "tcp://127.0.0.1:5560")
(msg-send (car Sockpair) "Can you see this?")
(prinl (msg-recv (car Sockpair)))
(end-sock Sockpair) )
(bye) )
# => Yep I can see it!
pil +
(load "nanomsg.l")
(unless (fork)
(let Sockpair
(protocol-connect "SUB" "tcp://127.0.0.1:5560")
(subscribe (car Sockpair) "test")
(while T (prinl "RECEIVED: " (msg-recv (car Sockpair))) (wait 1000 (unsubscribe 0 "test")))
(end-sock Sockpair) )
(bye) )
# => RECEIVED: test Hello World!
pil +
(load "nanomsg.l")
(let Sockpair
(protocol-bind "PUB" "tcp://127.0.0.1:5560")
(while T (msg-send (car Sockpair) "test Hello World!"))
(end-sock Sockpair) )
pil +
(load "nanomsg.l")
(unless (fork)
(let Sockpair
(protocol-connect "BUS" "tcp://127.0.0.1:5560")
(prinl (msg-recv (car Sockpair)))
(end-sock Sockpair) )
(bye) )
# => Hello World!
pil +
(load "nanomsg.l")
(unless (fork)
(let Sockpair
(protocol-bind "BUS" "tcp://127.0.0.1:5560")
(msg-send (car Sockpair) "Hello World!")
(end-sock Sockpair) )
(bye) )
pil +
(load "nanomsg.l")
(unless (fork)
(let Sockpair
(protocol-connect "PAIR" "tcp://127.0.0.1:5560")
(prinl (msg-recv (car Sockpair)))
(end-sock Sockpair) )
(bye) )
# => Hello World!
pil +
(load "nanomsg.l")
(unless (fork)
(let Sockpair
(protocol-bind "PAIR" "tcp://127.0.0.1:5560")
(prinl (msg-send (car Sockpair) "Hello World!"))
(end-sock Sockpair) )
(bye) )
pil +
(load "nanomsg.l")
(unless (fork)
(let Sockpair
(protocol-bind "PULL" "tcp://127.0.0.1:5560")
(prinl (msg-recv (car Sockpair)))
(end-sock Sockpair) )
(bye) )
# => Hello Pipeline
pil +
(load "nanomsg.l")
(unless (fork)
(let Sockpair
(protocol-connect "PUSH" "tcp://127.0.0.1:5560")
(prinl (msg-send (car Sockpair) "Hello Pipeline"))
(end-sock Sockpair) )
(bye) )
Note: The Surveyor protocol in Nanomsg is buggy, it's possible for this not to work as expected.
pil +
(load "nanomsg.l")
(unless (fork)
(let Sockpair (protocol-bind "SURVEYOR" "tcp://127.0.0.1:5560")
(msg-send (car Sockpair) "Knock knock.")
(prinl (msg-recv (car Sockpair)))
(end-sock Sockpair) )
(bye) )
# => Who's there?
pil +
(load "nanomsg.l")
(unless (fork)
(let Sockpair
(protocol-connect "RESPONDENT" "tcp://127.0.0.1:5560")
(prinl (msg-recv (car Sockpair)))
(msg-send (car Sockpair) "Who's there?")
(end-sock Sockpair) )
(bye) )
# => Knock knock.
Some situations require non-blocking I/O. You can call msg-recv
or msg-send
with a last argument T
to enable non-blocking mode. Be aware NIL
will be returned if EAGAIN
is received during a non-blocking call. You need to manually poll/loop over the socket in this situation.
Usage example:
...
(let Msg (msg-recv (car Sockpair) T)
(when Msg (fifo '*Messages Msg)) )
...
A fixed amount of memory is allocated for each receive buffer. The default setting is 8192
Bytes (8 KiB).
This can be changed with the environment variable NANOMSG_MAX_SIZE
. You can also overwrite the MSG_MAX_SIZE
global constant at runtime.
This library now comes with full unit tests. To run the tests, type:
make check
If you find any bugs or issues, please create an issue.
If you want to improve this library, please make a pull-request.
MIT License Copyright (c) 2015-2020 Alexander Williams, Unscramble license@unscramble.jp