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.
此时我已经在互联网上搜索了几个小时。有谁知道如何将从 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.