Josh Cherry <jcherry <at> ncbi.nlm.nih.gov> writes:
> Alternatively, it might work to provide or %apply an "out" typemap that
Hi Josh,
I have managed to get this working, here is the solution:
%define RETURN_COPY_FROM_VECTOR(TYPE)
%typemap(out) TYPE & front {
$result = SWIG_NewPointerObj(%new_copy(*$1, $*ltype), $descriptor,
SWIG_POINTER_OWN | %newpointer_flags);
}
%typemap(out) TYPE & back {
$result = SWIG_NewPointerObj(%new_copy(*$1, $*ltype), $descriptor,
SWIG_POINTER_OWN | %newpointer_flags);
}
%typemap(out) TYPE & __getitem__ {
$result = SWIG_NewPointerObj(%new_copy(*$1, $*ltype), $descriptor,
SWIG_POINTER_OWN | %newpointer_flags);
}
%enddef
RETURN_COPY_FROM_VECTOR(X)
In the process I have found a bug in the Python std::vector implementation.
The __getitem__ method has two versions, one takes an index, the other takes
a slice object. The version that takes a slice object returns a new std::vector
but does not use SWIG_POINTER_OWN and therefore leaks memory.
I cannot see a way to patch this up as the
typemap:
%typemap(out) TYPE & __getitem__
is only applied to the version of __getitem__ that takes an index, so there
seems no way to modify the other version through typemaps.
Also, if anyone is interested, here is the solution for C# and Java:
// For some unknown reason SWIGEXCODE causes a syntax error if used with
// RETURN_COPY_FROM_VECTOR So define our own version called SWIGEXCODE3
%define SWIGEXCODE3
"if ($modulePINVOKE.SWIGPendingException.Pending) throw
$modulePINVOKE.SWIGPendingException.Retrieve();"
%enddef
%define RETURN_COPY_FROM_VECTOR(TYPE)
%typemap(out) std::vector<TYPE>::const_reference getitem {
jresult = (void *) new TYPE (*result);
}
%typemap(csout, excode=SWIGEXCODE3) std::vector<TYPE>::const_reference getitem {
TYPE ret = new TYPE ($imcall, true);
$excode
return ret;
}
%enddef
RETURN_COPY_FROM_VECTOR(X)
%define RETURN_COPY_FROM_VECTOR(TYPE)
%typemap(out) std::vector<TYPE>::const_reference get {
*(std::vector< TYPE >::value_type **)&jresult = new TYPE (*result);
}
%typemap(javaout) std::vector<TYPE>::const_reference get {
return new TYPE ($jnicall, true);
}
%enddef
RETURN_COPY_FROM_VECTOR(X)
|