web-dev-qa-db-ja.com

Python:SWIGとctypes

Pythonでは、どのような状況で共有ライブラリのエントリポイントを呼び出すためにSWIGがctypesよりも優れた選択肢ですか? SWIGインターフェースファイルがまだない場合を考えてみましょう。

2つのパフォーマンスメトリックとは何ですか?

54
Kevin Little

SWIGは(かなり醜い)CまたはC++コードを生成します。単純な関数(直接変換できるもの)に使用するのは簡単で、より複雑な関数(Pythonで表現するために追加の変換ステップが必要な出力パラメーターを持つ関数など)にはかなり簡単に使用できます。インターフェイスファイルの一部としてCのビットを書き込む必要があります。単純な使い方以外の場合は、CPythonとそれがオブジェクトをどのように表すかについて理解する必要があります。難しいことではありませんが、覚えておくべきことです。

ctypesを使用すると、C関数、構造体、その他のデータに直接アクセスし、任意の共有ライブラリをロードできます。このためにCを記述する必要はありませんが、Cがどのように機能するかを理解する必要があります。 SWIGの裏返しです。コードを生成せず、実行時にコンパイラーを必要としませんが、単純な使用以外は、Cデータ型、キャスト、メモリ管理と整列作業。また、Cの構造体、共用体、配列を、適切なメモリレイアウトを含む同等のctypesデータ構造に手動または自動で変換する必要があります。

純粋な実行では、SWIGはctypesよりも高速である可能性があります-実際の作業に関する管理は、実行時にPythonではなく、コンパイル時にCで行われるためです。ただし、さまざまなC関数がたくさんありますが、それぞれ数回しかありませんが、オーバーヘッドが実際に顕著になることはほとんどありません。

開発時には、ctypesの起動コストははるかに低くなります。インターフェイスファイルについて学習する必要がなく、.cファイルを生成してコンパイルする必要もありません。警告をチェックアウトして沈黙させる必要もありません。最小限の労力で単一のC関数にジャンプして使い始め、それをさらに拡張することができます。そして、Pythonインタプリタで直接テストして試してみることができます。多くのコードをラップすることは、(ctypes-configureのように)単純化する試みがありますが、やや面倒です。

一方、SWIGは、複数の言語のラッパーを生成するために使用できます(上記のカスタムCコードのように、入力が必要な言語固有の詳細を除きます)。SWIGがほとんど処理できない多くのコードをラップする場合ヘルプ、コード生成は、ctypesの同等のものよりもセットアップがはるかに簡単です。

63
Thomas Wouters

私は、swigを使用する豊富な経験があります。 SWIGは、物を包むための迅速なソリューションであると主張しています。しかし、実際には...


短所:

SWIGは一般向けに開発されており、誰にとっても20以上の言語に対応しています。一般に、それは欠点につながります:
-設定が必要です(SWIG .iテンプレート)、時にはそれはトリッキーです、
-いくつかの特別なケースの扱いの欠如(pythonプロパティを参照)、
-一部の言語ではパフォーマンスが不足しています。

Pythonの短所:

1)コードスタイルの不一致。 C++とpythonには非常に異なるコードスタイルがあります(これは明らかです))。ターゲットコードをよりPythonishにすることの可能性は非常に限られています。例として、ゲッターとセッターからプロパティを作成します this q&a を参照

2)幅広いコミュニティの欠如。 SWIGには、優れたドキュメントがいくつかあります。しかし、ドキュメントにないものを捕まえた場合、情報はまったくありません。ブログもグーグルも役に立ちません。したがって、そのような場合、SWIGで生成されたコードを徹底的に掘る必要があります...それは恐ろしいことです。

長所:

  • 単純なケースでは、それは本当に迅速で簡単で簡単です

  • Swigインターフェイスファイルを一度作成した場合は、このC++コードを他の20以上の言語(!!!)にラップできます。

  • SWIGの大きな懸念の1つはパフォーマンスです。バージョン2.04以降、SWIGには「-builtin」フラグが含まれているため、SWIGは他の自動ラップ方法よりも高速です。少なくとも いくつかのベンチマーク はこれを示しています。


SWIGを使用するタイミング

だから私は自分のために小枝を使うのが良い2つのケースを結論づけました:

2)C++コードをラップする必要がある場合複数の言語の場合。あるいは、潜在的に、いくつかの言語のコードを配布する必要がある場合があるかもしれません。この場合、SWIGの使用は信頼できます。

1)rapidlyラップする必要がある場合一部のみ一部のC++ライブラリからの関数を最終使用のためにラップします。


ライブ体験

更新
SWIGを使用してライブラリを変換してから1年半が経過しました。

最初に、pythonバージョンを作成しました。SWIGで問題が発生した瞬間がありました-それは本当です。しかし、現在、ライブラリをJavaと.NETなので、3つの言語に1つのSWIGがあり、時間を大幅に節約するという点でSWIG rocksと言えます。

更新2
このライブラリにSWIGを使用するので2年になります。 SWIGはビルドシステムに統合されています。最近、C++ライブラリのAPIが大幅に変更されました。 SWIGは完全に機能しました。必要なのは、いくつかの%renameを.iファイルに追加することだけなので、CppCamelStyleFunctions()になりましたlooks_more_pythonish Pythonで。まず、発生する可能性のあるいくつかの問題を心配しましたが、何も問題はありませんでした。それは驚くべきものだった。いくつかの編集とすべてが3言語で配布されています。今回のケースでSWIGを使用することは良い解決策であったと確信しています。

更新
ライブラリにSWIGを使用して3年以上になります。 主な変更:python部分は純粋なpythonで完全に書き直されました。理由はPythonが純粋なpythonバージョンの動作がC++のラッピングよりも遅い場合でも、ユーザーがネイティブライブラリと格闘するのではなく、純粋なpythonで作業する方が便利です。

SWIGは引き続き.NETおよびJavaバージョンで使用されます。

ここでの主な質問は、「pythonにSWIGを使用しますか?プロジェクトを最初から始めたのですか?」ということです。ユーザーの要件をよりよく理解する機会を私たちに与えた期間。

89
MajesticRa

CTypesは非常にクールでSWIGよりもはるかに簡単ですが、不十分または悪意を持って記述されたpythonコードが実際にpythonプロセスをクラッシュさせる可能性があります。 boost pythonも検討してください。最終的にpythonインターフェイスを制御できるようになりますが、実際にはswigよりも簡単です。C++を使用している場合は、他の言語をミックスに追加します。

13
David Nehme

私の経験では、ctypesには大きな不利な点があります。何かがうまくいかない場合(そして、それは常に複雑なインターフェースに悪影響を及ぼします)、デバッグするのは地獄です。

問題は、スタックの大部分がctypes/ffiマジックによって隠されており、特定のポイントに到達した方法とパラメーター値がなぜであるのかを判断する簡単な方法がないことです。

10
Ilya

Pyrex を使用することもできます。これは、高レベルのPythonコードと低レベルのCコードの間の接着剤として機能します。- lxml が記述されていますたとえばパイレックスで。

8
Torsten Marek

私は逆張りするつもりですが、可能であれば、拡張ライブラリを standard Python API を使用して作成する必要があります。両方から統合されています。 CとPythonパースペクティブ... Perl APIの経験がある場合、それはvery うれしい驚き。

Ctypesもいいですが、他の人が言ったように、それはC++をしません。

ラップしようとしているライブラリの大きさはどれくらいですか?コードベースはどれくらい早く変更されますか?その他のメンテナンスの問題はありますか?これらはおそらくPythonバインディングを書くための最良の方法の選択に影響を与えるでしょう。

7
Dan Lenski

ctypesは素晴らしいですが、C++クラスを処理しません。私はまた、ctypesが直接のCバインディングよりも約10%遅いことも発見しましたが、それは呼び出す対象に大きく依存します。

Ctypesを使用する場合は、ctypeバインディングの膨大な例があるPygletおよびPyopenglプロジェクトを必ず確認してください。

6
Peter Shinners

まだ言及していなかった考慮事項をいくつか追加したかっただけです。 [編集:おっと、Mike Stederの答えが見つかりませんでした]

Cpy以外の実装(PyPy、IronPython、Jythonなど)を使用したい場合は、ctypesが唯一の方法です。 PyPyはC拡張機能の記述を許可しないため、pyrex/cythonおよびBoost.pythonは除外されます。同じ理由で、ctypesはIronPythonおよび(最終的には、すべてが動作すると)jythonで動作する唯一のメカニズムです。

他の誰かが述べたように、コンパイルは必要ありません。これは、.dllまたは.soの新しいバージョンが出てきた場合、それをドロップして、その新しいバージョンをロードできることを意味します。どのインターフェースも変更されていない限り、それは代わりのドロップです。

5
Sean Toner

SWIGはCPython実装のみを対象としていることを覚えておいてください。 ctypesはPyPyとIronPythonの実装でもサポートされているため、より広いPythonエコシステムとの互換性のために、ctypesでモジュールを作成する価値があります。

3
stderr

私はSWIGがそのアプローチ(通常、Pythonだけでなく)で少し肥大化し、明確な考え方を備えたPython codeきれいによく書かれたPythonコードを書くのではなく、SWIGに友好的である。これは、C++へのCバインディングを(C++を使用している場合)書き込み、ctypesを使用してインターフェイスする、IMHO任意のCレイヤーに。

インターフェースしているライブラリにライブラリの一部としてCインターフェースがある場合、ctypesのもう1つの利点は、サードパーティのライブラリにアクセスするために別のpythonバインディングライブラリをコンパイルする必要がないことです。これは、クロスプラットフォームのコンパイルの問題を回避する純粋なpythonソリューションを作成するのに特に適しています(異種プラットフォームで提供されるサードパーティライブラリの場合)。コンパイルされたコードを、クロスプラットフォームにやさしい方法でPyPiのようなものにデプロイしたいパッケージに埋め込む必要があるのは苦痛です。 Python SWIGまたは基になる明示的なCコードを使用するパッケージについての私の最も苛立たしい点の1つは、クロスプラットフォームで一般的に利用できないことです。クロスプラットフォームで利用可能なサードパーティライブラリを使用して開発している場合は、これを考慮してください。 a pythonそれらの周りのソリューション。

実際の例として、PyGTKを考えてみましょう。これは(私は信じています)、SWIGを使用してCコードを生成し、GTK C呼び出しへのインターフェースを提供します。私はこれを最も短い時間だけ使用しましたが、セットアップと使用が本当に面倒であることがわかりました。それはとても苛立たしい経験でした、そして私がウェブでGTKによって提供されたインターフェースの定義を見たとき、私はそれらのインターフェースのトランスレータをpython ctypesインターフェースに書くことはどんな単純な練習であろうか? 。PyGGIと呼ばれるプロジェクトが生まれ、1日でPyGTKを書き直して、GTK Cオブジェクト指向インターフェースに完全に一致する、より機能的で有用な製品にすることができました。また、Cコード作成のコンパイルを必要としませんでした。 (私は実際にはwebkitgtkに接続した後、それほどクロスプラットフォームではありませんでした)GTKをサポートする任意のプラットフォームにPyGGIを簡単にデプロイすることもできます。

0
nak