writing perl extensions: there’s more than one way to do it

17
Writing Perl Extensions: There’s more than one way to do it.

Upload: charlotte-perry

Post on 01-Jan-2016

216 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Writing Perl Extensions: There’s more than one way to do it

Writing Perl Extensions:There’s more than one way to do it.

Page 2: Writing Perl Extensions: There’s more than one way to do it

Why write an extension?

• speed

• reuse legacy code or libraries written in other languages

• add new language features

• example: The Perl Data Language

Page 3: Writing Perl Extensions: There’s more than one way to do it

What is an extension?• Compiled code which can be loaded (usually

dynamically) into a Perl program.

your_extension.pm:...require DynaLoader;bootstrap your_extension;...

• loads shared library -- @INC/auto/your_extension/libyour_extension.{ a so dll }

• Now functions from that shared library can be called as you would call Perl functions.

Page 4: Writing Perl Extensions: There’s more than one way to do it

Methods of writing an extension.

• write raw C code yourself

• use XS to glue your C code and perl

• use swig to create multi-language glue

• use Inline::C to do *all* the work for you

• use PDL::PP to create PDL aware XS code

Page 5: Writing Perl Extensions: There’s more than one way to do it

what we’re going to do.

• Write and extension which executes C code which looks like this:

char * hello(char * who) {

char * message = malloc(...);sprintf(message,”Hello %s\n”,who);return message;

}

Which does the equivilant ofsub hello { return “Hello $_[0]\n”; }

Page 6: Writing Perl Extensions: There’s more than one way to do it

Write your extension manually in C.

#include "EXTERN.h"#include "perl.h"#include "XSUB.h"

XS(XS_your_extension_hello) { dXSARGS; if (items != 1)

Perl_croak(aTHX_ "Usage: your_extension::hello(who)"); {

char * who = (char *)SvPV(ST(0),PL_na);char * RETVAL;dXSTARG;

RETVAL = malloc(100 * (sizeof (char)));sprintf(RETVAL, "hello %s\n",who);

sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; } XSRETURN(1);}

XS(boot_your_extension) { dXSARGS; char* file = __FILE__; XS_VERSION_BOOTCHECK ; newXS("your_extension::hello", XS_your_extension_hello, file); XSRETURN_YES;}

Page 7: Writing Perl Extensions: There’s more than one way to do it

Write a .xs file and use xsubpp to do most of the work for you.

#include "EXTERN.h"#include "perl.h"#include "XSUB.h"

MODULE = your_extension PACKAGE = your_extension

char * hello(who);char * who;

CODE:RETVAL = malloc(100 * (sizeof (char)));sprintf(RETVAL, "hello %s\n",who);

OUTPUT:RETVAL

Page 8: Writing Perl Extensions: There’s more than one way to do it

XS has a learning curve...

• perldoc perlxs and perlxstut (the xs tutorial) to learn lots of crazy things about .xs files.

• knowing perlguts and perlapi also helps.

Page 9: Writing Perl Extensions: There’s more than one way to do it

Use h2xs to make your .xs file from a header file.

• h2xs will scan a C .h file and do the right thing ™ to create the appropriate glue code to link your C functions and Perl.

• Always start with h2xs anyway, even if you’re not using xs -- because it sets up a Makefile.PL.

Page 10: Writing Perl Extensions: There’s more than one way to do it

Use swig to create simpler, multi-language interfaces.

• xs is very specific to Perl and its internals, you end up getting your hands dirty with it… useful sometimes but not always necessary.

• swig extensions can be easily be retarget’d to Python, Scheme, Guile, Tcl and Java.

Page 11: Writing Perl Extensions: There’s more than one way to do it

SWIG:Simplified Wrapper and Interface Generator

>swig -perl5 example.icreates => example.pm , example_wrap.c , example.doc

Must compile manually or use MakeMaker.pm to write a Makefile for you.

>gcc example.c # compile your file>gcc example_wrap.c -I<perl-header-location>>ld -shared example.o example_wrap.o -o example.so

Page 12: Writing Perl Extensions: There’s more than one way to do it

What SWIG does for you.

• Your C functions can be now called from perl. You can specify default arguments in the interface file.

• Global variables and #defined constants become package variables.

----example.i----- ---- example.pm -----

%module example use exampleint foo(int a); &example::foo(5)void bar(double, double b=3.0); &example:bar(4.4)double foobar; $example::foobar#define barfoo 5 $example::barfoo

Page 13: Writing Perl Extensions: There’s more than one way to do it

SWIG features.

• doubles, ints, char *, etc. get passed around as you would expect (and hope).

• pointers get passed to and from perl as blessed references ($$ref is C pointer).

• special magic exists for accessing C arrays.

• perl “shadow classes” may be used interface to C structs and C++ classes.

Page 14: Writing Perl Extensions: There’s more than one way to do it

Make your life simpler with Inline

use Inline C;

print "9 + 16 = ", add(9, 16), "\n"; print "9 - 16 = ", subtract(9, 16), "\n";

__END__ __C__ int add(int x, int y) { return x + y; } int subtract(int x, int y) { return x - y; }

Page 15: Writing Perl Extensions: There’s more than one way to do it

more Inline

perl -e 'use Inline C=>q/void greet(){printf("Hello, world\n");}/;greet'

Page 16: Writing Perl Extensions: There’s more than one way to do it

Inline.pm

• uses Inline::<language>.pm to do all the work based on the language you specify.

• supports: passing of various data types, multiple return values, variable argument lists, and if you’re really crazy, evaluation of C code at runtime.

Page 17: Writing Perl Extensions: There’s more than one way to do it

A few short words about the PDL preprocessor.

In the file example.pd:

pp_def( ‘sumover’,Pars => ‘a(n); [o] b();’,Code => ‘

double tmp=0;loop(n) %{

tmp += $a();%}$b() = tmp;’

);

• There’s also an Inline::PDLpp version.