1

私は C で Python モジュールを書いていますが、「参照」によって渡された引数の 1 つを使用して Python 関数を呼び出す必要があります。最終的な結果として、Python 関数が引数に対して行ったことが元の C 変数に保存されます。

int      *resume;      // this int is actually passed in to this body of code
PyObject *resumeInt;   // which was originally a C callback func for libnids, but
PyObject *ret;         // I removed/rewrote most of this code for clarity

resumeInt = Py_BuildValue("i",-1);
ret = PyObject_CallFunction(tcpResumeFunc, "(O)", resumeInt);    

*resume = PyInt_AsLong(resumeInt);
Py_DECREF(ret);
Py_DECREF(resumeInt);

テストするために、tcpResumeFunc が表す Python 関数で、渡された整数を = 5 に変更しました。ただし、このコードの最後に *resume を出力すると、初期値の -1 が保持されます。API の仕組みについて誤解していることはわかっています。助言がありますか?

4

1 に答える 1

4

Pythonで変数がどのように機能するかについて何か誤解していると思います。Pythonの変数には値が含まれていません。それらはそれらを参照します-「プリミティブ」がないことを除いて、Javaのように(さえint)。変数への割り当ては古い値を上書きしません。これにより、変数は新しい値を参照し、古い値の参照を停止します(他に何も参照されていない場合は、ガベージコレクションされる可能性があります)。

なぜ実際に値を返す(そして使用する)のではないのですか(Python関数は、それが単なる暗黙の戻りであっても、とにかく常に何かを返すためNone)?


編集:コメントの返信には長すぎるため、例を使用して作業します。

CからPyObject_CallFunctionを呼び出します。これは、PyObject*をPython関数に渡します。Pythonでは、関数パラメーター(これを呼びますspam)は、ポイントされたPyObjectを参照するようになりました。

関数を書くときspam += 6、それはと同じspam = spam + 6です。バイトコードインタープリターは、値6を表すPyObjectを取得し、2つのオブジェクトによって表される値を検査して追加し、合計を表す新しいPyObjectを作成(またはキャッシュからフェッチ)する特別なバイトコードを実行します。

次にspam、新しいオブジェクトにリバウンドされます。ただし、spam変数参照はメモリフェンスのPython側にあり、フェンスのC側のPyObject*と同じものではありません。

したがって、新しく作成/フェッチされたPyObjectをポイントすることresumeIntはありません。

実際には、PythonからPython関数を呼び出すのとまったく同じように動作します。それを試してみてください:

def fry(spam):
  spam += 1

eggs = 3
fry(eggs)
eggs # still 3!

これは、再バインドが別の変数であるにspam影響を与えないために発生します。eggs私たちは参照によって通過していません。参照を渡します。Javaと同じように。

于 2010-12-03T04:56:33.477 に答える