63

I'm desperately trying to expose a std::vector<bool> class member to a Python class.

Here is my C++ class:

class Test
{
  public:
    std::vector<bool> test_fail;
    std::vector<double> test_ok;
};

While the access and conversion of test_ok of type double (or int, float, ..) works, it does not for bool!

Here is my Cython class:

cdef class pyTest:
     cdef Test* thisptr
     cdef public vector[bool] test_fail
     cdef public vector[double] test_ok

     cdef __cinit__(self):
         self.thisptr = new Test()
         self.test_fail = self.thisptr.test_fail # compiles and works if commented
         self.test_ok = self.thisptr.test_ok

     cdef __dealloc__(self):
         del self.thisptr

The error I get is :

Error compiling Cython file:
------------------------------------------------------------
...




cdef extern from *:
    ctypedef bool X 'bool'
            ^
------------------------------------------------------------

vector.from_py:37:13: 'bool' is not a type identifier

I'm using python 2.7.6 and Cython 0.20.2 (also tried 0.20.1).

I also tried with properties but it does not work either.

Addendum: I do have the from libcpp cimport bool at the top of my pyx file, as well as the vector import.

What's wrong ?? I believe this might be a bug. Anyone knows how to circumvent this ? Thanks.

Carmellose
  • 4,815
  • 10
  • 38
  • 56
  • The Cython wiki is quite helpful regarding this issue: https://github.com/cython/cython/wiki/FAQ#id49 – 0 _ Mar 23 '17 at 01:36

3 Answers3

74

There's some extra C++ support you need to do. At the top of your .pyx file, add

from libcpp cimport bool

I'd take a look inside that to find the other things you might need, like std::string and STL containers

Ben
  • 2,065
  • 1
  • 13
  • 19
  • 1
    Can't seem to edit my answer: add `from libcpp.vector cimport vector` for the vector keyword – Ben Jul 09 '14 at 17:16
  • hello, I forgot to mention that I do have the `cimport bool` in the top of my pyx file :( – Carmellose Jul 10 '14 at 08:08
  • I think I misread. It seems to be complaining about the `'bool'` typedef. It's unnecessary IMO. If you've imported bool, you can declare any bool variable with `cdef bool x` – Ben Jul 10 '14 at 14:09
  • 8
    `from libcpp cimport bool as bool_t` would be better to solve the naming conflict with Python's bool. – mckelvin Nov 06 '14 at 10:18
48

In order to define boolean objects in cython, they need to be defined as bint. According to here: The bint of "boolean int" object is compiled to a c int, but get coerced to and from Cython as booleans.

Example:

cdef bint boolean_variable = True

source: types bint

Dalek
  • 4,168
  • 11
  • 48
  • 100
3

I have found a valid workaround, although it may not be optimal.

I have replaced the members types of the pytest class with python lists.

The conversion is now done implicitly, as described in the documentation: https://docs.cython.org/en/latest/src/userguide/wrapping_CPlusPlus.html#standard-library

All conversions create a new container and copy the data into it. The items in the containers are converted to a corresponding type automatically, which includes recursively converting containers inside of containers, e.g. a C++ vector of maps of strings.

So now, my class looks like this:

cdef class pyTest:
     cdef Test* thisptr
     cdef public list test_fail #now ok
     cdef public list test_ok

     cdef __cinit__(self):
         self.thisptr = new Test()
         self.test_fail = self.thisptr.test_fail # implicit copy & conversion
         self.test_ok = self.thisptr.test_ok # implicit copy and conversion

     cdef __dealloc__(self):
         del self.thisptr
Community
  • 1
  • 1
Carmellose
  • 4,815
  • 10
  • 38
  • 56