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