これを行うには、2 つの基本的な方法があります。
eval
1 つ目は、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 つを使用する必要があります。しかし、それらはドキュメントで簡単に見つけることができます。