繁体   English   中英

如何将Python布尔对象转换为C int(或C ++ boolean)(Python C API)

[英]How can I convert Python boolean object to C int (or C++ boolean) (Python C API)

我有一个变量PyObject ,我知道它是一个Python bool。 它可以是TrueFalse (例如Py_TruePy_False )。 现在我想以某种方式将其转换为C ++。

使用字符串执行此操作并不困难,有一个帮助函数 - PyBytes_AsString将python字符串转换为C字符串。 现在我需要类似的布尔值(或者因为C中没有bool )。

或者如果没有转换,也许某些功能可以与true或false进行比较? 类似于int PyBool_IsTrue(PyObject*)

以下是一些示例代码,可以更轻松地理解我需要的内容:

#include <Python.h>

int main()
{
    /* here I create Python boolean with value of True */
    PyObject *b = Py_RETURN_TRUE;
    /* now that I have it I would like to turn in into C type so that I can determine if it's True or False */
    /* something like */
    if (PyBool_IsTrue(b))
    { /* it's true! */ }
    else
    { /* it's false */ }
    return 0;
}

这显然不会起作用,因为没有像PyBool_IsTrue这样的函数:(我怎么能这样做?

Python标题的片段(boolobject.h):

/* Boolean object interface */

#ifndef Py_BOOLOBJECT_H
#define Py_BOOLOBJECT_H
#ifdef __cplusplus
extern "C" {
#endif


PyAPI_DATA(PyTypeObject) PyBool_Type;

#define PyBool_Check(x) (Py_TYPE(x) == &PyBool_Type)

/* Py_False and Py_True are the only two bools in existence.
Don't forget to apply Py_INCREF() when returning either!!! */

/* Don't use these directly */
PyAPI_DATA(struct _longobject) _Py_FalseStruct, _Py_TrueStruct;

/* Use these macros */
#define Py_False ((PyObject *) &_Py_FalseStruct)
#define Py_True ((PyObject *) &_Py_TrueStruct)

/* Macros for returning Py_True or Py_False, respectively */
#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False

/* Function to return a bool from a C long */
PyAPI_FUNC(PyObject *) PyBool_FromLong(long);

#ifdef __cplusplus
}
#endif
#endif /* !Py_BOOLOBJECT_H */

每个 Python对象都可以使用PyObject_IsTrue评估其真实性,并且您应优先使用它来指导PyTrue / PyFalse单例检查,除非您绝对知道该对象是PyBool

用法是:

int truthy = PyObject_IsTrue(someobj);
if (truthy == -1) return APPROPRIATEERRORRETURN;

if (truthy)
{ /* it's true! */ }
else
{ /* it's false */ }

如果你知道它肯定是一个bool,你可以测试someobj == Py_True ,或者使用PyNumber_AsSsize_t将任何逻辑整数类型(任何实现__index__boolint的子类,因此它在逻辑上也是一个整数)转换为有符号的size_t值(如果__index__返回的数字不符合有符号的size_t ,则返回-1并设置异常)。

一般来说不做someobj == Py_True的原因是因为它就像在if someobj is True:在Python层。 如果someobj1 ,或者是非空的str ,那将把它视为假,当Pythonic代码很少关注是True还是False ,而是“真实性”和“虚假”。

另外,这个:

PyObject *b = Py_RETURN_TRUE;

是错的。 这将增加PyTrue并返回它; 后续代码都不会执行。 你想要:

PyObject *b = Py_True;

借用参考,添加后续:

Py_INCREF(b);

如果你打算稍后返回它(因为它是一个不会消失的单例,使用借用的引用是正常的,除非你知道它将在以后DECREF ,例如因为你返回它并将所有权转移到一个不知道它的来电者是借来的参考。

答案是在Python标题中,但可能并不明显。

Python头文件在这里声明了2个有点静态的对象,有几个宏:

/* Don't use these directly */
PyAPI_DATA(struct _longobject) _Py_FalseStruct, _Py_TrueStruct;

/* Use these macros */
#define Py_False ((PyObject *) &_Py_FalseStruct)
#define Py_True ((PyObject *) &_Py_TrueStruct)

/* Macros for returning Py_True or Py_False, respectively */
#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False

似乎TrueFalse都是Python对象,Python中的所有TrueFalse值实际上都是对这两个全局Py_TruePy_False对象的引用。 使用Py_RETURN_TRUE返回此类对象时,引用计数会递增。

这意味着指向值为Py_True PyObject的每个C指针实际上都指向相同的内存地址。 因此,检查PyObject是真还是假是如此简单:

/* here I create Python boolean with value of True */
PyObject *b = Py_True;
Py_INCREF(b);
/* now we compare the address of pointer with address of Py_True */
if (b == Py_True)
{ /* it's true! */ }
else
{ /* it's false */ }

通常使用int PyBool_Check(PyObject*)来验证相关对象是否为Python boolean。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM