[C++-sig] Re: Indexing_suite when container is newed

Raoul Gough RaoulGough at yahoo.co.uk
Wed Oct 15 20:57:25 CEST 2003


"Niall Douglas" <s_sourceforge at nedprod.com> writes:

> Right, last error in the last file - everything else compiles! I have 
> a method called lasso() in FXGLViewer which returns an array of 
> FXGLObject pointers falling within the specified coordinates.
>
> Unfortunately the list returned is malloced and if not freed after 
> python is done with it would leak memory. My initial attempt was as 
> below:
>
> static indexing::iterator_pair<FXGLObject **> 
> FXGLViewer_lasso(FXGLViewer &c, FXint x1,FXint y1,FXint x2,FXint y2)
> {
> 	typedef indexing::iterator_pair<FXGLObject **> IterPair;
> 	class_<IterPair>( "FXGLViewer_lassoIndirect", init<FXGLObject **, 
> FXGLObject **>())
> 		.def(indexing::container_suite<IterPair>
> 			::with_policies(return_value_policy<manage_new_object>()));
> 	FXGLObject **data=c.lasso(x1,y1,x2,y2);
> 	return IterPair(data, data+(1<<16));
> }

I suppose you have some kind of class_<> for FXGLObject, but how does
Python deal with the FXGLObject * that the suite returns? I mean,
iterator_pair does only one level of indirection, so what happens to
the plain pointer before it gets handed back to Python?

>
> However it would appear that setting a policy at the container_suite 
> level sets it for the iterator_pair which isn't what I want. Anyway 
> besides the list is malloced and not newed, though in fact I've 
> replaced new and delete with my own versions which do call malloc.

Not sure what you mean here - iterator_pair doesn't have any
policies. The container suite applies the policies to the results of
(for instance) iterator_pair<...>::operator[] which returns an
FXGLObject * in this case, AFAICS.

>
> What one would want is the ability to call a destructor when the 
> iterator_pair is destroyed. Unfortunately I can't hack in a 
> destructor because it gets lost in the downcast and I can't use 
> auto_ptr because both of the iterators must be the same type (and the 
> end of array is not a valid memory location). So I'm guessing it 
> needs added support.

Sounds about right to me. But you would currently have the same
problem in C++, anyway, so I would first suggest coming up with a
class to manage the array in C++. You could then expose *that* class
to Python, and give it a function that returns an iterator_pair via
the return_internal_reference return policy. You would then have
something like:

>>> array_manager = getArray(...)
>>> array = array_manager.iter_pair()  # return_internal_reference

You could reduce this to:

>>> array = getArray(...).iter_pair()

The return_internal_reference policy links the lifetime of the two
Python objects together, so in the latter case, when array disappears
(e.g. if you "del" it) it also causes the object returned from
getArray() to go.

>
> I'd imagine copy construction needs to be destructive so myBegin and 
> myEnd would need to become mutable and one would need a user-
> overridable destructor.
>
> Or perhaps one could create a new custom type of return policy and 
> set that instead?
>
> Thoughts?

Well, if I was in danger of forgetting how much easier programming
with std::vector and boost::shared_ptr is compared to malloc and
arrays in C, you've just reminding me :-)

-- 
Raoul Gough.
(setq dabbrev-case-fold-search nil)





More information about the Cplusplus-sig mailing list