Skip to content

wxWidgets inheritance export? #1905

@Suryavarman

Description

@Suryavarman

MyWxClass to python

I use wxWidgets, wxPython and pybind11.

My project code is here: https://framagit.org/Suryavarman/ma/

and here a video

I have create a class from wxControl.

class M_DLL_EXPORT OgreView : public wxControl
{
    public:
            OgreView(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=0,
                     const wxValidator& validator = wxDefaultValidator, const wxString &name=wxPanelNameStr);
[…]
}

Here a part of code to export the OgreView to python.

    py::class_<API::wx::OgreView>(subModule, "wxOgreView")
        .def(py::init<>())
        .def(py::init<>
        (
             [] (py::object inWindow)
             {

                 wxWindow *window = API_Py::wxLoad<wxWindow>(inWindow.release(), "wxWindow");
                 wxASSERT(window);

                 return new API::wx::OgreView(window);
             }
        ), py::arg("inWindow")
        )
        .def("getParentClass", [](const API::wx::OgreView& self){return static_cast<wxControl*>(const_cast<API::wx::OgreView*>(&self));}, py::call_guard<py::gil_scoped_release>(), py::return_value_policy::reference, "Retourne la classe parente de wxOgreView.")
        ;

Here the casters:
wxPy.h
wxPy.tpp
wxPy.cpp

Note: the typed casters are define at the end of wxPy.h file.

M_WX_PY_CASTER(wxWindow, "wx.Window")
M_WX_PY_CASTER_NO_CLASSINFO(wxSize, "wx.Size")
M_WX_PY_CASTER_NO_CLASSINFO(wxPoint, "wx.Point")
M_WX_PY_CASTER(wxValidator, "wx.Validator")
M_WX_PY_CASTER(wxControl, "wx.Control")
M_WX_PY_CASTER(wxAuiNotebook, "wx._aui.AuiNotebook")
M_WX_PY_CASTER(wxFrame, "wx.Frame")

I want to remove the getParentClass to use directly OgreView parent class.
To do that there are two options (see pybind11 documentation)

  1. Load and add the PyObject parent
    py::object py_wx_module = py::module::import("wx");
    py::object py_type_wxControl = static_cast<py::object>(py_wx_module.attr("Control"));
    py::class_<API::wx::OgreView>(subModule, "wxOgreView", py_type_wxControl)
        .def(py::init<>
        (
  1. Load the wxPython module and let the casters working.
py::object py_wx_module = py::module::import("wx");

py::class_<API::wx::OgreView, wxControl>(subModule, "wxOgreView")
 .def(py::init<>
 (

The both doesn't work.

First option:

  1. During the loading module, it's crash here (segmentation fault):

pybind11.h > generic_type::initialize(const type_record &rec)
line: 933

        else if (rec.bases.size() == 1) {
            auto parent_tinfo = get_type_info((PyTypeObject *) rec.bases[0].ptr());
            tinfo->simple_ancestors = parent_tinfo->simple_ancestors;  // <--- crash here line 933
        }

parent_tinfo is null because, get_type_info return a nullptr if the types are not pybind11-registered.
Remark: It will be good to test the parent_tinfo value.

pybnd11/cast.h line 155-167 get_type_info function

// Gets a single pybind11 type info for a python type.  Returns nullptr if neither the type nor any
// ancestors are pybind11-registered.  Throws an exception if there are multiple bases--use
// `all_type_info` instead if you want to support multiple bases.

Second option:

  1. During the loading module, pybind11 send this error:

    ImportError: generic_type: type "wxOgreView" referenced unknown base type "wxControl"

Questions:

What does it mean exactly «pybind11-registered»? Define the caster is not enough?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions