2011-03-06 8 views
4

C++テンプレートとSWIGはうまく一緒に遊んでいません。SWIG with C++テンプレート:未定義シンボル

私は私のモジュールをインポートしようとすると、私はエラー

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"], 
     ) 

で構築:私はsimple.iにsimple.ccの内容を含めるとへの参照を削除すると

python setup.py build 

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

私は物事を少し短くするためにヘッダファイルを出しました。おそらく私はそれをより正常に見せるためにこれを残しておくべきでした。私が「テンプレート T double_it(T a);」という2つの場所を置き換えた場合、インクルードヘッダーステートメントでは、あなたのものに似たものが得られます。主な違いは、インターフェイスファイルにdouble_itの実装が含まれているため、リンクが必要ないことです。私がそれをしても動作させることができますが、実装が別の.ccファイルにある場合は問題があります。 –

+0

ヘッダーファイルに私のサンプルに追加しましたので、より正常に見えます。 –

+0

実際には、コンパイラがヘッダファイルを見つけて必要なバージョンを生成できるように、実装をヘッダファイルに入れなければなりません。唯一の選択肢は、.ccファイル内のテンプレートを明示的にインスタンス化して必要なインスタンス化が存在することを確認することです(コンパイラが必要なバージョンを生成し、リンク時に使用できるようにする)。 "テンプレートクラスdouble_it ; テンプレートクラスdouble_it ;"あなたが実行しているのは、C++とテンプレートのインスタンス化に関する一般的な質問です。具体的にSWIGについてはありません。 – lefticus

関連する問題