Я искал в Интернете в течение нескольких часов. Кто-нибудь знает, как проанализировать именованный кортеж, возвращенный из функции Python в структуру или просто в отдельные переменные. У меня проблемы с получением данных из возвращенного указателя. Я вызываю функцию Python, встроенную в C ++, используя вызов PyObject_CallFunction (), и я не знаю, что делать, когда у меня есть PyObject * для возвращаемых данных.
Я использую Python 2.7 для справки.
РЕДАКТИРОВАТЬ: я закончил тем, что перенес всю функциональность, которую я пытался сделать в Python и C ++, только на Python. В ближайшем будущем я опишу попытку стратегии, предложенную в комментариях к этому вопросу.
Я вызываю функцию Python, встроенную в C ++, используя
PyObject_CallFunction (), и я не знаю, что делать, когда у меня есть
PyObject * к возвращенным данным.
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
Проверка ошибок и подсчет ссылок довольно утомительны, но в большинстве случаев их можно устранить с помощью защитных классов или, что еще лучше, с помощью классов, написанных другими, такими как Boost.Python.
namedtuple
реализован исключительно в Python. Вы можете увидеть его полный источник в коллекциях. Это очень коротко. Имейте в виду, что namedtuple
сама по себе является функцией, которая создает класс в кадре, в котором она вызывается, и затем возвращает этот класс (не экземпляр этого класса). И именно этот возвращаемый класс затем используется для создания экземпляров. Таким образом, объект, который вы получаете, не тот, который вы хотите передать в C ++, если вы хотите передать отдельные экземпляры.
C ++ создает struct
определения во время компиляции. namedtuple
создает классы namedtuple во время выполнения. Если вы хотите связать их со структурами C ++, либо используйте PyObject, чтобы создать экземпляры вновь созданного класса внутри C ++ и назначить их struct
элементы во время компиляции. Или создайте экземпляры только что созданного класса в Python и передайте их C ++.
Или вы можете использовать _asdict
метод (предоставляется методом фабрики namedtuple для всех создаваемых им классов) и передает его в C ++, чтобы затем связать определенные во время выполнения данные с определенными во время компиляции данными.
Если вы действительно хотите выполнить основную часть работы в C ++, вы также можете использовать модуль Struct вместо namedtuple.
namedtuple — действительно швейцарский армейский нож Python для данных, которые остаются в Python. Это дает позиционный доступ, именованный доступ, и все элементы также являются «свойствами» (поэтому они имеют fget
метод доступа, который можно использовать в картах, фильтрах и т. д. вместо того, чтобы писать свои собственные лямбды).
Он существует для таких вещей, как привязка БД (когда вы не знаете, какие столбцы будут там во время выполнения). Это менее неуклюже, чем OrderedDict для преобразования данных из одного формата в другой. Когда он используется таким образом, накладные расходы на обработку строк ничто по сравнению с фактическим доступом к БД (даже встроенному). Но я бы не использовал namedtuple для больших массивов структур, которые должны использоваться в вычислениях.