Boost logo

Boost :

From: David Abrahams (abrahams_at_[hidden])
Date: 2000-11-02 16:09:43


----- Original Message -----
From: "Prabhu Ramachandran" <prabhu_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Thursday, November 02, 2000 2:18 PM
Subject: Re: [boost] Re: py_cpp update posted

> hi,
>
> >>>>> "David" == David Abrahams <abrahams_at_[hidden]> writes:
>
> >> http://freshmeat.net/projects/vtkpipeline
>
> David> Neat!

I would like to include links to some projects that use py_cpp in my
documentation. Would you be willing? Is the link above the right one?

> >> I have yet another feature request. I just added a private
> >> member (an int called var) to a class A. Under python is there
> >> no way that I can access this data member? For instance
> <snip>
> David> See the sections titled "Getters and Setters" and "Direct
> David> Access to Data Members" at
> David> http://people.ne.mediaone.net/abrahams/downloads/special.html
>
> Sorry, my fault, I should have looked more carefully before I asked.
> Thanks.

No problem.

> I have yet another question. This is more a general wrapper question.
> Let me say that there is a function that returns a float* which most
> probably is an array. Similarly if I have a function that takes a
> float* as an argument, what is the best way of wrapping this?

I think you have correctly perceived that it doesn't make sense for me to
automatically convert all pointers, since the ownership semantics are so
blurry.

> 1) If the array is small it makes sense to convert it to either a
> tuple or list. What is the easiest way to do this?? I am looking
> for a way that makes one write the least code. :)

How can you tell the length of the array from a single pointer?
Once you've answered that question, you can expose a wrapper function which
returns an instance of the py::Tuple or py::List class from objects.h. If
you are using a List, for example, you could write something like this:

py::List wrap_f()
{
  T* start = f();
  py::List x;
  for (T* p = start; p != start + length_constant; ++p)
     x.push_back(py::to_python(*p));
  return x;
}

> 2) If the array is large it may not make sense to use a list/tuple
> esp. if the values are used for computationally intense programs.

In this case you can do one of several somewhat dangerous things. Why
dangerous? Because python can not control the lifetime of the data, so the
data in the array may be destroyed or become invalid before the last
reference to it disappears. The basic approach is to make a small C++ class
which contains the pointer, and expose that:

// UNTESTED
template <class T>
struct dangerous_array
{
    dangerous_array(T* start, T* end)
        : m_start(start), m_end(end) {}

    // exposed as "__len__"
    std::size_t length() {
        return m_end - m_start;
    }

    // exposed as "__getitem__"
    T get_item(std::size_t n) {
        check_range(n);
        return start[n];
    }

    // exposed as "__setitem__" if the array is mutable
    void set_item(std::size_t n, const T& x) {
        check_range(n);
        start[n] = x;
    }
 private:
    void check_range(std::size_t n) {
        if (n >= m_end - m_start) {
            PyErr_SetString(PyExc_IndexError, "array index out of range");
            throw py::ErrorAlreadySet;
        }
    }
    T* m_start;
    T* m_end;
};

A reasonably safe approach would be to make a wrapper function for each
function that returns a T*, and expose that instead. If you're too lazy and
you really like to live on the edge, though, you can write to_python(T*) in
terms of to_python(const dangerous_array<T>&), and you'll automatically
convert all T* return values to a wrapped dangerous_array.

> 3) For an arbitrary class "class_A", say, can py_cpp handle
> references to class_A &instance, or class_A *instance?? i.e. will it
> wrap function calls to such objects? This question is obviously
> related to the earlier questions.

Yes, iff class_A has been exposed to python with a ClassWrapper<class_A>.
See http://people.ne.mediaone.net/abrahams/downloads/under-the-hood.html for
a few details.

> I am going to try and start actually wrapping _real_ libraries in a
> while. I anticipate problems like the above and hence the
> questions...

No problem, it was an excuse to write more material for my documentation.

-Dave


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk