4

Python インタープリターを組み込んだシステムに取り組んでおりPyObject*、C API から特定の文字列を作成する必要があります。

Python 内から適切に動作するためconst char*の適切な形式、つまり. eval()"{'bar': 42, 'baz': 50}"

現在、これはAPI (文字列を表す)PyObject*を使用して Python に渡されているため、Python インタープリターでは次のように記述できます。Py_Unicode_

foo = eval(myObject.value)
print(foo['bar']) # prints 42

const char*これをC 側で自動的に「評価」するように変更しPyObject*、完成した辞書を表す を返したいと思います。この文字列を C API の辞書に変換するにはどうすればよいですか?

4

1 に答える 1

4

これを行うには、2 つの基本的な方法があります。

eval1 つ目は、Python で行うのと同じ方法で単純に呼び出すことです。唯一の秘訣は、モジュールへのハンドルが必要なことbuiltinsです。これは、C API では無料で取得できないためです。これを行うにはいくつかの方法がありますが、非常に簡単な方法の 1 つは、インポートすることです。

/* or PyEval_GetBuiltins() if you know you're at the interpreter's top level */
PyObject *builtins = PyImport_ImportModule("builtins");
PyObject *eval = PyObject_GetAttrString(builtins, "eval");
PyObject *args = Py_BuildValue("(s)", expression_as_c_string);
PyObject *result = PyObject_Call(eval, args);

(これはテストされていないコードであり、少なくとも参照をリークし、C 側で例外を処理したい場合は NULL 戻りをチェックしません…しかし、アイデアを理解するには十分なはずです。)

これについての 1 つの良い点はast.literal_eval、まったく同じ方法で使用できることですeval(これは、無料の検証を取得することを意味します); 、およびに変更"builtins"するだけです。しかし、本当の利点は、Python で行っていることとまったく同じことを行っていることです。これは、まさにあなたが望んでいたことであることが既にわかっています。"ast""eval""literal_eval"eval

別の方法は、コンパイル API を使用することです。非常に高いレベルでは、Python ステートメントを構築するだけで済み"foo = eval(%s)"ますPyRun_SimpleString。その下で、 を使用Py_CompileStringして式を解析およびコンパイルし (別の手順で解析およびコンパイルすることもできますが、ここでは役に立ちません)、PyEval_EvalCode適切なグローバルおよびローカルで評価します。(グローバルを自分で追跡していない場合は、インタープリター リフレクション API PyEval_GetLocalsとを使用してPyEval_GetGlobalsください。) 各関数の非常に単純化されたバージョンを提供していることに注意してください。多くの場合、兄弟関数の 1 つを使用する必要があります。しかし、それらはドキュメントで簡単に見つけることができます。

于 2013-04-05T20:56:18.847 に答える