|
Boost : |
From: David Abrahams (abrahams_at_[hidden])
Date: 2001-05-14 19:28:34
Hi Donovan,
you are having what amounts to the same problem as Rainer Deyke had in this
thread: http://groups.yahoo.com/group/boost/message/10164. I don't find his
suggested approach for this nearly as objectionable as I once did, but I
don't think there's any way to make it work in the particular case you raise
below. The problem is that BaseNode has no virtual functions, so there is no
possible way that C++ can determine that your BaseNode* actually points to a
DerivedNode. If you are willing to give BaseNode a virtual function (e.g. a
virtual destructor), then I suggest you pursue Rainer's suggestion and try
to modify smart_ptr_to_python so that it tries to walk down the declared
inheritance hierarchy using dynamic_cast until it finds the most-derived
class. I don't have any time to do this myself right now, but I'd be happy
to give you advice and guidance.
Regards,
Dave
----- Original Message -----
From: "Donavon Keithley" <keithley_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Friday, May 04, 2001 6:02 PM
Subject: [boost] BPL: Inheritance Question
> I'm experimenting with a binary tree structure using polymorphic nodes,
but
> I seem to be losing object identity on the Python side.
>
> struct BaseNode
> {
> BaseNode* l;
> BaseNode* r;
> };
>
> struct DerivedNode : public BaseNode
> {
> int foo;
> };
>
> Following the cookbook, I wrap BaseNode* as follows:
>
> PyObject* to_python(BaseNode* p)
> {
> return
>
python::python_extension_class_converters<BaseNode>::smart_ptr_to_python(p);
> }
> PyObject* to_python(const BaseNode* p)
> {
> return to_python(const_cast<BaseNode*>(p));
> }
>
> Similarly for DerivedNode. And then build the classes like so:
>
> boost::python::class_builder<BaseNode> BaseNode_class(this_module,
> "BaseNode");
> BaseNode_class.def(boost::python::constructor<>());
> BaseNode_class.def_read_write(&BaseNode::l, "l");
> BaseNode_class.def_read_write(&BaseNode::r, "r");
>
> boost::python::class_builder<DerivedNode> DerivedNode_class(this_module,
> "DerivedNode");
> DerivedNode_class.def(boost::python::constructor<>());
> DerivedNode_class.def_read_write(&DerivedNode::foo, "foo");
> DerivedNode_class.declare_base(BaseNode_class, python::without_downcast);
>
> In Python:
>
> >>> dn0 = DerivedNode()
> >>> dn0.foo = 0
> >>> dn1 = DerivedNode()
> >>> dn1.foo = 1
> >>> dn0.l = dn1
> >>> dn0.l
> <BaseNode object at 00D46540> <-- Uh oh...
> >>> dn0.l.foo
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> AttributeError: foo
>
> This clearly doesn't work, so my question is what would be a correct
> approach?
>
> I've noticed -- and this is probably related -- that if I instantiate
> BaseNodes, it sort of works:
>
> >>> bn0 = BaseNode()
> >>> bn1 = BaseNode()
> >>> bn0.l = bn1
>
> I've verified that bn0.l and bn1 refer to the same instance of BaseNode on
> the C++ side, in spite of the fact that their Python identities are not
the
> same:
>
> >>> id(bn0.l)
> 13919552
> >>> id(bn1)
> 13920016
>
> I only barely understand how BPL works under the hood, but it seems that
> what I need here is proxies on the Python side -- that is, a to_python
> conversion that always returns the same PyObject for the same BaseNode* or
> DerivedNode*.
>
> Any insight would be greatly appreciated!
> --Donavon
>
>
> To unsubscribe, send email to: <mailto:boost-unsubscribe_at_[hidden]>
>
>
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
>
>
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk