Sie sind auf Seite 1von 35

EASY NATIVE WRAPPERS WITH

SWIG
2014 Barcelona Perl Workshop

Text
Every time you open a pipe to a program to do something
that Perl already knows how to do, God kills a kitten.

Check CPAN to save kittens.

- @pplu_io

Going Native
Obscure/Propietary libraries
Legacy code
Code Optimization*
Test harness
Glue

XS

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.
-perlxs 1:1

Hooking Perl to C using XS requires you to write a


shell.pm module to bootstrap an object file that has
been compiled from C code, which was in turn
generated by xsubpp from a.xs source file
containing pseudo-C annotated with an XS interface
description.

Brian D. Foy, Perl Best Practices

Hooking Perl to C using XS requires you


to write a shell.pm module
to bootstrap an object file
that has been compiled from C code,
which was in turn
generated by xsubpp
from a.xs source file
containing pseudo-C
annotated with an XS interface description.
Brian D. Foy, Perl Best Practices

If that sounds horribly complicated,


then you have achieved an accurate
understanding of the use of xsubpp.

Brian D. Foy, Perl Best Practices

Inline::C

Its C, but Inline!

Inline::C
#!/usr/bin/env perl
use strict;
use Inline C => << 'END_C';
void hello() {
printf("Hello, world!");
}
END_C
!

hello();

How does it work?

Live demo

SWIG
Simplified
Wrapper and
Interface
Generator

SWIG is an interface compiler that connects


programs written in C and C++ with scripting
languages such as Perl, Python, Ruby, and Tcl.
http://www.swig.org/exec.html

Purpose

Prototyping & Debugging


Systems Integration
Build extension modules

SWIG
Open Source (GPL)
Created in 1995 by Dave Beazley
Support for a couple dozen languages by 2014
http://www.swig.org/

Supported Languages
Tcl

Ocaml

Common Lisp

Python

Pike

Perl

C#

Octave

Java

Scheme

Go

Ruby

Modula-3

PHP

Lua

Javascript

http://www.swig.org/compat.html#SupportedLanguages

Interface definition
/* File : example.i */
!

%module example
!

%inline %{
extern int
gcd(int x, int y);
extern double Foo;
%}

C file
/* File : example.c */
!
/* A global variable */
double Foo = 3.0;
!
/* Compute the greatest common divisor of positive
integers */
int gcd(int x, int y) {
int g;
g = y;
while (x > 0) {
g = x;
x = y % x;
y = g;
}
return g;
}

Build Wrapper

swig -perl example.i

Compile & Link (Ideal)


cc -c example_wrap.c
!

cc -c example.c
!

ldd example_wrap.o example.o


example.so

-o

Compile & Link (Real World)


cc -c -fno-common -DPERL_DARWIN -fno-strict-aliasing pipe -fstack-protector -I/usr/local/include -I/opt/
local/include -I/Users/arturo/perl5/perlbrew/perls/
perl-5.10.1/lib/5.10.1//darwin-2level/CORE/
example_wrap.c
!

cc -c -fno-common -DPERL_DARWIN -fno-strict-aliasing pipe -fstack-protector -I/usr/local/include -I/opt/


local/include -I/Users/arturo/perl5/perlbrew/perls/
perl-5.10.1/lib/5.10.1//darwin-2level/CORE/ example.c
!

env MACOSX_DEPLOYMENT_TARGET=10.3 cc -bundle undefined dynamic_lookup -L/usr/local/lib -L/opt/


local/lib -fstack-protector example_wrap.o example.o
-o example.bundle

Hello, SWIG!

perl runme.pl
The gcd of 42 and 105 is 21
Foo = 3
Foo = 3.1415926

Getting There

Simpler interface file


Add SWIG to build chain

(#|%)include
%module MyModule
%{
#include "mymodule.h"
%}
!

%include "mymodule.h"

Makefile.PL
use 5.008000;
use Config;
use ExtUtils::MakeMaker;
use vars qw($version);
$version='0.1';
my $cmd = qq{swig -outdir lib -o Fact_wrap.c -perl Fact.i};
print "Executing $cmd\n";
system($cmd);
if($?==-1) {
die("failed to execute: $!");
} elsif($?>0) {
die("Error creating perl wrapper: $?");
}
WriteMakefile(
NAME
=> 'Fact',
VERSION
=> $version,
PREREQ_PM
=> {},
DEFINE => '-DMACOSX '.$Config{ccflags},
INC
=> '',
OBJECT => '$(O_FILES)',
clean => {
FILES => 'lib/Fact.pm Fact_wrap.c',
},
PMLIBDIRS => [ 'lib', 'lib/Fact' ],
);

Live demo!

structs
struct Vector {
double x,y;
};
package Vect::Vector;
use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
@ISA = qw( Vect );
%OWNER = ();
%ITERATORS = ();
*swig_x_get = *Vectc::Vector_x_get;
*swig_x_set = *Vectc::Vector_x_set;
*swig_y_get = *Vectc::Vector_y_get;
*swig_y_set = *Vectc::Vector_y_set;

Sane Accessors

my $v = Vect::Vector->new();
$v->{x}=3;
$v->{y}=4;

Distribute on CPAN

No need to force swig dependency


Include the generated wrapper (*_wrap.c, *.pm)
Include the interface definition as a courtesy

Tip of the Iceberg


C++
Exceptions
Typemaps
%perlcode

++$learn
http://www.slideshare.net/daoswald/getting-startedwith-perl-xs-and-inlinec
Cozens, Simon. Advanced Perl Programming
Orwant, Jon. Computer Science & Perl Programming
http://www.swig.org/

Q&A

Thank you!
@codehead
javier@rodriguez.org.mx
scribd.com/javierrgz