std::vector<T> wrapper improvements for .NET 2 implementing IEnumerable<T>
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@11156 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
df698a8d32
commit
6975ecd65c
3 changed files with 93 additions and 17 deletions
|
|
@ -1,6 +1,16 @@
|
||||||
Version 1.3.39 (in progress)
|
Version 1.3.39 (in progress)
|
||||||
============================
|
============================
|
||||||
|
|
||||||
|
2008-03-18: wsfulton
|
||||||
|
[C#] std::vector<T> wrapper improvements for .NET 2 and also providing the
|
||||||
|
necessary machinery to use the std::vector<T> wrappers with more advanced features such
|
||||||
|
as LINQ - the C# proxy class now derives from IEnumerable<>. The default is now to
|
||||||
|
generate code requiring .NET 2 as a minimum, although the C# code can be compiled
|
||||||
|
for .NET 1 by defining the SWIG_DOTNET_1 C# preprocessor constant. See the
|
||||||
|
std_vector.i file for more details.
|
||||||
|
|
||||||
|
*** POTENTIAL INCOMPATIBILITY ***
|
||||||
|
|
||||||
2008-03-12: wsfulton
|
2008-03-12: wsfulton
|
||||||
[Ruby] Fix #2676738 SWIG generated symbol name clashes.
|
[Ruby] Fix #2676738 SWIG generated symbol name clashes.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,14 +82,17 @@ public class li_std_vector_runme {
|
||||||
} catch (ArgumentException) {
|
} catch (ArgumentException) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if SWIG_DOTNET_1
|
||||||
{
|
{
|
||||||
|
// runtime check that 2D arrays fail
|
||||||
double[,] outputarray = new double[collectionSize,collectionSize];
|
double[,] outputarray = new double[collectionSize,collectionSize];
|
||||||
try {
|
try {
|
||||||
vect.CopyTo(outputarray);
|
vect.CopyTo(outputarray);
|
||||||
throw new Exception("CopyTo (5) test failed");
|
throw new Exception("CopyTo (5a) test failed");
|
||||||
} catch (ArgumentException) {
|
} catch (ArgumentException) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
StructVector inputvector = new StructVector();
|
StructVector inputvector = new StructVector();
|
||||||
int arrayLen = 10;
|
int arrayLen = 10;
|
||||||
|
|
@ -154,6 +157,9 @@ public class li_std_vector_runme {
|
||||||
throw new Exception("ICollection constructor null test failed");
|
throw new Exception("ICollection constructor null test failed");
|
||||||
} catch (ArgumentNullException) {
|
} catch (ArgumentNullException) {
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
myDoubleVector = new DoubleVector() { 123.4, 567.8, 901.2 };
|
||||||
|
}
|
||||||
|
|
||||||
// IndexOf() test
|
// IndexOf() test
|
||||||
for (int i=0; i<collectionSize; i++) {
|
for (int i=0; i<collectionSize; i++) {
|
||||||
|
|
@ -187,11 +193,22 @@ public class li_std_vector_runme {
|
||||||
throw new Exception("Repeat count test failed");
|
throw new Exception("Repeat count test failed");
|
||||||
|
|
||||||
// Also tests enumerator
|
// Also tests enumerator
|
||||||
System.Collections.IEnumerator myEnumerator = dv.GetEnumerator();
|
{
|
||||||
while ( myEnumerator.MoveNext() ) {
|
System.Collections.IEnumerator myEnumerator = dv.GetEnumerator();
|
||||||
if ((double)myEnumerator.Current != 77.7)
|
while ( myEnumerator.MoveNext() ) {
|
||||||
throw new Exception("Repeat test failed");
|
if ((double)myEnumerator.Current != 77.7)
|
||||||
|
throw new Exception("Repeat (1) test failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#if !SWIG_DOTNET_1
|
||||||
|
{
|
||||||
|
System.Collections.Generic.IEnumerator<double> myEnumerator = dv.GetEnumerator();
|
||||||
|
while ( myEnumerator.MoveNext() ) {
|
||||||
|
if (myEnumerator.Current != 77.7)
|
||||||
|
throw new Exception("Repeat (2) test failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -516,6 +533,13 @@ public class li_std_vector_runme {
|
||||||
li_std_vector.halve_in_place(dvec);
|
li_std_vector.halve_in_place(dvec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dispose()
|
||||||
|
{
|
||||||
|
using (StructVector vs = new StructVector() { new Struct(0.0), new Struct(11.1) } )
|
||||||
|
using (DoubleVector vd = new DoubleVector() { 0.0, 11.1 } ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// More wrapped methods
|
// More wrapped methods
|
||||||
{
|
{
|
||||||
RealVector v0 = li_std_vector.vecreal(new RealVector());
|
RealVector v0 = li_std_vector.vecreal(new RealVector());
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,22 @@
|
||||||
*
|
*
|
||||||
* SWIG typemaps for std::vector
|
* SWIG typemaps for std::vector
|
||||||
* C# implementation
|
* C# implementation
|
||||||
* The C# wrapper is made to look and feel like a typesafe C# System.Collections.ArrayList
|
* The C# wrapper is made to look and feel like a C# System.Collections.Generic.List<> collection.
|
||||||
* All the methods in IList are defined, but we don't derive from IList as this is a typesafe collection.
|
* For .NET 1 compatibility, define SWIG_DOTNET_1 when compiling the C# code; then the C# wrapper is
|
||||||
* Warning: heavy macro usage in this file. Use swig -E to get a sane view on the real file contents!
|
* made to look and feel like a typesafe C# System.Collections.ArrayList. All the methods in IList
|
||||||
|
* are defined, but we don't derive from IList as this is a typesafe collection and the C++ operator==
|
||||||
|
* must always be defined for the collection type (which it isn't).
|
||||||
*
|
*
|
||||||
* Very often the C# generated code will not compile as the C++ template type is not the same as the C#
|
* Very often the C# generated code will not compile as the C++ template type is not the same as the C#
|
||||||
* proxy type, so use the SWIG_STD_VECTOR_SPECIALIZE or SWIG_STD_VECTOR_SPECIALIZE_MINIMUM macro, eg
|
* proxy type, so use the SWIG_STD_VECTOR_SPECIALIZE or SWIG_STD_VECTOR_SPECIALIZE_MINIMUM macro, eg
|
||||||
*
|
*
|
||||||
* SWIG_STD_VECTOR_SPECIALIZE_MINIMUM(Klass, SomeNamespace::Klass)
|
* SWIG_STD_VECTOR_SPECIALIZE_MINIMUM(Klass, SomeNamespace::Klass)
|
||||||
* %template(VectKlass) std::vector<SomeNamespace::Klass>;
|
* %template(VectKlass) std::vector<SomeNamespace::Klass>;
|
||||||
|
*
|
||||||
|
* Note that IEnumerable<> is implemented in the proxy class which is useful for using LINQ with
|
||||||
|
* C++ std::vector wrappers.
|
||||||
|
*
|
||||||
|
* Warning: heavy macro usage in this file. Use swig -E to get a sane view on the real file contents!
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
// Warning: Use the typemaps here in the expectation that the macros they are in will change name.
|
// Warning: Use the typemaps here in the expectation that the macros they are in will change name.
|
||||||
|
|
@ -25,7 +32,7 @@
|
||||||
// MACRO for use within the std::vector class body
|
// MACRO for use within the std::vector class body
|
||||||
// CSTYPE and CTYPE respectively correspond to the types in the cstype and ctype typemaps
|
// CSTYPE and CTYPE respectively correspond to the types in the cstype and ctype typemaps
|
||||||
%define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CONST_REFERENCE_TYPE, CSTYPE, CTYPE...)
|
%define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CONST_REFERENCE_TYPE, CSTYPE, CTYPE...)
|
||||||
%typemap(csinterfaces) std::vector<CTYPE > "IDisposable, System.Collections.IEnumerable";
|
%typemap(csinterfaces) std::vector<CTYPE > "IDisposable, System.Collections.IEnumerable\n#if !SWIG_DOTNET_1\n , System.Collections.Generic.IEnumerable<CSTYPE>\n#endif\n";
|
||||||
%typemap(cscode) std::vector<CTYPE > %{
|
%typemap(cscode) std::vector<CTYPE > %{
|
||||||
public $csclassname(System.Collections.ICollection c) : this() {
|
public $csclassname(System.Collections.ICollection c) : this() {
|
||||||
if (c == null)
|
if (c == null)
|
||||||
|
|
@ -79,15 +86,30 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyTo(System.Array array) {
|
#if SWIG_DOTNET_1
|
||||||
|
public void CopyTo(System.Array array)
|
||||||
|
#else
|
||||||
|
public void CopyTo(CSTYPE[] array)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
CopyTo(0, array, 0, this.Count);
|
CopyTo(0, array, 0, this.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyTo(System.Array array, int arrayIndex) {
|
#if SWIG_DOTNET_1
|
||||||
|
public void CopyTo(System.Array array, int arrayIndex)
|
||||||
|
#else
|
||||||
|
public void CopyTo(CSTYPE[] array, int arrayIndex)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
CopyTo(0, array, arrayIndex, this.Count);
|
CopyTo(0, array, arrayIndex, this.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyTo(int index, System.Array array, int arrayIndex, int count) {
|
#if SWIG_DOTNET_1
|
||||||
|
public void CopyTo(int index, System.Array array, int arrayIndex, int count)
|
||||||
|
#else
|
||||||
|
public void CopyTo(int index, CSTYPE[] array, int arrayIndex, int count)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
if (array == null)
|
if (array == null)
|
||||||
throw new ArgumentNullException("array");
|
throw new ArgumentNullException("array");
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
|
|
@ -97,14 +119,19 @@
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
throw new ArgumentOutOfRangeException("count", "Value is less than zero");
|
throw new ArgumentOutOfRangeException("count", "Value is less than zero");
|
||||||
if (array.Rank > 1)
|
if (array.Rank > 1)
|
||||||
throw new ArgumentException("Multi dimensional array.");
|
throw new ArgumentException("Multi dimensional array.", "array");
|
||||||
if (index+count > this.Count || arrayIndex+count > array.Length)
|
if (index+count > this.Count || arrayIndex+count > array.Length)
|
||||||
throw new ArgumentException("Number of elements to copy is too large.");
|
throw new ArgumentException("Number of elements to copy is too large.");
|
||||||
for (int i=0; i<count; i++)
|
for (int i=0; i<count; i++)
|
||||||
array.SetValue(getitemcopy(index+i), arrayIndex+i);
|
array.SetValue(getitemcopy(index+i), arrayIndex+i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type-safe version of IEnumerable.GetEnumerator
|
#if !SWIG_DOTNET_1
|
||||||
|
System.Collections.Generic.IEnumerator<CSTYPE> System.Collections.Generic.IEnumerable<CSTYPE>.GetEnumerator() {
|
||||||
|
return new $csclassnameEnumerator(this);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
|
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
|
||||||
return new $csclassnameEnumerator(this);
|
return new $csclassnameEnumerator(this);
|
||||||
}
|
}
|
||||||
|
|
@ -118,7 +145,11 @@
|
||||||
/// whenever the collection is modified. This has been done for changes in the size of the
|
/// whenever the collection is modified. This has been done for changes in the size of the
|
||||||
/// collection but not when one of the elements of the collection is modified as it is a bit
|
/// collection but not when one of the elements of the collection is modified as it is a bit
|
||||||
/// tricky to detect unmanaged code that modifies the collection under our feet.
|
/// tricky to detect unmanaged code that modifies the collection under our feet.
|
||||||
public sealed class $csclassnameEnumerator : System.Collections.IEnumerator {
|
public sealed class $csclassnameEnumerator : System.Collections.IEnumerator
|
||||||
|
#if !SWIG_DOTNET_1
|
||||||
|
, System.Collections.Generic.IEnumerator<CSTYPE>
|
||||||
|
#endif
|
||||||
|
{
|
||||||
private $csclassname collectionRef;
|
private $csclassname collectionRef;
|
||||||
private int currentIndex;
|
private int currentIndex;
|
||||||
private object currentObject;
|
private object currentObject;
|
||||||
|
|
@ -170,6 +201,13 @@
|
||||||
throw new InvalidOperationException("Collection modified.");
|
throw new InvalidOperationException("Collection modified.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !SWIG_DOTNET_1
|
||||||
|
public void Dispose() {
|
||||||
|
currentIndex = -1;
|
||||||
|
currentObject = null;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
@ -293,6 +331,7 @@ SWIG_STD_VECTOR_MINIMUM_INTERNAL(const value_type&, CSTYPE, CTYPE)
|
||||||
|
|
||||||
// Extra methods added to the collection class if operator== is defined for the class being wrapped
|
// Extra methods added to the collection class if operator== is defined for the class being wrapped
|
||||||
// CSTYPE and CTYPE respectively correspond to the types in the cstype and ctype typemaps
|
// CSTYPE and CTYPE respectively correspond to the types in the cstype and ctype typemaps
|
||||||
|
// The class will then implement IList<>, which adds extra functionality
|
||||||
%define SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(CSTYPE, CTYPE...)
|
%define SWIG_STD_VECTOR_EXTRA_OP_EQUALS_EQUALS(CSTYPE, CTYPE...)
|
||||||
%extend {
|
%extend {
|
||||||
bool Contains(const value_type& value) {
|
bool Contains(const value_type& value) {
|
||||||
|
|
@ -312,10 +351,13 @@ SWIG_STD_VECTOR_MINIMUM_INTERNAL(const value_type&, CSTYPE, CTYPE)
|
||||||
index = (int)(self->rend() - 1 - rit);
|
index = (int)(self->rend() - 1 - rit);
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
void Remove(const value_type& value) {
|
bool Remove(const value_type& value) {
|
||||||
std::vector<CTYPE >::iterator it = std::find(self->begin(), self->end(), value);
|
std::vector<CTYPE >::iterator it = std::find(self->begin(), self->end(), value);
|
||||||
if (it != self->end())
|
if (it != self->end()) {
|
||||||
self->erase(it);
|
self->erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
%enddef
|
%enddef
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue