• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Embed--Basic PERL XS
 

Embed--Basic PERL XS

on

  • 1,474 views

Ever wanted to get C to run in Perl. Well here is one place to start

Ever wanted to get C to run in Perl. Well here is one place to start

Statistics

Views

Total Views
1,474
Views on SlideShare
1,471
Embed Views
3

Actions

Likes
1
Downloads
14
Comments
0

2 Embeds 3

http://www.linkedin.com 2
https://twitter.com 1

Accessibility

Categories

Upload Details

Uploaded via as OpenOffice

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Embed--Basic PERL XS Embed--Basic PERL XS Presentation Transcript

    • Perl XS By John Scoles The Pythian Group Black Art? Your Handy Friend ? Misunderstood Brain Sucking Zombie from Hell?
    • My XS Story! The funny thing is the Chinese use the same word for catastrophe as they use for opportunity
    • In The Beginning
      • 1800+ line Makefile.PL
      • 1000+ lines of XS
      • 800+ lines of Perl
      • 5300+ lines of pure 'C'
    • My 'C' Background
      • I can Spell 'c' correctly 87.654% of the time 18 times out of 20.
    • My XS Background at the time
      • Well I know of them!
      Bart Simpson said it best when asked if he knew long division or multiplication
    • A Complete
      • FNG
      • NEWBIE
      • RETARD
      • Whatever
    • So as Johny Cash would say
      • I Fell into a Burning Ring of Fire
    • But?
      • I Survived
    • So I went Looking for Answers
      • What there was, wasn't much
      • However I did learn 10 different ways to say “Hello World”
      • What there was, didn't help much
      • What there was, and still is, was dated
      • What there was, usually ended with
      • “ Read Perl Guts”
    • Why Is This?
      • This sums up the nature of XS programming
      • There are 10 ways to do the same thing!
      • None of them are 100% wrong
      • None of them are 100% right
    • Lets go back to the start
        • We all know that Perl is written in 'C'
        • Big Deal most languages are written in 'C'
        • Most 'C' stuff will be familiar to a 'Perl' programmer
        • Perl is very cozy with 'C'
    • A Few Things to know about 'C'
      • Can't do shit without a 'lib'
      • “I stand on the shoulders of giants!”
      • NANOS GIGANTIUM HUMERIS INSIDENTES
        • Compiled
        • Strictly Typed
        • No Memory Management
        • Function params are by value only
    • A Few Things to say about Perl
        • Interpreted
        • Loosely Typed
        • Managed Memory
        • Function params are by 'Ref' only
        • Perl is Just 'C' without types
    • Stop, Look, Listen!
        • What is it we are trying to do?
        • Credits to Navy Beans it is already on CPAN
        • Access an API
        • Improve performance of Perl
        • Link into a static Lib
    • How about DBI and DBD::Oracle
      • Access an API (OCI) for DBD::Oracle for sure
      • 'C' for DBI to make it speedy for one
      • 26 lines of code to do a fetch
      • Way back in the dark days there was a
      • direct link to OCI but it has died
      • Now with Dynamic Linking no need for static perl
    • Part the Second
      • 'C' and 'Perl' in Detail
      • Libs
      • Memory
      • Data
    • Data in 'C'
      • “ Those that go down to the 'C' in Structs”
      • Defined Types (U32, oratext)
      • Arrays of types (int[], char[])
      • Primitive types (int char etc)
      • Structs (named collection of types)
    • Struc
      • struc say_hi_in {
      • char* english;
      • char* french;
      • int* binary;
      • }
      • Must be declared at compile time
      • It takes up a block of memory
      • So an unitialized struc takes up the same space as an initialized one
      • NOT A HASH!!!
    • Memory in 'C'
      • “ If it is the Captain's mess? Let him clean it up!”
      • We have to do it.
      • malloc
      • free
      • 'C' is dumb must know what type it is pointing to
      • Pointers and such *,& and **
        • * a pointer to something
        • & the value the Pointer is pointing to
        • ** a pointer to a pointer
        • char * name;
    • Libs in 'C'
      • Points to an Object file .obj, .o, .so, .dll or even an exe
      • That can be shared
      • A .h or 'header file' is not necessarily code it is just a promise of code needed at compile time.
      • Usually just a prototype of the function or struct.
    • Data in Perl
      • Metadata
      • struc sv {
      • void* sv_any;
      • U32 sv_refcnt;
      • U32 sv_flags;
      • }
      • or Perl knows about itself.
      • This is ' undef ' in Perl!!!!
    • Our first look of the “Guts” of Perl
      • struc sv {
      • void* sv_any;
      • U32 sv_refcnt;
      • U32 sv_flags;
      • }
      • sv_any
      • Is a pointer to any other of the 'Perl' strucs
      • sv_refcnt
      • A count of the number of times this struc has been referenced
      • sv_flags
      • Holds the metadata of a 'Perl' variable.
        • It utilizes bit logic (bitmask)
    • Memory in 'PERL' II
      • When an object is referenced it is
      • Incremented by one
      • sv_refcnt
        • When an object goes out of scope it is
        • decremented by one
        • (most times)
        • (most times)
        • When it reaches 0 it is garbage collected by Perl
        • And the memory is freed
    • Libs in 'Perl'
      • A .pm file is code t hat can be shared .
    • How 'C' and 'Perl' Work
      • 'C'
        • Source ->
        • Compiler ->
        • Machine Code
      • 'Perl'
        • Sour c e ->
        • Interpreter ->
        • Syntax Tree ->
        • Interpreter ->
        • Machine Code
        • Syntax Tree->
        • {opcodes} =
        • struc{}
        • struc{} ->xsub pointer
        • If this just happens to point to a 'C' function
        • It will run
    • Finally down to Brass Tacks
      • Thank you good by:)
        • X
        • External
        • S
        • Subroutines
        • eXternal Subroutines or
        • XS
    • Now Some Code
      • Far be it form me to break with tradition
      • #Include <stdio.h>
      • void print_hi_larry(void) {
      • printf(“Hello Larry!”);
      • }
      • Int main(int argc,char *argv[]){
      • print_hi_larry();
      • exit(0);
      • }
        • So to the left is hello Larry in 'C'
    • How about a Perl File for it
      • lib/Hi_ larry.pm
      • Hi_ larry.xs
      • Makefile.PL
      • README
      • t/test.t
      • Changes
      • MANIFEST
        • Like most things in perl we have a Helper called
        • h2sx
        • In our case we do
        • H2sx -A -n Hi_ larry
        • And it generates all of our perl files thank you very much
    • So all we do is open the .xs file and add in our includes and function but not the main
      • #include “EXTERN.h”
      • #include perl.h”
      • #include XSUB.h”
      • #Include <stdio.h>
      • void print_hi_ larry (void) {
      • printf(“Hello Larry !”);
      • }
      • MODULE = Hi_ larry PACKAGE = Hi_ larry
      • void
      • print_hi_ larry ();
    • Now edit the Hi_ larry.pm
      • package Hi_ larry ;
      • use 5.008009;
      • use strict;
      • use warnings;
      • Use base (qw(Exporter DynaLoader))
      • @EXPORT_OK
      • our @EXPORT = qw( print_hi_ larry () );
      • our $VERSION = '0.01';
      • 1;
      • __END__
    • How about the test file as well
      • use Test::More tests => 2;
      • BEGIN { use_ok('Hi_larry') };
      • ok(Hi_ larry ::print_hi_ larry ,&quot;Hello Larry &quot;)
    • Now everyones fab
      • Perl Makefile.PL
        • c:>nmake test
        • And at the very end
        • t/Hi_larry....ok
        • Files=1, Tests=2, 0 wallclock secs ( 0.00 cusr + 0.00 csys = 0.00 CPU)
        • All tests successful
        • <--John don't forget to Insert lines of compiler gobbliegook here -->
    • So what is going on?
      • Well this really comes down to black majik and it differs form OS to OS and perl to perl lets just say
      • 1) our XS code is converted to 'C' (xsubpp)
      • 2) this code is compiled
      • 3) that compiled code is then transformed into something that can be shared into our 'Perl'
    • Some more Black Majik
      • We did get a generated '.c' file that you can look at that at your own peril.
      • But how does xsubpp know how to get data back and forth between 'C' and 'Perl'.
      • Well we know everything in Perl is a struc so it is a rather simple trick. It uses a typemap.
    • Typemap
        • Not much to it. A simple lookup table broken into three parts
        • Basic types
        • unsigned Int T_UV
        • unsigned Long T_UV
        • size_t T_UV
        • STRLEN T_UV
        • Input types
        • T_UV $var =($type)SvUV($arg)
        • Output types
        • T_UV sv_setuv($arg,(UV)$var)
        • Hey look at that we see perl guts again
        • To h2xs or not h2xs
        • To start yes
        • Good Beginnings = Good Endings
        • Keep It Simple Stupid
        • Kiss
        • Big differences between versions and systems
        • What might be good for the writer of h2sx might not be good for you
        • Get your 'C' to compile first
        • For a straight Lib port Yeah OK
    • What is in an .XS
        • Many ways to do anything and few rules
        • Chaos is great isn't it
        • Not quite 'Perl' and not quite 'C'
        • Not a Language
        • A large set of 'C' macros that we can use
        • Always in upper case
        • and most times followed by a “:”
    • Anatomy of an xs file
        • Starts with the three wise men
        • #include &quot;EXTERN.h&quot;
        • #include &quot;perl.h&quot;
        • #include &quot;XSUB.h&quot;
        • Next our C code or Not
        • In DBD::ORACLE there is none we compile it first and use
        • #include &quot;Oracle.h&quot;
        • As our only line of 'C' code in oracle.xs
        • At any time we can do our old 'C' friend
        • #ifdef
    • MODULE, PACKAGE, PREFIX, come next
        • MODULE = Hi_ larry PACKAGE = Hi_ larry
      • MODULE
      • So anything before the first one is 'C'
      • PACKAGE
      • Says my XS code starts here
      • Lets us organize our code
      • We can switch them up so your code can be non- contiguous
    • MODULE = Apache PACKAGE = Apache PREFIX = mod_perl INCLUDE: Oracle.xsi We can name it anything we want as long as it is an xs file .xsi seems to be the norm PREFIX Does the opposite of what you would think Strips off the prefix from the 'XS' functions I. E. Apache.xs int mod_perl_sent_header(r, val=0) And in perl it is called as sent_header(r, val=0) Next!
    • Now your Xsub
        • The simplest form has three parts
        • A return value description
        • And finally a description of the argument types
        • The name of the Xsub and its arguments
        • print_hi_ larry ();
        • void
        • <--John rember to change this to one that has arguments -->
    • Some Examples
      • #include <string.h>
      • STRLEN
      • strconcat(char* str1,char* str2, char* outstr){
      • strcpy(outstr, (const char*) srt1);
      • strcat(outstr,(const char*) str2);
      • return strlen(outstr);
      • }
        • And now the XS part
        • STRLEN
        • strconcat(str1, str2)
        • CODE:
        • PREINIT:
        • char* str1
        • char* str2
        • STRLEN length
        • length = strlen( str1) + strlen(str2)+1;
        • New(0,RETVAL,length,char);
        • OUTPUT:
        • RETVAL
        • Safefree(RETVAL);
        • CLEANUP:
        • length = strconcat(str1,str2,RETVAL);
    • The Black Majik
        • PREINIT:
        • CODE:
        • OUTPUT:
        • RETVAL
        • Lets you declare extra variables
        • 'C' code follows me
        • A special 'C' value just for you. That holds the 'return value'
        • Gives us a way to clean any messes we made
        • CLEANUP:
        • Used with CODE: to send RETVAL back to 'Perl'
    • The Evil Dark Majik with a -6 saving throw
        • Safefree(RETVAL);
        • void New(0,void* pointer, int length, type):
        • Perl Guts
        • This allocates some memory for us.
        • New(0,RETVAL,length,char):
        • length is the new length we calculated
        • char is what it is
        • void Safefree(void* pointer);
        • This deallocates some memory for us.
        • RETVAL which is a pointer to the memory we allocated
        • RETVAL which is a pointer to the memory we allocated
    • Interface Design
        • Make it as Perlish as possible
        • my $length = strconcat($str1.$str2,$outstring);
        • Is just plain bad.
        • Do not supply what we already know
        • my $fullname = full_name($first,$len_first,$last,$len_last)
        • Use PREFEX
        • MODULE = OCI PCKAGE = OCI
        • SV
        • oci_ping()
        • Would come out in perl as OCI::oci_ping()
    • How About Summing an Array
        • Here is our little 'C' that takes the number of ints to add, and an array of ints
        • typedef int intArray;
        • int sum(int num, intArray *array){
        • int thesum =0;
        • int thecount;
        • for (count = 0; count <num;count++){
        • thesum += array[count];
        • }
        • return thesum;
        • }
    • And our XS
        • int
        • sum_a_list(array, ...)
        • '...' is another XS thing meaning I do not know how many arguments there are
        • IntArray * array
        • Will not compile. A XS does not know what an 'IntArray' is.
        • We solve this by adding our own typemap file in the build dir
        • intArray * T_ARRAY
        • CODE:
        • RETVAL = sum(ix_array,array);
        • OUTPUT:
        • RETVAL
        • CLEANUP:
        • Safefree(array);
        • XS does know what a T_ARRAY is though
    • More Black Majik
        • ix_array
        • You might of noticed this little fellow
        • '...' will create the 'itmes' value for you automatically
        • This is the 'items' of the '...' that was passed in on the stack.
        • Int
        • not_number_count(...)
        • CODE:
        • for(i=0;i< itmes; i++){
    • The Stack
        • We have our one Gut Macro just for called ST(i) where i is the 0 based index of the stack
        • We might as well talk about the 'stack'
        • So in our last example if we add
        • SV *sv = ST(i);
        • As the next line. We would be saving a referace to the Stack value in a local SV called sv.
        • One thing with the Stack is it normally have only one value on the way back (RETVAL)
        • Until now!
    • Just Plain Eval Majik
        • Many times in Perl we want to return a list of alternating keys and values
        • Here is some of the XS code for this.
        • %say_hi = Hello::say_hi_in('eu');
        • Print $say_hi{'french'};
        • void
        • say_hi_in(local)
        • char * local
        • PPCODE:
        • switch (local) {
        • case REGION_EU:
        • EXTEND(SP,16);
        • PUSHs(sv_2mortal(newSVpv(“french”,”Bonjour”)));
        • PUSHs(sv_2mortal(newSVpv(“english”,”Hello”)));
    • The explanation
        • PPCODE:
        • Tells XS that I will be creating the return Stack
        • EXTEND(SP,16);
        • Tells XS to extend the return stack to 16 spots
        • PUSHs(sv_2mortal(newSVpv(“french”,”Bonjour”)));
        • PUSHs puts our value on the Stack
        • sv_2mortal
        • More Guts Majik. In this case we have to tell 'Perl' that the new value we are pushing is Mortal as only copy of the sv is assigned in Perl. So now they will be garbage collected.
        • newSVpv
        • Another Guts macro that creates a SV from a string.
    • How about embedding PERL
        • Surprisingly easy
        • #includes <EXTERN.h>
        • #includes <perl.h>
        • You Just include it.
        • static PerlInterpreter *my_perl;
        • int main(intargc,char **argv){
        • Char* command_line[] ={“”.”-e”,”print ”Hello C this is Larry ”;”};
        • }
        • my_perl = perl_alloc();
        • perl_constrct(my_perl);
        • perl_run(my_perl);
        • perl_parse(my_perl, NULL,3, command_line,(char **)NULL);
        • perl_destruct(my_perl);
        • perl_free(my_perl);
        • return 0;
    • Where to go from here
        • Well there is only 1 book
        • Extending and Embedding Perl
        • By Tim Jeness and Simon Cozens
        • Steal from other people like I do
    • ?
      • Its not the Falling the hurts
      • It is the sudden stop at the bottom that will kill you