2009-03-30 17 views
7

私はSWIGバインディングを初めて実装した2年ほど前にこの問題にぶつかりました。大量のコードを公開するとすぐに、SWIGがC++ファイルを出力してコンパイラがそれらを処理できないほど大きくなっています。この問題を回避できる唯一の方法は、複数のモジュールにインターフェイスを分割し、それらを別々にコンパイルすることでした。SWIGモジュールを分割してコンパイルすることはできますが、リンクするときに再結合することはできますか?

これにはいくつかの欠点があります。各モジュール•

は、他のモジュール内の依存関係について知っている必要があります。私は、この側面を扱うインターフェースファイルを生成するためのスクリプトを用意していますが、複雑さが増します。

各モジュールが追加されるたびに、ダイナミックリンカがコードにロードする時間が長くなります。すべてのサブモジュールをインポートするinit .pyファイルを追加しました。これにより、コードが分割されていることがユーザーにはわかりますが、常に見えるのは長い読み込み時間です。

私は現在、私たちのビルドスクリプト/ビルドプロセスを見直していると私は私が今持っているものよりも優れていたこの問題の解決策を見つけることができるかどうかを確認したかったです。理想的には、すべてのラッパーコードを含む共有ライブラリが1つあります。

誰も私がSWIGでこれを達成する方法を知っていますか?私は、特定のプロジェクトでRubyで書かれたカスタムコードを見てきましたが、出力をポスト処理してこれを可能にしていますが、Pythonラッパーの実現可能性を見てもそれほど簡単ではありません。コンパイルを行う必要がありますだけで何 - 適切に分割した場合

答えて

0

は、モジュールは、必ずしも他の人と同じ依存関係を持っている必要はありません。あなたが物事を適切に分割すると、循環依存性のないライブラリを持つことができます。複数のライブラリを使用する際の問題は、デフォルトではSWIGがランタイムコードを静的に宣言し、その結果、あるモジュールから別のモジュールにオブジェクトを渡す際の問題であるということです。 SWIGランタイムコードの共有バージョンを有効にする必要があります。

ドキュメント(SWIG Webページのドキュメントのリンクが壊れている)から:ランタイム関数が 各SWIGが生成したモジュールにプライベートで

。すなわち、 ランタイム機能は、「静的」リンケージと を宣言のみそのモジュールに 定義されたラッパー関数に 見えるされています。 このアプローチの唯一の問題は、複数 1つのSWIGモジュールが同じ アプリケーションで使用される場合、これらのモジュールは、多くの場合、型情報を共有する を必要とすることです。これは です。特に、 SWIGは、 の継承に関する情報を収集して共有する必要があるC++プログラムの場合は、 境界を越えた関係になります。

ダウンロードしたドキュメント(16.2節のSWIGランタイムコード)のこのセクションをチェックして、あるモジュールから別のモジュールにオブジェクトを渡すときにオブジェクトを適切に処理できるようにする方法を詳しく説明します。

FWIWは、私は、Python SWIGで働いていませんでしたが、TclのSWIGを行っています。

+0

私はあなたが少し逃してしまったと思います。あるモジュールから別のモジュールに物事を渡すときに問題はありません。すべてがうまく機能し、 "import"ステートメントを気にしてください。 問題は、複数のモジュールを1つの共有ライブラリにリンクして、コードを読み込む際の読み込み時間を短縮することです。 – jkp

+0

ああ、申し訳ありません、スピードアップのための解決策はありません。 Tclでは、パッケージメカニズムを使用してモジュールが必要になるまでモジュールのロードを遅らせることができました。これは物事をスピードアップするのに役立ちましたが、ローディングをスピードアップするだけで、サイコロはありませんでした。 –

0

私はTCLライブラリの同等のハックをした:私はいくつかの.oファイルにコンパイルされますが、単一でそれらのすべてをコンパイルされているいくつかの.cppファイルを生成し、いくつかのSWIGモジュールを使用しています。したがって、単一のTCL "load"コマンドでロードされるファイルです。

%module Top 
%header %{ 
    extern "C" { 
    SWIGEXPORT int Sub1_Init(Tcl_Interp *); 
    SWIGEXPORT int Sub2_Init(Tcl_Interp *); 
} 
%init %{ 
    if (Sub1_Init(interp) != TCL_OK) {return TCL_ERROR;} 
    if (Sub2_Init(interp) != TCL_OK) {return TCL_ERROR;} 
%} 

何も特別なことは、サブモジュールのファイルにありません:

アイデアは、すべてのサブモジュール(SUB1とSUB2)の初期化関数を呼び出すトップSWIGモジュール(トップ)を作成することです。 私はTop.soファイルで終わるので、 "load ./Top.so"というコマンドでTCLからロードする。

私はpythonを知らないが、似ている可能性が高い。しかし、Pythonの拡張機能がどのように読み込まれているかを理解する必要があるかもしれません。

関連する問題