[Boost.Python] How is shared_ptr<SubClass> matched with shared_ptr<Base> in signature?
We have a smart_ptr template of our own, sort of cloned from intrusive_ptr. But I'm having trouble with Python code passing subclass objects managed by this smart_ptr to C++ methods accepting smart_ptr<base class>. Consider: class Base: { ... }; class SubClass: public Base { ... }; class Interface { public: void method(smart_ptr<Base> arg) const; }; Of course SubClass* is implicitly convertible to Base*. In C++ code, smart_ptr<SubClass> is even implicitly convertible to smart_ptr<Base>. That is, given the definitions above, this C++ code compiles and runs correctly: Interface worker; smart_ptr<SubClass> objp = new SubClass(); worker.method(objp); We can inform Boost.Python that Base objects -- and, by implication, SubClass as well -- are to be managed using smart_ptr<>. class_<Base, smart_ptr<Base>, boost::noncopyable>("Base", no_init) ... ; class_<SubClass, bases<Base> >("SubClass") ... ; We have many methods that accept smart_ptr<Base> and do appropriately polymorphic things to SubClass and its siblings. However, if a Python caller attempts to pass a SubClass object to a method accepting smart_ptr<Base>: obj = Extension.SubClass() worker = Extension.Interface() worker.method(obj) we get the following runtime error: Boost.Python.ArgumentError: Python argument types in Interface.method(Interface, SubClass) did not match C++ signature: method(class Interface {lvalue}, class smart_ptr<class Base>) That's true for both Boost 1.31 and Boost 1.32. We have not yet tried this with Boost 1.33. We're using MSVC 7.1 on Windows XP Pro. Okay, I know this is our fault, something's wrong with our smart_ptr template definition. I know that because if I recompile with this: #define smart_ptr boost::shared_ptr instead of our own smart_ptr definition, it works just fine! As noted earlier, our smart_ptr is a variant of boost::intrusive_ptr. But it appears that either there's a mysterious requirement on the smart_ptr template that we're not fulfilling, or there's special recognition of boost::shared_ptr and possibly boost::intrusive_ptr in Boost.Python. What must we add to allow Boost.Python to recognize the legal conversion from smart_ptr<SubClass> to smart_ptr<Base> when it does its argument matching? [Your next question is: why not just use one of the Boost smart pointers? Short answer: that's what we WANTED to do! We tried shared_ptr and ran afoul of the second-conversion-from-same-dumb-pointer problem; we tried intrusive_ptr and got completely entangled in new cross-DLL dependencies because intrusive_ptr doesn't deal well with incomplete pointee types. Our smart_ptr is an attempt to trade away both issues, at the cost of a mandatory pointee base class. It almost works, too, except for this baffling bug...] Thanks for your help.
participants (1)
-
Nat Goodspeed