From 93eb7eae0b13e80430106d0ee2100ad097a2748c Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Fri, 27 Nov 2015 19:30:22 +0000 Subject: [PATCH] Limited Python/Ruby support for boost::array Hack to use the std::array support for boost::array. Is limited as it currently exposes some 'using' bugs in SWIG. For example, the type system fails to see that pointers to std::array and pointers to boost::array are the same. This approach saves having to maintain separate boost::array support. The 'using' bug ought to be fixed, otherwise separate boost_array.i files could be easily made from the std_array.i files. --- Examples/test-suite/common.mk | 1 + Examples/test-suite/cpp11_li_std_array.i | 9 +++ Examples/test-suite/li_boost_array.i | 77 +++++++++++++++++++ .../python/cpp11_li_std_array_runme.py | 3 + .../test-suite/python/li_boost_array_runme.py | 55 +++++++++++++ .../ruby/cpp11_li_std_array_runme.rb | 1 + .../test-suite/ruby/li_boost_array_runme.rb | 70 +++++++++++++++++ Lib/python/std_array.i | 4 +- Lib/ruby/std_array.i | 4 +- Lib/std/std_array.i | 3 - 10 files changed, 220 insertions(+), 7 deletions(-) create mode 100644 Examples/test-suite/li_boost_array.i create mode 100644 Examples/test-suite/python/li_boost_array_runme.py create mode 100644 Examples/test-suite/ruby/li_boost_array_runme.rb diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 114c568c5..7b114fe7b 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -258,6 +258,7 @@ CPP_TEST_CASES += \ langobj \ li_attribute \ li_attribute_template \ + li_boost_array \ li_boost_shared_ptr \ li_boost_shared_ptr_bits \ li_boost_shared_ptr_template \ diff --git a/Examples/test-suite/cpp11_li_std_array.i b/Examples/test-suite/cpp11_li_std_array.i index e8e50105f..74e34370c 100644 --- a/Examples/test-suite/cpp11_li_std_array.i +++ b/Examples/test-suite/cpp11_li_std_array.i @@ -2,6 +2,10 @@ #if defined(SWIGPYTHON) || defined(SWIGRUBY) +%{ +#include +%} + %include %template(ArrayInt6) std::array; @@ -16,6 +20,11 @@ std::array & arrayOutRef() { return a; } +const std::array & arrayOutConstRef() { + static std::array a = { -2, -1, 0, 0, 1, 2 }; + return a; +} + std::array * arrayOutPtr() { static std::array a = { -2, -1, 0, 0, 1, 2 }; return &a; diff --git a/Examples/test-suite/li_boost_array.i b/Examples/test-suite/li_boost_array.i new file mode 100644 index 000000000..4458e780d --- /dev/null +++ b/Examples/test-suite/li_boost_array.i @@ -0,0 +1,77 @@ +%module li_boost_array + +#if defined(SWIGPYTHON) || defined(SWIGRUBY) + +// Hack to use the std::array support for boost::array. +// Is limited as it currently exposes some 'using' bugs in SWIG though. +// For example, the type system fails to see that pointers to std::array +// and pointers to boost::array are the same. + +%{ +#include +namespace std { + using boost::array; +} +%} +namespace boost { + using std::array; +} + +%include + +%template(ArrayInt6) std::array; + +%inline %{ +boost::array arrayOutVal() { + const char carray[] = { -2, -1, 0, 0, 1, 2 }; + boost::array myarray; + for (size_t i=0; i<6; ++i) { + myarray[i] = carray[i]; + } + return myarray; +} + +boost::array & arrayOutRef() { + static boost::array a = { -2, -1, 0, 0, 1, 2 }; + return a; +} + +const boost::array & arrayOutConstRef() { + static boost::array a = { -2, -1, 0, 0, 1, 2 }; + return a; +} + +boost::array * arrayOutPtr() { + static boost::array a = { -2, -1, 0, 0, 1, 2 }; + return &a; +} + +boost::array arrayInVal(boost::array myarray) { + for (boost::array::iterator it = myarray.begin(); it!=myarray.end(); ++it) { + *it *= 10; + } + return myarray; +} + +const boost::array & arrayInConstRef(const boost::array & myarray) { + static boost::array a = myarray; + for (boost::array::iterator it = a.begin(); it!=a.end(); ++it) { + *it *= 10; + } + return a; +} + +void arrayInRef(boost::array & myarray) { + for (boost::array::iterator it = myarray.begin(); it!=myarray.end(); ++it) { + *it *= 10; + } +} + +void arrayInPtr(boost::array * myarray) { + for (boost::array::iterator it = myarray->begin(); it!=myarray->end(); ++it) { + *it *= 10; + } +} +%} + +#endif diff --git a/Examples/test-suite/python/cpp11_li_std_array_runme.py b/Examples/test-suite/python/cpp11_li_std_array_runme.py index d6e1348e9..3b1ceb2f8 100644 --- a/Examples/test-suite/python/cpp11_li_std_array_runme.py +++ b/Examples/test-suite/python/cpp11_li_std_array_runme.py @@ -64,6 +64,8 @@ ps = [0, 1, 2, 3, 4, 5] ai = ArrayInt6(ps) +compare_containers(ps, ai) + # slices compare_containers(ps[0:6], ai[0:6]) compare_containers(ps[0:10], ai[0:10]) @@ -137,6 +139,7 @@ setslice_exception(ai, []) # Check return compare_containers(arrayOutVal(), [-2, -1, 0, 0, 1, 2]) +compare_containers(arrayOutConstRef(), [-2, -1, 0, 0, 1, 2]) compare_containers(arrayOutRef(), [-2, -1, 0, 0, 1, 2]) compare_containers(arrayOutPtr(), [-2, -1, 0, 0, 1, 2]) diff --git a/Examples/test-suite/python/li_boost_array_runme.py b/Examples/test-suite/python/li_boost_array_runme.py new file mode 100644 index 000000000..4fa7eb882 --- /dev/null +++ b/Examples/test-suite/python/li_boost_array_runme.py @@ -0,0 +1,55 @@ +from li_boost_array import * +import sys + + +def failed(a, b, msg): + raise RuntimeError, msg + " " + str(list(a)) + " " + str(list(b)) + + +def compare_sequences(a, b): + if len(a) != len(b): + failed(a, b, "different sizes") + for i in range(len(a)): + if a[i] != b[i]: + failed(a, b, "elements are different") + +def compare_containers(pythonlist, swigarray): + compare_sequences(pythonlist, swigarray) + +ps = [0, 1, 2, 3, 4, 5] + +ai = ArrayInt6(ps) + +compare_containers(ps, ai) + +# Modify content +for i in range(len(ps)): + ps[i] = (ps[i] + 1) * 10 + ai[i] = (ai[i] + 1) * 10 +compare_containers(ps, ai) + +# Empty +ai = ArrayInt6() +compare_containers([0, 0, 0, 0, 0, 0], ai) + +# Check return +compare_containers(arrayOutVal(), [-2, -1, 0, 0, 1, 2]) +compare_containers(arrayOutConstRef(), [-2, -1, 0, 0, 1, 2]) +#compare_containers(arrayOutRef(), [-2, -1, 0, 0, 1, 2]) +#compare_containers(arrayOutPtr(), [-2, -1, 0, 0, 1, 2]) + +# Check passing arguments +ai = arrayInVal([9, 8, 7, 6, 5, 4]) +compare_containers(ai, [90, 80, 70, 60, 50, 40]) + +ai = arrayInConstRef([9, 8, 7, 6, 5, 4]) +compare_containers(ai, [90, 80, 70, 60, 50, 40]) + +#ai = ArrayInt6([9, 8, 7, 6, 5, 4]) +#arrayInRef(ai) +#compare_containers(ai, [90, 80, 70, 60, 50, 40]) + +#ai = ArrayInt6([9, 8, 7, 6, 5, 4]) +#arrayInPtr(ai) +#compare_containers(ai, [90, 80, 70, 60, 50, 40]) + diff --git a/Examples/test-suite/ruby/cpp11_li_std_array_runme.rb b/Examples/test-suite/ruby/cpp11_li_std_array_runme.rb index a7e678596..770f37c0f 100644 --- a/Examples/test-suite/ruby/cpp11_li_std_array_runme.rb +++ b/Examples/test-suite/ruby/cpp11_li_std_array_runme.rb @@ -89,6 +89,7 @@ setslice_exception(ai, []) # Check return compare_containers(arrayOutVal(), [-2, -1, 0, 0, 1, 2]) +compare_containers(arrayOutConstRef(), [-2, -1, 0, 0, 1, 2]) compare_containers(arrayOutRef(), [-2, -1, 0, 0, 1, 2]) compare_containers(arrayOutPtr(), [-2, -1, 0, 0, 1, 2]) diff --git a/Examples/test-suite/ruby/li_boost_array_runme.rb b/Examples/test-suite/ruby/li_boost_array_runme.rb new file mode 100644 index 000000000..a7b7720ea --- /dev/null +++ b/Examples/test-suite/ruby/li_boost_array_runme.rb @@ -0,0 +1,70 @@ +#!/usr/bin/env ruby +# +# Put description here +# +# +# +# +# + +require 'swig_assert' + +require 'li_boost_array' + +include Li_boost_array + + +def failed(a, b, msg) + raise RuntimeError, "#{msg} #{a} #{b}" +end + +def compare_sequences(a, b) + if a.size != b.size + failed(a, b, "different sizes") + end + for i in 0..a.size-1 + failed(a, b, "elements are different:") if a[i] != b[i] + end +end + +def compare_containers(rubyarray, swigarray) + compare_sequences(rubyarray, swigarray) +end + +ps = [0, 1, 2, 3, 4, 5] + +ai = ArrayInt6.new(ps) + +compare_containers(ps, ai) + +# Modify content +for i in 0..ps.size-1 + ps[i] = ps[i] * 10 + ai[i] = ai[i] * 10 +end +compare_containers(ps, ai) + +# Empty +ai = ArrayInt6.new() + +# Check return +compare_containers(arrayOutVal(), [-2, -1, 0, 0, 1, 2]) +compare_containers(arrayOutConstRef(), [-2, -1, 0, 0, 1, 2]) +#compare_containers(arrayOutRef(), [-2, -1, 0, 0, 1, 2]) +#compare_containers(arrayOutPtr(), [-2, -1, 0, 0, 1, 2]) + +# Check passing arguments +ai = arrayInVal([9, 8, 7, 6, 5, 4]) +compare_containers(ai, [90, 80, 70, 60, 50, 40]) + +ai = arrayInConstRef([9, 8, 7, 6, 5, 4]) +compare_containers(ai, [90, 80, 70, 60, 50, 40]) + +#ai = ArrayInt6.new([9, 8, 7, 6, 5, 4]) +#arrayInRef(ai) +#compare_containers(ai, [90, 80, 70, 60, 50, 40]) + +#ai = ArrayInt6.new([9, 8, 7, 6, 5, 4]) +#arrayInPtr(ai) +#compare_containers(ai, [90, 80, 70, 60, 50, 40]) + diff --git a/Lib/python/std_array.i b/Lib/python/std_array.i index b894868a0..19fb6cca1 100644 --- a/Lib/python/std_array.i +++ b/Lib/python/std_array.i @@ -39,7 +39,7 @@ template inline std::array* getslice(const std::array* self, Difference i, Difference j, Py_ssize_t step) { - using Sequence = std::array; + typedef std::array Sequence; typename Sequence::size_type size = self->size(); Difference ii = 0; Difference jj = 0; @@ -61,7 +61,7 @@ template inline void setslice(std::array* self, Difference i, Difference j, Py_ssize_t step, const InputSeq& is = InputSeq()) { - using Sequence = std::array; + typedef std::array Sequence; typename Sequence::size_type size = self->size(); Difference ii = 0; Difference jj = 0; diff --git a/Lib/ruby/std_array.i b/Lib/ruby/std_array.i index 6fb537a17..a4d3ef54b 100644 --- a/Lib/ruby/std_array.i +++ b/Lib/ruby/std_array.i @@ -39,7 +39,7 @@ template inline std::array* getslice(const std::array* self, Difference i, Difference j) { - using Sequence = std::array; + typedef std::array Sequence; typename Sequence::size_type size = self->size(); typename Sequence::size_type ii = swig::check_index(i, size, (i == size && j == size)); typename Sequence::size_type jj = swig::slice_index(j, size); @@ -56,7 +56,7 @@ template inline void setslice(std::array* self, Difference i, Difference j, const InputSeq& v) { - using Sequence = std::array; + typedef std::array Sequence; typename Sequence::size_type size = self->size(); typename Sequence::size_type ii = swig::check_index(i, size, true); typename Sequence::size_type jj = swig::slice_index(j, size); diff --git a/Lib/std/std_array.i b/Lib/std/std_array.i index 0676f670e..a308eccad 100644 --- a/Lib/std/std_array.i +++ b/Lib/std/std_array.i @@ -40,9 +40,6 @@ // for consistency, they expect and return a plain array pointer. // ------------------------------------------------------------------------ -%{ -#include -%} // exported classes