[C++-sig] Re: Problems with dynamic casts

Aaron Bentley abentley at panoramicfeedback.com
Wed Mar 16 22:13:03 CET 2005


David Abrahams wrote:
> Aaron Bentley <abentley at panoramicfeedback.com> writes:
> 
> 
>>Hi,
>>I'm having a problem with dynamic casting on an object constructed using 
>>Python.  It seems as though the type of an owned object is being lost.

> I suggest you reduce your problem to the smallest possible example
> that illustrates it.  The answer will probably become obvious to you,
> but if it doesn't, please post your example here.

Okay, here's some stripped down examples:

---foo.h---
class BaseClass
{
     public:
     BaseClass()
     {}
     virtual ~BaseClass()
     {}
};

---foo.cpp---
...
SubClass *subclass_cast(BaseClass *el)
{
     return dynamic_cast<SubClass *>(el);
}
---bar.h---
class SubClass: public BaseClass
{
     public:
     SubClass();
};
SubClass *subclass_cast(BaseClass *el);

void test_subclass(SubClass &el);
---bar.cpp---
...
SubClass::SubClass()
{
}
void test_subclass(SubClass &el)
{
     ;
}
--wrapper.cpp--
...
BaseClass *return_base(SubClass *el)
{
     return el;
}
...
BOOST_PYTHON_MODULE(_element)
{
     class_<BaseClass, std::auto_ptr<BaseClass>, boost::noncopyable>(
         "BaseClass", no_init)
         ;
     class_<SubClass, std::auto_ptr<SubClass>, bases<BaseClass>,
           boost::noncopyable>("SubClass")
       ;
     def ("subclass_cast", subclass_cast, return_internal_reference<1>());
     def ("test_subclass", test_subclass);
     def ("return_base", return_base, return_internal_reference<1>());

...
}
--- test.py ---
import _element
def run_test(test_func, converter, caster, subclass):
     print "Testing %s" % subclass.__name__
     subcl = subclass()
     try:
         test_func(subcl)
         print "subcl can be passed to %s directly" % test_func.__name__
     except Exception, e:
         print
         print e
         print "subcl cannot be passed to %s directly:" % test_func.__name__
     try:
         test_func(converter(subcl))
         print "subcl can be passed to %s when returned as a base class" % \
             test_func.__name__
     except Exception, e:
         print
         print e
         print "subcl cannot be passed to %s when returned as a base 
class" % \
             test_func.__name__
     try:
         assert caster((subcl)) is not None
         print "subcl can be dynamically cast from subclass"
     except Exception, e:
         print
         if len(str(e)) > 0:
             print e
         print e.__class__
         print "subcl cannot be dynamically cast from subclass"
     try:
         assert caster(converter(subcl)) is not None
         print "subcl can be dynamically cast from base class"
     except Exception, e:
         print
         if len(str(e)) > 0:
             print e
         print e.__class__
         print "subcl cannot be dynamically cast from base class"
run_test(_element.test_subclass, _element.return_base, 
_element.subclass_cast, _element.SubClass)


Everything except wrapper.cpp is built as one shared library.

When I run test.py, I get this:
Testing SubClass
subcl can be passed to test_subclass directly

Python argument types in
     pflib._element.test_subclass(SubClass)
did not match C++ signature:
     test_subclass(8SubClass {lvalue})
subcl cannot be passed to test_subclass when returned as a base class
subcl can be dynamically cast from subclass
subcl can be dynamically cast from base class

If I change the constructor for SubClass to an inline constructor, I get 
this:
Testing SubClass
subcl can be passed to test_subclass directly
subcl can be passed to test_subclass when returned as a base class

exceptions.AssertionError
subcl cannot be dynamically cast from subclass

exceptions.AssertionError
subcl cannot be dynamically cast from base class

So it seems I can't do implicit dynamic casts (passing a base-class 
pointer to a function taking a subclass pointer) and explicit dynamic 
casts at the same time.

Aaron

-- 
Aaron Bentley
Director of Technology
Panometrics, Inc.




More information about the Cplusplus-sig mailing list