Hi All,
AFAICT, I want to implement the following Perl call to XS code:
my (@ro,@wo,@eo) = nw_select(\@ri,\@wi,\@ei,$wait);
What I think I need is XS code to return the 3 LHS arrays or 'undef's as
appropriate. PerlXSTut Sample 7 seems a possible ideas source but alas
it is in the 'Coming soon' category at last check.
BACKGROUND
NetWare's fd_set struct is an FD_SETSIZE array of int's + a counter to
identify the last entry in the array, each int able to store a socket
handle. (NetWare select() does not work with file descriptors). This
means, AFAICT, it would be messy to patch the Perl pp_sselect code for
NetWare, so decided a separate XS module would better serve the task.
Based on Perl XS docs and the XS code in the Perl source, I have put the
following XS code together, although for simplicity and compactness here
will only include the 'can_read' array... Any feedback regarding the
correctness of the code so far is much appreciated, as the NetWare
debugger is just as 'unique' and I would like the best chance to only
have problems in the Perl code when I try getting this to work!
Lastly, based on Perl conventions, would the resulting module be more
appropriately named as IO::Select::NetWare or NetWare::Select, as I have
seen some Linux:: modules extant??
Now, finally, the XS code adapted/borrowed so far.
int
nw_select(reads, writes, errors, wtime)
SV* reads
SV* writes
SV* errors
SV* wtime
PREINIT:
NV value;
struct timeval timebuf;
struct timeval *tbuf = &timebuf;
SV *fd = NULL;
int numfds = 0;
int nfound = 0;
int i;
fd_set rdfds, wrfds, erfds;
fd_set *prds = NULL, *pwrs = NULL, *pers = NULL;
CODE:
/* Wait Time */
if (SvOK(wtime)) {
value = SvNV(wtime);
if (value < 0.0)
value = 0.0;
timebuf.tv_sec = (long)value;
value -= (NV)timebuf.tv_sec;
timebuf.tv_usec = (long)(value * 1000000.0);
}
else
tbuf = NULL;
/* Reads */
if ((SvROK(reads)) && (SvTYPE(SvRV(reads)) == SVt_PVAV)) {
prds = &rdfds;
FD_ZERO(prds);
while (av_len((AV*)reads) >= 0) {
if (rdfds.fd_count >= FD_SETSIZE)
croak("Too many sockets passed to NeWare::select(rd): Max ",
FD_SETSIZE);
fd = (SV*)av_shift((AV*)reads);
FD_SET(SvIV(fd), prds);
}
numfds += rdfds.fd_count;
}
[....]
/* Call LibC */
nfound = select( numfds + 1, prds, pwrs, pers, tbuf );
/* Reads */
if (prds == NULL) {
ST(0) = &PL_sv_undef;
} else {
ST(0) = newAV();
sv_2mortal((SV*)ST(0));
for (i = 0 ; i < rdfds.fd_count ; i++) {
sv_setpviv(fd, rdfds.fd_array[i]);
av_push(ST(0), fd);
}
}
Any and all feedback/comments welcome.
TIA,
Norm