2010-12-03 24 views
1

によって渡される引数(複数可)でPythonの関数を呼び出します。最終結果は、Python関数が引数に対して行うことが元のC変数に保存されることです。テストするにはPythonのCのAPI:私はCでのpythonモジュールを書いていると私はそれが「参照」によって渡される引数の一つでPythonの関数を呼び出す持っている必要があります参照

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); 

、私は= 5にtcpResumeFuncが渡された整数を変更表しPythonの機能を持っていた私は、このコードの末尾に*履歴書をプリントアウトすると、しかし、それはそれは初期だ保持値-1 。私は、APIの仕組みについて誤解していることを知っています。助言がありますか?

答えて

4

私はあなたが変数がPythonでどのように機能するかについて誤解していると思います。 Pythonの変数には値は含まれていません。 Javaのように、「プリミティブ」はありません(intもありません)。変数への代入は古い値を上書きしません。単に変数が新しい値を参照するようにし、古い値を参照するのを止めます(それ以外は何も参照しなければガベージコレクションされる可能性があります)。

実際に値を返すだけではなく(なぜなら、たとえそれが暗黙の復帰Noneであっても、Python関数は常に何かを返すので)?


編集:コメントの返信には時間がかかりすぎるため、例を使って作業してください。

Cから

、我々は、Pythonの関数にオーバーPyObject *を渡しPyObject_CallFunctionを呼び出します。 Pythonでは、functionパラメータ(これはspamと呼ぶ)は、PyObjectで指し示されたポイントを参照するようになりました。

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

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

したがって、resumeIntではありません。は、新しく作成/取得されたPyObjectをポイントします。

実際には、PythonからPython関数を呼び出すのとまったく同じように動作します。 spamを再バインドするeggsには影響しないため、この問題が発生した

def fry(spam): 
    spam += 1 

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

、別の変数である:それを試してみてください。私たちは参照渡しではありません。 の参照を値で渡しています。 Javaと同じように。

+0

私は* resumeInt以来と呼ばれるPython関数によって修正され、私は新しい* resumeIntが残されることになるPyObject_CallFunctionにそれを通過した後、同じオブジェクトを参照することを想定し(と思う)、ということを理解します。それからPyInt_AsLongでC変数に変換し直します。そのアイデアに何か問題はありますか?あなたの提案はもう少しエレガントで簡単に聞こえますが、私はこれを理解したいと思います。 –

+0

ああ、あなたの編集後、それは理にかなっています。だから私がやっていることはおそらく不可能だろう。値を返すようにコードを修正します。私は投票するだろうが、十分な評判はない。素晴らしい答えですが、ありがとう! –

関連する問題