pythonc++ubuntu-16.04swig

Wrapping a C++ file as a Python file using SWIG


I'm new to using SWIG and a bit out of my depth as a programmer. I would like to be able to call the functions of a C++ class in python 2 by importing the wrapped class as a module 'import C++_file' and then call it within my python class with something like 'C++_file.function(inputs)'.

Following http://intermediate-and-advanced-software-carpentry.readthedocs.io/en/latest/c++-wrapping.html, I am wrapping the header file multiplyChannel.h:

#include <vector>
#include <complex>

using namespace std;

class MultiplyChannel {
    public:
        MultiplyChannel(double in_alpha);
        void applyToVector(vector<complex<double> > *in_signal);
    private:
        double alpha;
};

which corresponds to my example C++ file multiplyChannel.cpp:

#include "multiplyChannel.h"
#include <vector>
#include <complex>

using namespace std;

MultiplyChannel::MultiplyChannel(double in_alpha){
    this->alpha = in_alpha;
}

void MultiplyChannel::applyToVector(vector<complex<double> > *in_signal){
    unsigned int size = in_signal->size();
    for (int i = 0; i < size; i++) {
        in_signal->at(i).real() = in_signal->at(i).real() * this->alpha;
        in_signal->at(i).imag() = in_signal->at(i).imag() * this->alpha;
    }
}

With the makefile:

all:
    swig -python -c++ -o mult.cpp swigdemo.i
    python setup.py build_ext --inplace

the wrapper file swigdemo.i:

%module swigdemo

%{
#include <stdlib.h>
#include "multiplyChannel.h"
%}

%include "multiplyChannel.h"

and setup.py build file:

from distutils.core import setup, Extension

extension_mod = Extension("_swigdemo", ["mult.cpp"])

setup(name = "swigdemo", ext_modules=[extension_mod])

by typing in my Ubuntu command window:

$ make
swig -python -c++ -o multiplyChannel.cpp swigdemo.i
python setup.py build_ext --inplace
running build_ext
$ python setup.py build
running build
running build_ext

Testing the import using C++_tester.py, I try to multiply the vector [1, 2, 3] into [5, 10, 15] using the MultiplyChannel object 'demo' with instance variable 'in_alpha' of 5x, multiplying all inputs by 5:

#!/usr/bin/python

import swigdemo

if __name__ == '__main__':
    demo = swigdemo.MultiplyChannel(in_alpha=5)
    out = demo.applyToVector(in_signal=[1, 2, 3])
    print(out)

I am not getting past even the import line, receiving the following error:

$ python C++_tester.py
ImportError: ./_swigdemo.so: undefined symbol: _ZN15MultiplyChannelC1Ed

And am unsure what to do as I cannot even gedit or vim into the .so file. I'm guessing my error lies in wrapping incorrectly in my wrapper, build, or makefile, as pretty much everything in the C++_tester.py file auto-completed in my Pycharm IDE.

Many thanks!


Solution

  • The problem was indeed related to extension build:

    In short, modify setup.py by adding multiplyChannel.cpp to the extension source flies list:

    extension_mod = Extension("_swigdemo", ["mult.cpp", "multiplyChannel.cpp"])
    

    Might also want to check: