The Perl API for the Mortally Terrified

161
The Perl API for the Mortally Terrified Mike Friedman YAPC::NA 2014 Orlando, FL @friedo

description

https://www.youtube.com/watch?v=-XITNDvqoTo Have you ever wanted to learn the secrets of the dark masters of Perl? Ever been curious about what an *SV is? Maybe you just want to make a subroutine really, really fast, but you're terrified of this thing called XS that stands in your way. This talk presents the Perl API for beginners from the ground up, explaining everything you need to know to get started hacking Perl in C. XS is not required, as the examples use the much smarter Inline module to get right at the core API with nothing in the way.

Transcript of The Perl API for the Mortally Terrified

Page 1: The Perl API for the Mortally Terrified

The Perl APIfor the

Mortally Terrified

Mike Friedman

YAPC::NA 2014

Orlando, FL

@friedo

Page 2: The Perl API for the Mortally Terrified

This talk is the product of a lengthy journey.

Page 3: The Perl API for the Mortally Terrified

The Perl APIWhat’s it good for?

Page 4: The Perl API for the Mortally Terrified

The Perl APIWhat’s it good for?

Make things fast:

Page 5: The Perl API for the Mortally Terrified

The Perl APIWhat’s it good for?

Make things fast: - Write your slow Perl code in C

Page 6: The Perl API for the Mortally Terrified

The Perl APIWhat’s it good for?

Make things fast: - Write your slow Perl code in C - Keep your fast Perl code in Perl

Page 7: The Perl API for the Mortally Terrified

The Perl APIWhat’s it good for?

Make Perl more useful:

Page 8: The Perl API for the Mortally Terrified

The Perl APIWhat’s it good for?

Make Perl more useful: - Interface with libraries written in C

Page 9: The Perl API for the Mortally Terrified

The Perl APIWhat’s it good for?

Make Perl more useful: - Interface with libraries written in C - Create modules exposing external APIs to Perl

Page 10: The Perl API for the Mortally Terrified

The Perl APIWhat’s it good for?

Make Perl do...stuff

Page 11: The Perl API for the Mortally Terrified

The Perl APIWhat’s it good for?

Make Perl do...stuff - Change opcodes on the fly?

Page 12: The Perl API for the Mortally Terrified

The Perl APIWhat’s it good for?

Make Perl do...stuff - Change opcodes on the fly? - Extend the parser?

Page 13: The Perl API for the Mortally Terrified

The Perl APIWhat’s it good for?

Make Perl do...stuff - Change opcodes on the fly? - Extend the parser? - Make exceptions work?

Page 14: The Perl API for the Mortally Terrified

The Perl APIWhat’s it good for?

Make Perl do...stuff - Change opcodes on the fly? - Extend the parser? - Make exceptions work? - Why not?

Page 15: The Perl API for the Mortally Terrified

The Perl APIWhat’s it good for?

Make Perl do...stuff - Change opcodes on the fly? - Extend the parser? - Make exceptions work? - Why not?

Page 16: The Perl API for the Mortally Terrified

XS

Page 17: The Perl API for the Mortally Terrified

What is XS?

perldoc perlxs:

XS is an interface description file format used to create an extension interface between Perl and C code (or a C library) which one wishes to use with Perl. The XS interface is combined with the library to create a new library which can then be either dynamically loaded or statically linked into perl. The XS interface description is written in the XS language and is the core component of the Perl extension interface.

Page 18: The Perl API for the Mortally Terrified
Page 19: The Perl API for the Mortally Terrified

XS is a specialized templating language for C.

Page 20: The Perl API for the Mortally Terrified

Some XS Code

Page 21: The Perl API for the Mortally Terrified

Some XS Code

XS Directives

Page 22: The Perl API for the Mortally Terrified

Some C Code made by xsubpp

Page 23: The Perl API for the Mortally Terrified

XS != Perl API

Page 24: The Perl API for the Mortally Terrified

For most things

Page 25: The Perl API for the Mortally Terrified

For most things

You don't actuallyhave to use XS.

Page 26: The Perl API for the Mortally Terrified

(OK. You don’t have to know that you’re using it.)

Page 27: The Perl API for the Mortally Terrified

Inline::C

Page 28: The Perl API for the Mortally Terrified

use Inline C;hello('Mike');hello('Cookie Monster');

__END__

__C__void hello(char* name) {  printf("Hello %s!\n", name);}

Page 29: The Perl API for the Mortally Terrified

use Inline C;hello('Mike');hello('Grover');

__END__

__C__void hello(char* name) {  printf("Hello %s!\n", name);}

Page 30: The Perl API for the Mortally Terrified

use Inline C;hello('Mike');hello('Grover');

__END__

__C__void hello(char* name) {  printf("Hello %s!\n", name);}

Page 31: The Perl API for the Mortally Terrified

use Inline C;hello('Mike');hello('Grover');

__END__

__C__void hello(char* name) {  printf("Hello %s!\n", name);}

Page 32: The Perl API for the Mortally Terrified

Inline::C Code in Perl

Page 33: The Perl API for the Mortally Terrified

Inline::C Code in Perl

Digest::MD5

Page 34: The Perl API for the Mortally Terrified

Inline::C Code in Perl

Digest::MD5

C Code Parse::RecDescent

Page 35: The Perl API for the Mortally Terrified

Inline::C Code in Perl

Digest::MD5

Create build in a temp dir

C Code Parse::RecDescent

Page 36: The Perl API for the Mortally Terrified

Inline::C Code in Perl

Digest::MD5

Create build in a temp dir

C Code Parse::RecDescent

Write XS

Page 37: The Perl API for the Mortally Terrified

Inline::C Code in Perl

Digest::MD5

Create build in a temp dir

C Code Parse::RecDescent

Write XS

Compile and install

Page 38: The Perl API for the Mortally Terrified

Inline::C Code in Perl

Digest::MD5

Create build in a temp dir

C Code Parse::RecDescent

Write XS

Compile and install

Page 39: The Perl API for the Mortally Terrified

How do we make Perl do stuff in C?

Page 40: The Perl API for the Mortally Terrified

How do we make Perl do stuff in C?

We need to understand Perl’s data structures.

Page 41: The Perl API for the Mortally Terrified

Handwaving Ahead

Page 42: The Perl API for the Mortally Terrified

A $scalar in Perl is represented by a struct called SV.

SvNULL

SvRV SvNVSvPV SvIV

(These are not all of them.)

Page 43: The Perl API for the Mortally Terrified

What does SV look like?

ANY

Page 44: The Perl API for the Mortally Terrified

What does SV look like?

Points to a struct with the scalar's metadata.

ANY

Page 45: The Perl API for the Mortally Terrified

What does SV look like?

Page 46: The Perl API for the Mortally Terrified

What does SV look like?

REFCNT

Page 47: The Perl API for the Mortally Terrified

What does SV look like?

Reference count for garbage collection

REFCNT

Page 48: The Perl API for the Mortally Terrified

What does SV look like?

Page 49: The Perl API for the Mortally Terrified

What does SV look like?

FLAGS TYPE

Page 50: The Perl API for the Mortally Terrified

What does SV look like?

Flags and type information

FLAGS TYPE

Page 51: The Perl API for the Mortally Terrified

What does SV look like?

Page 52: The Perl API for the Mortally Terrified

What does SV look like?

SV_U

Page 53: The Perl API for the Mortally Terrified

What does SV look like?

Points to a union with the actual scalar's data

SV_U

Page 54: The Perl API for the Mortally Terrified

What does SV look like?

Page 55: The Perl API for the Mortally Terrified

What does SV look like?

Page 56: The Perl API for the Mortally Terrified

What does SV look like?

The simplest scalar:undef

Page 57: The Perl API for the Mortally Terrified

What does SV look like?

The simplest scalar:undef

The "ANY" pointer is NULL, and TYPE is zero.

Page 58: The Perl API for the Mortally Terrified

undef is, like, totes boring.

Page 59: The Perl API for the Mortally Terrified

What about strings?

Page 60: The Perl API for the Mortally Terrified

What does SV look like?

Page 61: The Perl API for the Mortally Terrified

What does SV look like?

Strings

Page 62: The Perl API for the Mortally Terrified

What does SV look like?

Strings

"ANY" points to a "xpv", and TYPE is 4. *

* in Perl 5.20.

Page 63: The Perl API for the Mortally Terrified

What does SV look like?

Strings

"ANY" points to a "xpv", and TYPE is 4. *

* in Perl 5.20.

SV becomes SvPV

Page 64: The Perl API for the Mortally Terrified

What does SV look like?

Page 65: The Perl API for the Mortally Terrified

What does SV look like?

Integers

Page 66: The Perl API for the Mortally Terrified

What does SV look like?

Integers

"ANY" points to a "xpviv", and TYPE is 1. *

* in Perl 5.20.

Page 67: The Perl API for the Mortally Terrified

What does SV look like?

Integers

"ANY" points to a "xpviv", and TYPE is 1. *

* in Perl 5.20.

SV becomes SvIV

Page 68: The Perl API for the Mortally Terrified

What does SV look like?

Page 69: The Perl API for the Mortally Terrified

What does SV look like?

Floats

Page 70: The Perl API for the Mortally Terrified

What does SV look like?

Floats

"ANY" points to a "xpvnv", and TYPE is 2. *

* in Perl 5.20.

Page 71: The Perl API for the Mortally Terrified

What does SV look like?

Floats

"ANY" points to a "xpvnv", and TYPE is 2. *

* in Perl 5.20.

SV becomes SvNV

Page 72: The Perl API for the Mortally Terrified

WRITE CODE NOW?!??!!11!?

Page 73: The Perl API for the Mortally Terrified

Let's make something fast.

Page 74: The Perl API for the Mortally Terrified

#!/usr/bin/env perluse strict;use warnings;use Inline 'C';

print 'Give me a number: ';my $num_a = <STDIN>;

print 'Give me another number: ';my $num_b = <STDIN>;

printf "The sum is: %s\n", add( $num_a, $num_b );__END____C__

int add( int a, int b ) { return a + b;}

Page 75: The Perl API for the Mortally Terrified

#!/usr/bin/env perluse strict;use warnings;use Inline 'C';

print 'Give me a number: ';my $num_a = <STDIN>;

print 'Give me another number: ';my $num_b = <STDIN>;

printf "The sum is: %s\n", add( $num_a, $num_b );__END____C__

int add( int a, int b ) { return a + b;}

Page 76: The Perl API for the Mortally Terrified

#!/usr/bin/env perluse strict;use warnings;use Inline 'C';

print 'Give me a number: ';my $num_a = <STDIN>;

print 'Give me another number: ';my $num_b = <STDIN>;

printf "The sum is: %s\n", add( $num_a, $num_b );__END____C__

int add( int a, int b ) { return a + b;}

Page 77: The Perl API for the Mortally Terrified

#!/usr/bin/env perluse strict;use warnings;use Inline 'C';

print 'Give me a number: ';my $num_a = <STDIN>;

print 'Give me another number: ';my $num_b = <STDIN>;

printf "The sum is: %s\n", add( $num_a, $num_b );__END____C__

int add( int a, int b ) { return a + b;}

Page 78: The Perl API for the Mortally Terrified

#!/usr/bin/env perluse strict;use warnings;use Inline 'C';

print 'Give me a number: ';my $num_a = <STDIN>;

print 'Give me another number: ';my $num_b = <STDIN>;

printf "The sum is: %s\n", add( $num_a, $num_b );__END____C__

int add( int a, int b ) { return a + b;}

Page 79: The Perl API for the Mortally Terrified

#!/usr/bin/env perluse strict;use warnings;use Inline 'C';

print 'Give me a number: ';my $num_a = <STDIN>;

print 'Give me another number: ';my $num_b = <STDIN>;

printf "The sum is: %s\n", add( $num_a, $num_b );__END____C__

int add( int a, int b ) { return a + b;}

Page 80: The Perl API for the Mortally Terrified

bash-3.2$ perl cexp1.plGive me a number: 42Give me another number: 11The sum is: 53

Run it!

Page 81: The Perl API for the Mortally Terrified

bash-3.2$ perl cexp1.plGive me a number: 42Give me another number: 31.337The sum is: 73

Run it again!

Page 82: The Perl API for the Mortally Terrified

bash-3.2$ perl cexp1.plGive me a number: 42Give me another number: 31.337The sum is: 73

Run it again!

What happened?

Page 83: The Perl API for the Mortally Terrified

Inline::C is

CRAZY SMART

Page 84: The Perl API for the Mortally Terrified

intintintint

Inline::C is

CRAZY SMART

Page 85: The Perl API for the Mortally Terrified

Adding numbers:What will we need?

Page 86: The Perl API for the Mortally Terrified
Page 87: The Perl API for the Mortally Terrified

•SvIOK Is it a SvIV?

Page 88: The Perl API for the Mortally Terrified

•SvIOK Is it a SvIV?

•SvNOK Is it a SvNV?

Page 89: The Perl API for the Mortally Terrified

•SvIOK Is it a SvIV?

•SvNOK Is it a SvNV?

•SvIV Get the C int value from SV

Page 90: The Perl API for the Mortally Terrified

•SvIOK Is it a SvIV?

•SvNOK Is it a SvNV?

•SvIV Get the C int value from SV

•SvNV Get the C float value from SV

Page 91: The Perl API for the Mortally Terrified

•SvIOK Is it a SvIV?

•SvNOK Is it a SvNV?

•SvIV Get the C int value from SV

•SvNV Get the C float value from SV

•newSViv Make a new integer SV

Page 92: The Perl API for the Mortally Terrified

•SvIOK Is it a SvIV?

•SvNOK Is it a SvNV?

•SvIV Get the C int value from SV

•SvNV Get the C float value from SV

•newSViv Make a new integer SV

•newSVnv Make a new float SV

Page 93: The Perl API for the Mortally Terrified

use Inline 'C';

print 'Give me a number: ';my $num_a = <STDIN>;print 'Give me another number: ';my $num_b = <STDIN>;$num_a += 0; $num_b += 0;printf "The sum is: %s\n", add( $num_a, $num_b );__END____C__SV *add( SV *a, SV *b ) {

if ( SvIOK( a ) && SvIOK( b ) ) { return newSViv( SvIV( a ) + SvIV( b ) ); } else if ( SvNOK( a ) && SvNOK( b ) ) { return newSVnv( SvNV( a ) + SvNV( b ) ); } else { croak( "I don't know what to do!" ); }}

Page 94: The Perl API for the Mortally Terrified

use Inline 'C';

print 'Give me a number: ';my $num_a = <STDIN>;print 'Give me another number: ';my $num_b = <STDIN>;$num_a += 0; $num_b += 0; # coerceprintf "The sum is: %s\n", add( $num_a, $num_b );__END____C__SV *add( SV *a, SV *b ) {

if ( SvIOK( a ) && SvIOK( b ) ) { return newSViv( SvIV( a ) + SvIV( b ) ); } else if ( SvNOK( a ) && SvNOK( b ) ) { return newSVnv( SvNV( a ) + SvNV( b ) ); } else { croak( "I don't know what to do!" ); }}

Page 95: The Perl API for the Mortally Terrified

use Inline 'C';

print 'Give me a number: ';my $num_a = <STDIN>;print 'Give me another number: ';my $num_b = <STDIN>;$num_a += 0; $num_b += 0;printf "The sum is: %s\n", add( $num_a, $num_b );__END____C__SV *add( SV *a, SV *b ) {

if ( SvIOK( a ) && SvIOK( b ) ) { return newSViv( SvIV( a ) + SvIV( b ) ); } else if ( SvNOK( a ) && SvNOK( b ) ) { return newSVnv( SvNV( a ) + SvNV( b ) ); } else { croak( "I don't know what to do!" ); }}

Page 96: The Perl API for the Mortally Terrified

use Inline 'C';

print 'Give me a number: ';my $num_a = <STDIN>;print 'Give me another number: ';my $num_b = <STDIN>;$num_a += 0; $num_b += 0;printf "The sum is: %s\n", add( $num_a, $num_b );__END____C__SV *add( SV *a, SV *b ) {

if ( SvIOK( a ) && SvIOK( b ) ) { return newSViv( SvIV( a ) + SvIV( b ) ); } else if ( SvNOK( a ) && SvNOK( b ) ) { return newSVnv( SvNV( a ) + SvNV( b ) ); } else { croak( "I don't know what to do!" ); }}

Page 97: The Perl API for the Mortally Terrified

bash-3.2$ perl cexp2.pl Give me a number: 42Give me another number: 11The sum is: 53bash-3.2$ perl cexp2.pl

Run it!

Page 98: The Perl API for the Mortally Terrified

bash-3.2$ perl cexp2.pl Give me a number: 42Give me another number: 11The sum is: 53bash-3.2$ perl cexp2.pl

Run it!

bash-3.2$ perl cexp2.pl Give me a number: 53.4Give me another number: 6.54The sum is: 59.94

Page 99: The Perl API for the Mortally Terrified

bash-3.2$ perl cexp2.pl Give me a number: 42Give me another number: 11The sum is: 53bash-3.2$ perl cexp2.pl

Run it!

bash-3.2$ perl cexp2.pl Give me a number: 53.4Give me another number: 6.54The sum is: 59.94

Give me a number: 42Give me another number: 6.54I don't know what to do! at cexp2.pl line 16, <STDIN> line 2.

Page 100: The Perl API for the Mortally Terrified

Once you get this far, everything you need

is in perlapi.

Page 101: The Perl API for the Mortally Terrified

Let's do something with arrays.

Page 102: The Perl API for the Mortally Terrified

What does SV look like?

Page 103: The Perl API for the Mortally Terrified

What does SV look like?

Arrays

Page 104: The Perl API for the Mortally Terrified

What does SV look like?

Arrays

"ANY" points to a "xpvav"

Page 105: The Perl API for the Mortally Terrified

What does SV look like?

Arrays

"ANY" points to a "xpvav"

SV becomes AV

Page 106: The Perl API for the Mortally Terrified

Squaring numbers:What will we need?

Page 107: The Perl API for the Mortally Terrified

•SvRV Get SV from reference

Page 108: The Perl API for the Mortally Terrified

•SvRV Get SV from reference

•newAV Make a new array AV

Page 109: The Perl API for the Mortally Terrified

•SvRV Get SV from reference

•newAV Make a new array AV

•newRV Make a new reference

Page 110: The Perl API for the Mortally Terrified

•SvRV Get SV from reference

•newAV Make a new array AV

•newRV Make a new reference

•AvFILL Get size of array

Page 111: The Perl API for the Mortally Terrified

•SvRV Get SV from reference

•newAV Make a new array AV

•newRV Make a new reference

•AvFILL Get size of array

•av_fetch Get an element from array

Page 112: The Perl API for the Mortally Terrified

•SvRV Get SV from reference

•newAV Make a new array AV

•newRV Make a new reference

•AvFILL Get size of array

•av_fetch Get an element from array

•SvIOK Is it an int?

Page 113: The Perl API for the Mortally Terrified

•SvRV Get SV from reference

•newAV Make a new array AV

•newRV Make a new reference

•AvFILL Get size of array

•av_fetch Get an element from array

•SvIOK Is it an int?

•SvIV Get C int from SV

Page 114: The Perl API for the Mortally Terrified

•SvRV Get SV from reference

•newAV Make a new array AV

•newRV Make a new reference

•AvFILL Get size of array

•av_fetch Get an element from array

•SvIOK Is it an int?

•SvIV Get C int from SV

•av_push Obvs.

Page 115: The Perl API for the Mortally Terrified

#!/usr/bin/env perluse strict;use warnings;use Inline 'C';

print "Give me some numbers: ";my @numbers = map { $_ += 0 } split /,/, <STDIN>;

my $result = squares( \@numbers );printf "The squares are: %s\n", join ", ", @$result;

__END__

Page 116: The Perl API for the Mortally Terrified

#!/usr/bin/env perluse strict;use warnings;use Inline 'C';

print "Give me some numbers: ";my @numbers = map { $_ += 0 } split /,/, <STDIN>;

my $result = squares( \@numbers );printf "The squares are: %s\n", join ", ", @$result;

__END__

Page 117: The Perl API for the Mortally Terrified

__C__

SV *squares( SV *numbers ) { AV *array = (AV *)SvRV( numbers ); AV *return_array = newAV(); SV **tmp;

int len = AvFILL( array ); int i, val;

for( i = 0; i <= len; i++ ) { tmp = av_fetch( array, i, 1 ); if( !SvIOK( *tmp ) ) { croak( "Can't handle this value!" ); } val = SvIV( *tmp ); val = val * val;

av_push( return_array, newSViv( val ) ); }

return newRV_inc( (SV *)return_array );}

Page 118: The Perl API for the Mortally Terrified

__C__

SV *squares( SV *numbers ) { AV *array = (AV *)SvRV( numbers ); AV *return_array = newAV(); SV **tmp;

int len = AvFILL( array ); int i, val;

for( i = 0; i <= len; i++ ) { tmp = av_fetch( array, i, 1 ); if( !SvIOK( *tmp ) ) { croak( "Can't handle this value!" ); } val = SvIV( *tmp ); val = val * val;

av_push( return_array, newSViv( val ) ); }

return newRV_inc( (SV *)return_array );}

Page 119: The Perl API for the Mortally Terrified

__C__

SV *squares( SV *numbers ) { AV *array = (AV *)SvRV( numbers ); AV *return_array = newAV(); SV **tmp;

int len = AvFILL( array ); int i, val;

for( i = 0; i <= len; i++ ) { tmp = av_fetch( array, i, 1 ); if( !SvIOK( *tmp ) ) { croak( "Can't handle this value!" ); } val = SvIV( *tmp ); val = val * val;

av_push( return_array, newSViv( val ) ); }

return newRV_inc( (SV *)return_array );}

Page 120: The Perl API for the Mortally Terrified

__C__

SV *squares( SV *numbers ) { AV *array = (AV *)SvRV( numbers ); AV *return_array = newAV(); SV **tmp;

int len = AvFILL( array ); int i, val;

for( i = 0; i <= len; i++ ) { tmp = av_fetch( array, i, 1 ); if( !SvIOK( *tmp ) ) { croak( "Can't handle this value!" ); } val = SvIV( *tmp ); val = val * val;

av_push( return_array, newSViv( val ) ); }

return newRV_inc( (SV *)return_array );}

Page 121: The Perl API for the Mortally Terrified

__C__

SV *squares( SV *numbers ) { AV *array = (AV *)SvRV( numbers ); AV *return_array = newAV(); SV **tmp;

int len = AvFILL( array ); int i, val;

for( i = 0; i <= len; i++ ) { tmp = av_fetch( array, i, 1 ); if( !SvIOK( *tmp ) ) { croak( "Can't handle this value!" ); } val = SvIV( *tmp ); val = val * val;

av_push( return_array, newSViv( val ) ); }

return newRV_inc( (SV *)return_array );}

Page 122: The Perl API for the Mortally Terrified

__C__

SV *squares( SV *numbers ) { AV *array = (AV *)SvRV( numbers ); AV *return_array = newAV(); SV **tmp;

int len = AvFILL( array ); int i, val;

for( i = 0; i <= len; i++ ) { tmp = av_fetch( array, i, 1 ); if( !SvIOK( *tmp ) ) { croak( "Can't handle this value!" ); } val = SvIV( *tmp ); val = val * val;

av_push( return_array, newSViv( val ) ); }

return newRV_inc( (SV *)return_array );}

Page 123: The Perl API for the Mortally Terrified

__C__

SV *squares( SV *numbers ) { AV *array = (AV *)SvRV( numbers ); AV *return_array = newAV(); SV **tmp;

int len = AvFILL( array ); int i, val;

for( i = 0; i <= len; i++ ) { tmp = av_fetch( array, i, 1 ); if( !SvIOK( *tmp ) ) { croak( "Can't handle this value!" ); } val = SvIV( *tmp ); val = val * val;

av_push( return_array, newSViv( val ) ); }

return newRV( (SV *)return_array );}

Page 124: The Perl API for the Mortally Terrified

bash-3.2$ perl cexp3.pl Give me some numbers: 4,5,6,23The squares are: 16, 25, 36, 529

Run it!

Page 125: The Perl API for the Mortally Terrified

Let's do something with hashes.

Page 126: The Perl API for the Mortally Terrified

What does SV look like?

Page 127: The Perl API for the Mortally Terrified

What does SV look like?

Hashes

Page 128: The Perl API for the Mortally Terrified

What does SV look like?

Hashes

"ANY" points to a "xpvhv"

Page 129: The Perl API for the Mortally Terrified

What does SV look like?

Hashes

"ANY" points to a "xpvhv"

SV becomes HV

Page 130: The Perl API for the Mortally Terrified

Finding uniques:What will we need?

Page 131: The Perl API for the Mortally Terrified

•SvRV Get SV from reference

Page 132: The Perl API for the Mortally Terrified

•SvRV Get SV from reference

•newHV Make a new hash HV

Page 133: The Perl API for the Mortally Terrified

•SvRV Get SV from reference

•newHV Make a new hash HV

•newRV Make a new reference

Page 134: The Perl API for the Mortally Terrified

•SvRV Get SV from reference

•newHV Make a new hash HV

•newRV Make a new reference

•AvFILL Get size of array

Page 135: The Perl API for the Mortally Terrified

•SvRV Get SV from reference

•newHV Make a new hash HV

•newRV Make a new reference

•AvFILL Get size of array

•av_fetch Get an element from array

Page 136: The Perl API for the Mortally Terrified

•SvRV Get SV from reference

•newHV Make a new hash HV

•newRV Make a new reference

•AvFILL Get size of array

•av_fetch Get an element from array

•SvPOK Is it a string?

Page 137: The Perl API for the Mortally Terrified

•SvRV Get SV from reference

•newHV Make a new hash HV

•newRV Make a new reference

•AvFILL Get size of array

•av_fetch Get an element from array

•SvPOK Is it a string?

•SvPV Get C string from SV

Page 138: The Perl API for the Mortally Terrified

•SvRV Get SV from reference

•newHV Make a new hash HV

•newRV Make a new reference

•AvFILL Get size of array

•av_fetch Get an element from array

•SvPOK Is it a string?

•SvPV Get C string from SV

•hv_store Obvs.

Page 139: The Perl API for the Mortally Terrified

#!/usr/bin/env perluse strict;use warnings;use Inline 'C';

print "Give me some words: ";my @words = split /,/, <STDIN>;chomp @words;my $result = uniques( \@words );printf "The uniques are: %s\n", join ", ", %$result;

__END__

Page 140: The Perl API for the Mortally Terrified

__C__

SV *uniques( SV *words ) { AV *array = (AV *)SvRV( words ); HV *result = newHV(); SV **tmp;

int len = AvFILL( array ); int i; char *val;

for( i = 0; i <= len; i++ ) { tmp = av_fetch( array, i, 1 ); if( !SvPOK( *tmp ) ) { croak( "Can't handle this value!" ); }

val = SvPV_nolen( *tmp );

hv_store( result, val, strlen( val ), newSV(0), 0 ); }

return newRV( (SV *)result );}

Page 141: The Perl API for the Mortally Terrified

bash-3.2$ perl cexp4.pl Give me some words: foo,bar,baz,baz,foo,quux,narf,poitThe uniques are: bar, narf, baz, poit, quux, foo

Run it!

Page 142: The Perl API for the Mortally Terrified

What isMagic?

Page 143: The Perl API for the Mortally Terrified

Not that terrifying.

Page 144: The Perl API for the Mortally Terrified

Magic is a linked list of function pointers attached to a *SV.

Page 145: The Perl API for the Mortally Terrified

Magic is a linked list of function pointers attached to a *SV.

The functions implement custom read/write behavior.

Page 146: The Perl API for the Mortally Terrified

Magic is a linked list of function pointers attached to a *SV.

The functions implement custom read/write behavior.

Special vars like %ENV are implemented via Magic.

Page 147: The Perl API for the Mortally Terrified

$ENV{foo} = "blah";

Page 148: The Perl API for the Mortally Terrified

$ENV{foo} = "blah";

assignment op

Page 149: The Perl API for the Mortally Terrified

$ENV{foo} = "blah";

Magic on %ENV ?

assignment op

Page 150: The Perl API for the Mortally Terrified

$ENV{foo} = "blah";

Magic on %ENV ?

assignment op

Look up write function

Page 151: The Perl API for the Mortally Terrified

$ENV{foo} = "blah";

Magic on %ENV ?

assignment op

Look up write function

call libc setenv()

Page 152: The Perl API for the Mortally Terrified

tie() is also implemented via Magic.

Page 153: The Perl API for the Mortally Terrified

Terror defeated!

Page 154: The Perl API for the Mortally Terrified

Where do we go from here?

Page 155: The Perl API for the Mortally Terrified

Resources:

perlgutsFor details on how to manipulate Perl's

data structures.

Page 156: The Perl API for the Mortally Terrified

Resources:

perlapiFor a comprehensive reference to (almost)

everything you need to make perl do stuff.

Page 157: The Perl API for the Mortally Terrified

Resources:

Perlguts Illustrated

For pretty diagrams and explication.

Page 158: The Perl API for the Mortally Terrified

Resources:

Inline::C Cookbook

For common solutions to problemsinterfacing between Perl and C

Page 159: The Perl API for the Mortally Terrified

Resources:

Page 160: The Perl API for the Mortally Terrified

Resources:

Code samples

http://github.com/friedo/perl-api-terror

Page 161: The Perl API for the Mortally Terrified

YAPC::NA

Thank you.

Mike [email protected]

http://friedo.com/http://github.com/friedo/perl-api-terror