LINUX.ORG.RU

[c++][boost::python] Проблема с boost::shared_ptr.

 


0

1

Здравствуйте.

Возникла проблема, которую удалось локализовать и составить минимальную программу, воспроизводящую её. К сожалению, я не настолько хорошо знаю внутренне устройство boost::python, чтобы самостоятельно разобраться с выявленной ошибкой.

tree.h:

#ifndef _TREE_H_
#define _TREE_H_
#include <boost/smart_ptr.hpp>
#include <map>

class TreeNode;

typedef boost::shared_ptr<TreeNode> TreeNodePtr;

struct EdgeProperties {
    std::size_t weight;

    EdgeProperties();
    EdgeProperties(const std::size_t weight_);
};

typedef std::map<TreeNodePtr, EdgeProperties> EdgesMap;

class TreeNode {
    public:
        typedef std::map<TreeNodePtr, EdgeProperties> ChildNodes;

        const EdgeProperties& edgeProperties(const TreeNodePtr& node) const;
        const EdgesMap& childNodes() const;
        void addChild(const TreeNodePtr& node, const EdgeProperties& properties);
    private:
        EdgesMap children;
};

#endif

tree.cpp:

#include "tree.h"
#include <stdexcept>

EdgeProperties::EdgeProperties():
    weight()
{}

EdgeProperties::EdgeProperties(const std::size_t weight_):
    weight(weight_)
{}

const EdgeProperties& TreeNode::edgeProperties(const TreeNodePtr& node) const {
    EdgesMap::const_iterator pos(children.find(node));
    if (pos == children.end())
        throw std::runtime_error("Not in tree.");
    return pos->second;
}

const EdgesMap& TreeNode::childNodes() const {
    return children;
}

void TreeNode::addChild(const TreeNodePtr& node, const EdgeProperties& properties) {
    children[node] = properties;
}

trees_module.cpp:

#include <boost/python.hpp>
#include "tree.h"

using namespace boost::python;

template <class C>
inline boost::python::dict toDict(const C& v) {
    boost::python::dict d;
    for (typename C::const_iterator i = v.begin(); i != v.end(); ++i)
        d[i->first] = i->second;
    return d;
}

dict getChildNodes(const TreeNode& t) {
    return toDict(t.childNodes());
}

BOOST_PYTHON_MODULE(trees) {

    class_<EdgeProperties>("EdgeProperties", init<>())
        .def(init<const std::size_t>())
        .add_property("weight", &EdgeProperties::weight, &EdgeProperties::weight)
    ;

    class_<TreeNode, TreeNodePtr, boost::noncopyable>("TreeNode", init<>())
        .def("edgeProperties", &TreeNode::edgeProperties, return_internal_reference<>())
        .def("childNodes", &getChildNodes)
        .def("addChild", &TreeNode::addChild)
    ;

}

test.cpp:

#include "tree.h"
#include <iostream>
#include <iomanip>

int main(int, char**) {
    TreeNodePtr n0(new TreeNode());
    TreeNodePtr n1(new TreeNode());

    n0->addChild(n1, EdgeProperties(2));

    const EdgesMap& edges(n0->childNodes());
    std::cout
        << std::boolalpha << (edges.find(n1) != edges.end()) << std::endl
        << n0->edgeProperties(n1).weight << std::endl;

    return 0;
}

test.py:

from trees import *

n0 = TreeNode()
n1 = TreeNode()

n0.addChild(n1, EdgeProperties(2))

print n1 in n0.childNodes()
print n0.edgeProperties(n1).weight

Сборка и запуск:

$ g++ tree.cpp test.cpp -o test
$ g++ -shared -fPIC -lboost_python -lpython2.5 -I /usr/include/python2.5 tree.cpp trees_module.cpp -o trees.so
$ ./test
true
2
$ python test.py
True
Traceback (most recent call last):
  File "test.py", line 9, in <module>
    print n0.edgeProperties(n1)
RuntimeError: Not in tree.
$

Итак, вопрос: почему при вызове edgeProperties из python получается так, что n1 отсутствует в списке дочерних узлов n0, хотя строчкой ранее успешно проверяется, что он там есть? В то же время тест на с++ проходит успешно. Где ошибка?


Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.