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)
|
||||
============================
|
||||
|
||||
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
|
||||
[Ruby] Fix #2676738 SWIG generated symbol name clashes.
|
||||
|
||||
|
|
|
|||
|
|
@ -82,14 +82,17 @@ public class li_std_vector_runme {
|
|||
} catch (ArgumentException) {
|
||||
}
|
||||
}
|
||||
#if SWIG_DOTNET_1
|
||||
{
|
||||
// runtime check that 2D arrays fail
|
||||
double[,] outputarray = new double[collectionSize,collectionSize];
|
||||
try {
|
||||
vect.CopyTo(outputarray);
|
||||
throw new Exception("CopyTo (5) test failed");
|
||||
throw new Exception("CopyTo (5a) test failed");
|
||||
} catch (ArgumentException) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
{
|
||||
StructVector inputvector = new StructVector();
|
||||
int arrayLen = 10;
|
||||
|
|
@ -154,6 +157,9 @@ public class li_std_vector_runme {
|
|||
throw new Exception("ICollection constructor null test failed");
|
||||
} catch (ArgumentNullException) {
|
||||
}
|
||||
{
|
||||
myDoubleVector = new DoubleVector() { 123.4, 567.8, 901.2 };
|
||||
}
|
||||
|
||||
// IndexOf() test
|
||||
for (int i=0; i<collectionSize; i++) {
|
||||
|
|
@ -187,11 +193,22 @@ public class li_std_vector_runme {
|
|||
throw new Exception("Repeat count test failed");
|
||||
|
||||
// Also tests enumerator
|
||||
System.Collections.IEnumerator myEnumerator = dv.GetEnumerator();
|
||||
while ( myEnumerator.MoveNext() ) {
|
||||
if ((double)myEnumerator.Current != 77.7)
|
||||
throw new Exception("Repeat test failed");
|
||||
{
|
||||
System.Collections.IEnumerator myEnumerator = dv.GetEnumerator();
|
||||
while ( myEnumerator.MoveNext() ) {
|
||||
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);
|
||||
}
|
||||
|
||||
// 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
|
||||
{
|
||||
RealVector v0 = li_std_vector.vecreal(new RealVector());
|
||||
|
|
|
|||
|
|
@ -6,15 +6,22 @@
|
|||
*
|
||||
* SWIG typemaps for std::vector
|
||||
* C# implementation
|
||||
* The C# wrapper is 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.
|
||||
* Warning: heavy macro usage in this file. Use swig -E to get a sane view on the real file contents!
|
||||
* The C# wrapper is made to look and feel like a C# System.Collections.Generic.List<> collection.
|
||||
* For .NET 1 compatibility, define SWIG_DOTNET_1 when compiling the C# code; then the C# wrapper is
|
||||
* 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#
|
||||
* 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)
|
||||
* %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.
|
||||
|
|
@ -25,7 +32,7 @@
|
|||
// MACRO for use within the std::vector class body
|
||||
// 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...)
|
||||
%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 > %{
|
||||
public $csclassname(System.Collections.ICollection c) : this() {
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
throw new ArgumentNullException("array");
|
||||
if (index < 0)
|
||||
|
|
@ -97,14 +119,19 @@
|
|||
if (count < 0)
|
||||
throw new ArgumentOutOfRangeException("count", "Value is less than zero");
|
||||
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)
|
||||
throw new ArgumentException("Number of elements to copy is too large.");
|
||||
for (int i=0; i<count; 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() {
|
||||
return new $csclassnameEnumerator(this);
|
||||
}
|
||||
|
|
@ -118,7 +145,11 @@
|
|||
/// 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
|
||||
/// 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 int currentIndex;
|
||||
private object currentObject;
|
||||
|
|
@ -170,6 +201,13 @@
|
|||
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
|
||||
// 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...)
|
||||
%extend {
|
||||
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);
|
||||
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);
|
||||
if (it != self->end())
|
||||
if (it != self->end()) {
|
||||
self->erase(it);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
%enddef
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue