Re: XS to return Perl Arrays - and NetWare Select()

2011-06-11 Thread NormW

G/Morning,
On 11/06/2011 10:27 AM, mich...@insulin-pumpers.org wrote:

Take a look on CPAN at the C + macros code as well as the XS code in
Net::Interface in the xs module.

Thanks!
 Look at places that use PUSH or

XPUSH that return a variety of references. hv's, av's, etc...
examples of each type and their manipulation can be found in both the
xs and C modules found in the distro directory.

How many items you push on the stack before returning is up to your
code.

Yep... thought as much from the XS docs.
Will capsule where I'm up to in a following mail.
Norm


Re: XS to return Perl Arrays - and NetWare Select()

2011-06-11 Thread NormW

G/Morning All
Lights sometimes come on very slowly.
In addition to tweaking XS code to NetWare's select() to work (more 
anon) (finally) realised that IO::Select::INET was returning was an 
object and not the socket needed for select() (Doh!).


On the the XS problem that began here have (ftm) settled on the code as 
follows as (atm) it at least doesn't give NetWare abends (== segfault).
NetWare's loadable modules have pre-defined (at build) stack space and 
pushing objects of largely unknown size onto the stack can break things.



sub can_read # Adapted from IO::Select
{
  my $vec  = shift;
  my $wait = shift;
  my @r= $vec-handles;

  nw_select(\@r,undef,undef,$wait);

  @r;
}


Perl
--
XS

  /* Read Param array into int array */
  if ((SvROK(reads))  (SvTYPE(SvRV(reads)) == SVt_PVAV)) {
prda = (AV*) SvRV(reads);
prds = rdfds;
FD_ZERO(prds);
while (av_len((AV*)prda) = 0) {
  if (rdfds.fd_count = FD_SETSIZE)
croak(Too many sockets passed to NeWare::select(rd): Max , 
FD_SETSIZE);
  fd = (SV*)av_shift((AV*)prda);
  FD_SET(SvIV(fd), prds);
}
numfds += rdfds.fd_count;
  }

[...]

  /* Read int array and push back to Param array - int array always = Param */
  if (prds != NULL) {
av_clear((AV*)prda);
for (i = 0 ; i  rdfds.fd_count ; i++) {
  sv_setpviv(fd, rdfds.fd_array[i]);
  av_push((AV*)prda, fd);
}
  }


Modifying parameters is a computing 'taboo' so will return to stack 
passing return after I can get sockets out of ::INET and can find out 
how big the AV's are on the stack... unless the Sample 7 code comes by 
sooner. :-)


Thanks for the time and ideas.
FTM,
Norm


Re: XS to return Perl Arrays - and NetWare Select()

2011-06-09 Thread Brandon McCaig
On Wed, Jun 8, 2011 at 7:11 PM, NormW no...@gknw.net wrote:
 AFAICT, I want to implement the following Perl call to XS code:

 my (@ro,@wo,@eo) = nw_select(\@ri,\@wi,\@ei,$wait);

Perhaps you meant:

my ($ro, $wo, $eo) = nw_select(\@ri, \@wi, \@ei, $wait);

That is, instead of getting three arrays returned, getting three array
/references/ returned. The first is valid Perl, but it probably
doesn't do what you intended since the first array would get all of
the values returned by nw_select and the second two arrays would
always be empty.

bash $ perl -e 'EOF'
use strict;
use warnings;

use Data::Dumper;

sub example
{
my @first = (1..3);
my @second = (4..6);
my @third = (7..9);

return @first, @second, @third;
}

my (@first, @second, @third) = example;

print Dumper \@first, \@second, \@third;
EOF
$VAR1 = [
  1,
  2,
  3,
  4,
  5,
  6,
  7,
  8,
  9
];
$VAR2 = [];
$VAR3 = [];
bash $

See `perldoc perlsub` for details.

I'm afraid that I'm lurking here to try to learn XS by example so I
can't help with the XS implementation. :) Good luck.


-- 
Brandon McCaig http://www.bamccaig.com/ bamcc...@gmail.com
V zrna gur orfg jvgu jung V fnl. Vg qbrfa'g nyjnlf fbhaq gung jnl.
Castopulence Software http://www.castopulence.org/ bamcc...@castopulence.org


Re: XS to return Perl Arrays - and NetWare Select()

2011-06-09 Thread Josh Goldberg
What I do is something like

AV *results;
results = newAV();

something = (AV *)SvRV(*other_av_thing);

av_store(results,i, something);

RETVAL = results;
sv_2mortal((SV *)RETVAL);

On Wed, Jun 8, 2011 at 4:11 PM, NormW no...@gknw.net wrote:
 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 * 100.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




Re: XS to return Perl Arrays - and NetWare Select()

2011-06-09 Thread NormW

G/Morning,
On 10/06/2011 4:36 AM, Josh Goldberg wrote:

What I do is something like

AV *results;
results = newAV();

something = (AV *)SvRV(*other_av_thing);

av_store(results,i, something);

RETVAL = results;
sv_2mortal((SV *)RETVAL);
Have seen that method in several XS programs (and PerlXSTut iirc) but it 
is unclear if that works when 3 elements are to be returned; will have a 
closer look at the Perl XS docs...

Thx,
Norm