我试图做一个简单的派生指针到基指针转换,这是纯C ++中的正常行为。
但是,处理boost :: python,在python到C ++转换期间获得相同的行为在提取步骤失败。 Boost :: python :: extract无法从共享派生指针中提取共享基指针
这是来源:
#include <iostream>
#include <vector>
#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/python.hpp>
namespace bp = boost::python;
class A {
public:
A() : m_int(10) { }
A(int numb) : m_int(numb) { }
int get_m() const { return m_int; }
virtual ~A() {}
private:
int m_int;
};
class B: public A {
public:
B() : A(100) {}
};
using BPtr = boost::shared_ptr<B>;
using APtr = boost::shared_ptr<A>;
using AContainer = std::vector<APtr>;
using AContainerPtr = boost::shared_ptr<AContainer>;
std::ostream& operator<<(std::ostream& out, const A& obj) {
out << obj.get_m();
return out;
}
APtr CreateA() {
return boost::make_shared<A>();
}
BPtr CreateB() {
return boost::make_shared<B>();
}
AContainerPtr CreateEmptyAContainer() {
return boost::make_shared<AContainer>();
}
void PushBack(const AContainerPtr& cont, const bp::object& obj) {
bp::extract<const APtr&> a_obj(obj);
if (a_obj.check()) {
cont->push_back(a_obj);
} else {
std::cerr << "Non A object!!!\n";
}
}
void ext(const bp::object& iterable) {
bp::handle<> iter_ptr(PyObject_GetIter(iterable.ptr()));
PyObject* item_raw_ptr = PyIter_Next(iter_ptr.get());
bp::handle<> item_ptr(bp::allow_null<>(item_raw_ptr));
while (item_ptr.get()) {
bp::extract<const APtr&> ex(item_ptr.get());
if (ex.check()) {
std::cout << "APtr extracted!\n";
} else {
bp::extract<const BPtr&> ex(item_ptr.get());
if (ex.check()) {
std::cout << "BPtr extracted!\n";
} else {
std::cout << "Failed to extract!!!\n";
}
}
PyObject* item_raw_ptr = PyIter_Next(iter_ptr.get());
item_ptr = bp::handle<>(bp::allow_null<>(item_raw_ptr));
}
}
BOOST_PYTHON_MODULE(example) {
bp::class_<A, APtr, boost::noncopyable>("A", bp::init<>())
.def("__init__", bp::make_constructor(CreateA))
.def(bp::self_ns::str(bp::self))
;
bp::class_<B, bp::bases<A>, BPtr, boost::noncopyable>("B", bp::init<>())
.def("__init__", bp::make_constructor(CreateB))
;
bp::class_<AContainer, AContainerPtr, boost::noncopyable>("AContainer", bp::no_init)
.def("__init__", bp::make_constructor(CreateEmptyAContainer))
.def("__iter__", bp::iterator<AContainer>())
.def("__len__", &AContainer::size)
.def("append", PushBack)
;
bp::def("ext", ext);
bp::implicitly_convertible<BPtr, APtr>();
}
在linux上用gcc(g ++(GCC)5.2.0)编译它并在Python中以这种方式使用它:
#!/usr/bin/env python
import example
b = example.B()
print b # 100
print type(b) # <class 'example.B'>
print isinstance(b, example.B) # True
print isinstance(b, example.A) # True
l = [b]
example.ext(l) # BPtr extracted!
cont = example.AContainer()
cont.append(b) # Non A object!!!
我在评论中显示了结果。虽然期待&#34; APtr提取!&#34;要在example.ext([b])函数调用上打印,而不是抱怨const.append()函数调用,放入&#34; b&#34;到续。
即使添加implicitly_convertible&lt;&gt;()也无济于事。
请指出在这种情况下做错了什么?
我尝试在这个问题上上网,但实际上在所有情况下,派生类都是在python中定义的,解决方案是调用super()。 init 函数。
修改
我知道更改CreateB()函数(构造函数)的返回值以返回指向base的共享指针将完成我想要的操作。
但这并不是我想要手动完成的事情,因为这是基于指针转换的一个小问题。
答案 0 :(得分:0)
因此,经过长时间的调查后,我得出答案,只返回一个指向base的共享指针才能解决问题。 无论如何,感谢您的帮助。