develooper Front page | perl.xs | Postings from June 2011

XS to return Perl Arrays - and NetWare Select()

Thread Next
From:
NormW
Date:
June 8, 2011 16:12
Subject:
XS to return Perl Arrays - and NetWare Select()
Message ID:
4DF001AA.4020505@gknw.net
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


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About