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++-sig python.org
http:
//mail.python.org/mailman/listinfo/c++-sig
|