Reputation: 343
EDIT: I noticed my question was not clear enough; I hadn't specified n0 was an attribute of Edge.
I have two classes Nodes and Edges. Edge is defined (I omitted lots of methods and attributes that are of no interest here):
class Edge()
{
Node& n0;
public:
const Node& N0() const;
};
The accessor is coded as follows:
Node const& Edge::N0() const
{
return n0;
};
where n0 is a private reference to a Node() instance. The problem is that, while trying to expose this function with the following code:
class_<Edge>("Edge", init<Node&,Node&>())
.add_property("n0",&Edge::N0,return_internal_reference<>());
(the class Node is exposed right before) I get the error:
error: cannot create pointer to reference member ‘Edge::n0’
I could make the accessor return a copy of n0, and it would work fine (tested). However, if n0 were to be really heavy I would prefer for performance issues to return a const reference rather than a copy.
Can anyone explain to me what is wrong with what I am doing? I am pretty new to C++ and Boost.Python and admittedly don't understand much about the call policies yet.
Upvotes: 3
Views: 2477
Reputation: 5180
2 years later, you can still do it via add_property
if you use boost::python::make_function
:
class_<Edge>("Edge", init<Node&,Node&>())
.add_property(
"n0",
make_function(&Edge::N0, return_value_policy<reference_existing_object>()));
Upvotes: 4
Reputation: 343
So, I still don't understand why my orginal program or @ForEveR 's solutions won't work, but I did find a workaround that gives me what I wanted.
First, in the file where the edge class is defined, I defined the following function:
Node const& Edge_get_nodes(Edge& self)
{
return self.N0();
};
And I wrote for the wrapper:
class_<Edge>("Edge", init<Node&,Node&>())
.add_property("length",&Edge::GetLength)
.def("GetNode",&Edge_get_nodes,return_value_policy<reference_existing_object>());
Now, when I import the module in python, I can get n0 doing the following:
e1.GetNode()
Which is exactly what I wanted. Thanks for your help!
(if someone can explain to me why it works like this and not the other way, I'd be happy to know!)
Upvotes: 3
Reputation: 55887
// property creation
template <class Get>
void add_property(char const* name, Get const& fget, char const* doc=0);
template <class Get, class Set>
void add_property(
char const* name, Get const& fget, Set const& fset, char const* doc=0);
http://www.boost.org/doc/libs/1_50_0/libs/python/doc/v2/class.html#class_-spec
so
class_<Edge>("Edge", init<Node&,Node&>())
.add_property("n0",&Edge::N0, "get private edge");
should works.
Upvotes: -1