On 2015-03-06 02:00, Matt Gushee wrote:
> [...]
> Another issue with message length is whether there should be a default
> value. There is a Scheme function that generates a buffer for both
> sending and receiving functions.
> [...]
Hello,
for sending, I wouldn't allocate a separate buffer but just pass a
pointer to the contents of a string or blob and the length of the
container to the C function.
For receiving, however, there is no way to know how large the buffer
must be without also knowing the application level protocol. Since
CHICKEN is a high level language, I would try to avoid choosing an
arbitrary buffer size or even forcing the programmer to specify some
specific buffer size, since this could lead to memory overflow errors.
I would recommend to use the zmq_msg_init and zmq_msg_recv functions to
receive a message of arbitrary length and leave the allocation problems
to 0MQ, then you can extract the actual data and its length from the
message object using zmq_msg_data and zmq_msg_size. This approach is
somewhat less efficient than receiving into a prepared buffer, but it is
much easier to implement correctly.
For efficiency, you could provide an alternative API where the
programmer passes in a buffer and optional length that would receive the
message, but that API should definitely perform bounds checking.
Everything could be wrapped into a binding like this (beware, this code
snippet is completely untested):
(define (zmq-recv sock #!optional buf ofs len)
(if buf
(let* ((ofs (or ofs 0))
(len
(cond
((string? buf)
(let ((len (or len (- (string-length buf) ofs))))
(assert (and (<= 0 ofs)
(< (+ ofs len) (string-length buf))))
len))
((blob? buf)
(let ((len (or len (- (blob-size buf) ofs))))
(assert (and (<= 0 ofs)
(< (+ ofs len) (blob-size buf))))
len))
(else
(error 'zmq-recv "unknown buffer type")))))
(if (negative?
((foreign-lambda* int ((c-pointer sock)
(scheme-pointer buf)
(size_t ofs) (size_t len)
(int flags))
"C_return(zmq_recv("
" sock, ((char *)buf) + (ptrdiff_t)ofs, len"
"));")
sock buf ofs len 0))
(error 'zmq-recv "receive failed")
buf))
(let ((msg
(make-blob (foreign-value "sizeof(zmq_msg_t)" size_t))))
(if (negative?
((foreign-lambda int "zmq_msg_init" scheme-pointer) msg))
(error 'zmq-recv "failed to initialize message")
(set-finalizer!
msg (foreign-lambda int "zmq_msg_close" scheme-pointer)))
(if (negative?
((foreign-lambda int "zmq_msg_recv"
scheme-pointer scheme-pointer int)
msg socket 0))
(error 'zmq-recv "receive failed")
(let* ((len
((foreign-lambda size_t "zmq_msg_size"
scheme-object)
msg))
(buf (make-blob len)))
(move-memory!
((foreign-lambda c-pointer "zmq_msg_data" scheme-object)
msg)
buf len)
buf)))))
I hope this helps :-)
Ciao,
Thomas
--
When C++ is your hammer, every problem looks like your thumb.
_______________________________________________
Chicken-users mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/chicken-users