3

2つの異なるPython拡張モジュールがあります。それらをAとBと呼びましょう。モジュールAには、クラスメソッドの戻り型としてモジュールB内で使用したいcontainerというストレージクラス型が含まれています。

これを行う方法についてのドキュメントが見つからないようです。モジュール/クラスを作成するために、この記事に大まかに従いました。ただし、すべてのメソッドを静的として宣言しなかったため、アクセス可能でした:http: //nedbatchelder.com/text/whirlext.html

私の質問は、モジュールBのクラスメソッドのPyObject *戻り値として返すことができるコンテナのインスタンスを作成するにはどうすればよいですか?コンテナ定義は次のようになります。

typedef struct {
    PyObject_HEAD

    storageclass* cnt_;
} container;

問題のメソッド内で次のことを簡単に実行してみました。container_initは、コンテナークラスのtp_initとして登録したメソッドです。

pycnt::container* retval;
pycnt::container_init(retval, NULL, NULL);
return (PyObject*)retval;

ただし、Pythonインタープリターによると、メソッドを呼び出したクラスが返されます。(つまり、myclassinstance.mymethod()はmyclassinstanceを返します)。

私は明らかにこれを間違った方法で行っていますが、正しい方法が何であるかわかりません。助言がありますか?それを示唆する人を断ち切るためだけに-いいえ、SWIGやBoost::Pythonの使用には興味がありません。私はすでにそれを試しましたが、コンテナの基礎となるストレージクラスはどちらともうまく機能しませんでした(SWIGはそれを解析することさえできませんでした)。これまでのところ、自分で拡張機能を実行するのはかなり苦痛がありませんでしたが、私はこれに困惑しています。

4

1 に答える 1

3

あなたの問題はそれtype->tp_initがあなたが望むことをしないということです。type->tp_initインスタンス化を行うためにオブジェクトが割り当てられた後に呼び出されます。最初にを使用してオブジェクトを割り当てtype->tp_new、次にそのオブジェクトを最初の引数としてに渡す必要がありますtype->tp_init。初期化されていないポインタをに渡すのでtp_init、すべての賭けはオフになります。ただし、通常はどちらの関数も直接呼び出さず、代わりにPyObject_Call*()タイプオブジェクト自体のいずれかを呼び出して新しいインスタンスを作成します。または、通常のC関数を提供して、新しいインスタンスalaを作成しますPyFoo_New()

とはいえ、2つの拡張モジュール間で相互通信を行う通常の方法は、PythonAPIを介して行うことです。モジュールBでモジュールAをインポートして使用する場合は、呼び出しPyImport_Import()てモジュールオブジェクトPyObject_GetAttrString()を取得し、目的の型オブジェクトを取得し、いずれかを呼び出しPyObject_Call*()てインスタンス化します。その型へのポインタを格納したい場所ならどこでも、あなたはただ。を取るでしょうPyObject *

于 2010-01-26T00:06:04.290 に答える