Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

comment on

( #3333=superdoc: print w/replies, xml ) Need Help??
Felow monks,

Recently I was working a lot with XS, rewriting Perl functions to C to get speed where I need, since I'm working into an image processing module. To make my life easy I have added some resources to my module Class::HPLOO, that I will share them to you now.

Everybody that have worked with XS knows that is not a friendly thing, specially if you need to receive in your C functions Perl variables and return complex structures like ARRAYs and HASHEs.

One thing that make life easier is Inline::C, but even with Inline we have the problem to work with the perlapi. Well, I'm not here to say that the perlapi is not good, I'm just saying that compared to a normal Perl code, work with Perl variables from C is not a easy thing.

To make the life of my developers easier I have added some extra resources to Class::HPLOO. Class::HPLOO is a framework that already make the declaration of Perl classes easier. With it we can declare a package with a syntax similar to Java declaration of classes:

use Class::HPLOO ; class Point[0.01] extends GeoForms { sub Point ($x , $y) { $this->{x} = $x ; $this->{y} = $y ; } sub move_x( $mv_x ) { $this->{x} += $mv_x ; } sub move_y( $mv_y ) { $this->{y} += $mv_y ; } }
The similar code with pure Perl of the class above is:
package Point ; use strict qw(vars) ; use vars qw(@ISA $VERSION) ; push(@ISA , qw(GeoForms)) ; $VERSION = '0.01' ; sub new { my $class = shift ; my $this = bless({} , $class) ; my ( $x , $y ) = @_ ; $this->{x} = $x ; $this->{y} = $y ; return $this ; } sub move_x { my $this = shift ; my $mv_x = shift ; $this->{x} += $mv_x ; } sub move_y { my $this = shift ; my $mv_y = shift ; $this->{y} += $mv_y ; } 1;
The code from here is already simplier than a normal Perl class what give to us time.

Now the XS part:

To enable XS directly from functions in the class declaration I have used Inline and this syntax:

use Class::HPLOO ; class Point { sub Point ($x , $y) { $this->{x} = $x ; $this->{y} = $y ; } sub move_x( $mv_x ) { $this->{x} += $mv_x ; } sub[C] void move_y( SV* self , int mv_y ) { SV* sv_y = *hv_fetch( (HV*)SvRV(self) , "y" , strlen("y") , 0) ; int y = SvIV(sv_y) + mv_y ; sv_setsv_mg(sv_y , sv_2mortal(newSViv(y)) ) ; } }
But as we can see, the C code with all the perlapi functions is a mess, since I need to make many calls just to access and store values in the object (self).

To "fix" that I have added a pseudo syntax, defined at Class::HPLOO::InlineC. And the function stay clean:

sub[C] void move_y( SV* self , int mv_y ) { int y = self->{y}->int + mv_y ; self->{y} = int2sv(y) ; }
Then I have added many other syntaxes for ARRAY, HASH, etc...:
sub[C] SV* get_xy_ref( SV* self ) { AV* ret = newAV() ; // create an array. ret->[0] = self->{x} ; // store at $ret[0], filling the array a +nd creating the new element. ret->[1] = self->{y} ; // store at $ret[1]. return \{ret} ; // return a reference to the array. }
The code above with pure C should be:
sub[C] SV* get_xy_ref( SV* self ) { SV* self_hv = (HV*) SvRV(self) ; SV* sv_x = *hv_fetch( self_hv , "x" , strlen("x") , 0 ) ; SV* sv_y = *hv_fetch( self_hv , "y" , strlen("y") , 0 ) ; AV* ret = newAV() ; av_fill(ret , 1) ; av_store(ret , 0 , newSV(0)) ; av_store(ret , 1 , newSV(0)) ; sv_setsv( *av_fetch(ret, 0 ,0) , sv_x ) ; sv_setsv( *av_fetch(ret, 1 ,0) , sv_y ) ; return newRV_inc( ret ) ; }
Well, who knows the perlapi will understand well what is writed in the code above, but if you have never used the perlapi and just knows the basics of C you will understand well the previous code with the new pseudo syntax.

Is easy to see what a new simple syntax can bring to the developer, since from a function of 10 lines with 16 calls we can write a clean function with 4 lines and 6 calls (1 new array, 2 fetch , 2 store , 1 ref returned). But note that the main idea is not 10 lines to 4 lines, but the work to write the functions, since until now I have used only simple FETCH and STORE operations as examples! So, we can see that any simple code that work with Perl variables using just pure XS is a hell!

Well, now I only can say enjoy! ;-P

Graciliano M. P.
"Creativity is the expression of liberty".

In reply to The easy way to write XS code and work with Perl varaibles directly from C. (New resources on Class::HPLOO). by gmpassos

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others chanting in the Monastery: (9)
    As of 2020-07-07 11:55 GMT
    Find Nodes?
      Voting Booth?

      No recent polls found