boost :: python :: extract无法提取共享基指针

时间:2018-04-09 13:02:22

标签: python c++ boost shared-ptr boost-python

我试图做一个简单的派生指针到基指针转换,这是纯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的共享指针将完成我想要的操作。
但这并不是我想要手动完成的事情,因为这是基于指针转换的一个小问题。

1 个答案:

答案 0 :(得分:0)

因此,经过长时间的调查后,我得出答案,只返回一个指向base的共享指针才能解决问题。 无论如何,感谢您的帮助。