0

I'm trying to bind a union with pybind11 and I'm getting a strange error. I'm not sure if i'm hitting a limitation of pybind11, or i'm implementing this incorrectly.

Would anyone be able to point me in the right direction? Thanks!

#include <iostream>
#include <pybind11/pybind11.h>

namespace py = pybind11;

struct object {
   object();
   union union_type {
       bool boolean;
       uint64_t u64;
       int64_t  i64;
       double   f64;
   };
   union_type via;
};

PYBIND11_MODULE(example, m) {
    pybind11::class_<object, std::shared_ptr<object>> cl(m, "object", "Object class that corresponding stuff");
    pybind11::handle cl_type = cl;
    {
        auto & enclosing_class = cl;
        py::class_<object::union_type, std::shared_ptr<object::union_type>> cl(enclosing_class, "union_type", "");
        cl.def( pybind11::init( [](object::union_type const &o){ return new object::union_type(o); } ) );
        cl.def( pybind11::init( [](){ return new object::union_type(); } ) );
        cl.def_readwrite("boolean", &object::union_type::boolean);
        cl.def_readwrite("u64", &object::union_type::u64);
        cl.def_readwrite("i64", &object::union_type::i64);
        cl.def_readwrite("f64", &object::union_type::f64);
        cl.def("assign", (union object::union_type & (object::union_type::*)(const union object::union_type &)) &object::union_type::operator=, "C++: object::union_type::operator=(const union object::union_type &) --> union object::union_type &", pybind11::return_value_policy::automatic, pybind11::arg(""));
    }
}

error:

pybind11/pybind11.h: In instantiation of ‘pybind11::class_<type_, options>& pybind11::class_<type_, options>::def_readwrite(const char*, D C::*, const Extra& ...) \
[with C = object::union_type; D = bool; Extra = {}; type_ = object::union_type; options = {std::shared_ptr<object::union_type>}]’:
mytest.cpp:35:59:   required from here
python3.7m/pybind11/pybind11.h:1161:9: error: static assertion failed: def_readwrite() requires a class member (or base class member
)
         static_assert(std::is_base_of<C, type>::value, "def_readwrite() requires a class member (or base class member)");
         ^~~~~~~~~~~~~

edit - i compile with:

c++ -O3 -Wall -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` mytest.cpp -o example`python3-config --extension-suffix`
Mr. Buttons
  • 463
  • 1
  • 3
  • 9
  • Removed my answer as it was incomplete: &object::union_type is not a class member, like error tells you, &object::via is a class member – Oleg Bogdanov Feb 03 '19 at 21:13
  • also, mind that pointer to member of union is not the same as a pointer to class member (which type is union in this case) so this won't compile – Oleg Bogdanov Feb 03 '19 at 21:15
  • Okay thanks! Ya I'm not sure about 100% about the other code, this is just a small example to get this 'static_assert' error which is holding me back on a much larger project. – Mr. Buttons Feb 03 '19 at 21:42

1 Answers1

0

Based on general union question with polakovicp's suggestion there , you could apply:

 typedef union _union_type {
       bool boolean;
       uint64_t u64;
       int64_t  i64;
       double   f64;
   }union_type;

py::class_<union_type>(m, "union_type")
        .def(py::init<>())
        .def_property("boolean",
            [](union_type& self) -> const bool& 
            {
                return self.boolean;
            },
            [](union_type& self, const bool& value)
            {
                self.boolean = value;
            });
        .def_property("u64",
            [](union_type& self) -> const uint64_t& 
            {
                return self.u64;
            },
            [](union_type& self, const uint64_t& value)
            {
                self.u64 = value;
            });
        .def_property("i64",
            [](union_type& self) -> const int64_t& 
            {
                return self.i64;
            },
            [](union_type& self, const int64_t& value)
            {
                self.i64 = value;
            });
        .def_property("f64",
            [](union_type& self) -> const double& 
            {
                return self.f64;
            },
            [](union_type& self, const int64_t& value)
            {
                self.f64 = value;
            });
GM1
  • 380
  • 3
  • 14