Python NamedTuple 到 C++ 结构

Python NamedTuple to C++ Struct

此时我已经在互联网上搜索了几个小时。有谁知道如何将从 python 函数返回的 namedtuple 解析为结构或仅解析为单独的变量。我遇到问题的部分是从返回的指针中获取数据。我正在使用 PyObject_CallFunction() 调用调用嵌入在 C++ 中的 python 函数,我不知道在获得返回数据的 PyObject* 后该怎么做。

我正在使用 Python 2.7 作为参考。

编辑:我最终将我在 Python 和 C++ 中尝试做的所有功能暂时移动到 Python。我将在不久的将来更新有关尝试该问题评论中建议的策略的信息。

namedtuple 纯粹在 Python 中实现。您可以在 collections.py 中查看其完整源代码。它很短。要记住的是 namedtuple 本身是一个函数,它在调用它的框架中创建一个 class 然后 returns 这个 class (不是实例class)。正是这个返回的 class 然后用于创建实例。所以如果你想传递单个实例,你得到的对象不是你想传递给 C++ 的对象。

C++ 在编译时创建 struct 定义。 namedtuple 在 运行 时间创建命名元组 classes。如果要将它们绑定到 C++ 结构,请使用 PyObject 在 C++ 中创建新创建的 class' 实例,并在编译时将它们分配给 struct 元素。或者在 Python 中创建新创建的 class' 实例并将它们传递给 C++。

或者您可以使用 _asdict 方法(由 namedtuple 工厂方法为它构建的所有 classes 提供)并将其传递给 C++,然后进行 运行-time 的绑定定义的数据到编译时定义的数据。

如果你真的想用 C++ 完成大部分工作,你也可以使用 Struct 模块而不是使用 namedtuple。

namedtuple 对于 Python 中的数据来说确实是 Python 的瑞士军刀。它提供位置访问、命名访问,并且所有元素也是 "properties"(因此它们具有 fget 访问器方法,可用于映射、过滤器等,而不必编写自己的 lambda) .

它用于数据库绑定之类的事情(当您不知道 运行 时哪些列将在那里时)。在将数据从一种格式转换为另一种格式时,它没有 OrderedDict 笨拙。当以这种方式使用时,与数据库的实际访问(甚至嵌入式)相比,处理字符串的开销是微不足道的。但是我不会将 namedtuple 用于用于计算的大型结构数组。

I am calling a python function embedded in C++ using the PyObject_CallFunction() call and I don't know what to do once I have the PyObject* to the returned data.

A namedtuple 是一个元组子类,它另外将元组元素公开为命名属性。这意味着您可以选择是否以 obj[position]obj.attribute 访问其数据。后者通常更具可读性,但前者与元组拆包结合得很好。在 Python/C 中,作为元组访问它可能更容易,因为那时您可以使用便利函数 PyArg_ParseTuple,如评论中所示。

要提取对象的任意属性(不一定是 namedtuple),可以调用 PyObject_GetAttrString。给定一个描述点的对象,提取 x 之类的属性可能如下所示:

PyObject *point = ...;  // assume we get a new reference to point
if (!point)
  return NULL;
PyObject *x = PyObject_GetAttrString(point, "x");
if (!x) {
  // obj.x raised, possibly because point is of a different type
  Py_DECREF(point);
  return NULL;
}
double x_val = PyFloat_AsDouble(x);
Py_DECREF(x);     // x not used below this line
if (x_val == -1 && PyErr_Occurred()) {
  // obj.x is not float or float-like
  Py_DECREF(point);
  return NULL;
}
Py_DECREF(point); // point not used below this line

错误检查和引用计数非常繁琐,但是可以使用guard 类或者更好的是使用其他人编写的类来消除它,例如Boost.Python.