在嵌入 C++ 后从 Python 中提取值

Extracting value from Python after it's embedded in C++

我有以下嵌入 Python 的缩短程序(为了简短起见,它删除了所有错误处理等)。它创建 Python 函数作为字符串(这是我手头的问题所必需的),然后尝试调用它并使用 __builtin__.eval.

获取它返回的任何内容
#include <Python.h>
#include <iostream>

int main() {
  // Initialize Python
  Py_Initialize();

  // Import builtin to get an access to eval
  PyObject *builtins = PyImport_ImportModule("__builtin__");
  PyObject *eval = PyObject_GetAttrString(builtins, "eval");

  // Create an argument tuple for the eval
  PyObject * args = PyTuple_New(1);
  PyObject * name = PyString_FromString("f(10)");
  PyTuple_SetItem(args, 0, name);

  // Create a function
  PyRun_SimpleString("f = lambda x: x * 2 - 3");

  // Try to get the result of the function execution by calling eval on it
  PyObject * result = PyObject_CallObject(eval, args);

  // Fail if the result is null pointer
  assert(result != NULL);

  // Destroy Python frame
  Py_Finalize();
}

换句话说,这个程序类似于下面的 Python 程序:

f = lambda x: x * 2 - 3
import __builtin__
print __builtin__.eval("f(10)")

问题是:它在 Python 中完美运行(返回 17)。但在 C++ 中,PyObject_CallObject returns NULL 指针和程序在 assert 处失败,即使 eval 显然应该返回 f(10) 的结果。我的问题是为什么?

感谢您的回答!

P.S。如果您想尝试自己编译,请在 Unix 系统上使用以下命令(我在 Ubuntu 上使用它):

g++ -I/usr/include/python2.7 progname.cpp -lpython2.7 -g

实际上我自己已经想出了如何做到这一点。不需要使用 eval() 来提取函数执行的结果。相反,您可以执行以下操作:

#include <Python.h>
#include <iostream>

int main() {
  // Initialize Python
  Py_Initialize();

  // Create a function
  PyRun_SimpleString("f = lambda x: x * 2 - 3");

  // Import __main__ where the f is stored
  PyObject *main = PyImport_ImportModule("__main__");
  PyObject *function = PyObject_GetAttrString(main, "__function");

  // Create an argument tuple for the function
  PyObject * args = PyTuple_New(1);
  PyObject * first_argument = PyInt_FromLong(10);
  PyTuple_SetItem(args, 0, first_argument);

  // Call the function and get its result
  PyObject * result = PyObject_CallObject(function, args);

  // Output the result
  cout << PyInt_AsLong(result) << endl;

  // Destroy Python frame
  Py_Finalize();
}

但是,我仍然很好奇为什么 eval 没有像我原来的问题那样工作