http://qs321.pair.com?node_id=437318

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".