The Perl API
for the

Mortally Terrified
Mike Friedman
(friedo)

London Perl Workshop
November 30, 2013
Me
Mike Friedman
Mike Friedman
(friedo)
This talk
is the product of a lengthy journey.
This talk
is the product of a lengthy journey.

It's also a work in progress.
I have some limited
experience in integrating
Perl and C with XS, and
would enjoy the opportunity
to expand my skills in t...
i R dum.
- Learned from this book.
- Learned from this book.
- It’s very good
- Learned from this book.
- It’s very good
- The printing I got was messed up.
- Learned from this book.
- It’s very good
- The printing I got was messed up.
- Like every " was replaced by ©
The Perl API
What’s it good for?
Make things fast:
The Perl API
What’s it good for?
Make things fast:
- Write your slow Perl code in C
The Perl API
What’s it good for?
Make things fast:
- Write your slow Perl code in C
- Keep your fast Perl code in Perl
The Perl API
What’s it good for?
Make Perl more useful:
The Perl API
What’s it good for?
Make Perl more useful:
- Interface with libraries written in C
The Perl API
What’s it good for?
Make Perl more useful:
- Interface with libraries written in C
- Create modules exposing ...
The Perl API
What’s it good for?
Make Perl do...stuff
The Perl API
What’s it good for?
Make Perl do...stuff
- Change opcodes on the fly?
The Perl API
What’s it good for?
Make Perl do...stuff
- Change opcodes on the fly?
- Extend the parser?
The Perl API
What’s it good for?
Make Perl do...stuff
- Change opcodes on the fly?
- Extend the parser?
- Make exceptions w...
The Perl API
What’s it good for?
Make Perl do...stuff
- Change opcodes on the fly?
- Extend the parser?
- Make exceptions w...
The Perl API
What’s it good for?
Make Perl do...stuff
- Change opcodes on the fly?
- Extend the parser?
- Make exceptions w...
A Crash Course in

C
C Crash Course

Basic Types (there are more)
C Crash Course

Basic Types (there are more)
char

foo

= ‘a’;
C Crash Course

Basic Types (there are more)
char
int

foo
bar

= ‘a’;
= 42;
C Crash Course

Basic Types (there are more)
char
int
long

foo
bar
baz

= ‘a’;
= 42;
= 198547;
C Crash Course

Basic Types (there are more)
char
int
long
float

foo
bar
baz
quux

=
=
=
=

‘a’;
42;
198547;
3.14159;
C Crash Course

Basic Types (there are more)
char
int
long
float
double

foo
bar
baz
quux
splat

=
=
=
=
=

‘a’;
42;
19854...
C Crash Course

Pointers
C Crash Course

Pointers
char

*foo;

/* ptr to char

*/
C Crash Course

Pointers
char
int

*foo;
*bar;

/* ptr to char
/* ptr to int

*/
*/
C Crash Course

Pointers
char
int
long

*foo;
*bar;
*baz;

/* ptr to char
/* ptr to int
/* ptr to long

*/
*/
*/
C Crash Course

Pointers
char
int
long
float

*foo;
*bar;
*baz;
*quux;

/*
/*
/*
/*

ptr
ptr
ptr
ptr

to
to
to
to

char
in...
C Crash Course

Pointers
char
int
long
float
double

*foo;
*bar;
*baz;
*quux;
*splat;

/*
/*
/*
/*
/*

ptr
ptr
ptr
ptr
ptr...
C Crash Course

Pointers
char
int
long
float
double
void

*foo;
*bar;
*baz;
*quux;
*splat;
*fnarf;

/*
/*
/*
/*
/*
/*

ptr...
C Crash Course

Pointers are integer variables which
hold a memory address.
C Crash Course

C

Perl
C Crash Course

C
int i

Perl
= 42;

my $i

= 42;
C Crash Course

C
int i
= 42;
int *i_ptr = &i;

Perl
my $i
= 42;
my $i_ref = $i;
C Crash Course

C

Perl

int i
= 42;
my $i
= 42;
int *i_ptr = &i;
my $i_ref = $i;
Read unary & as “address-of.”
C Crash Course

C

Perl

int i
= 42;
my $i
= 42;
int *i_ptr = &i;
my $i_ref = $i;
Read unary & as “address-of.”
int j;

my...
C Crash Course

C

Perl

int i
= 42;
my $i
= 42;
int *i_ptr = &i;
my $i_ref = $i;
Read unary & as “address-of.”
int j;
j =...
C Crash Course

C

Perl

int i
= 42;
my $i
= 42;
int *i_ptr = &i;
my $i_ref = $i;
Read unary & as “address-of.”
int j;
j =...
C Crash Course

Aggregates
C Crash Course

Aggregates
int

foo[10];

/* array of ints */
C Crash Course

Aggregates
int
float

foo[10];
bar[12];

/* array of ints */
/* array of floats */
C Crash Course

Aggregates
int
float
char

foo[10];
bar[12];
baz[42];

/* array of ints */
/* array of floats */
/* a stri...
C Crash Course

Aggregates
C Crash Course

Aggregates
struct person {
int age;
char *name;
double acct_balance;
};
C Crash Course

Aggregates
struct person {
int age;
char *name;
double acct_balance;
};
age

*name

acct_balance
...
C Crash Course

Aggregates
C Crash Course

Aggregates
union thingy {
long num;
char chars[4];
foo_t *myfoo;
};
C Crash Course

Aggregates
union thingy {
long num;
char chars[4];
foo_t *myfoo;
};
thingy.num
thingy.chars
thingy.myfoo

...
C Crash Course

Using structs
C Crash Course

Using structs
struct person the_dude;
the_dude.age = 42;
the_dude.name = “jeffrey lebowski”;
the_dude.acct...
C Crash Course

Using structs
struct person the_dude;
the_dude.age = 42;
the_dude.name = “jeffrey lebowski”;
the_dude.acct...
C Crash Course

Typedefs
typedef struct {
int age;
char *name;
double acct_balance;
} person;
person the_dude;
XS
What is XS?

perldoc perlxs:
XS is an interface description file format used to create an
extension interface between Perl...
XS is a specialized templating
language for C.
Some XS Code
Some XS Code

This stuff is XS.
Some C Code made by xsubpp
XS != Perl API
For most things
For most things
You don't actually
have to use XS.
(OK.You don’t have to
know that you’re using it.)
Inline::C
use Inline C;
hello('Mike');
hello('Cookie Monster');
__END__
__C__
void hello(char* name) {
  printf("Hello %s!n", name);...
use Inline C;
hello('Mike');
hello('Grover');
__END__
__C__
void hello(char* name) {
  printf("Hello %s!n", name);
}
use Inline C;
hello('Mike');
hello('Grover');
__END__
__C__
void hello(char* name) {
  printf("Hello %s!n", name);
}
use Inline C;
hello('Mike');
hello('Grover');
__END__
__C__
void hello(char* name) {
  printf("Hello %s!n", name);
}
Inline::C Code in Perl
Inline::C Code in Perl
Digest::MD5
Inline::C Code in Perl
Digest::MD5
C Code

Parse::RecDescent
Inline::C Code in Perl
Digest::MD5
C Code

Parse::RecDescent

Create build in a temp dir
Inline::C Code in Perl
Digest::MD5
C Code

Parse::RecDescent

Create build in a temp dir
Write XS
Inline::C Code in Perl
Digest::MD5
C Code

Parse::RecDescent

Create build in a temp dir
Write XS
Compile and install
Inline::C Code in Perl
Digest::MD5
C Code

Parse::RecDescent

Create build in a temp dir
Write XS
Compile and install
How do we make
Perl do stuff in C?
How do we make
Perl do stuff in C?
We need to understand Perl’s data
structures.
Handwaving Ahead
A $scalar in Perl is represented by a struct called SV.
SvNULL

SvRV

SvPV

SvIV

(These are not all of them.)

SvNV
What does SV look like?
sv_refcnt

sv_flags

{

sv_any

flags

type
What does SV look like?
sv_refcnt

sv_flags

{

sv_any

flags

type

If this scalar is undef, then sv_any is NULL
What does SvPV (a string) look like?
sv_any

sv_refcnt

sv_flags

pvx

current len

alloc len

SV

xpv

char* a

s

t

r

i...
What do SvIV and SvNV look like?
sv_any

sv_refcnt

sv_flags

pvx

current len

alloc len

SV

xpviv

69

7a

00

00

ivx
c...
What do SvIV and SvNV look like?
sv_any

sv_refcnt

sv_flags

pvx

current len

alloc len

SV

xpvnv

6e

86

1b

f0

f9

i...
WRITE CODE NOW
?!??!!11!?
Let's make
something fast.
#!/usr/bin/env perl
use strict;
use warnings;
use Inline 'C';
print 'Give me a number: ';
my $num_a = <STDIN>;
print 'Give...
#!/usr/bin/env perl
use strict;
use warnings;
use Inline 'C';
print 'Give me a number: ';
my $num_a = <STDIN>;
print 'Give...
#!/usr/bin/env perl
use strict;
use warnings;
use Inline 'C';
print 'Give me a number: ';
my $num_a = <STDIN>;
print 'Give...
#!/usr/bin/env perl
use strict;
use warnings;
use Inline 'C';
print 'Give me a number: ';
my $num_a = <STDIN>;
print 'Give...
#!/usr/bin/env perl
use strict;
use warnings;
use Inline 'C';
print 'Give me a number: ';
my $num_a = <STDIN>;
print 'Give...
#!/usr/bin/env perl
use strict;
use warnings;
use Inline 'C';
print 'Give me a number: ';
my $num_a = <STDIN>;
print 'Give...
Run it!
bash-3.2$ perl cexp1.pl
Give me a number: 42
Give me another number: 11
The sum is: 53
Run it again!
bash-3.2$ perl cexp1.pl
Give me a number: 42
Give me another number: 31.337
The sum is: 73
Run it again!
bash-3.2$ perl cexp1.pl
Give me a number: 42
Give me another number: 31.337
The sum is: 73
What happened?
Inline::C
is
CRAZY
SMART
int
int
int
int

Inline::C
is
CRAZY
SMART
use Inline 'C';
print 'Give me a number: ';
my $num_a = <STDIN>;
print 'Give me another number: ';
my $num_b = <STDIN>;
$n...
use Inline 'C';
print 'Give me a number: ';
my $num_a = <STDIN>;
print 'Give me another number: ';
my $num_b = <STDIN>;
$n...
use Inline 'C';
print 'Give me a number: ';
my $num_a = <STDIN>;
print 'Give me another number: ';
my $num_b = <STDIN>;
$n...
use Inline 'C';
print 'Give me a number: ';
my $num_a = <STDIN>;
print 'Give me another number: ';
my $num_b = <STDIN>;
$n...
Run it!
bash-3.2$ perl cexp2.pl
Give me a number: 42
Give me another number: 11
The sum is: 53
bash-3.2$ perl cexp2.pl
Run it!
bash-3.2$ perl cexp2.pl
Give me a number: 42
Give me another number: 11
The sum is: 53
bash-3.2$ perl cexp2.pl
bas...
Run it!
bash-3.2$ perl cexp2.pl
Give me a number: 42
Give me another number: 11
The sum is: 53
bash-3.2$ perl cexp2.pl
bas...
Once you get this far,
everything you need
is in perlapi.
Let's do something
with arrays.
What does an AV look like?
sv_any

sv_refcnt

sv_flags

array

fill

max

SV

xpvav

*some fields omitted

alloc

array len
S...
#!/usr/bin/env perl
use strict;
use warnings;
use Inline 'C';
print "Give me some numbers: ";
my @numbers = map { $_ += 0 ...
#!/usr/bin/env perl
use strict;
use warnings;
use Inline 'C';
print "Give me some numbers: ";
my @numbers = map { $_ += 0 ...
SV *squares( SV *numbers ) {
AV *array = (AV *)SvRV( numbers );
AV *return_array = newAV();
SV **tmp;
int len = AvFILL( ar...
SV *squares( SV *numbers ) {
AV *array = (AV *)SvRV( numbers );
AV *return_array = newAV();
SV **tmp;
int len = AvFILL( ar...
SV *squares( SV *numbers ) {
AV *array = (AV *)SvRV( numbers );
AV *return_array = newAV();
SV **tmp;
int len = AvFILL( ar...
SV *squares( SV *numbers ) {
AV *array = (AV *)SvRV( numbers );
AV *return_array = newAV();
SV **tmp;
int len = AvFILL( ar...
SV *squares( SV *numbers ) {
AV *array = (AV *)SvRV( numbers );
AV *return_array = newAV();
SV **tmp;
int len = AvFILL( ar...
SV *squares( SV *numbers ) {
AV *array = (AV *)SvRV( numbers );
AV *return_array = newAV();
SV **tmp;
int len = AvFILL( ar...
SV *squares( SV *numbers ) {
AV *array = (AV *)SvRV( numbers );
AV *return_array = newAV();
SV **tmp;
int len = AvFILL( ar...
Run it!
bash-3.2$ perl cexp3.pl
Give me some numbers: 4,5,6,23
The squares are: 16, 25, 36, 529
Let's do something
with hashes.
What does an HV look like?
What does an HV look like?
(Diagram missing
What does an HV look like?
(Diagram missing
(So I stole this one))
What does an HV look like?
(Diagram missing
(So I stole this one))
#!/usr/bin/env perl
use strict;
use warnings;
use Inline 'C';
print "Give me some words: ";
my @words = split /,/, <STDIN>...
__C__
SV *uniques( SV *words ) {
AV *array = (AV *)SvRV( words );
HV *result = newHV();
SV **tmp;
int len = AvFILL( array ...
Run it!
bash-3.2$ perl cexp4.pl
Give me some words: foo,bar,baz,baz,foo,quux,narf,poit
The uniques are: bar, narf, baz, po...
What is
Magic?
Not that terrifying.
Not that terrifying.
(code sample missing)
Magic is a linked list of function pointers
attached to a *SV.
Magic is a linked list of function pointers
attached to a *SV.
The functions implement custom read/write
behavior.
Magic is a linked list of function pointers
attached to a *SV.
The functions implement custom read/write
behavior.
Special...
$ENV{foo} = "blah";
$ENV{foo} = "blah";
assignment op
$ENV{foo} = "blah";
assignment op
Magic on %ENV ?
$ENV{foo} = "blah";
assignment op
Magic on %ENV ?

Look up write function
$ENV{foo} = "blah";
assignment op
Magic on %ENV ?

Look up write function

call libc setenv()
tie() is also implemented via Magic.
Terror defeated!
Where do we go from
here?
Resources:

perlguts
For details on how to manipulate Perl's
data structures.
Resources:

perlapi
For a comprehensive reference to (almost)
everything you need to make perl do stuff.
Resources:

Perlguts Illustrated
For pretty diagrams and explication.
Resources:

Inline::C Cookbook
For common solutions to problems
interfacing between Perl and C
Resources:
Resources:

Code samples
http://github.com/friedo/perl-api-terror
London Perl
Workshop
Thank you.
Mike Friedman
friedo@friedo.com
http://friedo.com/
http://github.com/friedo/perl-api-terro...
The Perl API for the Mortally Terrified (beta)
The Perl API for the Mortally Terrified (beta)
Upcoming SlideShare
Loading in …5
×

The Perl API for the Mortally Terrified (beta)

1,506 views

Published on

A brief introduction to get you started in working with Perl's internal API. This presentation is a work in progress.

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

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,506
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
8
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

The Perl API for the Mortally Terrified (beta)

  1. 1. The Perl API for the Mortally Terrified Mike Friedman (friedo) London Perl Workshop November 30, 2013
  2. 2. Me Mike Friedman
  3. 3. Mike Friedman (friedo)
  4. 4. This talk is the product of a lengthy journey.
  5. 5. This talk is the product of a lengthy journey. It's also a work in progress.
  6. 6. I have some limited experience in integrating Perl and C with XS, and would enjoy the opportunity to expand my skills in this area.
  7. 7. i R dum.
  8. 8. - Learned from this book.
  9. 9. - Learned from this book. - It’s very good
  10. 10. - Learned from this book. - It’s very good - The printing I got was messed up.
  11. 11. - Learned from this book. - It’s very good - The printing I got was messed up. - Like every " was replaced by ©
  12. 12. The Perl API What’s it good for? Make things fast:
  13. 13. The Perl API What’s it good for? Make things fast: - Write your slow Perl code in C
  14. 14. The Perl API What’s it good for? Make things fast: - Write your slow Perl code in C - Keep your fast Perl code in Perl
  15. 15. The Perl API What’s it good for? Make Perl more useful:
  16. 16. The Perl API What’s it good for? Make Perl more useful: - Interface with libraries written in C
  17. 17. The Perl API What’s it good for? Make Perl more useful: - Interface with libraries written in C - Create modules exposing external APIs to Perl
  18. 18. The Perl API What’s it good for? Make Perl do...stuff
  19. 19. The Perl API What’s it good for? Make Perl do...stuff - Change opcodes on the fly?
  20. 20. The Perl API What’s it good for? Make Perl do...stuff - Change opcodes on the fly? - Extend the parser?
  21. 21. The Perl API What’s it good for? Make Perl do...stuff - Change opcodes on the fly? - Extend the parser? - Make exceptions work?
  22. 22. The Perl API What’s it good for? Make Perl do...stuff - Change opcodes on the fly? - Extend the parser? - Make exceptions work? - Why not?
  23. 23. The Perl API What’s it good for? Make Perl do...stuff - Change opcodes on the fly? - Extend the parser? - Make exceptions work? - Why not?
  24. 24. A Crash Course in C
  25. 25. C Crash Course Basic Types (there are more)
  26. 26. C Crash Course Basic Types (there are more) char foo = ‘a’;
  27. 27. C Crash Course Basic Types (there are more) char int foo bar = ‘a’; = 42;
  28. 28. C Crash Course Basic Types (there are more) char int long foo bar baz = ‘a’; = 42; = 198547;
  29. 29. C Crash Course Basic Types (there are more) char int long float foo bar baz quux = = = = ‘a’; 42; 198547; 3.14159;
  30. 30. C Crash Course Basic Types (there are more) char int long float double foo bar baz quux splat = = = = = ‘a’; 42; 198547; 3.14159; 3.14159265358979;
  31. 31. C Crash Course Pointers
  32. 32. C Crash Course Pointers char *foo; /* ptr to char */
  33. 33. C Crash Course Pointers char int *foo; *bar; /* ptr to char /* ptr to int */ */
  34. 34. C Crash Course Pointers char int long *foo; *bar; *baz; /* ptr to char /* ptr to int /* ptr to long */ */ */
  35. 35. C Crash Course Pointers char int long float *foo; *bar; *baz; *quux; /* /* /* /* ptr ptr ptr ptr to to to to char int long float */ */ */ */
  36. 36. C Crash Course Pointers char int long float double *foo; *bar; *baz; *quux; *splat; /* /* /* /* /* ptr ptr ptr ptr ptr to to to to to char int long float double */ */ */ */ */
  37. 37. C Crash Course Pointers char int long float double void *foo; *bar; *baz; *quux; *splat; *fnarf; /* /* /* /* /* /* ptr ptr ptr ptr ptr ptr to to to to to to char int long float double something */ */ */ */ */ */
  38. 38. C Crash Course Pointers are integer variables which hold a memory address.
  39. 39. C Crash Course C Perl
  40. 40. C Crash Course C int i Perl = 42; my $i = 42;
  41. 41. C Crash Course C int i = 42; int *i_ptr = &i; Perl my $i = 42; my $i_ref = $i;
  42. 42. C Crash Course C Perl int i = 42; my $i = 42; int *i_ptr = &i; my $i_ref = $i; Read unary & as “address-of.”
  43. 43. C Crash Course C Perl int i = 42; my $i = 42; int *i_ptr = &i; my $i_ref = $i; Read unary & as “address-of.” int j; my $j;
  44. 44. C Crash Course C Perl int i = 42; my $i = 42; int *i_ptr = &i; my $i_ref = $i; Read unary & as “address-of.” int j; j = *i_ptr; my $j; $j = $$i_ref;
  45. 45. C Crash Course C Perl int i = 42; my $i = 42; int *i_ptr = &i; my $i_ref = $i; Read unary & as “address-of.” int j; j = *i_ptr; my $j; $j = $$i_ref; Read unary * as “dereference.”
  46. 46. C Crash Course Aggregates
  47. 47. C Crash Course Aggregates int foo[10]; /* array of ints */
  48. 48. C Crash Course Aggregates int float foo[10]; bar[12]; /* array of ints */ /* array of floats */
  49. 49. C Crash Course Aggregates int float char foo[10]; bar[12]; baz[42]; /* array of ints */ /* array of floats */ /* a string! */
  50. 50. C Crash Course Aggregates
  51. 51. C Crash Course Aggregates struct person { int age; char *name; double acct_balance; };
  52. 52. C Crash Course Aggregates struct person { int age; char *name; double acct_balance; }; age *name acct_balance ...
  53. 53. C Crash Course Aggregates
  54. 54. C Crash Course Aggregates union thingy { long num; char chars[4]; foo_t *myfoo; };
  55. 55. C Crash Course Aggregates union thingy { long num; char chars[4]; foo_t *myfoo; }; thingy.num thingy.chars thingy.myfoo f3 de 42 9a
  56. 56. C Crash Course Using structs
  57. 57. C Crash Course Using structs struct person the_dude; the_dude.age = 42; the_dude.name = “jeffrey lebowski”; the_dude.acct_balance = 1.79;
  58. 58. C Crash Course Using structs struct person the_dude; the_dude.age = 42; the_dude.name = “jeffrey lebowski”; the_dude.acct_balance = 1.79; 00 2a age 3f 39 d2 90 a4 70 3d *name 0a d7 a3 fc acct_balance j e f f r e y ... 3f
  59. 59. C Crash Course Typedefs typedef struct { int age; char *name; double acct_balance; } person; person the_dude;
  60. 60. XS
  61. 61. 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.
  62. 62. XS is a specialized templating language for C.
  63. 63. Some XS Code
  64. 64. Some XS Code This stuff is XS.
  65. 65. Some C Code made by xsubpp
  66. 66. XS != Perl API
  67. 67. For most things
  68. 68. For most things You don't actually have to use XS.
  69. 69. (OK.You don’t have to know that you’re using it.)
  70. 70. Inline::C
  71. 71. use Inline C; hello('Mike'); hello('Cookie Monster'); __END__ __C__ void hello(char* name) {   printf("Hello %s!n", name); }
  72. 72. use Inline C; hello('Mike'); hello('Grover'); __END__ __C__ void hello(char* name) {   printf("Hello %s!n", name); }
  73. 73. use Inline C; hello('Mike'); hello('Grover'); __END__ __C__ void hello(char* name) {   printf("Hello %s!n", name); }
  74. 74. use Inline C; hello('Mike'); hello('Grover'); __END__ __C__ void hello(char* name) {   printf("Hello %s!n", name); }
  75. 75. Inline::C Code in Perl
  76. 76. Inline::C Code in Perl Digest::MD5
  77. 77. Inline::C Code in Perl Digest::MD5 C Code Parse::RecDescent
  78. 78. Inline::C Code in Perl Digest::MD5 C Code Parse::RecDescent Create build in a temp dir
  79. 79. Inline::C Code in Perl Digest::MD5 C Code Parse::RecDescent Create build in a temp dir Write XS
  80. 80. Inline::C Code in Perl Digest::MD5 C Code Parse::RecDescent Create build in a temp dir Write XS Compile and install
  81. 81. Inline::C Code in Perl Digest::MD5 C Code Parse::RecDescent Create build in a temp dir Write XS Compile and install
  82. 82. How do we make Perl do stuff in C?
  83. 83. How do we make Perl do stuff in C? We need to understand Perl’s data structures.
  84. 84. Handwaving Ahead
  85. 85. A $scalar in Perl is represented by a struct called SV. SvNULL SvRV SvPV SvIV (These are not all of them.) SvNV
  86. 86. What does SV look like? sv_refcnt sv_flags { sv_any flags type
  87. 87. What does SV look like? sv_refcnt sv_flags { sv_any flags type If this scalar is undef, then sv_any is NULL
  88. 88. What does SvPV (a string) look like? sv_any sv_refcnt sv_flags pvx current len alloc len SV xpv char* a s t r i n g 0
  89. 89. What do SvIV and SvNV look like? sv_any sv_refcnt sv_flags pvx current len alloc len SV xpviv 69 7a 00 00 ivx char* 3 1 3 3 7 0
  90. 90. What do SvIV and SvNV look like? sv_any sv_refcnt sv_flags pvx current len alloc len SV xpvnv 6e 86 1b f0 f9 ivx char* 3 . 21 09 40 nvx 1 4 1 5 9 0
  91. 91. WRITE CODE NOW ?!??!!11!?
  92. 92. Let's make something fast.
  93. 93. #!/usr/bin/env perl use 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: %sn", add( $num_a, $num_b ); __END__ __C__ int add( int a, int b ) { return a + b; }
  94. 94. #!/usr/bin/env perl use 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: %sn", add( $num_a, $num_b ); __END__ __C__ int add( int a, int b ) { return a + b; }
  95. 95. #!/usr/bin/env perl use 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: %sn", add( $num_a, $num_b ); __END__ __C__ int add( int a, int b ) { return a + b; }
  96. 96. #!/usr/bin/env perl use 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: %sn", add( $num_a, $num_b ); __END__ __C__ int add( int a, int b ) { return a + b; }
  97. 97. #!/usr/bin/env perl use 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: %sn", add( $num_a, $num_b ); __END__ __C__ int add( int a, int b ) { return a + b; }
  98. 98. #!/usr/bin/env perl use 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: %sn", add( $num_a, $num_b ); __END__ __C__ int add( int a, int b ) { return a + b; }
  99. 99. Run it! bash-3.2$ perl cexp1.pl Give me a number: 42 Give me another number: 11 The sum is: 53
  100. 100. Run it again! bash-3.2$ perl cexp1.pl Give me a number: 42 Give me another number: 31.337 The sum is: 73
  101. 101. Run it again! bash-3.2$ perl cexp1.pl Give me a number: 42 Give me another number: 31.337 The sum is: 73 What happened?
  102. 102. Inline::C is CRAZY SMART
  103. 103. int int int int Inline::C is CRAZY SMART
  104. 104. 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: %sn", 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!" ); } }
  105. 105. 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: %sn", 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!" ); } }
  106. 106. 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: %sn", 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!" ); } }
  107. 107. 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: %sn", 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!" ); } }
  108. 108. Run it! bash-3.2$ perl cexp2.pl Give me a number: 42 Give me another number: 11 The sum is: 53 bash-3.2$ perl cexp2.pl
  109. 109. Run it! bash-3.2$ perl cexp2.pl Give me a number: 42 Give me another number: 11 The sum is: 53 bash-3.2$ perl cexp2.pl bash-3.2$ perl cexp2.pl Give me a number: 53.4 Give me another number: 6.54 The sum is: 59.94
  110. 110. Run it! bash-3.2$ perl cexp2.pl Give me a number: 42 Give me another number: 11 The sum is: 53 bash-3.2$ perl cexp2.pl bash-3.2$ perl cexp2.pl Give me a number: 53.4 Give me another number: 6.54 The sum is: 59.94 Give me a number: 42 Give me another number: 6.54 I don't know what to do! at cexp2.pl line 16, <STDIN> line 2.
  111. 111. Once you get this far, everything you need is in perlapi.
  112. 112. Let's do something with arrays.
  113. 113. What does an AV look like? sv_any sv_refcnt sv_flags array fill max SV xpvav *some fields omitted alloc array len SV SV*[] SV ... ...
  114. 114. #!/usr/bin/env perl use 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: %sn", join ", ", @$result; __END__
  115. 115. #!/usr/bin/env perl use 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: %sn", join ", ", @$result; __END__
  116. 116. 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 ); }
  117. 117. 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 ); }
  118. 118. 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 ); }
  119. 119. 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 ); }
  120. 120. 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 ); }
  121. 121. 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 ); }
  122. 122. 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_noinc( (SV *)return_array ); }
  123. 123. Run it! bash-3.2$ perl cexp3.pl Give me some numbers: 4,5,6,23 The squares are: 16, 25, 36, 529
  124. 124. Let's do something with hashes.
  125. 125. What does an HV look like?
  126. 126. What does an HV look like? (Diagram missing
  127. 127. What does an HV look like? (Diagram missing (So I stole this one))
  128. 128. What does an HV look like? (Diagram missing (So I stole this one))
  129. 129. #!/usr/bin/env perl use 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: %sn", join ", ", %$result; __END__
  130. 130. __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_noinc( (SV *)result ); }
  131. 131. Run it! bash-3.2$ perl cexp4.pl Give me some words: foo,bar,baz,baz,foo,quux,narf,poit The uniques are: bar, narf, baz, poit, quux, foo
  132. 132. What is Magic?
  133. 133. Not that terrifying.
  134. 134. Not that terrifying. (code sample missing)
  135. 135. Magic is a linked list of function pointers attached to a *SV.
  136. 136. Magic is a linked list of function pointers attached to a *SV. The functions implement custom read/write behavior.
  137. 137. 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.
  138. 138. $ENV{foo} = "blah";
  139. 139. $ENV{foo} = "blah"; assignment op
  140. 140. $ENV{foo} = "blah"; assignment op Magic on %ENV ?
  141. 141. $ENV{foo} = "blah"; assignment op Magic on %ENV ? Look up write function
  142. 142. $ENV{foo} = "blah"; assignment op Magic on %ENV ? Look up write function call libc setenv()
  143. 143. tie() is also implemented via Magic.
  144. 144. Terror defeated!
  145. 145. Where do we go from here?
  146. 146. Resources: perlguts For details on how to manipulate Perl's data structures.
  147. 147. Resources: perlapi For a comprehensive reference to (almost) everything you need to make perl do stuff.
  148. 148. Resources: Perlguts Illustrated For pretty diagrams and explication.
  149. 149. Resources: Inline::C Cookbook For common solutions to problems interfacing between Perl and C
  150. 150. Resources:
  151. 151. Resources: Code samples http://github.com/friedo/perl-api-terror
  152. 152. London Perl Workshop Thank you. Mike Friedman friedo@friedo.com http://friedo.com/ http://github.com/friedo/perl-api-terror

×