3

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’</p>

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.

4

3 回答 3

4

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>()));
于 2018-01-26T09:17:52.593 回答
3

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!)

于 2012-07-15T22:04:52.643 回答
-1
// 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.

于 2012-07-15T08:56:06.963 回答