如何将 Python boolean object 转换为 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 布尔值。它可以是 True
或 False
(例如 Py_True
或 Py_False
)。现在我想以某种方式将它转换为 C++。
用字符串做这个并不难,有一个辅助函数 - PyBytes_AsString
将 python 字符串转换为 C 字符串。现在我需要类似布尔值的东西(或 int 因为 C 中没有 bool
)。
或者如果没有转换,也许一些函数可以与真或假进行比较?类似于 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
这样的功能 :( 我该怎么做?
Pythonheader(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 headers 中,但可能并不明显。
Python headers 在这里声明 2 个有点静态的 objects,有几个宏:
/* 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
似乎 True
和 False
实际上都是 Python object 并且 Python 中的所有值都是 True
或 False
实际上是对这两个全局 Py_True
和 Py_False
object 的引用。当使用 Py_RETURN_TRUE
返回这样的 object 时,引用计数会增加。
这意味着每个指向值为 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*)
来验证所讨论的 object 是否为 Python 布尔值。
每个 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 */ }
如果您知道 someobj == Py_True
绝对是布尔值,您可以只测试它,或者使用 PyNumber_AsSsize_t
转换任何逻辑整数类型(任何实现 __index__
和 bool
是 int
的子类,所以它在逻辑上也是一个整数)到有符号的 size_t
值(如果 __index__
returns 一个数字不适合有符号的 size_t
, 它会 return -1 异常设置).
一般不做someobj == Py_True
的原因是因为它就像在Python层做if someobj is True:
。如果 someobj
是 1
,或者一个非空的 str
,那么当 Pythonic 代码很少关心是 True
或者False
,而是 "truthiness" 和 "falsiness".
另外,这个:
PyObject *b = Py_RETURN_TRUE;
完全错误。这将增加 PyTrue
和 return 它; none 的后续代码将执行。你想要:
PyObject *b = Py_True;
对于借用的参考,添加后续:
Py_INCREF(b);
如果您打算稍后 return 它,使其成为拥有的引用(因为它是一个不会消失的单例,使用借来的引用很好,除非您知道它会 DECREF
稍后编辑,例如因为您 return 编辑它并将所有权传递给不知道它是借用引用的调用者)。
我有一个变量 PyObject
,我知道它是一个 Python 布尔值。它可以是 True
或 False
(例如 Py_True
或 Py_False
)。现在我想以某种方式将它转换为 C++。
用字符串做这个并不难,有一个辅助函数 - PyBytes_AsString
将 python 字符串转换为 C 字符串。现在我需要类似布尔值的东西(或 int 因为 C 中没有 bool
)。
或者如果没有转换,也许一些函数可以与真或假进行比较?类似于 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
这样的功能 :( 我该怎么做?
Pythonheader(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 headers 中,但可能并不明显。
Python headers 在这里声明 2 个有点静态的 objects,有几个宏:
/* 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
似乎 True
和 False
实际上都是 Python object 并且 Python 中的所有值都是 True
或 False
实际上是对这两个全局 Py_True
和 Py_False
object 的引用。当使用 Py_RETURN_TRUE
返回这样的 object 时,引用计数会增加。
这意味着每个指向值为 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*)
来验证所讨论的 object 是否为 Python 布尔值。
每个 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 */ }
如果您知道 someobj == Py_True
绝对是布尔值,您可以只测试它,或者使用 PyNumber_AsSsize_t
转换任何逻辑整数类型(任何实现 __index__
和 bool
是 int
的子类,所以它在逻辑上也是一个整数)到有符号的 size_t
值(如果 __index__
returns 一个数字不适合有符号的 size_t
, 它会 return -1 异常设置).
一般不做someobj == Py_True
的原因是因为它就像在Python层做if someobj is True:
。如果 someobj
是 1
,或者一个非空的 str
,那么当 Pythonic 代码很少关心是 True
或者False
,而是 "truthiness" 和 "falsiness".
另外,这个:
PyObject *b = Py_RETURN_TRUE;
完全错误。这将增加 PyTrue
和 return 它; none 的后续代码将执行。你想要:
PyObject *b = Py_True;
对于借用的参考,添加后续:
Py_INCREF(b);
如果您打算稍后 return 它,使其成为拥有的引用(因为它是一个不会消失的单例,使用借来的引用很好,除非您知道它会 DECREF
稍后编辑,例如因为您 return 编辑它并将所有权传递给不知道它是借用引用的调用者)。