From: <wsf...@us...> - 2008-09-18 13:32:36
|
Revision: 10872 http://swig.svn.sourceforge.net/swig/?rev=10872&view=rev Author: wsfulton Date: 2008-09-18 20:32:28 +0000 (Thu, 18 Sep 2008) Log Message: ----------- Add C# array typemaps provided by Antti Karanta. Modified Paths: -------------- trunk/CHANGES.current trunk/Doc/Manual/CSharp.html trunk/Examples/csharp/check.list trunk/Examples/test-suite/csharp/Makefile.in Added Paths: ----------- trunk/Examples/csharp/arrays/ trunk/Examples/csharp/arrays/Makefile trunk/Examples/csharp/arrays/example.c trunk/Examples/csharp/arrays/example.h trunk/Examples/csharp/arrays/example.i trunk/Examples/csharp/arrays/runme.cs trunk/Examples/test-suite/csharp/csharp_lib_arrays_runme.cs trunk/Examples/test-suite/csharp_lib_arrays.i trunk/Lib/csharp/arrays_csharp.i Modified: trunk/CHANGES.current =================================================================== --- trunk/CHANGES.current 2008-09-18 20:28:40 UTC (rev 10871) +++ trunk/CHANGES.current 2008-09-18 20:32:28 UTC (rev 10872) @@ -1,6 +1,12 @@ Version 1.3.37 (in progress) ============================= +2008-09-17: wsfulton + [C#] Added C# array typemaps provided by Antti Karanta. + The arrays provide a way to use MarshalAs(UnmanagedType.LPArray) + and pinning the array using 'fixed'. See arrays_csharp.i library file + for details. + 2008-09-18: wsfulton Document the optional module attribute in the %import directive, see Modules.html. Add a warning for Python wrappers when the @@ -49,10 +55,10 @@ - some minor aesthetic changes. 2008-09-12: bhy - [Python] Python 3.0 support branch merged into SWIG trunk. Thanks - Google Summer of Code 2008 for support this project! By default + [Python] Python 3.0 support branch merged into SWIG trunk. Thanks to + Google Summer of Code 2008 for supporting this project! By default SWIG will generate interface files compatible with both Python 2.x - and 3.0. And there's also some Python 3 new features could be + and 3.0. And there's also some Python 3 new features that can be enabled by passing a "-py3" command line option to SWIG. These features are: @@ -64,7 +70,7 @@ - Abstract base class support For details of Python 3 support and these features, please see the - "Python 3 Support" section in the "SWIG and Python" chapter of SWIG + "Python 3 Support" section in the "SWIG and Python" chapter of the SWIG documentation. The "-apply" command line option and support of generating codes Modified: trunk/Doc/Manual/CSharp.html =================================================================== --- trunk/Doc/Manual/CSharp.html 2008-09-18 20:28:40 UTC (rev 10871) +++ trunk/Doc/Manual/CSharp.html 2008-09-18 20:32:28 UTC (rev 10872) @@ -201,7 +201,12 @@ <li> <p> -Unlike the "javain" typemap, the "csin" typemap does not support the 'pgcpp' attribute as the C# module does not have a premature garbage collection prevention parameter. The "csin" typemap supports an additional optional attribute called 'cshin'. It should contain the parameter type and name whenever a <a href="Java.html#java_constructor_helper_function">constructor helper function</a> is generated due to the 'pre' or 'post' attributes. Note that 'pre', 'post' and 'cshin' attributes are not used for marshalling the property set. Please see the <a href="#csharp_date_marshalling">Date marshalling example</a> and <a href="#CSharp.html#csharp_date_properties">Date marshalling of properties example</a> for further understanding. +Unlike the "javain" typemap, the "csin" typemap does not support the 'pgcpp' attribute as the C# module does not have a premature garbage collection prevention parameter. +The "csin" typemap supports additional optional attributes called 'cshin' and 'terminator'. +The 'cshin' attribute should contain the parameter type and name whenever a <a href="Java.html#java_constructor_helper_function">constructor helper function</a> is generated due to the 'pre' or 'post' attributes. +The 'terminator' attribute normally just contains a closing brace for when the 'pre' attribute contains an opening brace, such as when a C# <tt>using</tt> or <tt>fixed</tt> block is started. +Note that 'pre', 'post', 'terminator' and 'cshin' attributes are not used for marshalling the property set. +Please see the <a href="#csharp_date_marshalling">Date marshalling example</a> and <a href="#CSharp.html#csharp_date_properties">Date marshalling of properties example</a> for further understanding of these "csin" applicable attributes. </p> </li> Added: trunk/Examples/csharp/arrays/Makefile =================================================================== --- trunk/Examples/csharp/arrays/Makefile (rev 0) +++ trunk/Examples/csharp/arrays/Makefile 2008-09-18 20:32:28 UTC (rev 10872) @@ -0,0 +1,20 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +SRCS = example.c +TARGET = example +INTERFACE = example.i +SWIGOPT = +CSHARPSRCS = *.cs +CSHARPFLAGS= -nologo -unsafe -out:runme.exe + +all:: csharp + +csharp:: + $(MAKE) -f $(TOP)/Makefile SRCS='$(SRCS)' SWIG='$(SWIG)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' csharp + $(MAKE) -f $(TOP)/Makefile CSHARPSRCS='$(CSHARPSRCS)' CSHARPFLAGS='$(CSHARPFLAGS)' csharp_compile + +clean:: + $(MAKE) -f $(TOP)/Makefile csharp_clean + +check: all Added: trunk/Examples/csharp/arrays/example.c =================================================================== --- trunk/Examples/csharp/arrays/example.c (rev 0) +++ trunk/Examples/csharp/arrays/example.c 2008-09-18 20:32:28 UTC (rev 10872) @@ -0,0 +1,22 @@ +/* File : example.c */ + +#include "example.h" + +/* copy the contents of the first array to the second */ +void myArrayCopy( int* sourceArray, int* targetArray, int nitems ) { + int i; + for ( i = 0; i < nitems; i++ ) { + targetArray[ i ] = sourceArray[ i ]; + } +} + +/* swap the contents of the two arrays */ +void myArraySwap( int* array1, int* array2, int nitems ) { + int i, temp; + for ( i = 0; i < nitems; i++ ) { + temp = array1[ i ]; + array1[ i ] = array2[ i ]; + array2[ i ] = temp; + } +} + Added: trunk/Examples/csharp/arrays/example.h =================================================================== --- trunk/Examples/csharp/arrays/example.h (rev 0) +++ trunk/Examples/csharp/arrays/example.h 2008-09-18 20:32:28 UTC (rev 10872) @@ -0,0 +1,4 @@ + +void myArrayCopy( int *sourceArray, int* targetArray, int nitems ); +void myArraySwap( int* array1, int* array2, int nitems ); + Added: trunk/Examples/csharp/arrays/example.i =================================================================== --- trunk/Examples/csharp/arrays/example.i (rev 0) +++ trunk/Examples/csharp/arrays/example.i 2008-09-18 20:32:28 UTC (rev 10872) @@ -0,0 +1,42 @@ +/* File : example.i */ +%module example + +%include "arrays_csharp.i" + +%apply int INPUT[] { int* sourceArray } +%apply int OUTPUT[] { int* targetArray } + +%apply int INOUT[] { int* array1 } +%apply int INOUT[] { int* array2 } + +%include "example.h" + +%clear int* sourceArray; +%clear int* targetArray; + +%clear int* array1; +%clear int* array2; + + +// Below replicates the above array handling but this time using the pinned (fixed) array typemaps +%csmethodmodifiers "public unsafe"; + +%apply int FIXED[] { int* sourceArray } +%apply int FIXED[] { int* targetArray } + +%inline %{ +void myArrayCopyUsingFixedArrays( int *sourceArray, int* targetArray, int nitems ) { + myArrayCopy(sourceArray, targetArray, nitems); +} +%} + +%apply int FIXED[] { int* array1 } +%apply int FIXED[] { int* array2 } + +%inline %{ +void myArraySwapUsingFixedArrays( int* array1, int* array2, int nitems ) { + myArraySwap(array1, array2, nitems); +} +%} + + Added: trunk/Examples/csharp/arrays/runme.cs =================================================================== --- trunk/Examples/csharp/arrays/runme.cs (rev 0) +++ trunk/Examples/csharp/arrays/runme.cs 2008-09-18 20:32:28 UTC (rev 10872) @@ -0,0 +1,43 @@ +using System; + +public class runme +{ + static void Main() + { + int[] source = { 1, 2, 3 }; + int[] target = new int[ source.Length ]; + + example.myArrayCopy( source, target, target.Length ); + + Console.WriteLine( "Contents of copy target array using default marshaling" ); + PrintArray( target ); + + target = new int[ source.Length ]; + + example.myArrayCopyUsingFixedArrays( source, target, target.Length ); + Console.WriteLine( "Contents of copy target array using fixed arrays" ); + PrintArray( target ); + + target = new int[] { 4, 5, 6 }; + example.myArraySwap( source, target, target.Length ); + Console.WriteLine( "Contents of arrays after swapping using default marshaling" ); + PrintArray( source ); + PrintArray( target ); + + source = new int[] { 1, 2, 3 }; + target = new int[] { 4, 5, 6 }; + + example.myArraySwapUsingFixedArrays( source, target, target.Length ); + Console.WriteLine( "Contents of arrays after swapping using fixed arrays" ); + PrintArray( source ); + PrintArray( target ); + } + + static void PrintArray( int[] a ) + { + foreach ( int i in a ) + Console.Write( "{0} ", i ); + Console.WriteLine(); + } +} + Modified: trunk/Examples/csharp/check.list =================================================================== --- trunk/Examples/csharp/check.list 2008-09-18 20:28:40 UTC (rev 10871) +++ trunk/Examples/csharp/check.list 2008-09-18 20:32:28 UTC (rev 10872) @@ -1,4 +1,5 @@ # see top-level Makefile.in +arrays callback class enum Modified: trunk/Examples/test-suite/csharp/Makefile.in =================================================================== --- trunk/Examples/test-suite/csharp/Makefile.in 2008-09-18 20:28:40 UTC (rev 10871) +++ trunk/Examples/test-suite/csharp/Makefile.in 2008-09-18 20:32:28 UTC (rev 10872) @@ -21,13 +21,17 @@ enum_thorough_typesafe \ exception_partial_info -CUSTOM_TEST_CASES = intermediary_classname +CUSTOM_TEST_CASES = \ + csharp_lib_arrays \ + intermediary_classname include $(srcdir)/../common.mk # Overridden variables here SWIGOPT += -namespace $*Namespace $(SWIGOPTSPECIAL) +CSHARPFLAGSSPECIAL = + # Rules for the different types of tests %.cpptest: $(setup) @@ -47,6 +51,8 @@ # Rules for custom tests intermediary_classname.customtest: $(MAKE) intermediary_classname.cpptest SWIGOPTSPECIAL="-dllimport intermediary_classname" +csharp_lib_arrays.customtest: + $(MAKE) csharp_lib_arrays.cpptest CSHARPFLAGSSPECIAL="-unsafe" # Makes a directory for the testcase if it does not exist setup = \ @@ -65,14 +71,14 @@ run_testcase = \ if [ -f $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then ( \ $(MAKE) -f $*/$(top_builddir)/$(EXAMPLES)/Makefile \ - CSHARPFLAGS='-nologo -out:$*_runme.exe' \ + CSHARPFLAGS='-nologo $(CSHARPFLAGSSPECIAL) -out:$*_runme.exe' \ CSHARPSRCS='`$(CSHARPCYGPATH_W) $(srcdir)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX)` \ $*$(CSHARPPATHSEPARATOR)*.cs' csharp_compile && \ env LD_LIBRARY_PATH="$*:$$LD_LIBRARY_PATH" PATH="$*:$$PATH" SHLIB_PATH="$*:$$SHLIB_PATH" $(RUNTOOL) $(INTERPRETER) $*_runme.exe; ) \ else ( \ cd $* && \ $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile \ - CSHARPFLAGS='-nologo -t:module -out:$*.netmodule' \ + CSHARPFLAGS='-nologo $(CSHARPFLAGSSPECIAL) -t:module -out:$*.netmodule' \ CSHARPSRCS='*.cs' csharp_compile; ); \ fi; Added: trunk/Examples/test-suite/csharp/csharp_lib_arrays_runme.cs =================================================================== --- trunk/Examples/test-suite/csharp/csharp_lib_arrays_runme.cs (rev 0) +++ trunk/Examples/test-suite/csharp/csharp_lib_arrays_runme.cs 2008-09-18 20:32:28 UTC (rev 10872) @@ -0,0 +1,70 @@ +using System; +using csharp_lib_arraysNamespace; + +public class runme +{ + static void Main() + { + { + int[] source = { 1, 2, 3, 4, 5 }; + int[] target = new int[ source.Length ]; + + csharp_lib_arrays.myArrayCopy( source, target, target.Length ); + CompareArrays(source, target); + } + + { + int[] source = { 1, 2, 3, 4, 5 }; + int[] target = new int[ source.Length ]; + + csharp_lib_arrays.myArrayCopyUsingFixedArrays( source, target, target.Length ); + CompareArrays(source, target); + } + + { + int[] source = { 1, 2, 3, 4, 5 }; + int[] target = new int[] { 6, 7, 8, 9, 10 }; + + csharp_lib_arrays.myArraySwap( source, target, target.Length ); + + for (int i=0; i<target.Length; ++i) + target[i] += 5; + CompareArrays(source, target); + } + + { + int[] source = { 1, 2, 3, 4, 5 }; + int[] target = new int[] { 6, 7, 8, 9, 10 }; + + csharp_lib_arrays.myArraySwapUsingFixedArrays( source, target, target.Length ); + + for (int i=0; i<target.Length; ++i) + target[i] += 5; + CompareArrays(source, target); + } + } + + static void CompareArrays( int[] a, int[] b ) + { + if (a.Length != b.Length) + throw new Exception("size mismatch"); + + for(int i=0; i<a.Length; ++i) { + if (a[i] != b[i]) { + Console.Error.WriteLine("a:"); + PrintArray(a); + Console.Error.WriteLine("b:"); + PrintArray(b); + throw new Exception("element mismatch"); + } + } + } + + static void PrintArray( int[] a ) + { + foreach ( int i in a ) + Console.Error.Write( "{0} ", i ); + Console.Error.WriteLine(); + } +} + Added: trunk/Examples/test-suite/csharp_lib_arrays.i =================================================================== --- trunk/Examples/test-suite/csharp_lib_arrays.i (rev 0) +++ trunk/Examples/test-suite/csharp_lib_arrays.i 2008-09-18 20:32:28 UTC (rev 10872) @@ -0,0 +1,61 @@ +%module csharp_lib_arrays + +%include "arrays_csharp.i" + +%apply int INPUT[] { int* sourceArray } +%apply int OUTPUT[] { int* targetArray } + +%apply int INOUT[] { int* array1 } +%apply int INOUT[] { int* array2 } + +%inline %{ +/* copy the contents of the first array to the second */ +void myArrayCopy( int* sourceArray, int* targetArray, int nitems ) { + int i; + for ( i = 0; i < nitems; i++ ) { + targetArray[ i ] = sourceArray[ i ]; + } +} + +/* swap the contents of the two arrays */ +void myArraySwap( int* array1, int* array2, int nitems ) { + int i, temp; + for ( i = 0; i < nitems; i++ ) { + temp = array1[ i ]; + array1[ i ] = array2[ i ]; + array2[ i ] = temp; + } +} +%} + + +%clear int* sourceArray; +%clear int* targetArray; + +%clear int* array1; +%clear int* array2; + + +// Below replicates the above array handling but this time using the pinned (fixed) array typemaps +%csmethodmodifiers myArrayCopyUsingFixedArrays "public unsafe"; +%csmethodmodifiers myArraySwapUsingFixedArrays "public unsafe"; + +%apply int FIXED[] { int* sourceArray } +%apply int FIXED[] { int* targetArray } + +%inline %{ +void myArrayCopyUsingFixedArrays( int *sourceArray, int* targetArray, int nitems ) { + myArrayCopy(sourceArray, targetArray, nitems); +} +%} + +%apply int FIXED[] { int* array1 } +%apply int FIXED[] { int* array2 } + +%inline %{ +void myArraySwapUsingFixedArrays( int* array1, int* array2, int nitems ) { + myArraySwap(array1, array2, nitems); +} +%} + + Added: trunk/Lib/csharp/arrays_csharp.i =================================================================== --- trunk/Lib/csharp/arrays_csharp.i (rev 0) +++ trunk/Lib/csharp/arrays_csharp.i 2008-09-18 20:32:28 UTC (rev 10872) @@ -0,0 +1,140 @@ +/* ----------------------------------------------------------------------------- + * See the LICENSE file for information on copyright, usage and redistribution + * of SWIG, and the README file for authors - http://www.swig.org/release.html. + * + * arrays_csharp.i + * + * This file contains a two approaches to marshaling arrays. The first uses + * default p/invoke marshaling and the second uses pinning of the arrays. + * + * Default marshalling approach + * ---------------------------- + * Array typemaps using default p/invoke marshaling. The data is copied to a separately + * allocated buffer when passing over the managed-native boundary. + * + * There are separate typemaps for in, out and inout arrays to enable avoiding + * unnecessary copying. + * + * Example usage: + * + * %include "arrays_csharp.i" + * %apply int INPUT[] { int* sourceArray } + * %apply int OUTPUT[] { int* targetArray } + * void myArrayCopy( int* sourceArray, int* targetArray, int nitems ); + * + * %apply int INOUT[] { int* array1, int *array2 } + * void myArraySwap( int* array1, int* array2, int nitems ); + * + * If handling large arrays you should consider using the pinning array typemaps + * described next. + * + * Pinning approach + * ---------------- + * Array typemaps using pinning. These typemaps pin the managed array given + * as parameter and pass a pointer to it to the c/c++ side. This is very + * efficient as no copying is done (unlike in the default array marshalling), + * but it makes garbage collection more difficult. When considering using + * these typemaps, think carefully whether you have callbacks that may cause + * the control to re-enter the managed side from within the call (and produce + * garbage for the gc) or whether other threads may produce enough garbage to + * trigger gc while the call is being executed. In those cases it may be + * wiser to use. + * + * Please note that when using fixed arrays, you have to mark your corresponding + * module class method unsafe using + * %csmethodmodifiers "public unsafe" + * (the visibility of the method is up to you). + * + * Example usage: + * + * %include "arrays_csharp.i" + * %apply int FIXED[] { int* sourceArray, int *targetArray } + * %csmethodmodifiers myArrayCopy "public unsafe"; + * void myArrayCopy( int *sourceArray, int* targetArray, int nitems ); + * + * ----------------------------------------------------------------------------- */ + +%define CSHARP_ARRAYS( CTYPE, CSTYPE ) + +// input only arrays + +%typemap(ctype) CTYPE INPUT[] "CTYPE*" +%typemap(cstype) CTYPE INPUT[] "CSTYPE[]" +%typemap(imtype, inattributes="[In, MarshalAs(UnmanagedType.LPArray)]") CTYPE INPUT[] "CSTYPE[]" +%typemap(csin) CTYPE INPUT[] "$csinput" + +%typemap(in) CTYPE INPUT[] "$1 = $input;" +%typemap(freearg) CTYPE INPUT[] "" +%typemap(argout) CTYPE INPUT[] "" + +// output only arrays + +%typemap(ctype) CTYPE OUTPUT[] "CTYPE*" +%typemap(cstype) CTYPE OUTPUT[] "CSTYPE[]" +%typemap(imtype, inattributes="[Out, MarshalAs(UnmanagedType.LPArray)]") CTYPE OUTPUT[] "CSTYPE[]" +%typemap(csin) CTYPE OUTPUT[] "$csinput" + +%typemap(in) CTYPE OUTPUT[] "$1 = $input;" +%typemap(freearg) CTYPE OUTPUT[] "" +%typemap(argout) CTYPE OUTPUT[] "" + +// inout arrays + +%typemap(ctype) CTYPE INOUT[] "CTYPE*" +%typemap(cstype) CTYPE INOUT[] "CSTYPE[]" +%typemap(imtype, inattributes="[In, Out, MarshalAs(UnmanagedType.LPArray)]") CTYPE INOUT[] "CSTYPE[]" +%typemap(csin) CTYPE INOUT[] "$csinput" + +%typemap(in) CTYPE INOUT[] "$1 = $input;" +%typemap(freearg) CTYPE INOUT[] "" +%typemap(argout) CTYPE INOUT[] "" + +%enddef // CSHARP_ARRAYS + +CSHARP_ARRAYS(signed char, sbyte) +CSHARP_ARRAYS(unsigned char, byte) +CSHARP_ARRAYS(short, short) +CSHARP_ARRAYS(unsigned short, ushort) +CSHARP_ARRAYS(int, int) +CSHARP_ARRAYS(unsigned int, uint) +// FIXME - on Unix 64 bit, long is 8 bytes but is 4 bytes on Windows 64 bit. +// How can this be handled sensibly? +// See e.g. http://www.xml.com/ldd/chapter/book/ch10.html +CSHARP_ARRAYS(long, int) +CSHARP_ARRAYS(unsigned long, uint) +CSHARP_ARRAYS(long long, long) +CSHARP_ARRAYS(unsigned long long, ulong) +CSHARP_ARRAYS(float, float) +CSHARP_ARRAYS(double, double) + + +%define CSHARP_ARRAYS_FIXED( CTYPE, CSTYPE ) + +%typemap(ctype) CTYPE FIXED[] "CTYPE*" +%typemap(imtype) CTYPE FIXED[] "IntPtr" +%typemap(cstype) CTYPE FIXED[] "CSTYPE[]" +%typemap(csin, + pre= " fixed ( CSTYPE* swig_ptrTo_$csinput = $csinput ) {", + terminator=" }") + CTYPE FIXED[] "(IntPtr)swig_ptrTo_$csinput" + +%typemap(in) CTYPE FIXED[] "$1 = $input;" +%typemap(freearg) CTYPE FIXED[] "" +%typemap(argout) CTYPE FIXED[] "" + + +%enddef // CSHARP_ARRAYS_FIXED + +CSHARP_ARRAYS_FIXED(signed char, sbyte) +CSHARP_ARRAYS_FIXED(unsigned char, byte) +CSHARP_ARRAYS_FIXED(short, short) +CSHARP_ARRAYS_FIXED(unsigned short, ushort) +CSHARP_ARRAYS_FIXED(int, int) +CSHARP_ARRAYS_FIXED(unsigned int, uint) +CSHARP_ARRAYS_FIXED(long, int) +CSHARP_ARRAYS_FIXED(unsigned long, uint) +CSHARP_ARRAYS_FIXED(long long, long) +CSHARP_ARRAYS_FIXED(unsigned long long, ulong) +CSHARP_ARRAYS_FIXED(float, float) +CSHARP_ARRAYS_FIXED(double, double) + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |