diff --git a/Doc/Manual/CSharp.html b/Doc/Manual/CSharp.html index b911060aa..d24427010 100644 --- a/Doc/Manual/CSharp.html +++ b/Doc/Manual/CSharp.html @@ -29,6 +29,7 @@
-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 constructor helper function is generated due to the 'pre' or 'post' attributes. Please see the Date marshalling example 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 an additional optional attribute called 'cshin'. It should contain the parameter type and name whenever a constructor helper function 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 Date marshalling example and Date marshalling of properties example for further understanding.
If C# attributes need adding to the set or get part of C# properties, when wrapping C/C++ variables, they can be added using the 'csvarin' and 'csvarout' typemaps respectively. +Note that the type used for the property is specified in the 'cstype' typemap. +If the 'out' attribute exists in this typemap, then the type used is from the 'out' attribute.
@@ -1611,7 +1614,7 @@ The CDate & and const CDate & C# code is generated fro-%typemap(jstype) SWIGTYPE & "$csclassname" +%typemap(cstype) SWIGTYPE & "$csclassname" %typemap(csin) SWIGTYPE & "$csclassname.getCPtr($csinput)"
public class Action : IDisposable {
...
- public int doSomething(System.DateTime dateIn, ref System.DateTime dateOut) {
+ public int doSomething(System.DateTime dateIn, out System.DateTime dateOut) {
CDate tempdateIn = new CDate(dateIn.Year, dateIn.Month, dateIn.Day);
CDate tempdateOut = new CDate();
try {
@@ -1683,7 +1686,7 @@ public class Action : IDisposable {
}
}
- static private IntPtr SwigConstructAction(System.DateTime dateIn, ref System.DateTime dateOut) {
+ static private IntPtr SwigConstructAction(System.DateTime dateIn, out System.DateTime dateOut) {
CDate tempdateIn = new CDate(dateIn.Year, dateIn.Month, dateIn.Day);
CDate tempdateOut = new CDate();
try {
@@ -1694,8 +1697,8 @@ public class Action : IDisposable {
}
}
- public Action(System.DateTime dateIn, ref System.DateTime dateOut)
- : this(Action.SwigConstructAction(dateIn, ref dateOut), true) {
+ public Action(System.DateTime dateIn, out System.DateTime dateOut)
+ : this(Action.SwigConstructAction(dateIn, out dateOut), true) {
if (examplePINVOKE.SWIGPendingException.Pending)
throw examplePINVOKE.SWIGPendingException.Retrieve();
}
@@ -1719,10 +1722,171 @@ A few things to note:
more local variables with the same name would be generated.
+So far we have considered the date as an input only and an output only type. +Now let's consider CDate * used as an input/output type. Consider the following C++ function which modifies the date passed in: +
+ +
+void addYears(CDate *pDate, int years) {
+ *pDate = CDate(pDate->getYear() + years, pDate->getMonth(), pDate->getDay());
+}
+
++If usage of CDate * commonly follows this input/output pattern, usage from C# like the following +
+ ++System.DateTime christmasEve = new System.DateTime(2000, 12, 24); +example.addYears(ref christmasEve, 10); // christmasEve now contains 2010-12-24 ++
+will be possible with the following CDate * typemaps +
+ ++%typemap(cstype, out="System.DateTime") CDate * "ref System.DateTime" + +%typemap(csin, + pre=" CDate temp$csinput = new CDate($csinput.Year, $csinput.Month, $csinput.Day);", + post=" $csinput = new System.DateTime(temp$csinput.getYear()," + " temp$csinput.getMonth(), temp$csinput.getDay(), 0, 0, 0);", + cshin="ref $csinput") CDate * + "$csclassname.getCPtr(temp$csinput)" ++
+Globals are wrapped by the module class and for a module called example, the typemaps result in the following code: +
+ +
+public class example {
+ public static void addYears(ref System.DateTime pDate, int years) {
+ CDate temppDate = new CDate(pDate.Year, pDate.Month, pDate.Day);
+ try {
+ examplePINVOKE.addYears(CDate.getCPtr(temppDate), years);
+ } finally {
+ pDate = new System.DateTime(temppDate.getYear(), temppDate.getMonth(), temppDate.getDay(), 0, 0, 0);
+ }
+ }
+ ...
+}
+
++The previous section looked at converting a C++ date class to System.DateTime for parameters. +This section extends this idea so that the correct marshalling is obtained when wrapping C++ variables. +Consider the same CDate class from the previous section and a global variable: +
+ ++CDate ImportantDate = CDate(1999, 12, 31); ++
+The aim is to use System.DateTime from C# when accessing this date as shown in the following usage where the module name is 'example': +
+ +
+example.ImportantDate = new System.DateTime(2000, 11, 22);
+System.DateTime importantDate = example.ImportantDate;
+Console.WriteLine("Important date: " + importantDate);
+
++When SWIG wraps a variable that is a class/struct/union, it is wrapped using a pointer to the type for the reasons given in Stucture data members. +The typemap type required is thus CDate *. Given that the previous section already designed CDate * typemaps, we'll use those same typemaps plus the 'csvarin' and 'csvarout' typemaps. + +
+%typemap(cstype, out="System.DateTime") CDate * "ref System.DateTime"
+
+%typemap(csin,
+ pre=" CDate temp$csinput = new CDate($csinput.Year, $csinput.Month, $csinput.Day);",
+ post=" $csinput = new System.DateTime(temp$csinput.getYear(),"
+ " temp$csinput.getMonth(), temp$csinput.getDay(), 0, 0, 0);",
+ cshin="ref $csinput") CDate *
+ "$csclassname.getCPtr(temp$csinput)"
+
+%typemap(csvarin, excode=SWIGEXCODE2) CDate * %{
+ /* csvarin typemap code */
+ set {
+ CDate temp$csinput = new CDate($csinput.Year, $csinput.Month, $csinput.Day);
+ $imcall;$excode
+ } %}
+
+%typemap(csvarout, excode=SWIGEXCODE2) CDate * %{
+ /* csvarout typemap code */
+ get {
+ IntPtr cPtr = $imcall;
+ CDate tempDate = (cPtr == IntPtr.Zero) ? null : new CDate(cPtr, $owner);$excode
+ return new System.DateTime(tempDate.getYear(), tempDate.getMonth(), tempDate.getDay(),
+ 0, 0, 0);
+ } %}
+
++For a module called example, the typemaps result in the following code: +
+ +
+public class example {
+ public static System.DateTime ImportantDate {
+ /* csvarin typemap code */
+ set {
+ CDate tempvalue = new CDate(value.Year, value.Month, value.Day);
+ examplePINVOKE.ImportantDate_set(CDate.getCPtr(tempvalue));
+ }
+ /* csvarout typemap code */
+ get {
+ IntPtr cPtr = examplePINVOKE.ImportantDate_get();
+ CDate tempDate = (cPtr == IntPtr.Zero) ? null : new CDate(cPtr, false);
+ return new System.DateTime(tempDate.getYear(), tempDate.getMonth(), tempDate.getDay(),
+ 0, 0, 0);
+ }
+ }
+ ...
+}
+
++Some points to note: +
+ +@@ -1822,7 +1986,7 @@ demonstrating that the class contains methods calling both unmanaged code - The following example is an alternative approach to adding managed code to the generated proxy class.
-diff --git a/Examples/test-suite/csharp/csharp_typemaps_runme.cs b/Examples/test-suite/csharp/csharp_typemaps_runme.cs index 42f2fe8d1..846644f09 100644 --- a/Examples/test-suite/csharp/csharp_typemaps_runme.cs +++ b/Examples/test-suite/csharp/csharp_typemaps_runme.cs @@ -15,13 +15,16 @@ public class runme initialLetters.Append(myChar); myChar = csharp_typemaps.partyon("off"); initialLetters.Append(myChar); - myChar = csharp_typemaps.STRINGCONSTANT; - initialLetters.Append(myChar); - if (initialLetters.ToString() != "bhox") + if (initialLetters.ToString() != "bho") throw new Exception("initial letters failed"); - if (csharp_typemaps.go != 'z') - throw new Exception("go variable failed"); + // $csinput expansion + csharp_typemaps.myInt = 1; + try { + csharp_typemaps.myInt = -1; + throw new Exception("oops"); + } catch (ApplicationException) { + } // Eager garbage collector test { diff --git a/Examples/test-suite/csharp_typemaps.i b/Examples/test-suite/csharp_typemaps.i index b982dc964..dcef278f6 100644 --- a/Examples/test-suite/csharp_typemaps.i +++ b/Examples/test-suite/csharp_typemaps.i @@ -22,14 +22,6 @@ return ret; } %} -// test valueparm attribute -%typemap(csvarin, excode=SWIGEXCODE2, valueparm="tempValue") char * %{ - set { - string tempValue = new string(value, 3); - $imcall;$excode - } %} - - %inline %{ namespace Space { class Things { @@ -38,8 +30,6 @@ namespace Space { static char* stop(char *val) { return val; } }; char* partyon(char *val) { return val; } - #define STRINGCONSTANT "xyz string" - char *go = "zap"; } %} @@ -100,3 +90,14 @@ Number times12(const Number* num) { }; %} +// Test $csinput expansion +%typemap(csvarin, excode=SWIGEXCODE2) int %{ + set { + if ($csinput < 0) + throw new ApplicationException("number too small!"); + $imcall;$excode + } %} + +%inline %{ +int myInt = 0; +%} diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 640050e2b..79761cdba 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -2652,6 +2652,7 @@ public: SwigType *pt = Getattr(p, "type"); if ((tm = Getattr(p, "tmap:csvarin"))) { substituteClassname(pt, tm); + Replaceall(tm, "$csinput", "value"); Replaceall(tm, "$imcall", imcall); excodeSubstitute(n, tm, "csvarin", p); Printf(module_class_code, "%s", tm); @@ -2869,8 +2870,7 @@ public: String *pn = Getattr(p, "name"); if (setter) { // Note that in C# properties, the input variable name is always called 'value' - String *valueparm = Getattr(p, "tmap:csvarin:valueparm"); - arg = valueparm ? Copy(valueparm) : NewString("value"); + arg = NewString("value"); } else { // Use C parameter name unless it is a duplicate or an empty parameter name int count = 0;