jdv has asked for the wisdom of the Perl Monks concerning the following question:

I am taking my first steps into XS in order to wrap a C++ library. The library implements a rather specialized compression algorithm and can be found here. I've managed to implement and successfully test the bindings using ExtUtils::XSpp. However, right now the classes and methods are just bare stubs to the C++ counterparts, and I would like to be able to make the interface more "perlish" - e.g. instead of writing

my $reader = Compress::DSRC::Archive->new; my $seq = Compress::DSRC::FastqRecord->new; while ($reader->next_seq($seq)) { # do something with $seq }
I would like to write:
my $reader = Compress::DSRC::Archive->new; while (my $seq = $reader->next_seq) { # do something with $seq }

I have a lot to learn about XS and this may turn out to be a simple problem, but I would appreciate any examples or pointers to the relevant documentation (especially examples). Since this is a matter of interface rather than function it is not a high priority, but it would be nice to make the interface consistent with the most typical perl syntax. Thanks in advance for any help. A truncated snippet of my *.xsp file is below.

#include "Globals.h" #include "FastqRecord.h" #include "FastqFile.h" #include "DsrcModule.h" #include "DsrcArchive.h" #include "ns.h" %module{Compress::DSRC}; %loadplugin{feature::default_xs_typemap}; %name{Compress::DSRC::FastqRecord} class FastqRecord { %name{new} FastqRecord(); ~FastqRecord(); std::string tag %get %set; std::string sequence %get %set; std::string plus %get %set; std::string quality %get %set; }; %name{Compress::DSRC::Archive} class DsrcArchive { %name{new} DsrcArchive(); ~DsrcArchive(); %name{start_decompress} void StartDecompress(std::string& filename +_); %name{next_seq} bool ReadNextRecord(FastqRecord& rec_); %name{finish_decompress} void FinishDecompress(); [..truncated...] };

Replies are listed 'Best First'.
Re: "Perlifying" an XSpp method
by Anonymous Monk on Mar 08, 2015 at 23:35 UTC

    I would like to write: ...

    No you wouldn't :)

    The beauty of mirroring the C++ api is you're mirroring the C++ api -- its like the same API, same names, same usage (basically)

    If you want to change it, don't make it the same , same level of wordiness, same names, but with slightly different semantics, make it easy to use, like

    yippy( sub { my($seq ) = @_; warn $seq; } ); sub yippy { my( $do_something ) = @_; my $reader = Compress::DSRC::Archive->new; my $seq = Compress::DSRC::FastqRecord->new; while ($reader->next_seq($seq)) { $do_something( $seq ); } }

    I have a lot to learn about XS ...

    :) Avoid XS as much as possible, unless you want to learn a lot about XS instead of just getting on with whatever task you have to complete :)

      The beauty of mirroring the C++ api is you're mirroring the C++ api -- its like the same API, same names, same usage (basically)

      Well, fair enough. This way of "recycling" the FastqRecord object seems awkward in an otherwise OO module (at least to someone who learned Perl first and only later delved into C/C++). I do see your point, however - sticking as close as possible to the C++ API probably has the least potential for confusion and will be easiest to maintain.

      Avoid XS as much as possible, unless you want to learn a lot about XS instead of just getting on with whatever task you have to complete

      That is advice that I have no problem embracing.

      If you still want the sameness, you can do like this

      sub Compress::DSRC::Archive::NextSeq { my( $reader ) = @_; my $seq = Compress::DSRC::FastqRecord->new; return $seq if $reader->next_seq($seq) return undef; }
        Thanks for this suggestion. I'm not sure why I didn't think of doing this in the Perl class rather than mucking about in the XS.