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
-
XS to return Perl Arrays - and NetWare Select()
by NormW