XS to return Perl Arrays - and NetWare Select()

[email protected] (NormW)
Newsgroups perl.xs
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.