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/
>
|