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

Reply via email to