SlideShare a Scribd company logo
1 of 48
Download to read offline
Extending Python
Francisco Fernández Castaño!
July 2014!
EuroPython, Berlin!
@fcofdezc
Roadmap
• Motivation
• Guidelines
• Native Extensions
• Ctypes
• CFFI
• Conclusions
Caution
Huge topic
Useless examples
Unix ^ CPython centric
Motivation
Why write in C?
Motivation
Speed
Using legacy code
Integration
Guidelines
C artifacts
Static libraries
Shared libraries
Static libraries
$ ar tv libdemo.a
rw-r--r-- 501/20 40 Jul 19 22:34 2014 __.SYMDEF SORTED
rw-r--r-- 501/20 2352 Jul 19 22:33 2014 a.o
rw-r--r-- 501/20 2352 Jul 19 22:33 2014 b.o
Shared libraries
Single copy in memory
Runtime load
Native extensions
C API
Native extensions
Hello world
Native extensions
#add.py
def sum(a, b):
return a + b
#include "Python.h"
// sum function.
static PyObject *
sum(PyObject *self, PyObject *args)
{
PyObject *_a = 0;
PyObject *_b = 0;
PyObject *result = NULL;
!
_a = PyTuple_GET_ITEM(args, 0);
_b = PyTuple_GET_ITEM(args, 1);
result = PyNumber_Add(_a, _b);
!
return result;
}
// Module functions table.
static PyMethodDef
module_functions[] = {
{ "sum", sum, METH_VARARGS, "Sum docstring." },
{ NULL }
};
// This function is called to initialize the module.
PyMODINIT_FUNC
initsum(void)
{
Py_InitModule3("sum", module_functions, "Hello world module.");
}
#include "Python.h"
static PyObject *
sum(PyObject *self, PyObject *args)
{
PyObject *_a = 0;
PyObject *_b = 0;
PyObject *result = NULL;
!
_a = PyTuple_GET_ITEM(args, 0);
_b = PyTuple_GET_ITEM(args, 1);
result = PyNumber_Add(_a, _b);
!
return result;
}
// Module functions table.
static PyMethodDef
module_functions[] = {
{ "sum", sum, METH_VARARGS, "Sum docstring." },
{ NULL }
};
// This function is called to initialize the module.
PyMODINIT_FUNC
initsum(void)
{
Py_InitModule3("sum", module_functions, "Hello world module.");
}
from distutils.core import setup, Extension
setup(name='sum',
version=‘1.0',
ext_modules=[Extension('sum', ['sum.c'])])
$ python
>>> import sum
>>> sum.sum(2, 3)
5
NAME
dlopen -- load and link a dynamic library or bundle
!
SYNOPSIS
#include <dlfcn.h>
!
void*
dlopen(const char* path, int mode);
// Python/dynload_shlib.c
.
.
handle = dlopen(pathname, dlopenflags);
!
if (handle == NULL) {
const char *error = dlerror();
if (error == NULL)
error = "unknown dlopen() error";
PyErr_SetString(PyExc_ImportError, error);
return NULL;
}
if (fp != NULL && nhandles < 128)
handles[nhandles++].handle = handle;
p = (dl_funcptr) dlsym(handle, funcname);
return p;
.
.
.
Memory management
Manual memory management
Python GC - RC
Py_INCREF(x) | Py_DECREF(x)
Cycle detector
Error management
Return NULL pointer as convention
Register Exceptions
Error management
.
.
.
if (err < 0) {
PyErr_SetString(PyExc_Exception, "Command failed");
return NULL;
}
.
.
.
Python 3 differences
!
static struct PyModuleDef examplemodule = {
PyModuleDef_HEAD_INIT,
"sum",
"sum module doc string",
-1,
module_functions,
NULL,
NULL,
NULL,
NULL
};
!
PyMODINIT_FUNC
PyInit_sum(void)
{
PyModule_Create(&examplemodule);
}
CTypes
Advanced FFI for Python
Allows call functions from Shared libs
Create, access, manipulate C data types
CTypes
ctypes type C type
c_bool _Bool
c_char char
c_wchar wchar_t
c_byte char
c_ubyte unsigned char
c_short short
c_ushort unsigned short
c_int int
c_uint unsigned int
c_long long
c_ulong unsigned long
c_longlong __int64 or long long
c_ulonglong unsigned __int64 or unsigned long long
c_float float
c_double double
c_longdouble long double
c_char_p char * (NUL terminated)
c_wchar_p wchar_t * (NUL terminated)
c_void_p void *
CTypes - structs
from ctypes import *
class POINT(Structure):
_fields_ = [("x", c_int),
("y", c_int)]
!
class RECT(Structure):
_fields_ = [("upperleft", POINT),
("lowerright", POINT)]
CTypes - example
Implemented fibonacci as c function
Map as Python code
Measure differences between Python and C
CTypes - example
int fib(int n){
if ( n < 2 )
return n;
else
return fib(n-1) + fib(n-2);
}
CTypes - example
import ctypes
lib_fib = ctypes.CDLL("libfib.so")
!
def ctypes_fib(n):
return lib_fib.fib(ctypes.c_int(n))
!
def py_fib(n):
if n < 2:
return n
else:
return py_fib(n-1) + py_fib(n-2)
CTypes - times
In [3]: %timeit fib.ctypes_fib(20)
10000 loops, best of 3: 63.8 µs per loop
!
In [4]: %timeit fib.py_fib(20)
100 loops, best of 3: 3.62 ms per loop
CTypes - Fortran example
Use of existing fortran code
Take random code at github
https://github.com/astrofrog/fortranlib
Wrap using ctypes
CTypes - Fortran example
.
.
real(dp) function mean_dp(x, mask)
implicit none
real(dp),intent(in) :: x(:)
logical,intent(in),optional :: mask(:)
if(present(mask)) then
mean_dp = sum(x, mask=mask)/size(x)
else
mean_dp = sum(x)/size(x)
end if
end function mean_dp
.
.
CTypes - Fortran example
➜ bin git:(master) ✗ nm -g lib_statistics.so
0000000000001eab T ___lib_statistics_MOD_clipped_mean_dp
0000000000000afc T ___lib_statistics_MOD_clipped_mean_sp
000000000000306c T ___lib_statistics_MOD_mean_dp
0000000000001c55 T ___lib_statistics_MOD_mean_sp
0000000000002db0 T ___lib_statistics_MOD_median_dp
00000000000019b0 T ___lib_statistics_MOD_median_sp
0000000000002544 T ___lib_statistics_MOD_quantile_dp
000000000000115a T ___lib_statistics_MOD_quantile_sp
0000000000002299 T ___lib_statistics_MOD_variance_dp
0000000000000ec3 T ___lib_statistics_MOD_variance_sp
U __gfortran_arandom_r4
U __gfortran_arandom_r8
U __gfortran_os_error
U __gfortran_pack
U __gfortran_pow_i4_i4
U __gfortran_runtime_error
U __gfortran_runtime_error_at
U __gfortran_st_write
U __gfortran_st_write_done
U __gfortran_stop_string
CTypes - Fortran example
from ctypes import *
!
# Statistics fortran lib
st_lib = CDLL(“lib_statistics.so")
!
mean = st_lib.__lib_statistics_MOD_mean_dp
mean.argtypes = [POINTER(c_float*2)]
mean.restype = c_float
!
vals = (c_float*2)(2.0, 3.0)
!
print mean(vals)
CTypes
static PyObject *py_dl_open(PyObject *self, PyObject *args)
{
char *name;
void * handle;
#ifdef RTLD_LOCAL
int mode = RTLD_NOW | RTLD_LOCAL;
#else
/* cygwin doesn't define RTLD_LOCAL */
int mode = RTLD_NOW;
#endif
if (!PyArg_ParseTuple(args, "z|i:dlopen", &name, &mode))
return NULL;
mode |= RTLD_NOW;
handle = ctypes_dlopen(name, mode);
if (!handle) {
char *errmsg = ctypes_dlerror();
if (!errmsg)
errmsg = "dlopen() error";
PyErr_SetString(PyExc_OSError,
errmsg);
return NULL;
}
return PyLong_FromVoidPtr(handle);
}
CFFI
Advanced FFI for Python
Allows call functions from Shared libs
Create, access, manipulate C data types
Both API and ABI access
CFFI
Mostly the same as CTypes
CFFI
Recommended way to extend PyPy
CFFI - ABI
from cffi import FFI
ffi = FFI()
ffi.cdef("""
int printf(const char *format, …);""")
C = ffi.dlopen(None)
arg = ffi.new("char[]", "world")
C.printf("hi there, %s!n", arg)
CFFI - API level
import cffi
ffi = cffi.FFI()
!
ffi.cdef("""
int fib(int n);
""")
!
lib = ffi.verify(r'''
int fib(int n){
if ( n < 2 )
return n;
else
return fib(n-1) + fib(n-2);
}''')
!
print lib.fib(10)
CFFI - API level
import cffi
ffi = cffi.FFI()
!
ffi.cdef("""
int fib(int n);
""")
!
lib = ffi.verify(r'''
int fib(int n){
if ( n < 2 )
return n;
else
return fib(n-1) + fib(n-2);
}''')
!
print lib.fib(“asd”)
Boom!
Traceback (most recent call last):
File "fib.py", line 16, in <module>
print lib.fib("asd")
TypeError: an integer is required
CFFI - API level
from cffi import FFI
ffi = FFI()
ffi.cdef("""
typedef struct {
float x, y;
} point;
""")
point = ffi.new("point *")
point.x = 2.0
point.y = 3.0
static PyObject *b_load_library(PyObject *self, PyObject *args)
{
char *filename_or_null, *printable_filename;
void *handle;
DynLibObject *dlobj;
int flags = 0;
!
.
.
.
if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0)
flags |= RTLD_NOW;
!
printable_filename = filename_or_null ? filename_or_null : "<None>";
handle = dlopen(filename_or_null, flags);
if (handle == NULL) {
const char *error = dlerror();
PyErr_Format(PyExc_OSError, "cannot load library %s: %s",
printable_filename, error);
return NULL;
}
!
dlobj = PyObject_New(DynLibObject, &dl_type);
if (dlobj == NULL) {
dlclose(handle);
return NULL;
}
dlobj->dl_handle = handle;
dlobj->dl_name = strdup(printable_filename);
return (PyObject *)dlobj;
}
Conclusions
Three different ways
Same principles
Less portable -> More portable
Harder -> Easier
Questions?
Danke!

More Related Content

What's hot

C++ Advanced
C++ AdvancedC++ Advanced
C++ Advanced
Vivek Das
 
Pysmbc Python C Modules are Easy
Pysmbc Python C Modules are EasyPysmbc Python C Modules are Easy
Pysmbc Python C Modules are Easy
Roberto Polli
 
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6 1
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6  1ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6  1
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6 1
Little Tukta Lita
 

What's hot (20)

Boost.Python: C++ and Python Integration
Boost.Python: C++ and Python IntegrationBoost.Python: C++ and Python Integration
Boost.Python: C++ and Python Integration
 
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java script
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java scriptCodiLime Tech Talk - Grzegorz Rozdzialik: What the java script
CodiLime Tech Talk - Grzegorz Rozdzialik: What the java script
 
[C++ korea] effective modern c++ study item 3 understand decltype +이동우
[C++ korea] effective modern c++ study   item 3 understand decltype +이동우[C++ korea] effective modern c++ study   item 3 understand decltype +이동우
[C++ korea] effective modern c++ study item 3 understand decltype +이동우
 
Paradigmas de Linguagens de Programacao - Aula #5
Paradigmas de Linguagens de Programacao - Aula #5Paradigmas de Linguagens de Programacao - Aula #5
Paradigmas de Linguagens de Programacao - Aula #5
 
OpenGurukul : Language : C++ Programming
OpenGurukul : Language : C++ ProgrammingOpenGurukul : Language : C++ Programming
OpenGurukul : Language : C++ Programming
 
Threads and Callbacks for Embedded Python
Threads and Callbacks for Embedded PythonThreads and Callbacks for Embedded Python
Threads and Callbacks for Embedded Python
 
Summary of C++17 features
Summary of C++17 featuresSummary of C++17 features
Summary of C++17 features
 
C++ Advanced
C++ AdvancedC++ Advanced
C++ Advanced
 
Basic c++ 11/14 for python programmers
Basic c++ 11/14 for python programmersBasic c++ 11/14 for python programmers
Basic c++ 11/14 for python programmers
 
RAII and ScopeGuard
RAII and ScopeGuardRAII and ScopeGuard
RAII and ScopeGuard
 
Pysmbc Python C Modules are Easy
Pysmbc Python C Modules are EasyPysmbc Python C Modules are Easy
Pysmbc Python C Modules are Easy
 
OpenGurukul : Language : PHP
OpenGurukul : Language : PHPOpenGurukul : Language : PHP
OpenGurukul : Language : PHP
 
C++ via C#
C++ via C#C++ via C#
C++ via C#
 
PHP 8: Process & Fixing Insanity
PHP 8: Process & Fixing InsanityPHP 8: Process & Fixing Insanity
PHP 8: Process & Fixing Insanity
 
Tiramisu概要
Tiramisu概要Tiramisu概要
Tiramisu概要
 
C Programming Tutorial - www.infomtec.com
C Programming Tutorial - www.infomtec.comC Programming Tutorial - www.infomtec.com
C Programming Tutorial - www.infomtec.com
 
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6 1
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6  1ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6  1
ฟังก์ชั่นย่อยและโปรแกรมมาตรฐาน ม. 6 1
 
Kamil witecki asynchronous, yet readable, code
Kamil witecki asynchronous, yet readable, codeKamil witecki asynchronous, yet readable, code
Kamil witecki asynchronous, yet readable, code
 
TDD in C - Recently Used List Kata
TDD in C - Recently Used List KataTDD in C - Recently Used List Kata
TDD in C - Recently Used List Kata
 
Vocabulary Types in C++17
Vocabulary Types in C++17Vocabulary Types in C++17
Vocabulary Types in C++17
 

Similar to Extending Python - EuroPython 2014

Yapcasia2011 - Hello Embed Perl
Yapcasia2011 - Hello Embed PerlYapcasia2011 - Hello Embed Perl
Yapcasia2011 - Hello Embed Perl
Hideaki Ohno
 
Getting Started Cpp
Getting Started CppGetting Started Cpp
Getting Started Cpp
Long Cao
 
C ISRO Debugging
C ISRO DebuggingC ISRO Debugging
C ISRO Debugging
splix757
 
Functions And Header Files In C++ | Bjarne stroustrup
Functions And Header Files In C++ | Bjarne stroustrupFunctions And Header Files In C++ | Bjarne stroustrup
Functions And Header Files In C++ | Bjarne stroustrup
SyedHaroonShah4
 
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
eugeniadean34240
 

Similar to Extending Python - EuroPython 2014 (20)

Gcrc talk
Gcrc talkGcrc talk
Gcrc talk
 
Create your own PHP extension, step by step - phpDay 2012 Verona
Create your own PHP extension, step by step - phpDay 2012 VeronaCreate your own PHP extension, step by step - phpDay 2012 Verona
Create your own PHP extension, step by step - phpDay 2012 Verona
 
Start Wrap Episode 11: A New Rope
Start Wrap Episode 11: A New RopeStart Wrap Episode 11: A New Rope
Start Wrap Episode 11: A New Rope
 
Notes about moving from python to c++ py contw 2020
Notes about moving from python to c++ py contw 2020Notes about moving from python to c++ py contw 2020
Notes about moving from python to c++ py contw 2020
 
Zn task - defcon russia 20
Zn task  - defcon russia 20Zn task  - defcon russia 20
Zn task - defcon russia 20
 
Yapcasia2011 - Hello Embed Perl
Yapcasia2011 - Hello Embed PerlYapcasia2011 - Hello Embed Perl
Yapcasia2011 - Hello Embed Perl
 
Cluj.py Meetup: Extending Python in C
Cluj.py Meetup: Extending Python in CCluj.py Meetup: Extending Python in C
Cluj.py Meetup: Extending Python in C
 
Getting Started Cpp
Getting Started CppGetting Started Cpp
Getting Started Cpp
 
Php extensions
Php extensionsPhp extensions
Php extensions
 
Take advantage of C++ from Python
Take advantage of C++ from PythonTake advantage of C++ from Python
Take advantage of C++ from Python
 
from java to c
from java to cfrom java to c
from java to c
 
C
CC
C
 
C ISRO Debugging
C ISRO DebuggingC ISRO Debugging
C ISRO Debugging
 
Functions And Header Files In C++ | Bjarne stroustrup
Functions And Header Files In C++ | Bjarne stroustrupFunctions And Header Files In C++ | Bjarne stroustrup
Functions And Header Files In C++ | Bjarne stroustrup
 
Living With Legacy Code
Living With Legacy CodeLiving With Legacy Code
Living With Legacy Code
 
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
20145-5SumII_CSC407_assign1.htmlCSC 407 Computer Systems II.docx
 
Python Bindings Overview
Python Bindings OverviewPython Bindings Overview
Python Bindings Overview
 
Writing MySQL UDFs
Writing MySQL UDFsWriting MySQL UDFs
Writing MySQL UDFs
 
Tdd with python unittest for embedded c
Tdd with python unittest for embedded cTdd with python unittest for embedded c
Tdd with python unittest for embedded c
 
4Developers 2018: Evolution of C++ Class Design (Mariusz Łapiński)
4Developers 2018: Evolution of C++ Class Design (Mariusz Łapiński)4Developers 2018: Evolution of C++ Class Design (Mariusz Łapiński)
4Developers 2018: Evolution of C++ Class Design (Mariusz Łapiński)
 

More from fcofdezc

Extending Python - FOSDEM 2015
Extending Python - FOSDEM 2015Extending Python - FOSDEM 2015
Extending Python - FOSDEM 2015
fcofdezc
 
Biicode OpenExpoDay
Biicode OpenExpoDayBiicode OpenExpoDay
Biicode OpenExpoDay
fcofdezc
 
biicode, reuse and play
biicode, reuse and playbiicode, reuse and play
biicode, reuse and play
fcofdezc
 
Graph databases, a little connected tour
Graph databases, a little connected tourGraph databases, a little connected tour
Graph databases, a little connected tour
fcofdezc
 

More from fcofdezc (13)

Knowing your garbage collector - PyCon Italy 2015
Knowing your garbage collector - PyCon Italy 2015Knowing your garbage collector - PyCon Italy 2015
Knowing your garbage collector - PyCon Italy 2015
 
STM on PyPy
STM on PyPySTM on PyPy
STM on PyPy
 
Knowing your garbage collector - FOSDEM 2015
Knowing your garbage collector - FOSDEM 2015Knowing your garbage collector - FOSDEM 2015
Knowing your garbage collector - FOSDEM 2015
 
Extending Python - FOSDEM 2015
Extending Python - FOSDEM 2015Extending Python - FOSDEM 2015
Extending Python - FOSDEM 2015
 
Extending Python - Codemotion Milano 2014
Extending Python - Codemotion Milano 2014Extending Python - Codemotion Milano 2014
Extending Python - Codemotion Milano 2014
 
Understanding PyPy - PyConEs 14
Understanding PyPy - PyConEs 14Understanding PyPy - PyConEs 14
Understanding PyPy - PyConEs 14
 
Knowing your Garbage Collector / Python Madrid
Knowing your Garbage Collector / Python MadridKnowing your Garbage Collector / Python Madrid
Knowing your Garbage Collector / Python Madrid
 
Knowing your Python Garbage Collector
Knowing your Python Garbage CollectorKnowing your Python Garbage Collector
Knowing your Python Garbage Collector
 
Graph databases - EuroPython 2014
Graph databases - EuroPython 2014Graph databases - EuroPython 2014
Graph databases - EuroPython 2014
 
Biicode OpenExpoDay
Biicode OpenExpoDayBiicode OpenExpoDay
Biicode OpenExpoDay
 
Graph Databases, a little connected tour (Codemotion Rome)
Graph Databases, a little connected tour (Codemotion Rome)Graph Databases, a little connected tour (Codemotion Rome)
Graph Databases, a little connected tour (Codemotion Rome)
 
biicode, reuse and play
biicode, reuse and playbiicode, reuse and play
biicode, reuse and play
 
Graph databases, a little connected tour
Graph databases, a little connected tourGraph databases, a little connected tour
Graph databases, a little connected tour
 

Recently uploaded

Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 

Recently uploaded (20)

%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - Keynote
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 

Extending Python - EuroPython 2014

  • 1. Extending Python Francisco Fernández Castaño! July 2014! EuroPython, Berlin! @fcofdezc
  • 2. Roadmap • Motivation • Guidelines • Native Extensions • Ctypes • CFFI • Conclusions
  • 7. Static libraries $ ar tv libdemo.a rw-r--r-- 501/20 40 Jul 19 22:34 2014 __.SYMDEF SORTED rw-r--r-- 501/20 2352 Jul 19 22:33 2014 a.o rw-r--r-- 501/20 2352 Jul 19 22:33 2014 b.o
  • 8. Shared libraries Single copy in memory Runtime load
  • 12. #include "Python.h" // sum function. static PyObject * sum(PyObject *self, PyObject *args) { PyObject *_a = 0; PyObject *_b = 0; PyObject *result = NULL; ! _a = PyTuple_GET_ITEM(args, 0); _b = PyTuple_GET_ITEM(args, 1); result = PyNumber_Add(_a, _b); ! return result; } // Module functions table. static PyMethodDef module_functions[] = { { "sum", sum, METH_VARARGS, "Sum docstring." }, { NULL } }; // This function is called to initialize the module. PyMODINIT_FUNC initsum(void) { Py_InitModule3("sum", module_functions, "Hello world module."); }
  • 14. static PyObject * sum(PyObject *self, PyObject *args) { PyObject *_a = 0; PyObject *_b = 0; PyObject *result = NULL; ! _a = PyTuple_GET_ITEM(args, 0); _b = PyTuple_GET_ITEM(args, 1); result = PyNumber_Add(_a, _b); ! return result; }
  • 15. // Module functions table. static PyMethodDef module_functions[] = { { "sum", sum, METH_VARARGS, "Sum docstring." }, { NULL } };
  • 16. // This function is called to initialize the module. PyMODINIT_FUNC initsum(void) { Py_InitModule3("sum", module_functions, "Hello world module."); }
  • 17. from distutils.core import setup, Extension setup(name='sum', version=‘1.0', ext_modules=[Extension('sum', ['sum.c'])])
  • 18. $ python >>> import sum >>> sum.sum(2, 3) 5
  • 19. NAME dlopen -- load and link a dynamic library or bundle ! SYNOPSIS #include <dlfcn.h> ! void* dlopen(const char* path, int mode);
  • 20. // Python/dynload_shlib.c . . handle = dlopen(pathname, dlopenflags); ! if (handle == NULL) { const char *error = dlerror(); if (error == NULL) error = "unknown dlopen() error"; PyErr_SetString(PyExc_ImportError, error); return NULL; } if (fp != NULL && nhandles < 128) handles[nhandles++].handle = handle; p = (dl_funcptr) dlsym(handle, funcname); return p; . . .
  • 21. Memory management Manual memory management Python GC - RC Py_INCREF(x) | Py_DECREF(x) Cycle detector
  • 22. Error management Return NULL pointer as convention Register Exceptions
  • 23. Error management . . . if (err < 0) { PyErr_SetString(PyExc_Exception, "Command failed"); return NULL; } . . .
  • 24. Python 3 differences ! static struct PyModuleDef examplemodule = { PyModuleDef_HEAD_INIT, "sum", "sum module doc string", -1, module_functions, NULL, NULL, NULL, NULL }; ! PyMODINIT_FUNC PyInit_sum(void) { PyModule_Create(&examplemodule); }
  • 25. CTypes Advanced FFI for Python Allows call functions from Shared libs Create, access, manipulate C data types
  • 26. CTypes ctypes type C type c_bool _Bool c_char char c_wchar wchar_t c_byte char c_ubyte unsigned char c_short short c_ushort unsigned short c_int int c_uint unsigned int c_long long c_ulong unsigned long c_longlong __int64 or long long c_ulonglong unsigned __int64 or unsigned long long c_float float c_double double c_longdouble long double c_char_p char * (NUL terminated) c_wchar_p wchar_t * (NUL terminated) c_void_p void *
  • 27. CTypes - structs from ctypes import * class POINT(Structure): _fields_ = [("x", c_int), ("y", c_int)] ! class RECT(Structure): _fields_ = [("upperleft", POINT), ("lowerright", POINT)]
  • 28. CTypes - example Implemented fibonacci as c function Map as Python code Measure differences between Python and C
  • 29. CTypes - example int fib(int n){ if ( n < 2 ) return n; else return fib(n-1) + fib(n-2); }
  • 30. CTypes - example import ctypes lib_fib = ctypes.CDLL("libfib.so") ! def ctypes_fib(n): return lib_fib.fib(ctypes.c_int(n)) ! def py_fib(n): if n < 2: return n else: return py_fib(n-1) + py_fib(n-2)
  • 31. CTypes - times In [3]: %timeit fib.ctypes_fib(20) 10000 loops, best of 3: 63.8 µs per loop ! In [4]: %timeit fib.py_fib(20) 100 loops, best of 3: 3.62 ms per loop
  • 32. CTypes - Fortran example Use of existing fortran code Take random code at github https://github.com/astrofrog/fortranlib Wrap using ctypes
  • 33. CTypes - Fortran example . . real(dp) function mean_dp(x, mask) implicit none real(dp),intent(in) :: x(:) logical,intent(in),optional :: mask(:) if(present(mask)) then mean_dp = sum(x, mask=mask)/size(x) else mean_dp = sum(x)/size(x) end if end function mean_dp . .
  • 34. CTypes - Fortran example ➜ bin git:(master) ✗ nm -g lib_statistics.so 0000000000001eab T ___lib_statistics_MOD_clipped_mean_dp 0000000000000afc T ___lib_statistics_MOD_clipped_mean_sp 000000000000306c T ___lib_statistics_MOD_mean_dp 0000000000001c55 T ___lib_statistics_MOD_mean_sp 0000000000002db0 T ___lib_statistics_MOD_median_dp 00000000000019b0 T ___lib_statistics_MOD_median_sp 0000000000002544 T ___lib_statistics_MOD_quantile_dp 000000000000115a T ___lib_statistics_MOD_quantile_sp 0000000000002299 T ___lib_statistics_MOD_variance_dp 0000000000000ec3 T ___lib_statistics_MOD_variance_sp U __gfortran_arandom_r4 U __gfortran_arandom_r8 U __gfortran_os_error U __gfortran_pack U __gfortran_pow_i4_i4 U __gfortran_runtime_error U __gfortran_runtime_error_at U __gfortran_st_write U __gfortran_st_write_done U __gfortran_stop_string
  • 35. CTypes - Fortran example from ctypes import * ! # Statistics fortran lib st_lib = CDLL(“lib_statistics.so") ! mean = st_lib.__lib_statistics_MOD_mean_dp mean.argtypes = [POINTER(c_float*2)] mean.restype = c_float ! vals = (c_float*2)(2.0, 3.0) ! print mean(vals)
  • 36. CTypes static PyObject *py_dl_open(PyObject *self, PyObject *args) { char *name; void * handle; #ifdef RTLD_LOCAL int mode = RTLD_NOW | RTLD_LOCAL; #else /* cygwin doesn't define RTLD_LOCAL */ int mode = RTLD_NOW; #endif if (!PyArg_ParseTuple(args, "z|i:dlopen", &name, &mode)) return NULL; mode |= RTLD_NOW; handle = ctypes_dlopen(name, mode); if (!handle) { char *errmsg = ctypes_dlerror(); if (!errmsg) errmsg = "dlopen() error"; PyErr_SetString(PyExc_OSError, errmsg); return NULL; } return PyLong_FromVoidPtr(handle); }
  • 37. CFFI Advanced FFI for Python Allows call functions from Shared libs Create, access, manipulate C data types Both API and ABI access
  • 38. CFFI Mostly the same as CTypes
  • 39. CFFI Recommended way to extend PyPy
  • 40. CFFI - ABI from cffi import FFI ffi = FFI() ffi.cdef(""" int printf(const char *format, …);""") C = ffi.dlopen(None) arg = ffi.new("char[]", "world") C.printf("hi there, %s!n", arg)
  • 41. CFFI - API level import cffi ffi = cffi.FFI() ! ffi.cdef(""" int fib(int n); """) ! lib = ffi.verify(r''' int fib(int n){ if ( n < 2 ) return n; else return fib(n-1) + fib(n-2); }''') ! print lib.fib(10)
  • 42. CFFI - API level import cffi ffi = cffi.FFI() ! ffi.cdef(""" int fib(int n); """) ! lib = ffi.verify(r''' int fib(int n){ if ( n < 2 ) return n; else return fib(n-1) + fib(n-2); }''') ! print lib.fib(“asd”)
  • 43. Boom! Traceback (most recent call last): File "fib.py", line 16, in <module> print lib.fib("asd") TypeError: an integer is required
  • 44. CFFI - API level from cffi import FFI ffi = FFI() ffi.cdef(""" typedef struct { float x, y; } point; """) point = ffi.new("point *") point.x = 2.0 point.y = 3.0
  • 45. static PyObject *b_load_library(PyObject *self, PyObject *args) { char *filename_or_null, *printable_filename; void *handle; DynLibObject *dlobj; int flags = 0; ! . . . if ((flags & (RTLD_NOW | RTLD_LAZY)) == 0) flags |= RTLD_NOW; ! printable_filename = filename_or_null ? filename_or_null : "<None>"; handle = dlopen(filename_or_null, flags); if (handle == NULL) { const char *error = dlerror(); PyErr_Format(PyExc_OSError, "cannot load library %s: %s", printable_filename, error); return NULL; } ! dlobj = PyObject_New(DynLibObject, &dl_type); if (dlobj == NULL) { dlclose(handle); return NULL; } dlobj->dl_handle = handle; dlobj->dl_name = strdup(printable_filename); return (PyObject *)dlobj; }
  • 46. Conclusions Three different ways Same principles Less portable -> More portable Harder -> Easier