Здравствуйте.
Возникла проблема, которую удалось локализовать и составить минимальную программу, воспроизводящую её. К сожалению, я не настолько хорошо знаю внутренне устройство 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, хотя строчкой ранее успешно проверяется, что он там есть? В то же время тест на с++ проходит успешно. Где ошибка?