Re: [pygccxml-development] questions about inheritance
Brought to you by:
mbaas,
roman_yakovenko
From: Kevin W. <kev...@gm...> - 2008-03-01 18:03:11
|
Say I have class A { public: virtual void DoSomething() = 0; }; and class B { public: void Something() { /* ... */ } virtual void DoSomething() { Something(); } }; I want to hide the DoSomething methods from Python, but keep Something exposed. So I do mb.calldefs(lambda d: d.name.startswith('Do')).exclude() to hide the DoSomethings(). The problem is, class A has other methods that I need, so I use A.include() to include it. I get compile errors, saying "cannot instantiate abstract class." I think what is happening, is that by excluding the pure virtual functions in A, I'm fooling Py++ into generating invalid wrappers for A (since all the pure virtual functions are "hidden"). Does "exclude" work this way? If not, Py++ must be getting confused about some other aspect of the classes and I'll have to investigate further. (Ideally what I really want is to finalize ALL classes unless I say so explicitly that a method should be overridden. This seems ideal for performance. I found the finalize function in the contrib folder, and it seems to work, but I'm still not sure how to handle the more complex case outlined above.) I also have another, entirely unrelated question :-D In the class hierachy I'm attempting to get something working with, there is an entire category of classes (all with one common base class) that are "owned" entirely by C++, since they have operating system window resources. When you create a button, for instance, you attach it to a window, and the window is responsible for destroying it. You call something like window->Destroy(), and then the Python reference to the button has to become "invalid." The other wrapper for this GUI library that exists (created with SWIG) has a clever solution where the __class__ of the object is assigned to a special "DeadObject" class, and any further attribute accesses on the object raise Exceptions (instead of crash the program ;) ). I'm having trouble figuring out to achieve this kind of behavior with boost. Basically, the object lifetime of a wxButton, for instance, is not at all determined by any python objects which may reference it. It's constructor takes a wxWindow* parent which immediately gains ownership of the wxButton, and Destroys its children when it is Destroyed. If the Python reference to the button goes away, nothing at all should happen. How does that idea fit into Boost's object lifetime management, if at all? On Thu, Feb 28, 2008 at 2:55 PM, Roman Yakovenko <rom...@gm...> wrote: > On Thu, Feb 28, 2008 at 7:33 PM, Kevin Watters <kev...@gm...> wrote: > > I'm using Py++ with a complex class hierarchy with lots of virtual methods. > > It should not be a problem > > > > As one example, wxWindow inherits from wxObject. But Py++ is > > generating class wrappers which don't reflect any inheritance at all. > > The class declaration for wxWindow looks like > > > > bp::class_< wxWindow, boost::noncopyable >( "Window" ) > > .def( bp::init< >() ) > > .def( bp::init< wxWindow *, wxWindowID, bp::optional< wxPoint > > const &, wxSize const &, long int, wxString const & > >(( > > bp::arg("parent"), bp::arg("winid"), bp::arg("pos")=wxDefaultPosition, > > bp::arg("size")=wxDefaultSize, bp::arg("style")=(long int)(0), > > bp::arg("name")=wxString(wxPanelNameStr) )) ) > > > > > > Note the missing bp::bases. > > > > Oddly enough, if I load up a module builder in a console and query > > wxWindow for its bases with the "recursive_bases" property, I see that > > pygccxml has successively pulled out a chain of classes that looks > > correct: "wxWindow -> wxCocoaNSView -> wxWindowBase -> wxEvtHandler -> > > wxTrackable -> wxObject" > > > > By which criteria does Py++ decide to expose inhertiance? Do I need to > > "include" each of the classes listed in wxWindow's recursive_bases > > property? What if I want just the wxObject methods to be exposed? > > I read your script. I think I understand what the problem is. > Take a look on this document. > http://language-binding.net/pyplusplus/documentation/tutorials/module_builder/module_builder.html#declarations-customization > > I guess this is the problem. You can check it by testing "ignore" value > > mb.class_( 'wxObject' ).ignore > > Basically I suggest you to exclude everything and than to include all > declarations you want to expose. > mb = module_builder_t(...) > mb.global_ns.exclude() > > mb.classes( lambda decl: decl.startswith( 'wx' ) ).include() > > > > > (For reference, my code generator is at > > http://code.google.com/p/wxpy/source/browse/trunk/generate_code.py) > > Why do you use so much try...except blocks? > > For example: > try: mb.mem_funs(name = 'CloneGDIRefData').exclude() > except: pass > > If the function is there Py++ will find it an exclude, if it not > there, than exception will be thrown and you will be noted that the > were some changes in source files? > > I ask, because I want to understand whether the problem in Py++ > interface or this is just your use case. > > > > Any help is much appreciated! > > HTH > > -- > Roman Yakovenko > C++ Python language binding > http://www.language-binding.net/ > |