Add experimental Python bindings

This commit adds some experimental Python bindings. These likely need some
further refinement in the building/deployment area, but should serve as a
useful testbed for experimentation and interactive analysis of filters and
the library's behaviour.
This commit is contained in:
Laurence Withers 2014-07-07 16:43:39 +00:00
parent 911b3eab3d
commit 5681c97b4e
5 changed files with 177 additions and 0 deletions

5
python/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
.ipynb_checkpoints/
__pycache__/
build/
iir.py
pyiir_wrap.cxx

25
python/README Normal file
View File

@ -0,0 +1,25 @@
Experimental Python bindings
============================
These bindings are currently experimental, as it is not yet clear how best
to create and maintain them. They are built upon the C++ interface as the
object oriented nature of it sits much better with Python.
At present, it is necessary to compile and install the C++ library before
working with the bindings.
To generate the bindings, swig 3.0.2 has been used, but earlier versions
may work too:
swig -c++ -python -py3 pyiir.i
To build the extension, distutils is used:
python3 setup.py build_ext
Note that the -L ${LIBDIR} option may be handy if libiir++ is not installed
into the system library path.
To install the extension:
python3 setup.py install

1
python/iir++.h Symbolic link
View File

@ -0,0 +1 @@
../obj/iir++.h

130
python/pyiir.i Normal file
View File

@ -0,0 +1,130 @@
%module iir
%include <complex.i>
%{
#include "iir++.h"
%}
/*
* Add bounds checking
*
* The Python library is targetted at experimentation. It is therefore
* reasonable to protect its object query and creation interfaces with code
* that performs bounds checking on arguments.
*/
%exception IIR::Coeff::c {
if(arg2 < 0 || arg2 >= arg1->nc()) {
char buf[80];
snprintf(buf, sizeof(buf), "Index of c coefficient (%d) out of bounds "
"(0,%d).", arg2, arg1->nc() - 1);
PyErr_SetString(PyExc_RuntimeError, buf);
return NULL;
}
$action
}
%exception IIR::Coeff::d {
if(arg2 < 0 || arg2 >= arg1->nd()) {
char buf[80];
snprintf(buf, sizeof(buf), "Index of d coefficient (%d) out of bounds "
"(0,%d).", arg2, arg1->nd() - 1);
PyErr_SetString(PyExc_RuntimeError, buf);
return NULL;
}
$action
}
%exception IIR::Filter::getCoeffSet {
if(arg2 < 0 || arg2 >= arg1->numCoeffSet()) {
char buf[80];
snprintf(buf, sizeof(buf), "Index of coefficient set (%d) out of bounds "
"(0,%d).", arg2, arg1->numCoeffSet() - 1);
PyErr_SetString(PyExc_RuntimeError, buf);
return NULL;
}
$action
}
%exception IIR::ButterworthLowPass {
if(arg1 < 1) {
char buf[80];
snprintf(buf, sizeof(buf), "Invalid filter order (%d). Must be > 0.",
arg1);
PyErr_SetString(PyExc_RuntimeError, buf);
return NULL;
}
$action
}
%exception IIR::ButterworthHighPass {
if(arg1 < 1) {
char buf[80];
snprintf(buf, sizeof(buf), "Invalid filter order (%d). Must be > 0.",
arg1);
PyErr_SetString(PyExc_RuntimeError, buf);
return NULL;
}
$action
}
%exception IIR::ButterworthBandPass {
if(arg1 < 1) {
char buf[80];
snprintf(buf, sizeof(buf), "Invalid filter order (%d). Must be > 0.",
arg1);
PyErr_SetString(PyExc_RuntimeError, buf);
return NULL;
}
if(arg3 > arg4) {
PyErr_SetString(PyExc_RuntimeError, "Low corner frequency exceeds "
"high corner frequency.");
return NULL;
}
$action
}
%exception IIR::ButterworthBandStop {
if(arg1 < 1) {
char buf[80];
snprintf(buf, sizeof(buf), "Invalid filter order (%d). Must be > 0.",
arg1);
PyErr_SetString(PyExc_RuntimeError, buf);
return NULL;
}
if(arg3 > arg4) {
PyErr_SetString(PyExc_RuntimeError, "Low corner frequency exceeds "
"high corner frequency.");
return NULL;
}
$action
}
/*
* Invalid filter string handling
*
* The C++ library uses a "valid()" member in IIR::Filter to avoid throwing an
* exception if the constructor is passed an invalid filter string. Python's
* exceptions are a much nicer fit, however, so use those instead.
*
* Notes:
* 1. Doesn't match if we prepend it with the namespace.
* 2. Applies to all constructors.
*/
%exception Filter {
$action
if(!result->valid()) {
PyErr_SetString(PyExc_RuntimeError, "Invalid filter description string.");
delete result;
return NULL;
}
}
%include "iir++.h"
// vim: ts=4:sw=4

16
python/setup.py Normal file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
from distutils.core import setup, Extension
iir_module = Extension('_iir',
sources=['pyiir_wrap.cxx'],
libraries=['iir++'],
)
setup(name = 'iir',
version = '1.0.3',
author = 'Laurence Withers',
description = 'IIR filter',
ext_modules = [iir_module],
py_modules = ['iir'],
)