List Info

Thread: convert child class to child class ?




convert child class to child class ?
country flaguser name
United States
2007-10-10 16:53:06
Hi all,

I am trying to wrap some C++ code that involves an object
factory and 
manager and I seem to be stumped by how boost is converting
types. I have a 
base class and a few classes that inherit from it and a
factory to create 
instances of these classes. Using the factory I can
successfully create 
objects of the proper type. Following the tutorial I have
virtual functions 
behaving properly. However, if I try to call methods that
only exist in a 
child class, I get an Argument Error:

ArgumentError: Python argument types in
    childobj.ChildOnly(childobj)
did not match C++ signature:
    ChildOnly(struct childobj )

 I have tried writing a function that will cast the pointer
to a child class 
pointer. This lets me call child only methods, but then i
get the mirror 
error when I try to call base class methods. The confounding
part is that it 
appears that the type information is correct in python.

If I create an instance without using the factory (child =
childobj()) then 
everything works just fine.

I guess I could write converters to go both ways and just
cast to whatever 
type I need for the current function call, but that is
hardly ideal. If 
anyone has any suggestions about how I can get around this
(maybe a type 
converter that I'm not aware of?) I would appreciate it.

Here is my code:


C++ code:
------------------------------------------------------------
-----------
struct baseobj
{
    virtual std::string ID() {return
std::string("BaseObj");}
    void SetVal(int v) {val = v;}
    int GetVal() {return val;}
    int val;
};

struct childobj : public baseobj
{
    virtual std::string ID() {return
std::string("ChildObj");}
    std::string ChildOnly() {return "OK";}
};

baseobj* createobj(std::string kind)
{
    if(kind == "Base")
    {
        return new baseobj();
    }
    else if(kind == "Child")
    {
        return new childobj();
    }
    else
    {
        return NULL;
    }
}

childobj* CastToChild(baseobj* pobj)
{
    return static_cast<childobj*>(pobj);
}

struct BaseWrap : baseobj,
boost::python::wrapper<baseobj>
{
    std::string ID()
    {
        if(boost::python::override f =
this->get_override("ID"))
            return ID();
        return baseobj::ID();
    }
    std::string default_ID() {return
this->baseobj::ID();}
};

BOOST_PYTHON_MODULE(extending)
{
using namespace boost::python;

class_<BaseWrap,
boost::noncopyable>("baseobj")
.def("ID", &baseobj::ID, &BaseWrap::ID,
"Returns the ID of the object")
.def("GetVal", &baseobj::GetVal)
.def("SetVal", &baseobj::SetVal)
;

class_<childobj, bases<BaseWrap>
>("childobj")
.def("ChildOnly", &childobj::ChildOnly)
;

implicitly_convertible<childobj,baseobj>();
class_<objman>("objman")
.def("SetObj", &objman::SetObj)
.def("GetObj", &objman::GetObj, 
return_value_policy<reference_existing_object>())
;

def("create", &createobj,
return_value_policy<manage_new_object>() );

def("callID", &callID );

def("CastToChild", &CastToChild, 
return_value_policy<reference_existing_object>());

}


Python:
------------------------------------------------------------
----------------
>>> from extending import *
>>> base = create("Base")
>>> base.ID()
'BaseObj'
>>> child = create("Child")
>>> child.ID()
'ChildObj'
>>> child.ChildOnly()
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in
<module>
    child.ChildOnly()
ArgumentError: Python argument types in
    childobj.ChildOnly(childobj)
did not match C++ signature:
    ChildOnly(struct childobj )
>>> castchild = CastToChild(child)
>>> castchild.ChildOnly()
'OK'
>>> castchild.ID()
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in
<module>
    castchild.ID()
ArgumentError: Python argument types in
    baseobj.ID(childobj)
did not match C++ signature:
    ID(struct BaseWrap )
    ID(struct baseobj )



_______________________________________________
C++-sig mailing list
C++-sigpython.org
http:
//mail.python.org/mailman/listinfo/c++-sig

Re: convert child class to child class ?
country flaguser name
Germany
2007-10-11 06:01:12
Am Mittwoch, 10. Oktober 2007 23:53:06 schrieb Steven
Wyckoff:
> BOOST_PYTHON_MODULE(extending)
> {
> using namespace boost::python;
>
> class_<BaseWrap,
boost::noncopyable>("baseobj")
> .def("ID", &baseobj::ID,
&BaseWrap::ID, "Returns the ID of the
object")
> .def("GetVal", &baseobj::GetVal)
> .def("SetVal", &baseobj::SetVal)
> ;
>
> class_<childobj, bases<BaseWrap>
>("childobj")
> .def("ChildOnly", &childobj::ChildOnly)
> ;

I never used wrapper<>, but did you try
bases<baseobj>?
I mean - childobj *is* derived from baseobj, not BaseWrap.

-- 
Ciao, /  /
     /--/
    /  / ANS
_______________________________________________
C++-sig mailing list
C++-sigpython.org
http:
//mail.python.org/mailman/listinfo/c++-sig

Re: convert child class to child class ?
country flaguser name
United States
2007-10-11 11:32:19
Hans Meine wrote:
> Am Mittwoch, 10. Oktober 2007 23:53:06 schrieb Steven
Wyckoff:
>> BOOST_PYTHON_MODULE(extending)
>> {
>> using namespace boost::python;
>>
>> class_<BaseWrap,
boost::noncopyable>("baseobj")
>> .def("ID", &baseobj::ID,
&BaseWrap::ID, "Returns the ID of the
object")
>> .def("GetVal", &baseobj::GetVal)
>> .def("SetVal", &baseobj::SetVal)
>> ;
>>
>> class_<childobj, bases<BaseWrap>
>("childobj")
>> .def("ChildOnly",
&childobj::ChildOnly)
>> ;
> 
> I never used wrapper<>, but did you try
bases<baseobj>?
> I mean - childobj *is* derived from baseobj, not
BaseWrap.
> 

That was it! That was the sneaky, silly thing I was doing
wrong that 
broke everything. Switching to bases<baseobj> seems to
let boost cast 
properly when legal just as one would expect it should.
Thanks for the help!

Steven

_______________________________________________
C++-sig mailing list
C++-sigpython.org
http:
//mail.python.org/mailman/listinfo/c++-sig

[1-3]

about | contact  Other archives ( Real Estate discussion Medical topics )