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:
parent
c1fb598f6e
commit
c60b129351
7 changed files with 679 additions and 12 deletions
|
|
@ -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 << "Base - UIntMethod(" << x << ")" << std::endl;
|
||||
return x;
|
||||
}
|
||||
virtual void BaseBoolMethod(const Base &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->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 && 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->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 &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 &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>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue