Python のマニュアルには、C と C++ の両方で Python のモジュールを作成できると書かれています。C++ を使用する場合、クラスやテンプレートなどを利用できますか? 残りのライブラリーやインタープリターとの互換性がなくなるのではないでしょうか?
4 に答える
フック関数の実装が C で実装されているか C++ で実装されているかは問題ではありません。実際、C++ テンプレートや Boost ライブラリを積極的に利用する Python 拡張機能をいくつか見てきました。問題ない。:-)
ブーストの人々は、Pythonで使用するためにC++コードのラッピングを行うための優れた自動化された方法を持っています。
それは呼ばれます:Boost.Python
SWIGよりも優れたC++の構造のいくつか、特にテンプレートメタプログラミングを扱います。
あなたが興味を持っているのはSWIGというプログラムです。C++ コードの Python ラッパーとインターフェイスを生成します。テンプレート、継承、名前空間などで使用していますが、うまく機能します。
C++言語のすべての機能を使用できるはずです。Extending Python Documentation(2.6.2)には、C ++を使用できると記載されていますが、次の注意事項が記載されています。
C++で拡張モジュールを作成することができます。いくつかの制限が適用されます。メインプログラム(Pythonインタープリター)がCコンパイラーによってコンパイルおよびリンクされている場合、コンストラクターを持つグローバルオブジェクトまたは静的オブジェクトは使用できません。メインプログラムがC++コンパイラによってリンクされている場合、これは問題ではありません。Pythonインタープリターによって呼び出される関数(特にモジュール初期化関数)は、extern"C"を使用して宣言する必要があります。Pythonヘッダーファイルをextern"C"{...}で囲む必要はありません—シンボル__cplusplusが定義されている場合(最近のすべてのC ++コンパイラがこのシンボルを定義している場合)、Pythonヘッダーファイルはすでにこの形式を使用しています。
最初の制限である「コンストラクターを持つグローバルまたは静的オブジェクトは使用できません」は、ほとんどのC++コンパイラーがこのタイプのストレージ期間でオブジェクトを初期化する方法と関係があります。たとえば、次のコードについて考えてみます。
class Foo { Foo() { } };
static Foo f;
int main(int argc, char** argv) {}
mainが実行される前に、「Foo」コンストラクターが「f」に対して呼び出されるように、コンパイラーは特別なコードを発行する必要があります。Python拡張機能に静的ストレージ期間のオブジェクトがあり、PythonインタープリターがC ++用にコンパイルおよびリンクされていない場合、この特別な初期化コードは作成されません。
2番目の制限である「Pythonインタープリターによって呼び出される関数(特にモジュール初期化関数)は、extern "C"を使用して宣言する必要があります」は、C++の名前マングリングと関係があります。ほとんどのC++コンパイラは、Cツールチェーンに提供されているのと同じリンカーを使用できるように名前を変更します。たとえば、次のようになります。
void a_function_python_calls(void* foo);
C ++コンパイラは、「a_function_python_calls」という名前への参照を「a_function_python_calls@1vga」のようなものに変換する場合があります。この場合、Pythonライブラリとリンクしようとすると、未解決の外部が発生する可能性があります。