2011-03-06 49 views
4

C++模板和痛饮没有很好地一起玩我。SWIG C++模板:未定义的符号

当我试图导入我的模块我得到的错误

ImportError: ./_simple.so: undefined symbol: _Z9double_itIiET_S0_ 

我使用痛饮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. 

回答

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编译器,即使它是一个简化版本。

上面应该让你去。

+0

我离开了头文件出来,使事情有点短。也许我应该让它看起来更加正常。如果您替换了我拥有的两个地方“template T double_it(T a);”使用包含头文件的声明,您会得到与您相似的内容。主要区别在于您现在在接口文件中包含double_it的实现,因此不需要链接。如果我这样做,我也可以得到它的工作,但如果实现在单独的.cc文件中,则遇到问题。 –

+0

我在头文件中添加了我的示例,因此看起来更加正常。 –

+0

您必须将实现放在头文件中,以便编译器能够找到它并生成所需的版本。唯一的选择是显式实例化.cc文件中的模板,以确保您需要的实例存在(以确保编译器生成您需要的版本并在链接时可用)。 “模板类double_it ; 模板类double_it ”;你碰到的是一个关于C++和模板实例化的普遍问题,而不是关于SWIG的具体问题 – lefticus