SWIG with C++ templates: undefined symbol
C++ Templates and SWIG aren't playing nicely together for me.
When I try to import my module I get the开发者_开发技巧 error
ImportError: ./_simple.so: undefined symbol: _Z9double_itIiET_S0_
I am using SWIG 1.3.
Here is a simple example showing the problem:
//file: simple.h
template <typename T>
T double_it (T a);
//file: simple.cc
template <typename T>
T double_it (T a) {
return (2 * a);
}
//file: simple.i
%module "simple"
%{
#include "simple.h"
%}
%include "simple.h"
%template(int_double_it) double_it <int>;
%template(float_double_it) double_it <float>;
#file: setup.py
from distutils.core import setup, Extension
simple_module = Extension('_simple',
sources=['simple.i', 'simple.cc'],
swig_opts=['-c++'],
)
setup (name = 'simple',
ext_modules = [simple_module],
py_modules = ["simple"],
)
Then build in with:
python setup.py build
If I include the contents of simple.cc into simple.i and remove the reference to simple.cc from the setup.py then everything works fine, but that isn't really a solution when things get more complex.
Next I'll give a counter example of something that is similar but doesn't use templates and works fine.
//file: simple.h
int double_it (int a);
//file: simple.cc
int double_it (int a) {
return (2 * a);
}
//file: simple.i
//Same as before but with %template statements removed.
%module "simple"
%{
#include "simple.h"
%}
%include "simple.h"
#file: setup.py
#Identical to previous example.
Typically templates are defined in a header file instead of in a cc file. With the setup you have, the compiler cannot find / compile the implementation of the template.
You will need to change the organization of the code so that the template implementation is available:
//file: simple.hh
template <typename T>
T double_it (T a) {
return (2 * a);
}
//file: simple.i
%module "simple"
%{
#include "simple.hh"
%}
%include "simple.hh" // include it directly into here
%template(int_double_it) double_it <int>;
%template(float_double_it) double_it <float>;
#file: setup.py
from distutils.core import setup, Extension
simple_module = Extension('_simple',
sources=['simple.i', 'simple.hh'],
swig_opts=['-c++'],
)
setup (name = 'simple',
ext_modules = [simple_module],
py_modules = ["simple"],
)
I appreciate that your example is simplified, but it illustrates the point. You do not have to %include
the implementation directly (but you do need to #include
it), but you do have to provide some implementation to the SWIG compiler, even if it is a simplified version.
The above should get you going.
精彩评论