Director support added

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@9096 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2006-05-13 23:15:37 +00:00
commit c60b129351
7 changed files with 679 additions and 12 deletions

View file

@ -18,6 +18,7 @@
<li><a href="#csharp_exception_example_exception_specifications">C# exception example using exception specifications</a>
<li><a href="#csharp_custom_application_exception">Custom C# ApplicationException example</a>
</ul>
<li><a href="#csharp_directors">C# Directors</a>
<li><a href="#csharp_typemap_examples">C# Typemap examples</a>
<ul>
<li><a href="#csharp_memory_management_member_variables">Memory management when returning references to member variables</a>
@ -55,14 +56,9 @@ Monodoc, available from the Mono project, has a very useful section titled <a hr
<p>
The C# module is very similar to the Java module, so until some more complete documentation has been written,
please use the <a href="Java.html#Java">Java documentation</a> as a guide to using SWIG with C#.
The C# module has the same major SWIG features as the Java module.
The rest of this section should be read in conjunction with the Java documentation as it lists the main differences.
<p>
Director support (virtual method callbacks into C#) has not yet been implemented and is the main missing feature compared to Java.
Less of the STL is supported and there are also a few minor utility typemaps in the various.i library which are missing.
<p>
The most noteable differences to Java are the following:
<ul>
@ -898,6 +894,399 @@ try {
</pre>
</div>
<H2><a name="csharp_directors"></a>C# Directors</H2>
<p>
The SWIG directors feature adds extra code to the generated C# proxy classes that enable these classes to be used in cross-language polymorphism.
Essentially, 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.
</p>
<p>
The following sections provide information on the C# director implementation and contain most of the information required to use the C# directors.
However, the <a href=Java.html#java_directors>Java directors</a> section should also be read in order to gain more insight into directors.
</p>
<H3><a name="csharp_directors_example"></a>Directors example</H3>
<p>
Imagine we are wrapping a C++ base class, <tt>Base</tt>, from which we would like to inherit in C#.
Such a class is shown below as well as another class, <tt>Caller</tt>, which calls the virtual method <tt>UIntMethod</tt>
from pure unmanaged C++ code.
</p>
<div class="code">
<pre>
// file: example.h
class Base {
public:
virtual ~Base() {}
virtual unsigned int UIntMethod(unsigned int x) {
std::cout &lt;&lt; "Base - UIntMethod(" &lt;&lt; x &lt;&lt; ")" &lt;&lt; std::endl;
return x;
}
virtual void BaseBoolMethod(const Base &amp;b, bool flag) {}
};
class Caller {
public:
Caller(): m_base(0) {}
~Caller() { delBase(); }
void set(Base *b) { delBase(); m_base = b; }
void reset() { m_base = 0; }
unsigned int UIntMethodCall(unsigned int x) { return m_base-&gt;UIntMethod(x); }
private:
Base *m_base;
void delBase() { delete m_base; m_base = 0; }
};
</pre>
</div>
<p>
The director feature is turned off by default and the following simple interface file shows how directors are enabled
for the class <tt>Base</tt>.
</p>
<div class="code">
<pre>
/* File : example.i */
%module(directors="1") example
%{
#include "example.h"
%}
%feature("director") Base;
%include "example.h"
</pre>
</div>
<p>
The following is a C# class inheriting from <tt>Base</tt>:
</p>
<div class="code">
<pre>
public class CSharpDerived : Base
{
public override uint UIntMethod(uint x)
{
Console.WriteLine("CSharpDerived - UIntMethod({0})", x);
return x;
}
}
</pre>
</div>
<p>
The <tt>Caller</tt> class can demonstrate the <tt>UIntMethod</tt> method being called from unmanaged code using the following C# code:
</p>
<div class="targetlang">
<pre>
public class runme
{
static void Main()
{
Caller myCaller = new Caller();
// Test pure C++ class
using (Base myBase = new Base())
{
makeCalls(myCaller, myBase);
}
// Test director / C# derived class
using (Base myBase = new CSharpDerived())
{
makeCalls(myCaller, myBase);
}
}
static void makeCalls(Caller myCaller, Base myBase)
{
myCaller.set(myBase);
myCaller.UIntMethodCall(123);
myCaller.reset();
}
}
</pre>
</div>
<p>
If the above is run, the output is then:
</p>
<div class="shell">
<pre>
Base - UIntMethod(123)
CSharpDerived - UIntMethod(123)
</pre>
</div>
<H3><a name="csharp_directors_implementation"></a>Directors implementation</H3>
<p>
The previous section demonstrated a simple example where the virtual <tt>UIntMethod</tt> method was called from
C++ code, even when the overridden method is implemented in C#.
The intention of this section is to gain an insight into how the director feature works.
It shows the generated code for the two virtual methods, <tt>UIntMethod</tt> and <tt>BaseBoolMethod</tt>,
when the director feature is enabled for the <tt>Base</tt> class.
</p>
<p>
Below is the generated C# <tt>Base</tt> director class.
</p>
<div class="code">
<pre>
using System;
using System.Runtime.InteropServices;
public class Base : IDisposable {
private HandleRef swigCPtr;
protected bool swigCMemOwn;
internal Base(IntPtr cPtr, bool cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = new HandleRef(this, cPtr);
}
internal static HandleRef getCPtr(Base obj) {
return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr;
}
~Base() {
Dispose();
}
public virtual void Dispose() {
if(swigCPtr.Handle != IntPtr.Zero &amp;&amp; swigCMemOwn) {
swigCMemOwn = false;
examplePINVOKE.delete_Base(swigCPtr);
}
swigCPtr = new HandleRef(null, IntPtr.Zero);
GC.SuppressFinalize(this);
}
public virtual uint UIntMethod(uint x) {
uint ret = examplePINVOKE.Base_UIntMethod(swigCPtr, x);
return ret;
}
public virtual void BaseBoolMethod(Base b, bool flag) {
examplePINVOKE.Base_BaseBoolMethod(swigCPtr, Base.getCPtr(b), flag);
if (examplePINVOKE.SWIGPendingException.Pending) throw examplePINVOKE.SWIGPendingException.Retrieve();
}
public Base() : this(examplePINVOKE.new_Base(), true) {
SwigDirectorConnect();
}
private void SwigDirectorConnect() {
if (SwigDerivedClassHasMethod("UIntMethod", swigMethodTypes0))
swigDelegate0 = new SwigDelegateBase_0(SwigDirectorUIntMethod);
if (SwigDerivedClassHasMethod("BaseBoolMethod", swigMethodTypes1))
swigDelegate1 = new SwigDelegateBase_1(SwigDirectorBaseBoolMethod);
examplePINVOKE.Base_director_connect(swigCPtr, swigDelegate0, swigDelegate1);
}
private bool SwigDerivedClassHasMethod(string methodName, Type[] methodTypes) {
System.Reflection.MethodInfo methodInfo = this.GetType().GetMethod(methodName, methodTypes);
bool hasDerivedMethod = methodInfo.DeclaringType.IsSubclassOf(typeof(Base));
return hasDerivedMethod;
}
private uint SwigDirectorUIntMethod(uint x) {
return UIntMethod(x);
}
private void SwigDirectorBaseBoolMethod(IntPtr b, bool flag) {
BaseBoolMethod(new Base(b, false), flag);
}
internal delegate uint SwigDelegateBase_0(uint x);
internal delegate void SwigDelegateBase_1(IntPtr b, bool flag);
private SwigDelegateBase_0 swigDelegate0;
private SwigDelegateBase_1 swigDelegate1;
private static Type[] swigMethodTypes0 = new Type[] { typeof(uint) };
private static Type[] swigMethodTypes1 = new Type[] { typeof(Base), typeof(bool) };
}
</pre>
</div>
<p>
Everything from the <tt>SwigDirectorConnect()</tt> method and below is code that is only generated when
directors are enabled.
The design comprises a C# delegate being initialised for each virtual method on construction of the class.
Let's examine the <tt>BaseBoolMethod</tt>.
</p>
<p>
In the <tt>Base</tt> constructor a call is made to <tt>SwigDirectorConnect()</tt> which contains the initialisation code for all the virtual methods.
It uses a support method, <tt>SwigDerivedClassHasMethod()</tt>, which simply uses reflection to determine if the named method,
BaseBoolMethod, with the list of required parameter types, exists in a subclass.
If it does not exist, the delegate is not initialised as there is no need for unmanaged code to call back into managed C# code.
However, if there is an overridden method in any subclass, the delegate is required.
It is then initialised to the <tt>SwigDirectorBaseBoolMethod</tt> which in turn will call <tt>BaseBoolMethod</tt> if invoked.
The delegate is not initialised to the <tt>BaseBoolMethod</tt> directly as quite often types will need marshalling from the unmanaged type
to the managed type in which case an intermediary method (<tt>SwigDirectorBaseBoolMethod</tt>) is required for the marshalling.
In this case, the C# <tt>Base</tt> class needs to be created from the unmanaged <tt>IntPtr</tt> type.
</p>
<p>
The last thing that <tt>SwigDirectorConnect()</tt> does is to pass the delegates to the unmanaged code.
It calls the intermediary method <tt>Base_director_connect()</tt> which is really a call to the C function <tt>CSharp_Base_director_connect()</tt>.
This method simply maps each C# delegate onto a C function pointer.
</p>
<div class="code">
<pre>
SWIGEXPORT void SWIGSTDCALL CSharp_Base_director_connect(void *objarg,
SwigDirector_Base::SWIG_Callback0_t callback0,
SwigDirector_Base::SWIG_Callback1_t callback1) {
Base *obj = (Base *)objarg;
SwigDirector_Base *director = dynamic_cast<SwigDirector_Base *>(obj);
if (director) {
director-&gt;swig_connect_director(callback0, callback1);
}
}
class SwigDirector_Base : public Base, public Swig::Director {
public:
SwigDirector_Base();
virtual unsigned int UIntMethod(unsigned int x);
virtual ~SwigDirector_Base();
virtual void BaseBoolMethod(Base const &amp;b, bool flag);
typedef unsigned int (SWIGSTDCALL* SWIG_Callback0_t)(unsigned int);
typedef void (SWIGSTDCALL* SWIG_Callback1_t)(void *, unsigned int);
void swig_connect_director(SWIG_Callback0_t callbackUIntMethod, SWIG_Callback1_t callbackBaseBoolMethod);
private:
SWIG_Callback0_t swig_callbackUIntMethod;
SWIG_Callback1_t swig_callbackBaseBoolMethod;
void swig_init_callbacks();
};
void SwigDirector_Base::swig_connect_director(SWIG_Callback0_t callbackUIntMethod,
SWIG_Callback1_t callbackBaseBoolMethod) {
swig_callbackUIntMethod = callbackUIntMethod;
swig_callbackBaseBoolMethod = callbackBaseBoolMethod;
}
</pre>
</div>
<p>
Note that for each director class SWIG creates an unmanaged director class for making the callbacks. For example <tt>Base</tt> has <tt>SwigDirector_Base</tt> and <tt>SwigDirector_Base</tt>
is derived from <tt>Base</tt>.
Should a C# class be derived from <tt>Base</tt>, the underlying C++ <tt>SwigDirector_Base</tt> is created rather than <tt>Base</tt>.
The <tt>SwigDirector_Base</tt> class then implements all the virtual methods, redirecting calls up to managed code if the callback/delegate is non-zero.
The implementation of <tt>SwigDirector_Base::BaseBoolMethod</tt> shows this - the callback is made by invoking the <tt>swig_callbackBaseBoolMethod</tt> function pointer:
</p>
<div class="code">
<pre>
void SwigDirector_Base::BaseBoolMethod(Base const &amp;b, bool flag) {
void * jb = 0 ;
unsigned int jflag ;
if (!swig_callbackBaseBoolMethod) {
Base::BaseBoolMethod(b,flag);
return;
} else {
jb = (Base *) &b;
jflag = flag;
swig_callbackBaseBoolMethod(jb, jflag);
}
}
</pre>
</div>
<H3><a name="csharp_typemap_examples"></a>Director caveats</H3>
<p>
There are a few gotchas with directors.
The first is that the base class virtual method should not be called directly otherwise a stack overflow will occur due to recursive calls.
This might be fixed in a future version of SWIG, but is likely to slow down virtual methods calls.
For example, given <tt>Base</tt> as a director enabled class:
</p>
<div class="code">
<pre>
class Base {
public:
virtual ~Base();
virtual unsigned int UIntMethod(unsigned int x);
};
</pre>
</div>
<p>
Do not directly call the base method from a C# derived class:
</p>
<div class="code">
<pre>
public class CSharpDerived : Base
{
public override uint UIntMethod(uint x)
{
return base.UIntMethod(x);
}
}
</pre>
</div>
<p>
Secondly, if default parameters are used, it is recommended to follow a pattern of always calling a single method in any C# derived class.
An example will clarify this and the reasoning behind the recommendation. Consider the following C++ class wrapped as a director class:
</p>
<div class="code">
<pre>
class Defaults {
public:
virtual ~Defaults();
virtual void DefaultMethod(int a=-100);
};
</pre>
</div>
<p>
Recall that C++ methods with default parameters generate overloaded methods for each defaulted parameter, so a C# derived class can be created
with two <tt>DefaultMethod</tt> override methods:
</p>
<div class="code">
<pre>
public class CSharpDefaults : Defaults
{
public override void DefaultMethod()
{
DefaultMethod(-100); // note C++ default value used
}
public override void DefaultMethod(int x)
{
}
}
</pre>
</div>
<p>
It may not be clear at first, but should a user intend to call <tt>CSharpDefaults.DefaultMethod()</tt> from C++, a call is actually made to <tt>CSharpDefaults.DefaultMethod(int)</tt>.
This is because the initial call is made in C++ and therefore the <tt>DefaultMethod(int)</tt> method will be called as is expected with C++ calls to methods with defaults,
with the default being set to -100.
The callback/delegate matching this method is of course the overloaded method <tt>DefaultMethod(int)</tt>.
However, a call from C# to <tt>CSharpDefaults.DefaultMethod()</tt> will of course call this exact method and in order for behaviour to be consistent with calls from C++, the implementation
should pass the call on to <tt>CSharpDefaults.DefaultMethod(int)</tt>using the C++ default value, as shown above.
</p>
<H2><a name="csharp_typemap_examples"></a>17.4 C# Typemap examples</H2>

View file

@ -85,7 +85,7 @@
%typemap(cstype) SWIGTYPE & "$csclassname"
/* pointer to a class member */
%typemap(ctype) SWIGTYPE (CLASS::*) "int"
%typemap(ctype) SWIGTYPE (CLASS::*) "void *"
%typemap(imtype, out="IntPtr") SWIGTYPE (CLASS::*) "HandleRef"
%typemap(cstype) SWIGTYPE (CLASS::*) "$csclassname"
@ -95,6 +95,12 @@
%typemap(in) bool
%{ $1 = $input ? true : false; %}
%typemap(directorout) bool
%{ $1 = $input ? true : false; %}
%typemap(csdirectorin) bool "$iminput"
%typemap(csdirectorout) bool "$cscall"
%typemap(in) char,
signed char,
unsigned char,
@ -110,6 +116,66 @@
double
%{ $1 = ($1_ltype)$input; %}
%typemap(directorout) char,
signed char,
unsigned char,
short,
unsigned short,
int,
unsigned int,
long,
unsigned long,
long long,
unsigned long long,
float,
double
%{ $1 = ($1_ltype)$input; %}
%typemap(directorin) bool "$input = $1;"
%typemap(directorin) char "$input = $1;"
%typemap(directorin) signed char "$input = $1;"
%typemap(directorin) unsigned char "$input = $1;"
%typemap(directorin) short "$input = $1;"
%typemap(directorin) unsigned short "$input = $1;"
%typemap(directorin) int "$input = $1;"
%typemap(directorin) unsigned int "$input = $1;"
%typemap(directorin) long "$input = $1;"
%typemap(directorin) unsigned long "$input = $1;"
%typemap(directorin) long long "$input = $1;"
%typemap(directorin) unsigned long long "$input = $1;"
%typemap(directorin) float "$input = $1;"
%typemap(directorin) double "$input = $1;"
%typemap(csdirectorin) char,
signed char,
unsigned char,
short,
unsigned short,
int,
unsigned int,
long,
unsigned long,
long long,
unsigned long long,
float,
double
"$iminput"
%typemap(csdirectorout) char,
signed char,
unsigned char,
short,
unsigned short,
int,
unsigned int,
long,
unsigned long,
long long,
unsigned long long,
float,
double
"$cscall"
%typemap(out) bool %{ $result = $1; %}
%typemap(out) char %{ $result = $1; %}
%typemap(out) signed char %{ $result = $1; %}
@ -126,16 +192,31 @@
%typemap(out) double %{ $result = $1; %}
/* char * - treat as String */
%typemap(in) char * %{ $1 = ($1_ltype)$input; %}
%typemap(in) char * %{ $1 = $input; %}
%typemap(out) char * %{ $result = SWIG_csharp_string_callback((const char *)$1); %}
%typemap(directorout) char * %{ $1 = $input; %}
%typemap(directorin) char * %{ $input = SWIG_csharp_string_callback($1); %}
%typemap(csdirectorin) char * "$iminput"
%typemap(csdirectorout) char * "$cscall"
%typemap(out, null="") void ""
%typemap(csdirectorin) void "$iminput"
%typemap(csdirectorout) void "$cscall"
%typemap(directorin) void ""
/* primitive types by const reference */
%typemap(in) const bool & ($*1_ltype temp)
%{ temp = $input ? true : false;
$1 = &temp; %}
%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const bool &
%{ static $*1_ltype temp;
temp = $input ? true : false;
$1 = &temp; %}
%typemap(csdirectorin) const bool & "$iminput"
%typemap(csdirectorout) const bool & "$cscall"
%typemap(in) const char & ($*1_ltype temp),
const signed char & ($*1_ltype temp),
const unsigned char & ($*1_ltype temp),
@ -152,6 +233,65 @@
%{ temp = ($*1_ltype)$input;
$1 = &temp; %}
%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const char &,
const signed char &,
const unsigned char &,
const short &,
const unsigned short &,
const int &,
const unsigned int &,
const long &,
const unsigned long &,
const long long &,
const float &,
const double &
%{ static $*1_ltype temp;
temp = ($*1_ltype)$input;
$1 = &temp; %}
%typemap(directorin) const bool & "$input = $1_name;"
%typemap(directorin) const char & "$input = $1_name;"
%typemap(directorin) const signed char & "$input = $1_name;"
%typemap(directorin) const unsigned char & "$input = $1_name;"
%typemap(directorin) const short & "$input = $1_name;"
%typemap(directorin) const unsigned short & "$input = $1_name;"
%typemap(directorin) const int & "$input = $1_name;"
%typemap(directorin) const unsigned int & "$input = $1_name;"
%typemap(directorin) const long & "$input = $1_name;"
%typemap(directorin) const unsigned long & "$input = $1_name;"
%typemap(directorin) const long long & "$input = $1_name;"
%typemap(directorin) const float & "$input = $1_name;"
%typemap(directorin) const double & "$input = $1_name;"
%typemap(csdirectorin) const char & ($*1_ltype temp),
const signed char & ($*1_ltype temp),
const unsigned char & ($*1_ltype temp),
const short & ($*1_ltype temp),
const unsigned short & ($*1_ltype temp),
const int & ($*1_ltype temp),
const unsigned int & ($*1_ltype temp),
const long & ($*1_ltype temp),
const unsigned long & ($*1_ltype temp),
const long long & ($*1_ltype temp),
const float & ($*1_ltype temp),
const double & ($*1_ltype temp)
"$iminput"
%typemap(csdirectorout) const char & ($*1_ltype temp),
const signed char & ($*1_ltype temp),
const unsigned char & ($*1_ltype temp),
const short & ($*1_ltype temp),
const unsigned short & ($*1_ltype temp),
const int & ($*1_ltype temp),
const unsigned int & ($*1_ltype temp),
const long & ($*1_ltype temp),
const unsigned long & ($*1_ltype temp),
const long long & ($*1_ltype temp),
const float & ($*1_ltype temp),
const double & ($*1_ltype temp)
"$cscall"
%typemap(out) const bool & %{ $result = *$1; %}
%typemap(out) const char & %{ $result = *$1; %}
%typemap(out) const signed char & %{ $result = *$1; %}
@ -175,6 +315,14 @@
return $null;
}
$1 = *argp; %}
%typemap(directorout) SWIGTYPE
%{ if (!$input) {
SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Unexpected null return for type $1_type", 0);
return $null;
}
$1 = *($&1_ltype)$input; %}
%typemap(out) SWIGTYPE
#ifdef __cplusplus
%{ $result = new $1_ltype(($1_ltype &)$1); %}
@ -186,6 +334,11 @@
}
#endif
%typemap(directorin) SWIGTYPE
%{ $input = (void *)&$1; %}
%typemap(csdirectorin) SWIGTYPE "new $&csclassname($iminput, false)"
%typemap(csdirectorout) SWIGTYPE "$&csclassname.getCPtr($cscall).Handle"
/* Generic pointers and references */
%typemap(in) SWIGTYPE * %{ $1 = ($1_ltype)$input; %}
%typemap(in) SWIGTYPE (CLASS::*) %{ $1 = *($&1_ltype)&$input; %}
@ -195,8 +348,23 @@
return $null;
} %}
%typemap(out) SWIGTYPE *, SWIGTYPE & %{ $result = (void *)$1; %}
%typemap(out) SWIGTYPE (CLASS::*) %{ *($&1_ltype)&$result = $1; %}
%typemap(out) SWIGTYPE (CLASS::*) %{ $result = (void *)&$1; %}
%typemap(directorout) SWIGTYPE *, SWIGTYPE (CLASS::*)
%{ $1 = ($1_ltype)$input; %}
%typemap(directorin) SWIGTYPE *, SWIGTYPE (CLASS::*)
%{ $input = ($1_ltype) $1; %}
%typemap(directorout) SWIGTYPE &
%{ if (!$input) {
SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Unexpected null return for type $1_type", 0);
return $null;
}
$1 = ($1_ltype)$input; %}
%typemap(directorin) SWIGTYPE &
%{ $input = ($1_ltype) &$1; %}
%typemap(csdirectorin) SWIGTYPE *, SWIGTYPE (CLASS::*), SWIGTYPE & "new $csclassname($iminput, false)"
%typemap(csdirectorout) SWIGTYPE *, SWIGTYPE (CLASS::*), SWIGTYPE & "$csclassname.getCPtr($cscall).Handle"
/* Default array handling */
%typemap(in) SWIGTYPE [] %{ $1 = ($1_ltype)$input; %}
@ -206,6 +374,12 @@
%typemap(in) char[ANY], char[] %{ $1 = $input; %}
%typemap(out) char[ANY], char[] %{ $result = SWIG_csharp_string_callback($1); %}
%typemap(directorout) char[ANY], char[] %{ $1 = $input; %}
%typemap(directorin) char[ANY], char[] %{ $input = SWIG_csharp_string_callback($1); %}
%typemap(csdirectorin) char[ANY], char[] "$iminput"
%typemap(csdirectorout) char[ANY], char[] "$cscall"
/* Typecheck typemaps - The purpose of these is merely to issue a warning for overloaded C++ functions
* that cannot be overloaded in C# as more than one C++ type maps to a single C# type */
@ -609,7 +783,7 @@
}
%}
%typemap(csconstruct, excode=SWIGEXCODE) SWIGTYPE %{: this($imcall, true) {$excode
%typemap(csconstruct, excode=SWIGEXCODE,directorconnect="\n SwigDirectorConnect();") SWIGTYPE %{: this($imcall, true) {$excode$directorconnect
}
%}
@ -632,6 +806,12 @@
base.Dispose();
}
%typemap(directordisconnect, methodname="swigDirectorDisconnect") SWIGTYPE %{
protected void $methodname() {
swigCMemOwn = false;
$imcall;
}
%}
/* C# specific directives */
#define %csconst(flag) %feature("cs:const","flag")

View file

@ -18,6 +18,13 @@
$1 = &temp; %}
%typemap(out) const enum SWIGTYPE & %{ $result = *$1; %}
%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const enum SWIGTYPE &
%{ static $*1_ltype temp = ($*1_ltype)$input;
$1 = &temp; %}
%typemap(directorin) const enum SWIGTYPE & "$input = $1_name;"
%typemap(csdirectorin) const enum SWIGTYPE & "($*csclassname)$iminput"
%typemap(csdirectorout) const enum SWIGTYPE & "(int)$cscall"
%typecheck(SWIG_TYPECHECK_POINTER) const enum SWIGTYPE & ""
%typemap(throws, canthrow=1) const enum SWIGTYPE &
@ -46,6 +53,11 @@
%typemap(in) enum SWIGTYPE %{ $1 = ($1_ltype)$input; %}
%typemap(out) enum SWIGTYPE %{ $result = $1; %}
%typemap(directorout) enum SWIGTYPE %{ $1 = ($1_ltype)$input; %}
%typemap(directorin) enum SWIGTYPE "$input = $1;"
%typemap(csdirectorin) enum SWIGTYPE "($csclassname)$iminput"
%typemap(csdirectorout) enum SWIGTYPE "(int)$cscall"
%typecheck(SWIG_TYPECHECK_POINTER) enum SWIGTYPE ""
%typemap(throws, canthrow=1) enum SWIGTYPE

View file

@ -20,6 +20,13 @@
$1 = &temp; %}
%typemap(out) const enum SWIGTYPE & %{ $result = *$1; %}
%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const enum SWIGTYPE &
%{ static $*1_ltype temp = ($*1_ltype)$input;
$1 = &temp; %}
%typemap(directorin) const enum SWIGTYPE & "$input = $1_name;"
%typemap(csdirectorin) const enum SWIGTYPE & "$iminput"
%typemap(csdirectorout) const enum SWIGTYPE & "$cscall"
%typecheck(SWIG_TYPECHECK_INT32) const enum SWIGTYPE & ""
%typemap(throws, canthrow=1) const enum SWIGTYPE &
@ -48,6 +55,11 @@
%typemap(in) enum SWIGTYPE %{ $1 = ($1_ltype)$input; %}
%typemap(out) enum SWIGTYPE %{ $result = $1; %}
%typemap(directorout) enum SWIGTYPE %{ $1 = ($1_ltype)$input; %}
%typemap(directorin) enum SWIGTYPE "$input = $1;"
%typemap(csdirectorin) enum SWIGTYPE "$iminput"
%typemap(csdirectorout) enum SWIGTYPE "$cscall"
%typecheck(SWIG_TYPECHECK_INT32) enum SWIGTYPE ""
%typemap(throws, canthrow=1) enum SWIGTYPE

View file

@ -19,6 +19,13 @@
$1 = &temp; %}
%typemap(out) const enum SWIGTYPE & %{ $result = *$1; %}
%typemap(directorout,warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const enum SWIGTYPE &
%{ static $*1_ltype temp = ($*1_ltype)$input;
$1 = &temp; %}
%typemap(directorin) const enum SWIGTYPE & "$input = $1_name;"
%typemap(csdirectorin) const enum SWIGTYPE & "$*csclassname.swigToEnum($iminput)"
%typemap(csdirectorout) const enum SWIGTYPE & "$cscall.swigValue"
%typecheck(SWIG_TYPECHECK_POINTER) const enum SWIGTYPE & ""
%typemap(throws, canthrow=1) const enum SWIGTYPE &
@ -47,6 +54,11 @@
%typemap(in) enum SWIGTYPE %{ $1 = ($1_ltype)$input; %}
%typemap(out) enum SWIGTYPE %{ $result = $1; %}
%typemap(directorout) enum SWIGTYPE %{ $1 = ($1_ltype)$input; %}
%typemap(directorin) enum SWIGTYPE "$input = $1;"
%typemap(csdirectorin) enum SWIGTYPE "$csclassname.swigToEnum($iminput)"
%typemap(csdirectorout) enum SWIGTYPE "$cscall.swigValue"
%typecheck(SWIG_TYPECHECK_POINTER) enum SWIGTYPE ""
%typemap(throws, canthrow=1) enum SWIGTYPE

View file

@ -6,7 +6,7 @@
*
* Typemaps for std::string and const std::string&
* These are mapped to a C# String and are passed around by value.
*
*
* To use non-const std::string references use the following %apply. Note
* that they are passed by value.
* %apply const std::string & {std::string &};
@ -26,6 +26,8 @@ class string;
%typemap(ctype) string "char *"
%typemap(imtype) string "string"
%typemap(cstype) string "string"
%typemap(csdirectorin) string "$iminput"
%typemap(csdirectorout) string "$cscall"
%typemap(in, canthrow=1) string
%{ if (!$input) {
@ -35,6 +37,15 @@ class string;
$1 = std::string($input); %}
%typemap(out) string %{ $result = SWIG_csharp_string_callback($1.c_str()); %}
%typemap(directorout, canthrow=1) string
%{ if (!$input) {
SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null string", 0);
return $null;
}
$1 = std::string($input); %}
%typemap(directorin) string %{ $input = SWIG_csharp_string_callback($1.c_str()); %}
%typemap(csin) string "$csinput"
%typemap(csout, excode=SWIGEXCODE) string {
string ret = $imcall;$excode
@ -61,6 +72,8 @@ class string;
%typemap(ctype) const string & "char *"
%typemap(imtype) const string & "string"
%typemap(cstype) const string & "string"
%typemap(csdirectorin) const string & "$iminput"
%typemap(csdirectorout) const string & "$cscall"
%typemap(in, canthrow=1) const string &
%{ if (!$input) {
@ -77,6 +90,17 @@ class string;
return ret;
}
%typemap(directorout, canthrow=1, warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const string &
%{ if (!$input) {
SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null string", 0);
return $null;
}
/* possible thread/reentrant code problem */
static std::string $1_str($input);
$1 = &$1_str; %}
%typemap(directorin) const string & %{ $input = SWIG_csharp_string_callback($1->c_str()); %}
%typemap(csvarin, excode=SWIGEXCODE2) const string & %{
set {
$imcall;$excode

View file

@ -15,7 +15,7 @@ INPUT typemaps
--------------
These typemaps are used for pointer/reference parameters that are input only
are mapped to a C# input parameter.
and are mapped to a C# input parameter.
The following typemaps can be applied to turn a pointer or reference into a simple
input value. That is, instead of passing a pointer or reference to an object,
@ -62,10 +62,21 @@ In C# you could then use it like this:
%typemap(imtype) TYPE *INPUT, TYPE &INPUT "CSTYPE"
%typemap(cstype) TYPE *INPUT, TYPE &INPUT "CSTYPE"
%typemap(csin) TYPE *INPUT, TYPE &INPUT "$csinput"
%typemap(csdirectorin) TYPE *INPUT, TYPE &INPUT "$iminput"
%typemap(csdirectorout) TYPE *INPUT, TYPE &INPUT "$cscall"
%typemap(in) TYPE *INPUT, TYPE &INPUT
%{ $1 = ($1_ltype)&$input; %}
%typemap(directorout) TYPE *INPUT, TYPE &INPUT
%{ $1 = ($1_ltype)&$input; %}
%typemap(directorin) TYPE &INPUT
%{ $input = (CTYPE *)$1; %}
%typemap(directorin) TYPE *INPUT
%{ $input = (CTYPE *)$1; %}
%typemap(typecheck) TYPE *INPUT = TYPE;
%typemap(typecheck) TYPE &INPUT = TYPE;
%enddef
@ -143,10 +154,24 @@ value returned in the second output parameter. In C# you would use it like this:
%typemap(imtype) TYPE *OUTPUT, TYPE &OUTPUT "out CSTYPE"
%typemap(cstype) TYPE *OUTPUT, TYPE &OUTPUT "out CSTYPE"
%typemap(csin) TYPE *OUTPUT, TYPE &OUTPUT "out $csinput"
%typemap(csdirectorin) TYPE *OUTPUT, TYPE &OUTPUT "$iminput"
%typemap(csdirectorout) TYPE *OUTPUT, TYPE &OUTPUT "$cscall"
%typemap(in) TYPE *OUTPUT, TYPE &OUTPUT
%{ $1 = ($1_ltype)$input; %}
%typemap(directorout,warning="Need to provide TYPE *OUTPUT directorout typemap") TYPE *OUTPUT, TYPE &OUTPUT {
}
%typemap(directorin) TYPE &OUTPUT
%{ $input = &$1; %}
%typemap(directorin,warning="Need to provide TYPE *OUTPUT directorin typemap, TYPE array length is unknown") TYPE *OUTPUT
{
}
%typecheck(SWIG_TYPECHECK_##TYPECHECKPRECEDENCE) TYPE *OUTPUT, TYPE &OUTPUT ""
%enddef
@ -228,10 +253,23 @@ of the function return value.
%typemap(imtype) TYPE *INOUT, TYPE &INOUT "ref CSTYPE"
%typemap(cstype) TYPE *INOUT, TYPE &INOUT "ref CSTYPE"
%typemap(csin) TYPE *INOUT, TYPE &INOUT "ref $csinput"
%typemap(csdirectorin) TYPE *INOUT, TYPE &INOUT "$iminput"
%typemap(csdirectorout) TYPE *INOUT, TYPE &INOUT "$cscall"
%typemap(in) TYPE *INOUT, TYPE &INOUT
%{ $1 = ($1_ltype)$input; %}
%typemap(directorout,warning="Need to provide TYPE *INOUT directorout typemap") TYPE *INOUT, TYPE &INOUT {
}
%typemap(directorin) TYPE &INOUT
%{ $input = &$1; %}
%typemap(directorin,warning="Need to provide TYPE *INOUT directorin typemap, TYPE array length is unknown") TYPE *INOUT, TYPE &INOUT
{
}
%typecheck(SWIG_TYPECHECK_##TYPECHECKPRECEDENCE) TYPE *INOUT, TYPE &INOUT ""
%enddef