[C++-sig] convert child class to child class {lvalue} ?
Steven Wyckoff
steven.wyckoff at gmail.com
Wed Oct 10 23:53:06 CEST 2007
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 {lvalue})
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 {lvalue})
>>> 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 {lvalue})
ID(struct baseobj {lvalue})
More information about the Cplusplus-sig
mailing list