Что такое "правильный" способ передать логическое расширение Python C?
Это простой пример из документации python (http://docs.python.org/extending/extending.html):
static PyObject *
spam_system(PyObject *self, PyObject *args)
{
const char *command;
int sts;
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
sts = system(command);
return Py_BuildValue("i", sts);
}
Если я хочу передать дополнительный логический параметр функции - какой "правильный" способ сделать это?
Кажется, что нет опции bool для перехода к PyArg_ParseTuple(). Поэтому я подумал о следующем:
- прочитайте целое число и просто используйте значение (поскольку bool является подклассом int)
- вызов PyBool_FromLong() для целого числа
- прочитать и объект и вызвать PyBool_Check(), чтобы убедиться, что это bool
- возможно, есть способ получить любой тип переменной и получить ее значение истинности (т.е. пустой массив будет ложным и т.д.), что обычно делает функция python.
Любое из этих предпочтительных? Другие варианты?
Ответы
Ответ 1
4 возможно, есть способ получить любой тип переменной и получить ее значение истинности (т.е. пустой массив будет ложным и т.д.), что и есть питон функция обычно делаю.
Да: (из Справочник по API Python/C)
int PyObject_IsTrue(PyObject *o)
Возвращает 1, если объект o считается истинным, а 0 - иным. Это эквивалентно выражению Python, а не o. При сбое, return -1.
ИЗМЕНИТЬ. Чтобы ответить на фактический вопрос, я думаю, что подход 1 правильный, потому что int действительно соответствует типу C. Подход 4 хорош, но если вы задокументируете свою функцию как взятие bool, вы не обязаны принимать только любой объект. Явные проверки типов, как в 3 без причины, не одобряются в Python. Преобразование в другой объект Python, как в 2, не помогает вашему C-коду.
Ответ 2
В настоящее время синтаксический анализ целого числа (как "i"
) является принятым способом для bool.
Из Python 3.3, PyArg_ParseTuple
примет "p"
(для "предикат" ), за последние НОВОСТИ:
- Проблема # 14705: семейство функций PyArg_Parse() теперь поддерживает формат "p" единица, которая принимает аргумент "boolean predicate". Он преобразует любой Python значение в целое число - 0, если оно "ложно", а 1 - в противном случае.
Обратите внимание, что при использовании PyArg_ParseTuple
с "p"
аргумент должен быть (указатель на) int
, а не тип C99 bool
:
int x; // not "bool x"
PyArg_ParseTuple(args, kwds, "p", &x);
Ответ 3
Я нашел другой подход:
PyObject* py_expectArgs;
bool expectArgs;
PyArg_ParseTupleAndKeywords(args, keywds, (char *)"O!", (char **)kwlist, &PyBool_Type, &py_expectArgs);
expectArgs = PyObject_IsTrue(py_expectArgs);
В случае неправильного вызова параметра существует "авто" исключение. "Аргумент 1 должен быть bool, а не int"