Fix #3475492 - iterating through std::vector wrappers of enumerations.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12916 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2012-03-13 07:10:24 +00:00
parent 3340045d67
commit 50693941c6
13 changed files with 253 additions and 0 deletions

View File

@ -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

View File

@ -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 \

View File

@ -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");
}
}

View File

@ -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");
}
}

View File

@ -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<numbers> nums;
void fill_numbers() {
nums.push_back(ten);
nums.push_back(twenty);
nums.push_back(thirty);
}
};
%}
%template(vector_numbers) std::vector<EnumVector::numbers>;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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<Type > {
typedef Type value_type;
static int asval(octave_value obj, value_type *val) {
return SWIG_AsVal(int)(obj, (int *)val);
}
};
template <> struct traits_from<Type > {
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 <std/std_common.i>
//

View File

@ -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<Type > {
typedef Type value_type;
static int asval(PyObject *obj, value_type *val) {
return SWIG_AsVal(int)(obj, (int *)val);
}
};
template <> struct traits_from<Type > {
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 <std/std_common.i>

View File

@ -1,2 +1,6 @@
%include <rstdcommon.swg>
%include <std/std_common.i>
%define %traits_enum(Type...)
%enddef

View File

@ -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<Type > {
typedef Type value_type;
static int asval(VALUE obj, value_type *val) {
return SWIG_AsVal(int)(obj, (int *)val);
}
};
template <> struct traits_from<Type > {
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 <std/std_common.i>

View File

@ -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),