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

It’s 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

R

Perl

C#

Octave

Java

Scheme

Go

Ruby

Modula-3

D

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

Sign up to vote on this title
UsefulNot useful