diff --git a/CHANGES.current b/CHANGES.current index ebebf8939..6e36827d0 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -5,6 +5,9 @@ See the RELEASENOTES file for a summary of changes in each release. Version 2.0.5 (in progress) =========================== +2012-03-13: wsfulton + [Python, Ruby, Octave] Fix #3475492 - iterating through std::vector wrappers of enumerations. + 2012-02-27: xavier98 (patches from Karl Wette) [Octave] Use -globals . to load global variables in module namespace [Octave] Comment declaration of unimplemented function swig_register_director diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 08da73451..77984251a 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -472,6 +472,7 @@ CPP_STD_TEST_CASES += \ li_std_pair \ li_std_string \ li_std_vector \ + li_std_vector_enum \ naturalvar \ smart_pointer_inherit \ template_typedef_fnc \ diff --git a/Examples/test-suite/csharp/li_std_vector_enum_runme.cs b/Examples/test-suite/csharp/li_std_vector_enum_runme.cs new file mode 100644 index 000000000..0d88a4952 --- /dev/null +++ b/Examples/test-suite/csharp/li_std_vector_enum_runme.cs @@ -0,0 +1,27 @@ +// This test tests all the methods in the C# collection wrapper + +using System; +using li_std_vector_enumNamespace; + +public class li_std_vector_enum_runme { + + public static void Main() { + EnumVector ev = new EnumVector(); + + check((int)ev.nums[0], 10); + check((int)ev.nums[1], 20); + check((int)ev.nums[2], 30); + + int expected = 10; + foreach (EnumVector.numbers val in ev.nums) { + check((int)val, expected); + expected += 10; + } + } + + private static void check(int a, int b) { + if (a != b) + throw new ApplicationException("values don't match"); + } +} + diff --git a/Examples/test-suite/java/li_std_vector_enum_runme.java b/Examples/test-suite/java/li_std_vector_enum_runme.java new file mode 100644 index 000000000..f6fa632a3 --- /dev/null +++ b/Examples/test-suite/java/li_std_vector_enum_runme.java @@ -0,0 +1,27 @@ +import li_std_vector_enum.*; + +public class li_std_vector_enum_runme { + + static { + try { + System.loadLibrary("li_std_vector_enum"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) throws Throwable + { + EnumVector ev = new EnumVector(); + + check(ev.getNums().get(0).swigValue(), 10); + check(ev.getNums().get(1).swigValue(), 20); + check(ev.getNums().get(2).swigValue(), 30); + } + + private static void check(int a, int b) { + if (a != b) + throw new RuntimeException("values don't match"); + } +} diff --git a/Examples/test-suite/li_std_vector_enum.i b/Examples/test-suite/li_std_vector_enum.i new file mode 100644 index 000000000..e4e0144e5 --- /dev/null +++ b/Examples/test-suite/li_std_vector_enum.i @@ -0,0 +1,23 @@ +%module li_std_vector_enum + +%include "std_vector.i" + +%inline %{ + class EnumVector { + public: + EnumVector() { fill_numbers(); } + + enum numbers {ten=10, twenty=20, thirty=30}; + + std::vector nums; + + void fill_numbers() { + nums.push_back(ten); + nums.push_back(twenty); + nums.push_back(thirty); + } + }; +%} + +%template(vector_numbers) std::vector; + diff --git a/Examples/test-suite/octave/li_std_vector_enum_runme.m b/Examples/test-suite/octave/li_std_vector_enum_runme.m new file mode 100644 index 000000000..471e7bf39 --- /dev/null +++ b/Examples/test-suite/octave/li_std_vector_enum_runme.m @@ -0,0 +1,27 @@ +li_std_vector_enum + +function check(a, b) + if (a != b) + error("incorrect match"); + endif +end + +ev = EnumVector(); + +check(ev.nums(0), 10); +check(ev.nums(1), 20); +check(ev.nums(2), 30); + +it = ev.nums.begin(); +v = it.value(); +check(v, 10); +it.next(); +v = it.value(); +check(v, 20); + +#expected = 10 +#ev.nums.each do|val| +# swig_assert(val == expected) +# expected += 10 +#end + diff --git a/Examples/test-suite/python/li_std_vector_enum_runme.py b/Examples/test-suite/python/li_std_vector_enum_runme.py new file mode 100644 index 000000000..a2c8534f3 --- /dev/null +++ b/Examples/test-suite/python/li_std_vector_enum_runme.py @@ -0,0 +1,24 @@ +import li_std_vector_enum + +def check(a, b): + if (a != b): + raise RuntimeError("Not equal: ", a, b) + +ev = li_std_vector_enum.EnumVector() + +check(ev.nums[0], 10) +check(ev.nums[1], 20) +check(ev.nums[2], 30) + +it = ev.nums.iterator() +v = it.value() +check(v, 10) +it.next() +v = it.value() +check(v, 20) + +expected = 10 +for val in ev.nums: + check(val, expected) + expected += 10 + diff --git a/Examples/test-suite/ruby/li_std_vector_enum_runme.rb b/Examples/test-suite/ruby/li_std_vector_enum_runme.rb new file mode 100755 index 000000000..c997fd04f --- /dev/null +++ b/Examples/test-suite/ruby/li_std_vector_enum_runme.rb @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby + +require 'swig_assert' +require 'li_std_vector_enum' +include Li_std_vector_enum + +ev = EnumVector.new() + +swig_assert(ev.nums[0] == 10) +swig_assert(ev.nums[1] == 20) +swig_assert(ev.nums[2] == 30) + +it = ev.nums.begin +v = it.value() +swig_assert(v == 10) +it.next() +v = it.value() +swig_assert(v == 20) + +expected = 10 +ev.nums.each do|val| + swig_assert(val == expected) + expected += 10 +end + diff --git a/Lib/octave/std_common.i b/Lib/octave/std_common.i index d13d2d637..9aebf7f45 100644 --- a/Lib/octave/std_common.i +++ b/Lib/octave/std_common.i @@ -31,6 +31,37 @@ namespace swig { } %enddef +/* Traits for enums. This is bit of a sneaky trick needed because a generic template specialization of enums + is not possible (unless using template meta-programming which SWIG doesn't support because of the explicit + instantiations required using %template). The STL containers define the 'front' method and the typemap + below is used whenever the front method is wrapped returning an enum. This typemap simply picks up the + standard enum typemap, but additionally drags in a fragment containing the traits_asval and traits_from + required in the generated code for enums. */ + +%define %traits_enum(Type...) + %fragment("SWIG_Traits_enum_"{Type},"header", + fragment=SWIG_AsVal_frag(int), + fragment=SWIG_From_frag(int), + fragment="StdTraits") { +namespace swig { + template <> struct traits_asval { + typedef Type value_type; + static int asval(octave_value obj, value_type *val) { + return SWIG_AsVal(int)(obj, (int *)val); + } + }; + template <> struct traits_from { + typedef Type value_type; + static octave_value from(const value_type& val) { + return SWIG_From(int)((int)val); + } + }; +} +} +%typemap(out, fragment="SWIG_Traits_enum_"{Type}) const enum SWIGTYPE& front %{$typemap(out, const enum SWIGTYPE&)%} +%enddef + + %include // diff --git a/Lib/python/std_common.i b/Lib/python/std_common.i index 3290e21f8..401bbde7f 100644 --- a/Lib/python/std_common.i +++ b/Lib/python/std_common.i @@ -33,6 +33,36 @@ namespace swig { } %enddef +/* Traits for enums. This is bit of a sneaky trick needed because a generic template specialization of enums + is not possible (unless using template meta-programming which SWIG doesn't support because of the explicit + instantiations required using %template). The STL containers define the 'front' method and the typemap + below is used whenever the front method is wrapped returning an enum. This typemap simply picks up the + standard enum typemap, but additionally drags in a fragment containing the traits_asval and traits_from + required in the generated code for enums. */ + +%define %traits_enum(Type...) + %fragment("SWIG_Traits_enum_"{Type},"header", + fragment=SWIG_AsVal_frag(int), + fragment=SWIG_From_frag(int), + fragment="StdTraits") { +namespace swig { + template <> struct traits_asval { + typedef Type value_type; + static int asval(PyObject *obj, value_type *val) { + return SWIG_AsVal(int)(obj, (int *)val); + } + }; + template <> struct traits_from { + typedef Type value_type; + static PyObject *from(const value_type& val) { + return SWIG_From(int)((int)val); + } + }; +} +} +%typemap(out, fragment="SWIG_Traits_enum_"{Type}) const enum SWIGTYPE& front %{$typemap(out, const enum SWIGTYPE&)%} +%enddef + %include diff --git a/Lib/r/std_common.i b/Lib/r/std_common.i index fec0efe51..ab26b23a6 100644 --- a/Lib/r/std_common.i +++ b/Lib/r/std_common.i @@ -1,2 +1,6 @@ %include %include + +%define %traits_enum(Type...) +%enddef + diff --git a/Lib/ruby/std_common.i b/Lib/ruby/std_common.i index 16365a414..14fba0df3 100644 --- a/Lib/ruby/std_common.i +++ b/Lib/ruby/std_common.i @@ -34,6 +34,36 @@ namespace swig { } %enddef +/* Traits for enums. This is bit of a sneaky trick needed because a generic template specialization of enums + is not possible (unless using template meta-programming which SWIG doesn't support because of the explicit + instantiations required using %template). The STL containers define the 'front' method and the typemap + below is used whenever the front method is wrapped returning an enum. This typemap simply picks up the + standard enum typemap, but additionally drags in a fragment containing the traits_asval and traits_from + required in the generated code for enums. */ + +%define %traits_enum(Type...) + %fragment("SWIG_Traits_enum_"{Type},"header", + fragment=SWIG_AsVal_frag(int), + fragment=SWIG_From_frag(int), + fragment="StdTraits") { +namespace swig { + template <> struct traits_asval { + typedef Type value_type; + static int asval(VALUE obj, value_type *val) { + return SWIG_AsVal(int)(obj, (int *)val); + } + }; + template <> struct traits_from { + typedef Type value_type; + static VALUE from(const value_type& val) { + return SWIG_From(int)((int)val); + } + }; +} +} +%typemap(out, fragment="SWIG_Traits_enum_"{Type}) const enum SWIGTYPE& front %{$typemap(out, const enum SWIGTYPE&)%} +%enddef + %include diff --git a/Lib/std/std_vector.i b/Lib/std/std_vector.i index 147f7449d..e4f9f140d 100644 --- a/Lib/std/std_vector.i +++ b/Lib/std/std_vector.i @@ -69,6 +69,7 @@ namespace std { typedef _Alloc allocator_type; %traits_swigtype(_Tp); + %traits_enum(_Tp); %fragment(SWIG_Traits_frag(std::vector<_Tp, _Alloc >), "header", fragment=SWIG_Traits_frag(_Tp),