PageRenderTime 35ms CodeModel.GetById 10ms app.highlight 13ms RepoModel.GetById 2ms app.codeStats 0ms

/trunk/Doc/Manual/CSharp.html

#
HTML | 1908 lines | 1577 code | 329 blank | 2 comment | 0 complexity | d40273460f28f5a3adc7becc17368b36 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
   2<html>
   3<head>
   4<title>SWIG and C#</title>
   5<link rel="stylesheet" type="text/css" href="style.css">
   6</head>
   7<body bgcolor="#FFFFFF">
   8<H1><a name="CSharp"></a>19 SWIG and C#</H1>
   9<!-- INDEX -->
  10<div class="sectiontoc">
  11<ul>
  12<li><a href="#CSharp_introduction">Introduction</a>
  13<li><a href="#CSharp_differences_java">Differences to the Java module</a>
  14<li><a href="#CSharp_void_pointers">Void pointers</a>
  15<li><a href="#CSharp_arrays">C# Arrays</a>
  16<ul>
  17<li><a href="#CSharp_arrays_swig_library">The SWIG C arrays library</a>
  18<li><a href="#CSharp_arrays_pinvoke_default_array_marshalling">Managed arrays using P/Invoke default array marshalling</a>
  19<li><a href="#CSharp_arrays_pinning">Managed arrays using pinning</a>
  20</ul>
  21<li><a href="#CSharp_exceptions">C# Exceptions</a>
  22<ul>
  23<li><a href="#CSharp_exception_example_check_typemap">C# exception example using "check" typemap</a>
  24<li><a href="#CSharp_exception_example_percent_exception">C# exception example using %exception</a>
  25<li><a href="#CSharp_exception_example_exception_specifications">C# exception example using exception specifications</a>
  26<li><a href="#CSharp_custom_application_exception">Custom C# ApplicationException example</a>
  27</ul>
  28<li><a href="#CSharp_directors">C# Directors</a>
  29<ul>
  30<li><a href="#CSharp_directors_example">Directors example</a>
  31<li><a href="#CSharp_directors_implementation">Directors implementation</a>
  32<li><a href="#CSharp_director_caveats">Director caveats</a>
  33</ul>
  34<li><a href="#CSharp_multiple_modules">Multiples modules</a>
  35<li><a href="#CSharp_typemap_examples">C# Typemap examples</a>
  36<ul>
  37<li><a href="#CSharp_memory_management_member_variables">Memory management when returning references to member variables</a>
  38<li><a href="#CSharp_memory_management_objects">Memory management for objects passed to the C++ layer</a>
  39<li><a href="#CSharp_date_marshalling">Date marshalling using the csin typemap and associated attributes</a>
  40<li><a href="#CSharp_date_properties">A date example demonstrating marshalling of C# properties</a>
  41<li><a href="#CSharp_partial_classes">Turning wrapped classes into partial classes</a>
  42<li><a href="#CSharp_extending_proxy_class">Extending proxy classes with additional C# code</a>
  43<li><a href="#CSharp_enum_underlying_type">Underlying type for enums</a>
  44</ul>
  45</ul>
  46</div>
  47<!-- INDEX -->
  48
  49
  50
  51<H2><a name="CSharp_introduction"></a>19.1 Introduction</H2>
  52
  53
  54<p>
  55The purpose of the C# module is to offer an automated way of accessing existing C/C++ code from .NET languages.
  56The wrapper code implementation uses C# and the Platform Invoke (PInvoke) interface to access natively compiled C/C++ code.
  57The PInvoke interface has been chosen over Microsoft's Managed C++ interface as it is portable to both Microsoft Windows and non-Microsoft platforms.
  58PInvoke is part of the ECMA/ISO C# specification.
  59It is also better suited for robust production environments due to the Managed C++ flaw called the
  60<a href="http://msdn.microsoft.com/en-us/library/aa290048(VS.71).aspx">Mixed DLL Loading Problem</a>.
  61SWIG C# works equally well on non-Microsoft operating systems such as Linux, Solaris and Apple Mac using
  62<a href="http://www.mono-project.com/Main_Page">Mono</a> and <a href="http://www.dotgnu.org/pnet.html">Portable.NET</a>.
  63</p>
  64
  65<p>
  66To get the most out of this chapter an understanding of interop is required.
  67The <a href="http://msdn.microsoft.com">Microsoft Developer Network (MSDN)</a> has a good reference guide in a section titled "Interop Marshaling".
  68Monodoc, available from the Mono project, has a very useful section titled <a href="http://www.mono-project.com/Interop_with_Native_Libraries">Interop with native libraries</a>.
  69</p>
  70
  71<H2><a name="CSharp_differences_java"></a>19.2 Differences to the Java module</H2>
  72
  73
  74<p>
  75The C# module is very similar to the Java module, so until some more complete documentation has been written,
  76please use the <a href="Java.html#Java">Java documentation</a> as a guide to using SWIG with C#.
  77The C# module has the same major SWIG features as the Java module.
  78The rest of this section should be read in conjunction with the Java documentation as it lists the main differences.
  79
  80The most notable differences to Java are the following:
  81<ul>
  82
  83<li>
  84When invoking SWIG use the <tt>-csharp</tt> command line option instead of <tt>-java</tt>.
  85</li>
  86
  87<li>
  88The <tt>-nopgcpp</tt> command line option does not exist.
  89</li>
  90
  91<li>
  92The <tt>-package</tt> command line option does not exist.
  93</li>
  94
  95<li>
  96The <tt>-namespace &lt;name&gt;</tt> commandline option will generate all code into the namespace specified by <tt>&lt;name&gt;</tt>.
  97C# supports nested namespaces that are not lexically nested, so nested namespaces will of course also work. For example:
  98<tt>-namespace com.bloggs.widget</tt>, will generate code into C# namespaces:
  99
 100<div class="code"><pre>
 101namespace com.bloggs.widget {
 102  ...
 103}
 104</pre></div>
 105Note that by default, the generated C# classes have no namespace and the module name is unrelated to namespaces. The module name is just like in Java and is merely used to name some of the generated classes.
 106</li>
 107
 108<li>
 109The <a href="SWIGPlus.html#SWIGPlus_nspace">nspace feature</a> is also supported as described in this general section with a C# example.
 110Unlike Java which requires the use of the -package option when using the <tt>nspace</tt> feature, the -namespace option is not mandatory for C#.
 111</li>
 112
 113<li>
 114The <tt>-dllimport &lt;name&gt;</tt> commandline option specifies the name of the DLL for the <tt>DllImport</tt> attribute for every PInvoke method. If this commandline option is not given, the <tt>DllImport</tt> DLL name is the same as the module name. This option is useful for when one wants to invoke SWIG multiple times on different modules, yet compile all the resulting code into a single DLL.
 115</li>
 116
 117<li>
 118C/C++ variables are wrapped with C# properties and not JavaBean style getters and setters.
 119</li>
 120
 121<li>
 122Global constants are generated into the module class. There is no constants interface.
 123</li>
 124
 125<li>
 126There is no implementation for type unsafe enums - not deemed necessary.
 127</li>
 128
 129<li>
 130The default enum wrapping approach is proper C# enums, not typesafe enums.
 131<br>
 132Note that %csconst(0) will be ignored when wrapping C/C++ enums with proper C# enums.
 133This is because C# enum items must be initialised from a compile time constant.
 134If an enum item has an initialiser and the initialiser doesn't compile as C# code,
 135then the %csconstvalue directive must be used as %csconst(0) will have no effect.
 136If it was used, it would generate an illegal runtime initialisation via a PInvoke call.
 137</li>
 138
 139<li>
 140C# doesn't support the notion of throws clauses.
 141Therefore there is no 'throws' typemap attribute support for adding exception classes to a throws clause.
 142Likewise there is no need for an equivalent to <tt>%javaexception</tt>.
 143In fact, throwing C# exceptions works quite differently, see <a href="CSharp.html#CSharp_exceptions">C# Exceptions</a> below.
 144</li>
 145
 146<li>
 147The majority of the typemaps are in csharp.swg, not java.swg.
 148</li>
 149
 150<li>
 151<p>Typemap equivalent names:</p>
 152
 153<div class="code"><pre>
 154jni                         -&gt; ctype
 155jtype                       -&gt; imtype
 156jstype                      -&gt; cstype
 157javain                      -&gt; csin
 158javaout                     -&gt; csout
 159javadirectorin              -&gt; csdirectorin
 160javadirectorout             -&gt; csdirectorout
 161javainterfaces              -&gt; csinterfaces and csinterfaces_derived
 162javabase                    -&gt; csbase
 163javaclassmodifiers          -&gt; csclassmodifiers
 164javacode                    -&gt; cscode
 165javaimports                 -&gt; csimports
 166javabody                    -&gt; csbody
 167javafinalize                -&gt; csfinalize
 168javadestruct                -&gt; csdestruct
 169javadestruct_derived        -&gt; csdestruct_derived
 170</pre></div>
 171
 172</li>
 173
 174<li>
 175<p>Typemap macros:</p>
 176<div class="code"><pre>
 177SWIG_JAVABODY_PROXY         -&gt; SWIG_CSBODY_PROXY
 178SWIG_JAVABODY_TYPEWRAPPER   -&gt; SWIG_CSBODY_TYPEWRAPPER
 179</pre></div>
 180</li>
 181
 182<li>
 183<p>Additional typemaps:</p>
 184
 185<div class="code"><pre>
 186csvarin                     C# code property set typemap
 187csvarout                    C# code property get typemap
 188csattributes                C# attributes for attaching to proxy classes/enums
 189</pre></div>
 190
 191</li>
 192
 193<li>
 194<p>Feature equivalent names:</p>
 195<div class="code"><pre>
 196%javaconst                  -&gt; %csconst
 197%javaconstvalue             -&gt; %csconstvalue
 198%javamethodmodifiers        -&gt; %csmethodmodifiers
 199</pre></div>
 200</li>
 201
 202<li>
 203<p>Pragma equivalent names:</p>
 204<div class="code"><pre>
 205%pragma(java)               -&gt; %pragma(csharp)
 206jniclassbase                -&gt; imclassbase
 207jniclassclassmodifiers      -&gt; imclassclassmodifiers
 208jniclasscode                -&gt; imclasscode
 209jniclassimports             -&gt; imclassimports
 210jniclassinterfaces          -&gt; imclassinterfaces
 211</pre></div>
 212</li>
 213
 214<li>
 215<p>Special variable equivalent names:</p>
 216<div class="code"><pre>
 217$javaclassname              -&gt; $csclassname
 218$&amp;javaclassname             -&gt; $&amp;csclassname
 219$*javaclassname             -&gt; $*csclassname
 220$javaclazzname              -&gt; $csclazzname
 221$javainput                  -&gt; $csinput
 222$jnicall                    -&gt; $imcall
 223</pre></div>
 224</li>
 225
 226<li>
 227<p>
 228Unlike 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. 
 229The "csin" typemap supports additional optional attributes called 'cshin' and 'terminator'. 
 230The '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. 
 231The '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.
 232Note that 'pre', 'post', 'terminator' and 'cshin' attributes are not used for marshalling the property set.
 233Please see the <a href="#CSharp_date_marshalling">Date marshalling example</a> and <a href="#CSharp_date_properties">Date marshalling of properties example</a> for further understanding of these "csin" applicable attributes.
 234</p>
 235</li>
 236
 237<li>
 238<p>
 239Support for asymmetric type marshalling. The 'ctype', 'imtype' and 'cstype' typemaps support an optional <tt>out</tt> attribute which is used for output types.
 240If this typemap attribute is specified, then the type specified in the attribute is used for output types and
 241the type specified in the typemap itself is used for the input type.
 242If this typemap attribute is not specified, then the type used for both input and output is the type specified in the typemap.
 243An example shows that <tt>char *</tt> could be marshalled in different ways, 
 244</p>
 245
 246<div class="code">
 247<pre>
 248%typemap(imtype, out="IntPtr") char * "string"
 249char * function(char *);
 250</pre>
 251</div>
 252
 253<p>
 254The output type is thus IntPtr and the input type is string. The resulting intermediary C# code is:
 255</p>
 256
 257<div class="code">
 258<pre>
 259public static extern IntPtr function(string jarg1);
 260</pre>
 261</div>
 262
 263</li>
 264
 265<li>
 266<p>
 267Support for type attributes.
 268The 'imtype' and 'cstype' typemaps can have an optional <tt>inattributes</tt> and <tt>outattributes</tt> typemap attribute.
 269The 'imtype' typemap can also have an optional <tt>directorinattributes</tt> and <tt>directoroutattributes</tt>
 270typemap attribute which attaches to director delegates, an implementation detail of directors, see <a href="#CSharp_directors_implementation">directors implementation</a>.
 271Note that there are C# attributes and typemap attributes, don't get confused between the two!!
 272The C# attributes specified in these typemap attributes are generated wherever the type is used in the C# wrappers.
 273These can be used to specify any C# attribute associated with a C/C++ type, but are more typically used for the C# <tt>MarshalAs</tt> attribute.
 274For example:
 275</p>
 276
 277<div class="code">
 278<pre>
 279%typemap(imtype,
 280         inattributes="[MarshalAs(UnmanagedType.LPStr)]",
 281         outattributes="[return: MarshalAs(UnmanagedType.LPStr)]") const char * "String"
 282
 283const char * GetMsg() {}
 284void SetMsg(const char *msg) {}
 285</pre>
 286</div>
 287
 288<p>
 289The intermediary class will then have the marshalling as specified by everything in the 'imtype' typemap:
 290</p>
 291
 292<div class="code">
 293<pre>
 294class examplePINVOKE {
 295  ...
 296  [DllImport("example", EntryPoint="CSharp_GetMsg")]
 297  [return: MarshalAs(UnmanagedType.LPStr)]
 298  public static extern String GetMsg();
 299
 300  [DllImport("example", EntryPoint="CSharp_SetMsg")]
 301  public static extern void SetMsg([MarshalAs(UnmanagedType.LPStr)]String jarg1);
 302}
 303</pre>
 304</div>
 305
 306<p>
 307Note that the <tt>DllImport</tt> attribute is always generated, irrespective of any additional attributes specified.
 308</p>
 309
 310<p>
 311These attributes are associated with the C/C++ parameter type or return type, which is subtly different to 
 312the attribute features and typemaps covered next.
 313Note that all these different C# attributes can be combined so that a method has more than one attribute.
 314</p>
 315
 316<p>
 317The <tt>directorinattributes</tt> and <tt>directoroutattributes</tt> typemap attribute are attached to the delegates in the director class, for example, the SwigDelegateBase_0
 318</p>
 319
 320</li>
 321
 322<li>
 323<p>
 324Support for attaching C# attributes to wrapped methods, variables and enum values.
 325This is done using the <tt>%csattributes</tt> feature, see <a href="Customization.html#Customization_features">%feature directives</a>.
 326Note that C# attributes are attached to proxy classes and enums using the <tt>csattributes</tt> typemap.
 327For example, imagine we have a custom attribute class, <tt>ThreadSafeAttribute</tt>, for labelling thread safety.
 328The following SWIG code shows how to attach this C# attribute to some methods and the class declaration itself:
 329</p>
 330
 331<div class="code">
 332<pre>
 333%typemap(csattributes) AClass          "[ThreadSafe]"
 334%csattributes AClass::AClass(double d) "[ThreadSafe(false)]"
 335%csattributes AClass::AMethod()        "[ThreadSafe(true)]"
 336
 337%inline %{
 338class AClass {
 339public:
 340  AClass(double a) {}
 341  void AMethod() {}
 342};
 343%}
 344</pre>
 345</div>
 346
 347<p>
 348will generate a C# proxy class:
 349</p>
 350
 351<div class="code">
 352<pre>
 353[ThreadSafe]
 354public class AClass : IDisposable {
 355  ...
 356  [ThreadSafe(false)]
 357  public AClass(double a) ...
 358
 359  [ThreadSafe(true)]
 360  public void AMethod() ...
 361}
 362</pre>
 363</div>
 364
 365<p>
 366If C# attributes need adding to the <tt>set</tt> or <tt>get</tt> part of C# properties, when wrapping C/C++ variables,
 367they can be added using the 'csvarin' and 'csvarout' typemaps respectively.
 368Note that the type used for the property is specified in the 'cstype' typemap.
 369If the 'out' attribute exists in this typemap, then the type used is from the 'out' attribute.
 370</p>
 371
 372<p>
 373An example for attaching attributes to the enum and enum values is shown below.
 374</p>
 375
 376<div class="code">
 377<pre>
 378%typemap(csattributes) Couleur "[System.ComponentModel.Description(\"Colours\")]"
 379%csattributes Rouge "[System.ComponentModel.Description(\"Red\")]"
 380%csattributes Vert "[System.ComponentModel.Description(\"Green\")]"
 381%inline %{
 382  enum Couleur { Rouge, Orange, Vert };
 383%}
 384</pre>
 385</div>
 386
 387<p>
 388which will result in the following C# enum:
 389</p>
 390
 391<div class="code">
 392<pre>
 393[System.ComponentModel.Description("Colours")]
 394public enum Couleur {
 395  [System.ComponentModel.Description("Red")]
 396  Rouge,
 397  Orange,
 398  [System.ComponentModel.Description("Green")]
 399  Vert
 400}
 401</pre>
 402</div>
 403</li>
 404
 405<li>
 406<p>
 407The intermediary classname has <tt>PINVOKE</tt> appended after the module name instead of <tt>JNI</tt>, for example <tt>modulenamePINVOKE</tt>.
 408</p>
 409</li>
 410
 411<li>
 412<p>
 413The <tt>%csmethodmodifiers</tt> feature can also be applied to variables as well as methods.
 414In addition to the default <tt>public</tt> modifier that SWIG generates when <tt>%csmethodmodifiers</tt> is not
 415specified, the feature will also replace the <tt>virtual</tt>/<tt>new</tt>/<tt>override</tt> modifiers that SWIG thinks is appropriate.
 416This feature is useful for some obscure cases where SWIG might get the <tt>virtual</tt>/<tt>new</tt>/<tt>override</tt> modifiers incorrect, for example with multiple inheritance.
 417</p>
 418</li>
 419
 420<li>
 421<a name="CSharp_module_directive"></a>
 422<p>
 423The name of the intermediary class can be changed from its default, that is, the module name with PINVOKE appended after it. 
 424The module directive attribute <tt>imclassname</tt> is used to achieve this:
 425</p>
 426
 427<div class="code">
 428<pre>
 429%module (imclassname="name") modulename
 430</pre>
 431</div>
 432
 433<p>
 434If <tt>name</tt> is the same as <tt>modulename</tt> then the module class name gets changed
 435from <tt>modulename</tt> to <tt>modulenameModule</tt>.
 436</p>
 437</li>
 438
 439<li>
 440There is no additional 'premature garbage collection prevention parameter' as the marshalling of the <tt>HandleRef</tt> object
 441takes care of ensuring a reference to the proxy class is held until the unmanaged call completed.
 442</li>
 443
 444</ul>
 445
 446<p>
 447<b><tt>$dllimport</tt></b><br>
 448This is a C# only special variable that can be used in typemaps, pragmas, features etc.
 449The special variable will get translated into the value specified by the <tt>-dllimport</tt> commandline option
 450if specified, otherwise it is equivalent to the <b>$module</b> special variable.
 451</p>
 452
 453<p>
 454<b><tt>$imclassname</tt></b><br>
 455This special variable expands to the intermediary class name. For C# this is usually the same as '$modulePINVOKE' ('$moduleJNI' for Java),
 456unless the imclassname attribute is specified in the <a href="CSharp.html#CSharp_module_directive">%module directive</a>.
 457</p>
 458
 459<p>
 460The directory <tt>Examples/csharp</tt> has a number of simple examples. 
 461Visual Studio .NET 2003 solution and project files are available for compiling with the Microsoft .NET C# compiler on Windows.
 462If your SWIG installation went well on a Unix environment and your C# compiler was detected, you should be able to type <tt>make</tt> in each example directory, 
 463then <tt>ilrun runme.exe</tt> (Portable.NET C# compiler) or <tt>mono runme.exe</tt> (Mono C# compiler) to run the examples.
 464Windows users can also get the examples working using a
 465<a href="http://www.cygwin.com">Cygwin</a> or <a href="http://www.mingw.org">MinGW</a> environment for automatic configuration of the example makefiles.
 466Any one of the three C# compilers (Portable.NET, Mono or Microsoft) can be detected from within a Cygwin or Mingw environment if installed in your path. 
 467
 468<H2><a name="CSharp_void_pointers"></a>19.3 Void pointers</H2>
 469
 470
 471<p>
 472By default SWIG treats <tt>void *</tt> as any other pointer and hence marshalls it as a type wrapper class called <tt>SWIGTYPE_p_void</tt>.
 473If you want to marshall with the .NET <tt>System.IntPtr</tt> type instead, there is a simple set of named typemaps called
 474<tt>void *VOID_INT_PTR</tt> that can be used.
 475They can be applied like any other named typemaps:
 476</p>
 477
 478
 479<div class="code">
 480<pre>
 481%apply void *VOID_INT_PTR { void * }
 482void * f(void *v);
 483</pre>
 484</div>
 485
 486<H2><a name="CSharp_arrays"></a>19.4 C# Arrays</H2>
 487
 488
 489<p>
 490There are various ways to pass arrays from C# to C/C++. 
 491The default wrapping treats arrays as pointers and as such simple type wrapper classes are generated, 
 492eg <tt>SWIGTYPE_p_int</tt> when wrapping the C type <tt>int []</tt> or <tt>int *</tt>.
 493This gives a rather restricted use of the underlying unmanaged code and the most practical way to use arrays is to enhance or customise
 494with one of the following three approaches; namely the SWIG C arrays library, P/Invoke default array marshalling or 
 495pinned arrays.
 496</p>
 497
 498<H3><a name="CSharp_arrays_swig_library"></a>19.4.1 The SWIG C arrays library</H3>
 499
 500
 501<p>
 502The C arrays library keeps all the array memory in the unmanaged layer.
 503The library is available to all language modules and is documented in the <a href="Library.html#Library_carrays">carrays.i library</a> section.
 504Please refer to this section for details, but for convenience, the C# usage for the two examples outlined there is shown below.
 505</p>
 506
 507<p>
 508For the <tt>%array_functions</tt> example, the equivalent usage would be:
 509</p>
 510
 511<div class="code">
 512<pre>
 513SWIGTYPE_p_double a = example.new_doubleArray(10);  // Create an array
 514for (int i=0; i&lt;10; i++)
 515  example.doubleArray_setitem(a,i,2*i);             // Set a value
 516example.print_array(a);                             // Pass to C
 517example.delete_doubleArray(a);                      // Destroy array
 518</pre>
 519</div>
 520
 521<p>
 522and for the <tt>%array_class</tt> example, the equivalent usage would be:
 523</p>
 524
 525<div class="code">
 526<pre>
 527doubleArray c = new doubleArray(10);    // Create double[10]
 528for (int i=0; i&lt;10; i++)
 529  c.setitem(i, 2*i);                    // Assign values
 530example.print_array(c.cast());          // Pass to C
 531</pre>
 532</div>
 533
 534
 535<H3><a name="CSharp_arrays_pinvoke_default_array_marshalling"></a>19.4.2 Managed arrays using P/Invoke default array marshalling</H3>
 536
 537
 538<p>
 539In the P/Invoke default marshalling scheme, one needs to designate whether the invoked function will treat a managed
 540array parameter as input, output, or both. When the function is invoked, the CLR allocates a separate chunk of memory as big as the given managed array, 
 541which is automatically released at the end of the function call. If the array parameter is marked as being input, the content of the managed array is copied
 542into this buffer when the call is made. Correspondingly, if the array parameter is marked as being output, the contents of the reserved buffer are copied
 543back into the managed array after the call returns. A pointer to this buffer
 544is passed to the native function.
 545</p>
 546
 547<p>
 548The reason for allocating a separate buffer is to leave the CLR free to relocate the managed array object 
 549during garbage collection. If the overhead caused by the copying is causing a significant performance penalty, consider pinning the managed array and
 550passing a direct reference as described in the next section.
 551</p>
 552
 553<p>
 554For more information on the subject, see  the
 555<a href="http://msdn.microsoft.com/en-us/library/z6cfh6e6(VS.80).aspx">Default Marshaling for Arrays</a> article
 556on MSDN.
 557</p>
 558
 559
 560<p>
 561The P/Invoke default marshalling is supported by the <tt>arrays_csharp.i</tt> library via the INPUT, OUTPUT and INOUT typemaps. 
 562Let's look at some example usage. Consider the following C function:
 563</p>
 564<div class="code">
 565<pre>
 566void myArrayCopy(int *sourceArray, int *targetArray, int nitems);
 567</pre>
 568</div>
 569
 570<p>
 571We can now instruct SWIG to use the default marshalling typemaps by 
 572</p>
 573
 574<div class="code">
 575<pre>
 576%include "arrays_csharp.i"
 577
 578%apply int INPUT[]  {int *sourceArray}
 579%apply int OUTPUT[] {int *targetArray}
 580</pre>
 581</div>
 582
 583<p>
 584As a result, we get the following method in the module class:
 585</p>
 586
 587<div class="code">
 588<pre>
 589public static void myArrayCopy(int[] sourceArray, int[] targetArray, int nitems) {
 590    examplePINVOKE.myArrayCopy(sourceArray, targetArray, nitems);
 591}
 592</pre>
 593</div>
 594
 595<p>
 596If we look beneath the surface at the corresponding intermediary class code, we see
 597that SWIG has generated code that uses attributes 
 598(from the System.Runtime.InteropServices namespace) to tell the CLR to use default
 599marshalling for the arrays:
 600</p>
 601
 602<div class="code">
 603<pre>
 604[DllImport("example", EntryPoint="CSharp_myArrayCopy")]
 605public static extern void myArrayCopy([In, MarshalAs(UnmanagedType.LPArray)]int[] jarg1, 
 606                                      [Out, MarshalAs(UnmanagedType.LPArray)]int[] jarg2,
 607                                       int jarg3);
 608</pre>
 609</div>
 610
 611<p>
 612As an example of passing an inout array (i.e. the target function will both read from and
 613write to the array), consider this C function that swaps a given number of elements
 614in the given arrays:
 615</p>
 616
 617<div class="code">
 618<pre>
 619void myArraySwap(int *array1, int *array2, int nitems);
 620</pre>
 621</div>
 622
 623<p>
 624Now, we can instruct SWIG to wrap this by
 625</p>
 626
 627<div class="code">
 628<pre>
 629%include "arrays_csharp.i"
 630
 631%apply int INOUT[] {int *array1}
 632%apply int INOUT[] {int *array2}
 633</pre>
 634</div>
 635
 636<p>
 637This results in the module class method
 638</p>
 639
 640<div class="code">
 641<pre>
 642  public static void myArraySwap(int[] array1, int[] array2, int nitems) {
 643    examplePINVOKE.myArraySwap(array1, array2, nitems);
 644  }
 645</pre>
 646</div>
 647
 648<p>
 649and intermediary class method
 650</p>
 651
 652<div class="code">
 653<pre>
 654  [DllImport("example", EntryPoint="CSharp_myArraySwap")]
 655  public static extern void myArraySwap([In, Out, MarshalAs(UnmanagedType.LPArray)]int[] jarg1, 
 656                                        [In, Out, MarshalAs(UnmanagedType.LPArray)]int[] jarg2,
 657                                         int jarg3);
 658</pre>
 659</div>
 660
 661
 662<H3><a name="CSharp_arrays_pinning"></a>19.4.3 Managed arrays using pinning</H3>
 663
 664
 665<p>
 666It is also possible to pin a given array in memory (i.e. fix its location in memory), obtain a
 667direct pointer to it, and then pass this pointer to the wrapped C/C++ function. This approach
 668involves no copying, but it makes the work of the garbage collector harder as 
 669the managed array object can not be relocated before the fix on the array is released. You should avoid 
 670fixing arrays in memory in cases where the control may re-enter the managed side via a callback and/or
 671another thread may produce enough garbage to trigger garbage collection.
 672</p>
 673
 674<p>
 675For more information, see the <a href="http://msdn.microsoft.com/en-us/library/f58wzh21(VS.80).aspx">fixed statement</a> in the C# language reference.
 676</p>
 677
 678
 679<p>
 680Now let's look at an example using pinning, thus avoiding the CLR making copies
 681of the arrays passed as parameters. The <tt>arrays_csharp.i</tt> library file again provides the required support via the <tt>FIXED</tt> typemaps.
 682Let's use the same function from the previous section:
 683</p>
 684
 685<div class="code">
 686<pre>
 687void myArrayCopy(int *sourceArray, int *targetArray, int nitems);
 688</pre>
 689</div>
 690
 691<p>
 692We now need to declare the module class method unsafe, as we are using pointers:
 693</p>
 694
 695<div class="code">
 696<pre>
 697%csmethodmodifiers myArrayCopy "public unsafe";
 698 </pre>
 699</div>
 700
 701<p>
 702Apply the appropriate typemaps to the array parameters:
 703</p>
 704
 705<div class="code">
 706<pre>
 707%include "arrays_csharp.i"
 708
 709%apply int FIXED[] {int *sourceArray}
 710%apply int FIXED[] {int *targetArray}
 711</pre>
 712</div>
 713
 714<p>
 715Notice that there is no need for separate in, out or inout typemaps as is the
 716case when using P/Invoke default marshalling. 
 717</p>
 718
 719<p>
 720As a result, we get the following method in the module class:
 721</p>
 722
 723<div class="code">
 724<pre>
 725  public unsafe static void myArrayCopy(int[] sourceArray, int[] targetArray, int nitems) {
 726    fixed ( int *swig_ptrTo_sourceArray = sourceArray ) {
 727    fixed ( int *swig_ptrTo_targetArray = targetArray ) {
 728    {
 729      examplePINVOKE.myArrayCopy((IntPtr)swig_ptrTo_sourceArray, (IntPtr)swig_ptrTo_targetArray,
 730                                 nitems);
 731    }
 732    }
 733    }
 734  }
 735</pre>
 736</div>
 737
 738<p>
 739On the method signature level the only difference to the version using P/Invoke default
 740marshalling is the "unsafe" quantifier, which is required because we are handling pointers.
 741</p>
 742
 743<p>
 744Also the intermediary class method looks a little different from the default marshalling
 745example - the method is expecting an IntPtr as the parameter type.
 746</p>
 747
 748<div class="code">
 749<pre>
 750[DllImport("example", EntryPoint="CSharp_myArrayCopy")]
 751public static extern void myArrayCopy(IntPtr jarg1, IntPtr jarg2, int jarg3);
 752</pre>
 753</div>
 754
 755
 756
 757<H2><a name="CSharp_exceptions"></a>19.5 C# Exceptions</H2>
 758
 759
 760<p>
 761It is possible to throw a C# Exception from C/C++ code.
 762SWIG already provides the framework for throwing C# exceptions if it is able to detect that a C++ exception could be thrown.
 763Automatically detecting that a C++ exception could be thrown is only possible when a C++ exception specification is used,
 764see <a href="SWIGPlus.html#SWIGPlus_exception_specifications">Exception specifications</a>. 
 765The <a href="Customization.html#Customization_exception">Exception handling with %exception</a> section details the <tt>%exception</tt> feature.
 766Customised code for handling exceptions with or without a C++ exception specification is possible and the details follow.
 767However anyone wishing to do this should be familiar with the contents of the sections referred to above.
 768</p>
 769
 770<p>
 771Unfortunately a C# exception cannot simply be thrown from unmanaged code for a variety of reasons.
 772Most notably being that throwing a C# exception results in exceptions being thrown across the C PInvoke interface and C does not understand exceptions.
 773The design revolves around a C# exception being constructed and stored as a pending exception, to be thrown only when the unmanaged code has completed.
 774Implementing this is a tad involved and there are thus some unusual typemap constructs.
 775Some practical examples follow and they should be read in conjunction with the rest of this section.
 776</p>
 777
 778<p>
 779First some details about the design that must be followed.
 780Each typemap or feature that generates <b>unmanaged code</b> supports an attribute called <tt>canthrow</tt>.
 781This is simply a flag which when set indicates that the code in the typemap/feature has code which might want to throw a C# exception.
 782The code in the typemap/feature can then raise a C# exception by calling one of the C functions,
 783<tt>SWIG_CSharpSetPendingException()</tt> or <tt>SWIG_CSharpSetPendingExceptionArgument()</tt>.
 784When called, the function makes a callback into the managed world via a delegate.
 785The callback creates and stores an exception ready for throwing when the unmanaged code has finished.
 786The typemap/feature unmanaged code is then expected to force an immediate return from the unmanaged wrapper function,
 787so that the pending managed exception can then be thrown.
 788The support code has been carefully designed to be efficient as well as thread-safe.
 789However to achieve the goal of efficiency requires some optional code generation in the <b>managed code</b> typemaps.
 790Code to check for pending exceptions is generated if and only if the unmanaged code has code to set a pending exception,
 791that is if the <tt>canthrow</tt> attribute is set.
 792The optional managed code is generated using the <tt>excode</tt> typemap attribute and <tt>$excode</tt> special variable in the relevant managed code typemaps.
 793Simply, if any relevant unmanaged code has the <tt>canthrow</tt> attribute set, then any occurrences of <tt>$excode</tt>
 794is replaced with the code in the <tt>excode</tt> attribute.
 795If the <tt>canthrow</tt> attribute is not set, then any occurrences of <tt>$excode</tt> are replaced with nothing.
 796</p>
 797
 798<p>
 799The prototypes for the <tt>SWIG_CSharpSetPendingException()</tt> and <tt>SWIG_CSharpSetPendingExceptionArgument()</tt> functions are
 800</p>
 801
 802<div class="code">
 803<pre>
 804static void SWIG_CSharpSetPendingException(SWIG_CSharpExceptionCodes code,
 805                                           const char *msg);
 806
 807static void SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpExceptionArgumentCodes code,
 808                                                   const char *msg,
 809                                                   const char *param_name);
 810</pre>
 811</div>
 812
 813<p>
 814The first parameter defines which .NET exceptions can be thrown:
 815</p>
 816
 817<div class="code">
 818<pre>
 819typedef enum {
 820  SWIG_CSharpApplicationException,
 821  SWIG_CSharpArithmeticException,
 822  SWIG_CSharpDivideByZeroException,
 823  SWIG_CSharpIndexOutOfRangeException,
 824  SWIG_CSharpInvalidCastException,
 825  SWIG_CSharpInvalidOperationException,
 826  SWIG_CSharpIOException,
 827  SWIG_CSharpNullReferenceException,
 828  SWIG_CSharpOutOfMemoryException,
 829  SWIG_CSharpOverflowException,
 830  SWIG_CSharpSystemException
 831} SWIG_CSharpExceptionCodes;
 832
 833typedef enum {
 834  SWIG_CSharpArgumentException,
 835  SWIG_CSharpArgumentNullException,
 836  SWIG_CSharpArgumentOutOfRangeException,
 837} SWIG_CSharpExceptionArgumentCodes;
 838</pre>
 839</div>
 840
 841<p>
 842where, for example, <tt>SWIG_CSharpApplicationException</tt> corresponds to the .NET exception, <tt>ApplicationException</tt>.
 843The <tt>msg</tt> and <tt>param_name</tt> parameters contain the C# exception message and parameter name associated with the exception.
 844</p>
 845
 846
 847<p>
 848The <tt>%exception</tt> feature in C# has the <tt>canthrow</tt> attribute set.
 849The <tt>%csnothrowexception</tt> feature is like <tt>%exception</tt>, but it does not have the <tt>canthrow</tt> attribute
 850set so should only be used when a C# exception is not created.
 851</p>
 852
 853
 854<H3><a name="CSharp_exception_example_check_typemap"></a>19.5.1 C# exception example using "check" typemap</H3>
 855
 856
 857<p>
 858Lets say we have the following simple C++ method:
 859</p>
 860
 861
 862<div class="code">
 863<pre>
 864void positivesonly(int number);
 865</pre>
 866</div>
 867
 868<p>
 869and we want to check that the input <tt>number</tt> is always positive and if not throw a C# <tt>ArgumentOutOfRangeException</tt>.
 870The "check" typemap is designed for checking input parameters. Below you will see the <tt>canthrow</tt> attribute is set because
 871the code contains a call to <tt>SWIG_CSharpSetPendingExceptionArgument()</tt>. The full example follows:
 872</p>
 873
 874<div class="code">
 875<pre>
 876%module example
 877
 878%typemap(check, canthrow=1) int number %{
 879if ($1 &lt; 0) {
 880  SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentOutOfRangeException,
 881                                         "only positive numbers accepted", "number");
 882  return $null;
 883}
 884// SWIGEXCODE is a macro used by many other csout typemaps
 885%define SWIGEXCODE
 886 "\n    if ($modulePINVOKE.SWIGPendingException.Pending)"
 887 "\n      throw $modulePINVOKE.SWIGPendingException.Retrieve();"
 888%enddef
 889%typemap(csout, excode=SWIGEXCODE) void {
 890    $imcall;$excode
 891  }
 892%}
 893
 894%inline %{
 895
 896void positivesonly(int number) {
 897}
 898
 899%}
 900</pre>
 901</div>
 902
 903<p>
 904When the following C# code is executed:
 905</p>
 906
 907<div class="code">
 908<pre>
 909public class runme {
 910    static void Main() {
 911      example.positivesonly(-1);
 912    }
 913}
 914</pre>
 915</div>
 916
 917<p>
 918The exception is thrown:
 919</p>
 920
 921<div class="code">
 922<pre>
 923Unhandled Exception: System.ArgumentOutOfRangeException: only positive numbers accepted
 924Parameter name: number
 925in &lt;0x00034&gt; example:positivesonly (int)
 926in &lt;0x0000c&gt; runme:Main ()
 927</pre>
 928</div>
 929
 930<p>
 931Now let's analyse the generated code to gain a fuller understanding of the typemaps. The generated unmanaged C++ code is:
 932</p>
 933
 934
 935<div class="code">
 936<pre>
 937SWIGEXPORT void SWIGSTDCALL CSharp_positivesonly(int jarg1) {
 938    int arg1 ;
 939    
 940    arg1 = (int)jarg1; 
 941    
 942    if (arg1 &lt; 0) {
 943        SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentOutOfRangeException,
 944                                               "only positive numbers accepted", "number");
 945        return ;
 946    }
 947    
 948    positivesonly(arg1);
 949    
 950}
 951</pre>
 952</div>
 953
 954<p>
 955This largely comes from the "check" typemap. The managed code in the module class is:
 956</p>
 957
 958<div class="code">
 959<pre>
 960public class example {
 961  public static void positivesonly(int number) {
 962    examplePINVOKE.positivesonly(number);
 963    if (examplePINVOKE.SWIGPendingException.Pending)
 964      throw examplePINVOKE.SWIGPendingException.Retrieve();
 965  }
 966
 967}
 968</pre>
 969</div>
 970
 971<p>
 972This comes largely from the "csout" typemap. 
 973</p>
 974
 975<p>
 976The "csout" typemap is the same as the default void "csout" typemap so is not strictly necessary for the example.
 977However, it is shown to demonstrate what managed output code typemaps should contain,
 978that is, a <tt>$excode</tt> special variable and an <tt>excode</tt> attribute.
 979Also note that <tt>$excode</tt> is expanded into the code held in the <tt>excode</tt> attribute.
 980The <tt>$imcall</tt> as always expands into <tt>examplePINVOKE.positivesonly(number)</tt>.
 981The exception support code in the intermediary class, <tt>examplePINVOKE</tt>, is not shown, but is contained within the inner classes,
 982<tt>SWIGPendingException</tt> and <tt>SWIGExceptionHelper</tt> and is always generated.
 983These classes can be seen in any of the generated wrappers.
 984However, all that is required of a user is as demonstrated in the "csin" typemap above.
 985That is, is to check <tt>SWIGPendingException.Pending</tt> and to throw the exception returned by <tt>SWIGPendingException.Retrieve()</tt>.
 986</p>
 987
 988<p>
 989If the "check" typemap did not exist, then
 990the following module class would instead be generated:
 991</p>
 992
 993<div class="code">
 994<pre>
 995public class example {
 996  public static void positivesonly(int number) {
 997    examplePINVOKE.positivesonly(number);
 998  }
 999
1000}
1001</pre>
1002</div>
1003
1004<p>
1005Here we see the pending exception checking code is omitted.
1006In fact, the code above would be generated if the <tt>canthrow</tt> attribute was not in the "check" typemap, such as:
1007</p>
1008
1009<div class="code">
1010<pre>
1011%typemap(check) int number %{
1012if ($1 &lt; 0) {
1013  SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentOutOfRangeException,
1014                                         "only positive numbers accepted", "number");
1015  return $null;
1016}
1017%}
1018</pre>
1019</div>
1020
1021<p>
1022Note that if SWIG detects you have used <tt>SWIG_CSharpSetPendingException()</tt> or <tt>SWIG_CSharpSetPendingExceptionArgument()</tt>
1023without setting the <tt>canthrow</tt> attribute you will get a warning message similar to
1024</p>
1025
1026<div class="code">
1027<pre>
1028example.i:21: Warning 845: Unmanaged code contains a call to a SWIG_CSharpSetPendingException
1029method and C# code does not handle pending exceptions via the canthrow attribute.
1030</pre>
1031</div>
1032<p>
1033Actually it will issue this warning for any function beginning with <tt>SWIG_CSharpSetPendingException</tt>.
1034</P>
1035
1036<H3><a name="CSharp_exception_example_percent_exception"></a>19.5.2 C# exception example using %exception</H3>
1037
1038
1039<p>
1040Let's consider a similar, but more common example that throws a C++ exception from within a wrapped function.
1041We can use <tt>%exception</tt> as mentioned in <a href="Customization.html#Customization_exception">Exception handling with %exception</a>.
1042</p>
1043
1044<div class="code">
1045<pre>
1046%exception negativesonly(int value) %{
1047try {
1048  $action
1049} catch (std::out_of_range e) {
1050  SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, e.what());
1051}
1052%}
1053
1054%inline %{
1055#include &lt;stdexcept&gt;
1056void negativesonly(int value) {
1057  if (value &gt;= 0)
1058    throw std::out_of_range("number should be negative");
1059}
1060%}
1061</pre>
1062</div>
1063
1064<p>
1065The generated unmanaged code this time catches the C++ exception and converts it into a C# <tt>ApplicationException</tt>.
1066</p>
1067
1068<div class="code">
1069<pre>
1070SWIGEXPORT void SWIGSTDCALL CSharp_negativesonly(int jarg1) {
1071    int arg1 ;
1072    
1073    arg1 = (int)jarg1; 
1074    
1075    try {
1076        negativesonly(arg1);
1077        
1078    } catch (std::out_of_range e) {
1079        SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, e.what());
1080        return ;
1081    }
1082    
1083}
1084</pre>
1085</div>
1086
1087<p>
1088The managed code generated does check for the pending exception as mentioned earlier as the C# version of <tt>%exception</tt> has the <tt>canthrow</tt> attribute set by default:
1089</p>
1090
1091<div class="code">
1092<pre>
1093  public static void negativesonly(int value) {
1094    examplePINVOKE.negativesonly(value);
1095    if (examplePINVOKE.SWIGPendingException.Pending)
1096      throw examplePINVOKE.SWIGPendingException.Retrieve();
1097  }
1098</pre>
1099</div>
1100
1101<H3><a name="CSharp_exception_example_exception_specifications"></a>19.5.3 C# exception example using exception specifications</H3>
1102
1103
1104<p>
1105When C++ exception specifications are used, SWIG is able to detect that the method might throw an exception.
1106By default SWIG will automatically generate code to catch the exception and convert it into a managed <tt>ApplicationException</tt>,
1107as defined by the default "throws" typemaps.
1108The following example has a user supplied "throws" typemap which is used whenever an exception specification contains a <tt>std::out_of_range</tt>,
1109such as the <tt>evensonly</tt> method below.
1110</p>
1111
1112<div class="code">
1113<pre>
1114%typemap(throws, canthrow=1) std::out_of_range {
1115  SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentException, $1.what(), NULL);
1116  return $null;
1117}
1118
1119%inline %{
1120#include &lt;stdexcept&gt;
1121void evensonly(int input) throw (std::out_of_range) {
1122  if (input%2 != 0)
1123    throw std::out_of_range("number is not even");
1124}
1125%}
1126</pre>
1127</div>
1128
1129<p>
1130Note that the type for the throws typemap is the type in the exception specification.
1131SWIG generates a try catch block with the throws typemap code in the catch handler.
1132</p>
1133
1134<div class="code">
1135<pre>
1136SWIGEXPORT void SWIGSTDCALL CSharp_evensonly(int jarg1) {
1137    int arg1 ;
1138    
1139    arg1 = (int)jarg1; 
1140    try {
1141        evensonly(arg1);
1142    }
1143    catch(std::out_of_range &amp;_e) {
1144      {
1145          SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentException, (&amp;_e)-&gt;what(), NULL);
1146          return ;
1147      }
1148    }
1149    
1150}
1151</pre>
1152</div>
1153
1154<p>
1155Multiple catch handlers are generated should there be more than one exception specifications declared.
1156</p>
1157
1158<H3><a name="CSharp_custom_application_exception"></a>19.5.4 Custom C# ApplicationException example</H3>
1159
1160
1161<p>
1162This example involves a user defined exception.
1163The conventional .NET exception handling approach is to create a custom <tt>ApplicationException</tt> and throw it in your application.
1164The goal in this example is to convert the STL <tt>std::out_of_range</tt> exception into one of these custom .NET exceptions.
1165</p>
1166
1167
1168<p>
1169The default exception handling is quite easy to use as the <tt>SWIG_CSharpSetPendingException()</tt> and <tt>SWIG_CSharpSetPendingExceptionArgument()</tt>
1170methods are provided by SWIG.
1171However, for a custom C# exception, the boiler plate code that supports these functions needs replicating.
1172In essence this consists of some C/C++ code and C# code.
1173The C/C++ code can be generated into the wrapper file using the <tt>%insert(runtime)</tt> directive and
1174the C# code can be generated into the intermediary class using the <tt>imclasscode</tt> pragma as follows:
1175
1176</p>
1177
1178<div class="code">
1179<pre>
1180%insert(runtime) %{
1181  // Code to handle throwing of C# CustomApplicationException from C/C++ code.
1182  // The equivalent delegate to the callback, CSharpExceptionCallback_t, is CustomExceptionDelegate
1183  // and the equivalent customExceptionCallback instance is customDelegate
1184  typedef void (SWIGSTDCALL* CSharpExceptionCallback_t)(const char *);
1185  CSharpExceptionCallback_t customExceptionCallback = NULL;
1186
1187  extern "C" SWIGEXPORT
1188  void SWIGSTDCALL CustomExceptionRegisterCallback(CSharpExceptionCallback_t customCallback) {
1189    customExceptionCallback = customCallback;
1190  }
1191
1192  // Note that SWIG detects any method calls named starting with
1193  // SWIG_CSharpSetPendingException for warning 845
1194  static void SWIG_CSharpSetPendingExceptionCustom(const char *msg) {
1195    customExceptionCallback(msg);
1196  }
1197%}
1198
1199%pragma(csharp) imclasscode=%{
1200  class CustomExceptionHelper {
1201    // C# delegate for the C/C++ customExceptionCallback
1202    public delegate void CustomExceptionDelegate(string message);
1203    static CustomExceptionDelegate customDelegate =
1204                                   new CustomExceptionDelegate(SetPendingCustomException);
1205
1206    [DllImport("$dllimport", EntryPoint="CustomExceptionRegisterCallback")]
1207    public static extern
1208           void CustomExceptionRegisterCallback(CustomExceptionDelegate customCallback);
1209
1210    static void SetPendingCustomException(string message) {
1211      SWIGPendingException.Set(new CustomApplicationException(message));
1212    }
1213
1214    static CustomExceptionHelper() {
1215      CustomExceptionRegisterCallback(customDelegate);
1216    }
1217  }
1218  static CustomExceptionHelper exceptionHelper = new CustomExceptionHelper();
1219%}
1220</pre>
1221</div>
1222
1223<p>
1224The method stored in the C# delegate instance, <tt>customDelegate</tt> is what gets called by the C/C++ callback.
1225However, the equivalent to the C# delegate, that is the C/C++ callback, needs to be assigned before any unmanaged code is executed.
1226This is achieved by putting the initialisation code in the intermediary class.
1227Recall that the intermediary class contains all the PInvoke methods, so the static variables in the intermediary class will be initialised
1228before any of the PInvoke methods in this class are called.
1229The <tt>exceptionHelper</tt> static variable ensures the C/C++ callback is initialised with the value in <tt>customDelegate</tt> by calling
1230the <tt>CustomExceptionRegisterCallback</tt> method in the <tt>CustomExceptionHelper</tt> static constructor.
1231Once this has been done, unmanaged code can make callbacks into the managed world as <tt>customExceptionCallback</tt> will be initialised with a valid callback/delegate.
1232Any calls to <tt>SWIG_CSharpSetPendingExceptionCustom()</tt> will make the callback to create the pending exception in the same way that
1233<tt>SWIG_CSharpSetPendingException()</tt> and <tt>SWIG_CSharpSetPendingExceptionArgument()</tt> does.
1234In fact the method has been similarly named so that SWIG can issue the warning about missing <tt>canthrow</tt> attributes as discussed earlier.
1235It is an invaluable warning as it is easy to forget the <tt>canthrow</tt> attribute when writing typemaps/features.
1236</p>
1237
1238<p>
1239The <tt>SWIGPendingException</tt> helper class is not shown, but is generated as an inner class into the intermediary class.
1240It stores the pending exception in Thread Local Storage so that the exception handling mechanism is thread safe.
1241</p>
1242
1243<p>
1244The boiler plate code above must be used in addition to a handcrafted <tt>CustomApplicationException</tt>:
1245</p>
1246
1247<div class="code">
1248<pre>
1249// Custom C# Exception
1250class CustomApplicationException : System.ApplicationException {
1251  public CustomApplicationException(string message) 
1252    : base(message) {
1253  }
1254}
1255</pre>
1256</div>
1257
1258<p>
1259and the SWIG interface code:
1260</p>
1261
1262<div class="code">
1263<pre>
1264%typemap(throws, canthrow=1) std::out_of_range {
1265  SWIG_CSharpSetPendingExceptionCustom($1.what());
1266  return $null;
1267}
1268
1269%inline %{
1270void oddsonly(int input) throw (std::out_of_range) {
1271  if (input%2 != 1)
1272    throw std::out_of_range("number is not odd");
1273}
1274%}
1275</pre>
1276</div>
1277
1278<p>
1279The "throws" typemap now simply calls our new <tt>SWIG_CSharpSetPendingExceptionCustom()</tt> function so that the exception can be caught, as such:
1280</p>
1281
1282<div class="code">
1283<pre>
1284try {
1285  example.oddsonly(2);
1286} catch (CustomApplicationException e) {
1287  ...
1288}
1289</pre>
1290</div>
1291
1292<H2><a name="CSharp_directors"></a>19.6 C# Directors</H2>
1293
1294
1295<p>
1296The SWIG directors feature adds extra code to the generated C# proxy classes that enable these classes to be used in cross-language polymorphism.
1297Essentially, it enables unmanaged C++ code to call back into managed code for virtual methods so that a C# class can derive from a wrapped C++ class.
1298</p>
1299
1300<p>
1301The following sections provide information on the C# director implementation and contain most of the information required to use the C# directors.
1302However, the <a href="Java.html#Java_directors">Java directors</a> section should also be read in order to gain more insight into directors.
1303</p>
1304
1305<H3><a name="CSharp_directors_example"></a>19.6.1 Directors example</H3>
1306
1307
1308<p>
1309Imagine we are wrapping a C++ base class, <tt>Base</tt>, from which we would like to inherit in C#.
1310Such a class is shown below as well as another class, <tt>Caller</tt>, which calls the virtual method <tt>UIntMethod</tt>
1311from pure unmanaged C++ code.
1312</p>
1313
1314
1315<div class="code">
1316<pre>
1317// file: example.h
1318class Base {
1319public:
1320  virtual ~Base() {}
1321
1322  virtual unsigned int UIntMethod(unsigned int x) {
1323    std::cout &lt;&lt; "Base - UIntMethod(" &lt;&lt; x &lt;&lt; ")" &lt;&lt; std::endl;
1324    return x;
1325  }
1326  virtual void BaseBoolMethod(const Base &amp;b, bool flag) {}
1327};
1328
1329class Caller {
1330public:
1331  Caller(): m_base(0) {}
1332  ~Caller() { delBase(); }
1333  void set(Base *b) { delBase(); m_base = b; }
1334  void reset() { m_base = 0; }
1335  unsigned int UIntMethodCall(unsigned int x) { return m_base-&gt;UIntMethod(x); }
1336
1337private:
1338  Base *m_base;
1339  void delBase() { delete m_base; m_base = 0; }
1340};
1341</pre>
1342</div>
1343
1344<p>
1345The director feature is turned off by default and the following simple interface file shows how directors are enabled
1346for the class <tt>Base</tt>.
1347</p>
1348
1349<div class="code">
1350<pre>
1351/* File : example.i */
1352%module(directors="1") example
1353%{
1354#include "example.h"
1355%}
1356
1357%feature("director") Base;
1358
1359%include "example.h"
1360</pre>
1361</div>
1362
1363<p>
1364The following is a C# class inheriting from <tt>Base</tt>:
1365</p>
1366
1367<div class="code">
1368<pre>
1369public class CSharpDerived : Base
1370{
1371  public override uint UIntMethod(uint x)
1372  {
1373    Console.WriteLine("CSharpDerived - UIntMethod({0})", x);
1374    return x;
1375  }
1376}
1377</pre>
1378</div>
1379
1380<p>
1381The <tt>Caller</tt> class can demonstrate the <tt>UIntMethod</tt> method being called from unmanaged code using the following C# code:
1382</p>
1383
1384<div class="targetlang">
1385<pre>
1386public class runme
1387{
1388  static void Main() 
1389  {
1390    Caller myCaller = new Caller();
1391
1392    // Test pure C++ class
1393    using (Base myBase = new Base())
1394    {
1395      makeCalls(myCaller, myBase);
1396    }
1397
1398    // Test director / C# derived class
1399    using (Base myBase = new CSharpDerived())
1400    {
1401      makeCalls(myCaller, myBase);
1402    }
1403  }
1404
1405  static void makeCalls(Caller myCaller, Base myBase)
1406  {
1407    myCaller.set(myBase);
1408    myCaller.UIntMethodCall(123);
1409    myCaller.reset();
1410  }
1411}
1412</pre>
1413</div>
1414
1415<p>
1416If the above is run, the output is then:
1417</p>
1418
1419<div class="shell">
1420<pre>
1421Base - UIntMethod(123)
1422CSharpDerived - UIntMethod(123)
1423</pre>
1424</div>
1425
1426<H3><a name="CSharp_directors_implementation"></a>19.6.2 Directors implementation</H3>
1427
1428
1429<p>
1430The previous section demonstrated a simple example where the virtual <tt>UIntMethod</tt> method was called from
1431C++ code, even when the overridden method is implemented in C#.
1432The intention of this section is to gain an insight into how the director feature works. 
1433It shows the generated code for the two virtual methods, <tt>UIntMethod</tt> and <tt>BaseBoolMethod</tt>,
1434when the director feature is enabled for the <tt>Base</tt> class.
1435</p>
1436
1437<p>
1438Below is the generated C# <tt>Base</tt> director class.
1439</p>
1440
1441<div class="code">
1442<pre>
1443using System;
1444using System.Runtime.InteropServices;
1445
1446public class Base : IDisposable {
1447  private HandleRef swigCPtr;
1448  protected bool swigCMemOwn;
1449
1450  internal Base(IntPtr cPtr, bool cMemoryOwn) {
1451    swigCMemOwn = cMemoryOwn;
1452    swigCPtr = new HandleRef(this, cPtr);
1453  }
1454
1455  internal static HandleRef getCPtr(Base obj) {
1456    return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
1457  }
1458
1459  ~Base() {
1460    D…

Large files files are truncated, but you can click here to view the full file