python with a swig of c++

22
Python with a of C++ Bob McNaughton PyData NYC 2015

Upload: bobmcn

Post on 12-Apr-2017

368 views

Category:

Software


1 download

TRANSCRIPT

Page 1: Python with a  SWIG of c++

Python with a of C++

Bob McNaughtonPyData NYC 2015

Page 2: Python with a  SWIG of c++

• Simplified Wrapper and Interface Generator• Allow the use of C/C++ from other languages• http://swig.org/• Originally developed by Dave Beazly• First released in February 1996• Latest release 3.0.7, August 3rd, 2015• Actively maintained, several releases a year

What is SWIG?

Page 3: Python with a  SWIG of c++

What other languages?$ swig -helpTarget Language Options -allegrocl - Generate ALLEGROCL wrappers -chicken - Generate CHICKEN wrappers -clisp - Generate CLISP wrappers -cffi - Generate CFFI wrappers -csharp - Generate C# wrappers -guile - Generate Guile wrappers -java - Generate Java wrappers -lua - Generate Lua wrappers -modula3 - Generate Modula 3 wrappers -mzscheme - Generate Mzscheme wrappers -ocaml - Generate Ocaml wrappers -perl - Generate Perl wrappers -php - Generate PHP wrappers -pike - Generate Pike wrappers -python - Generate Python wrappers -ruby - Generate Ruby wrappers -sexp - Generate Lisp S-Expressions wrappers -tcl - Generate Tcl wrappers -uffi - Generate Common Lisp / UFFI wrappers -xml - Generate XML wrappers

Page 4: Python with a  SWIG of c++

Are there any alternatives?• Cython• cTypes• Cpython C API

Page 5: Python with a  SWIG of c++

Why would you ever want to call C/C++ from Python?

• Speed• Existing C/C++ libraries

• With or without source• Develop faster initially with Python

• Speed up parts that the profiler shows as critical

Page 6: Python with a  SWIG of c++

C++ Fibonacci if (n < 0) nextTerm = -1; else if (n == 0) nextTerm = 0; else if (n == 1) nextTerm = 1; else { firstTerm = 0; secondTerm = 1; for (int i = 0; i < n-1; ++i) { nextTerm = firstTerm + secondTerm; firstTerm = secondTerm; secondTerm = nextTerm; } }

Page 7: Python with a  SWIG of c++

Python Fibonaccidef fib(n): if (n < 0): return -1 elif (n == 0): return 0 elif (n == 1): return 1 else: a,b = 0,1 for i in range(n-1): a,b = b,a+b return a

Page 8: Python with a  SWIG of c++

How do they compare?

• Had to run both multiple times to get something measurable• C++ significantly faster• Python doesn’t overflow

Page 9: Python with a  SWIG of c++

C++ Library routinelong long fib(int n){ long long firstTerm = 0, secondTerm = 1, nextTerm; if (n < 0) return -1; if (n == 0) return 0; if (n == 1) return 1; for (int i = 1; i < n-1; ++i) { nextTerm = firstTerm + secondTerm; if (nextTerm < secondTerm) // Overflow! return -1; firstTerm = secondTerm; secondTerm = nextTerm; } return nextTerm;}

Page 10: Python with a  SWIG of c++

C++ Header File

long long fib(int n);

Page 11: Python with a  SWIG of c++

Make a shared object or dll

g++ -g –c –o fibl.o fibl.cppg++ -g –shared –fPIC –Wl,-soname,libfib.so –o libfib.so fibl.o

Page 12: Python with a  SWIG of c++

Use this .so from C++#include <iostream>#include <stdlib.h>#include "fib.h" using namespace std; int main(int argc, char* argv[]) { if (argc < 2) { cout << "Usage: " << argv[0] << " <fibonacci number to print>" << endl; return -1; } long n = strtol(argv[1], NULL, 10); for (int i=0; i<100000; i++) { fib(n); } cout << "Fibonacci Number " << n << " is " << fib(n) << endl; return 0;}

Page 13: Python with a  SWIG of c++

Compile with:

g++ -g –L. –lfib –o fibm fibm.cpp

Page 14: Python with a  SWIG of c++

How does it compare to no .so?

Slightly slowerStill overflows

Page 15: Python with a  SWIG of c++

Now call the same .so from Python

SWIG interface file, fibl.i

%module fibl%{#include "fib.h"%}%include "fib.h"

Page 16: Python with a  SWIG of c++

Run SWIG on the interface file

swig –python fibl.i

Produces fibl_wrap.c and fibl.py

Page 17: Python with a  SWIG of c++

Turn the SWIG outputs into a .so

g++ -g –fpic –c fibl_wrap.c –I /usr/include/python3.5mg++ -g –shared –L. –lfib fibl_wrap.o –o _fibl.so

$ ldd _fibl.so linux-vdso.so.1 (0x00007ffdd6d9e000) libfib.so => ./libfib.so (0x00007fcbdc07e000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007fcbdbcc9000) libm.so.6 => /usr/lib/libm.so.6 (0x00007fcbdb9cb000) libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007fcbdb7b4000) libc.so.6 => /usr/lib/libc.so.6 (0x00007fcbdb410000) /usr/lib64/ld-linux-x86-64.so.2 (0x000055f6c1f6c000)

Page 18: Python with a  SWIG of c++

Now call the .so from Python

import sysimport fibl x=int(sys.argv[1]) for i in range (1, 100000): fibl.fib(x) print("Fibonacci number", x, "is", fibl.fib(x))

Page 19: Python with a  SWIG of c++

Now how do the results compare?

C++ still faster, but it is much closer nowPython now overflows

Page 20: Python with a  SWIG of c++

What about a more complicated example?

#include <rw/sortvec.h>#include <rw/collstr.h> int main (){ RWSortedVector sv; sv.insert(new RWCollectableString("dog")); sv.insert(new RWCollectableString("cat")); sv.insert(new RWCollectableString("fish")); RWSortedVectorIterator next(sv); RWCollectableString* item; while( (item = (RWCollectableString*)next() ) != 0) std::cout << *item << std::endl; sv.clearAndDestroy(); return 0;}

Page 21: Python with a  SWIG of c++

Try the obvious SWIG interface file%module fibl%{#include <rw/sortvec.h>#include <rw/collstr.h>%}%include <rw/sortvec.h>%include <rw/collstr.h>

Page 22: Python with a  SWIG of c++

Conclusion

• Works fine for C • C++ can be a problem.• The only option if all you have is a header file and a dynamic library