SWIG与C++模板:未定义符号
我在使用C++模板和SWIG的时候遇到了一些麻烦。
当我尝试导入我的模块时,出现了这个错误:
ImportError: ./_simple.so: undefined symbol: _Z9double_itIiET_S0_
我使用的是SWIG 1.3版本。
下面是一个简单的例子,展示了这个问题:
//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"],
)
然后用以下命令进行构建:
python setup.py build
如果我把simple.cc的内容直接放到simple.i里面,并且从setup.py中去掉对simple.cc的引用,那么一切都能正常工作。但是,当事情变得复杂时,这并不是一个真正的解决办法。
接下来,我会给出一个类似的反例,这个例子不使用模板,并且能够正常工作。
//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.
1 个回答
3
通常情况下,模板会在头文件中定义,而不是在源文件(cc文件)中。根据你现在的设置,编译器找不到或者无法编译这个模板的实现。
你需要调整一下代码的组织结构,让模板的实现能够被找到:
//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"],
)
我知道你的例子是简化过的,但它说明了问题。你不需要直接使用 %include
来包含实现(但你确实需要用 #include
来包含它),不过你必须给SWIG编译器提供一些实现,即使是简化版的也可以。
以上内容应该能帮助你入门。