SWIG与C++模板:未定义符号

4 投票
1 回答
3494 浏览
提问于 2025-04-16 13:07

我在使用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编译器提供一些实现,即使是简化版的也可以。

以上内容应该能帮助你入门。

撰写回答