Commit c7c9347a authored by Karl Wette's avatar Karl Wette
Browse files

Merge branch 'swig-fix-copyout' into 'master'

SWIG: %swiglal_array_copyout...() should make copies of array elements

See merge request lscsoft/lalsuite!1324
parents d0df9e99 8ad31c88
......@@ -323,8 +323,12 @@ static const LALStatus swiglal_empty_LALStatus = {0, NULL, NULL, NULL, NULL, 0,
/// struct-copies the pointer to the supplied output pointer.
///
%fragment("swiglal_from_SWIGTYPE", "header") {
SWIGINTERNINLINE SWIG_Object swiglal_from_SWIGTYPE(SWIG_Object self, void *ptr, bool isptr, swig_type_info *tinfo, int tflags) {
return SWIG_NewPointerObj(isptr ? *((void**)ptr) : ptr, tinfo, tflags);
SWIGINTERNINLINE SWIG_Object swiglal_from_SWIGTYPE(SWIG_Object self, bool copyobj, void *ptr, size_t len, bool isptr, swig_type_info *tinfo, int tflags) {
void *vptr = isptr ? *((void**)ptr) : ptr;
if (copyobj) {
vptr = memcpy(XLALCalloc(1, len), vptr, len);
}
return SWIG_NewPointerObj(vptr, tinfo, copyobj ? tflags | SWIG_POINTER_OWN : tflags);
}
}
%fragment("swiglal_as_SWIGTYPE", "header") {
......
......@@ -68,6 +68,7 @@ extern COMPLEX8 swig_lal_test_COMPLEX8_matrix[2][3];
// Test fixed and dynamic arrays typemaps.
void swig_lal_test_copyin_array1(REAL8 INPUT[3], REAL8 scale, REAL8 OUTPUT[3]);
void swig_lal_test_copyin_array2(INT4 INPUT[3][2], INT4 scale, INT4 OUTPUT[3][2]);
void swig_lal_test_copyin_array3(LIGOTimeGPS INPUT[2], REAL8 scale, LIGOTimeGPS OUTPUT[2]);
// Test input views of string array structs.
BOOLEAN swig_lal_test_viewin_LALStringVector(LALStringVector* copyout, const LALStringVector* viewin);
......
......@@ -426,7 +426,7 @@ SWIGINTERN bool swiglal_release_parent(void *ptr) {
}
// Copy the C array to the returned Octave array.
octave_value sloav_array_out() const {
octave_value sloav_array_out(const bool copyobj = false) const {
// Check that C array pointer is valid.
if (!sloav_ptr) {
......@@ -447,7 +447,7 @@ SWIGINTERN bool swiglal_release_parent(void *ptr) {
objidx.front()(0) = get_scalar_idx(idx, objdims) + 1;
// Copy the C array element to the Octave array.
octave_value objelem = HELPER::outcall(sloav_parent, sloav_get_element_ptr(idx), sloav_isptr, sloav_tinfo, sloav_tflags);
octave_value objelem = HELPER::outcall(sloav_parent, copyobj, sloav_get_element_ptr(idx), sloav_esize, sloav_isptr, sloav_tinfo, sloav_tflags);
obj = obj.subsasgn(obj.is_cell() ? "{" : "(", objidx, objelem);
// Increment the Octave array index.
......@@ -866,7 +866,7 @@ SWIGINTERN bool swiglal_release_parent(void *ptr) {
}
// Convert the array element stored at elemptr to an octave_value.
static octave_value outcall(const octave_value& parent, void *elemptr, const bool isptr, swig_type_info *const tinfo, const int tflags) {
static octave_value outcall(const octave_value& parent, const bool copyobj, void *elemptr, const size_t esize, const bool isptr, swig_type_info *const tinfo, const int tflags) {
return OUTCALL;
}
......@@ -960,7 +960,7 @@ SWIGINTERN bool swiglal_release_parent(void *ptr) {
// Create a local array view, then use its sloav_array_out() member to copy the viewed C array
// to the output Octave array.
%swiglal_oct_array_view_class(ACFTYPE) arrview(parent, ptr, esize, ndims, dims, strides, isptr, tinfo, tflags);
return arrview.sloav_array_out();
return arrview.sloav_array_out(true);
}
%}
......@@ -1099,7 +1099,7 @@ SWIGINTERN bool swiglal_release_parent(void *ptr) {
// are not supported, and so ISOVTYPEEXPR is 'false'.
%swiglal_oct_array_frags(SWIGTYPE, "swiglal_as_SWIGTYPE", "swiglal_from_SWIGTYPE",
%arg(swiglal_as_SWIGTYPE(parent, objelem, elemptr, esize, isptr, tinfo, tflags)),
%arg(swiglal_from_SWIGTYPE(parent, elemptr, isptr, tinfo, tflags)),
%arg(swiglal_from_SWIGTYPE(parent, copyobj, elemptr, esize, isptr, tinfo, tflags)),
octave_cell, Cell, cell_value, false);
// Array conversion fragments for arrays of LAL strings. Note that input views are not supported,
......
......@@ -571,6 +571,8 @@ SWIGINTERN bool swiglal_release_parent(void *ptr) {
assert(tinfo != NULL);
// Get the Python object wrapping the C array element.
const bool copyobj = false;
const size_t esize = PyArray_DESCR(nparr)->elsize;
const int tflags = 0;
PyObject* parent = PyArray_BASE(nparr);
return OUTCALL;
......@@ -839,8 +841,10 @@ SWIGINTERN bool swiglal_release_parent(void *ptr) {
void* elemptr = swiglal_py_get_element_ptr(ptr, esize, ndims, strides, idx);
// Copy the C array element to the NumPy array.
const bool copyobj = true;
PyObject* objelem = OUTCALL;
PyArray_SETITEM(nparr, PyArray_GetPtr((PyArrayObject*)nparr, idx), objelem);
Py_CLEAR(objelem);
// Increment the NumPy array index.
swiglal_py_increment_idx(ndims, dims, idx);
......@@ -1016,7 +1020,7 @@ SWIGINTERN bool swiglal_release_parent(void *ptr) {
// Array conversion fragments for generic arrays, e.g. SWIG-wrapped types.
%swiglal_py_array_objview_frags(SWIGTYPE, "swiglal_as_SWIGTYPE", "swiglal_from_SWIGTYPE",
%arg(swiglal_as_SWIGTYPE(parent, objelem, elemptr, esize, isptr, tinfo, tflags)),
%arg(swiglal_from_SWIGTYPE(parent, elemptr, isptr, tinfo, tflags)));
%arg(swiglal_from_SWIGTYPE(parent, copyobj, elemptr, esize, isptr, tinfo, tflags)));
// Array conversion fragments for arrays of LAL strings.
%swiglal_py_array_objview_frags(LALchar, "SWIG_AsLALcharPtrAndSize", "SWIG_FromLALcharPtr",
......
......@@ -66,6 +66,12 @@ void swig_lal_test_copyin_array2(INT4 INPUT[3][2], INT4 scale, INT4 OUTPUT[3][2]
}
}
}
void swig_lal_test_copyin_array3(LIGOTimeGPS INPUT[2], REAL8 scale, LIGOTimeGPS OUTPUT[2]) {
for (int i = 0; i < 2; ++i) {
OUTPUT[i] = INPUT[i];
XLALGPSMultiply(&OUTPUT[i], scale);
}
}
// Test input views of string array structs.
BOOLEAN swig_lal_test_viewin_LALStringVector(LALStringVector* copyout, const LALStringVector* viewin) {
......
......@@ -275,6 +275,9 @@ assert(all(swig_lal_test_copyin_array1(a1in, 2.5) == a1out));
a2in = int32([3,2; 7,6; 12,10]);
a2out = a2in * 15;
assert(all(swig_lal_test_copyin_array2(a2in, 15) == a2out));
a3in = {lal.LIGOTimeGPS(1234.5); lal.LIGOTimeGPS(678.9)};
a3out = {a3in{1} * 3; a3in{2} * 3};
assert(all(cellfun(@(x, y) x == y, lal.swig_lal_test_copyin_array3(a3in, 3), a3out)));
try
swig_lal_test_viewin_array1([0,0,0,0], 0);
expected_exception = 1;
......@@ -285,6 +288,9 @@ try
expected_exception = 1;
end_try_catch
assert(!expected_exception);
clear a3in;
clear a3out;
LALCheckMemoryLeaks();
disp("PASSED fixed and dynamic arrays typemaps")
## check input views of string array structs
......
......@@ -276,6 +276,9 @@ assert((lal.swig_lal_test_copyin_array1(a1in, 2.5) == a1out).all())
a2in = numpy.array([[3,2], [7,6], [12,10]], dtype=numpy.int32)
a2out = a2in * 15
assert((lal.swig_lal_test_copyin_array2(a2in, 15) == a2out).all())
a3in = numpy.array([lal.LIGOTimeGPS(1234.5), lal.LIGOTimeGPS(678.9)])
a3out = a3in * 3
assert((lal.swig_lal_test_copyin_array3(a3in, 3) == a3out).all())
try:
lal.swig_lal_test_copyin_array1(numpy.array([0,0,0,0], dtype=numpy.double), 0)
expected_exception = True
......@@ -288,6 +291,9 @@ try:
except:
pass
assert(not expected_exception)
del a3in
del a3out
lal.CheckMemoryLeaks()
print("PASSED fixed and dynamic arrays typemaps")
## check input views of string array structs
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment