[C++-sig] Re: to_python_converters with internal-ref-like management

esatel eli at water.ca.gov
Tue Sep 14 23:22:49 CEST 2004


I am still working on Jonothan Brandmeyer's solution. I'm a beginner to the 
object API, so it may take a bit.

In the meantime, is the following a bad solution to this problem? It uses a 
free function in C++ as a member accessor in python, and it uses call 
policies to set up the dependency that I want. Minus a few lines of 
conversion details, the whole thing looks like:

// A free function
PyObject* slice_getter( multi_array_holder& holder){
   subarray=holder.get_slice()
   return(convert_to_numarrayptr(subarray));  //details omitted
}

// The salient part of the python wrapper
      .def("get_slice", &get_the_slice, 
with_custodian_and_ward_postcall<0,1>())

I have only tested this for object lifetime management. It appears to 
work -- the multi_array_holder won't get destroyed while a subarray points 
to it.

This solution seem to circumvent the whole to_python_converter apparatus, 
which scares me a bit -- is the only downside that the code isn't reusable, 
or is there other voodoo performed by to_python_converter I am going to wish 
I had?

Thanks,
Eli




"esatel" <eli at water.ca.gov> wrote in message 
news:chqk0r$3lq$1 at sea.gmane.org...
> Hi. I have a question about how/whether it is possible to use a
> to_python_converter and still take advantage of lifetime management using
> weak references. It is a special case, but kind of an interesting one.
>
> I have a an class called array_holder containing a large member of class
> boost::multi_array. Member functions of my array_holder class return 
> sliced
> subarrays of the parent array. Because of the way multi_array works (to
> manage large objects), in C++ subarrays contain pointers to, rather than
> copies of, the underlying data from the parent array.
>
> When I wrap the array_holder class for python, I want to return subarrays
> from these methods as PyArrays. I can do this without copying any of the
> underlying data as follows (some pseudo code is included below):
> 1. The array_holder method returns by value a (new) subarray object
> containing a pointer to the (original) multi_array data.
> 2. The converter converts the subarray to a PyArray without copying the
> data -- it creates a new PyArray and points it to the same base address as
> the subarray.
>
> However, to be safe, the array_holder (which contains the multi_array
> managing the data) to last as long as the subarray. Is there a slick way 
> to
> do this? I realize that I can eliminate the need for this dependence 
> through
> copies, but the size of the arrays involved (slices >10000 doubles)
> motivates me to avoid the wasted motion.
>
> Thanks,
> Eli
>
>
> The following pseudo-code mimics how I do it unsafely:
>
> /* multi_array and sub_array are in Boost -- 
>   both contain a raw char* pointer to data */
> typedef multi_array<int, 2>::array_view<2>::type subarray_type;
>
> class array_holder
> {
> public:
>  subarray_type get_slice();    // creates the new subarray object,
>                                // sets the *data pointer of the subarray 
> to
>                                // that of the multi_array
>  }
> private:
>  array_type m_multi_array();
> }
>
> struct marray_to_pyarray
> {
>    static PyObject* convert(subarray_type const& a)
>    {
>        PyObject* po =  PyArray_FromDimsAndData(2,
>                          (int*) a.shape(),
>                          PyArray_DOUBLE,
>                   (char*) a.origin()   // point to the subarray data
>                          );
> return po;
>    }
> };
>
> void export_array_holder(){
>    import_array();
>    class_<multi_array_creator>("array_holder")
>        .def("slice", &array_holder::get_slice);
>    to_python_converter<subarray_type, marray_to_pyarray>();
> }
>
> BOOST_PYTHON_MODULE(demo_array){
>  export_array_holder();
> } 






More information about the Cplusplus-sig mailing list