Hello,
I'm trying to use the poll function of the ZMQ (version 4.2) binding. In C (and C++) you just pass an allocated array of zmq_pollitems_t and the length.
I tried doing the Nim equivalent :
var p1 = cast[ptr TPollItem](alloc0(2*sizeof(TPollItem))) # Allocate memory for 2 TPollItem object
var p2 = cast[ptr TPollItem](cast[int](p1) + cast[int](sizeof(TPollItem))) # Get the start adress of the second object
p1[] = TPollItem(socket: d1.s, events: ZMQ_POLLIN) # Write first in the memory adress
p2[] = TPollItem(socket: d2.s, events: ZMQ_POLLIN) # Write second object in the memory adress
var res : int = poll(p1, 2, 10000)
echo res
if res >= 0 :
var res1 = bitand(p1.revents, ZMQ_POLLIN.cshort)
var res2 = bitand(p2.revents, ZMQ_POLLIN.cshort)
echo "res1:", res1, " && res2:", res2
But it only works for the first TPollItem (i can swap the socket used in the TPollItem so I know it's not a connexion problem) and I never get a POLLIN flag set in p2.
Also, on the same subject, the Nim pollitem are defined as follow :
type
TPollItem*{.pure, final.} = object
socket*: PSocket
fd*: cint
events*: cshort
revents*: cshort
poller*: pointer
proc poll*(items: ptr TPollItem, nitems: cint, timeout: clong): cint{.
cdecl, importc: "zmq_poll", dynlib: zmqdll.}
What is the pointer poller ? In C it is just defined as a struct :
typedef struct
{
void* //socket//;
int //fd//;
short //events//;
short //revents//;
} zmq_pollitem_t;
int zmq_poll (zmq_pollitem_t *items, int nitems, long timeout);
Something like this:
type
TPollItem* = object
socket*: PSocket
fd*: cint
events*: cshort
revents*: cshort
poller*: pointer
proc poll*(items: ptr UncheckedArray[TPollItem], nitems: cint, timeout: clong): cint{.
cdecl, importc: "zmq_poll", dynlib: zmqdll.}
template asUncheckedArray(a): untyped = cast[ptr UncheckedArray[typeof(a[0])]](addr a[0])
var a: array[2, TPollItem]
a[0] = TPollItem(socket: d1.s, events: ZMQ_POLLIN)
a[1] = TPollItem(socket: d2.s, events: ZMQ_POLLIN)
# Poll on 2 element starting at adress p1
var res : int = poll(asUncheckedArray(a), 2, 10000)
echo res
if res >= 0 :
var res1 = bitand(p1.revents, ZMQ_POLLIN.cshort)
var res2 = bitand(p2.revents, ZMQ_POLLIN.cshort)
echo "res1:", res1, " && res2:", res2
Hi,
Thanks for the UncheckedArray trick to access underlying C-array.
asUncheckedArray will return a type :
ptr UncheckedArray[TPollItem]
I tried both :
var res : int = poll(asUncheckedArray(p)[0].addr, 2, 10000)
var res : int = poll(cast[ptr TPollItem](asUncheckedArray(p)), 2, 10000)
to get a ptr TPollItem back. Both gives me same result as the code I posted.
I also tried to define a poll function with UncheckedArray ptr parameters :
proc poll*(items: ptr UncheckedArray[TPollItem], nitems: cint, timeout: clong): cint{.
cdecl, importc: "zmq_poll", dynlib: zmqdll.}
var res : int = poll(asUncheckedArray(p), 2, -1)
In all those case, I only the first TPollItem is receiving data. If I try to receive manually data on the second connexion with no POLLIN flag set (since I know data is present in a trivial) I can receive the data normally.
Ah yes that was the cause of the problem.
I reported the bug here : https://github.com/nim-lang/nim-zmq/issues/14
I have a fork of nim-zmq where I added some examples, I can fix the problem and submit a Pull Request.