Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have a variable PyObject that I know is a Python bool. It either is True or False (eg. Py_True or Py_False). Now I would like to convert it to C++ somehow.

Doing this with strings isn't so hard, there is a helper function for that - PyBytes_AsString that converts python string into C string. Now I need something like that for boolean (or int as there is no bool in C).

Or if there isn't conversion, maybe some function that can compare with true or false? Something like int PyBool_IsTrue(PyObject*)?

Here is some example code for easier understanding of what I need:

#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;
}

This obviously wouldn't work as there is no such function like PyBool_IsTrue :( how can I do that?

Snippet of Python header (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 */
like image 822
Petr Avatar asked Oct 09 '16 21:10

Petr


People also ask

How do I change Boolean data type in Python?

We can evaluate values and variables using the Python bool() function. This method is used to return or convert a value to a Boolean value i.e., True or False, using the standard truth testing procedure.

How do you convert boolean to in Python?

Method 1: Convert String to Boolean in Python using bool() The bool() method in general takes only one parameter(here x), on which the standard truth testing procedure can be applied. If no parameter is passed, then by default it returns False.

What is a boolean object Python?

The Python Boolean type is one of Python's built-in data types. It's used to represent the truth value of an expression. For example, the expression 1 <= 2 is True , while the expression 0 == 1 is False . Understanding how Python Boolean values behave is important to programming well in Python.

How do you get a boolean input from user in Python?

bool() in Python input Here we take input in boolean( True/ False) in boolean type with bool() function and check whether it is returned true or false.


1 Answers

Every Python object can have its truthiness evaluated with PyObject_IsTrue, and you should use this in preference to direct PyTrue/PyFalse singleton checking unless you absolutely know, for certain, that the object is a PyBool.

Usage is:

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

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

You can just test someobj == Py_True if you know it's definitely a bool, or use PyNumber_AsSsize_t to convert any logical integer type (anything implementing __index__, and bool is a subclass of int, so it's also logically an integer) to a signed size_t value (if __index__ returns a number that doesn't fit in signed size_t, it will return -1 with exception set).

The reason not to do someobj == Py_True in general is because it's like doing if someobj is True: at the Python layer. If someobj is 1, or an non-empty str, that will treat it as false, when Pythonic code is rarely concerned about being True or False, but rather, "truthiness" and "falsiness".

In addition, this:

PyObject *b = Py_RETURN_TRUE;

is flat wrong. That will incref PyTrue and return it; none of the subsequent code will execute. You'd want:

PyObject *b = Py_True;

for a borrowed reference, adding a subsequent:

Py_INCREF(b);

to make it an owned reference if you intended to return it later (since it's a singleton that won't go away, using a borrowed reference is fine unless you know it will be DECREFed later, e.g. because you returned it and passed ownership to a caller who can't know it's a borrowed reference).

like image 88
ShadowRanger Avatar answered Oct 05 '22 12:10

ShadowRanger