C# exception handling improvements - they are robust and don't leak anymore. Requires typemap modifications using attribute canthrow in any unmanaged code typemaps that throw an exception and excode attribute in csout and csconstruct typemaps.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@6934 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2005-02-02 22:44:32 +00:00
commit a78579ec3f
12 changed files with 288 additions and 156 deletions

View file

@ -165,7 +165,7 @@ $1 = &temp; %}
%typemap(out) const double & %{ $result = *$1; %}
/* Default handling. Object passed by value. Convert to a pointer */
%typemap(in) SWIGTYPE ($&1_type argp)
%typemap(in, canthrow=1) SWIGTYPE ($&1_type argp)
%{ argp = ($&1_ltype)$input;
if (!argp) {
SWIG_CSharpThrowException(SWIG_CSharpNullReferenceException, "Attempt to dereference null $1_type");
@ -185,7 +185,7 @@ $1 = &temp; %}
/* Generic pointers and references */
%typemap(in) SWIGTYPE * %{ $1 = ($1_ltype)$input; %}
%typemap(in) SWIGTYPE (CLASS::*) %{ $1 = *($&1_ltype)&$input; %}
%typemap(in) SWIGTYPE & %{ $1 = ($1_ltype)$input;
%typemap(in, canthrow=1) SWIGTYPE & %{ $1 = ($1_ltype)$input;
if(!$1) {
SWIG_CSharpThrowException(SWIG_CSharpNullReferenceException, "$1_type reference is null");
} %}
@ -285,7 +285,7 @@ $1 = &temp; %}
/* Exception handling */
%typemap(throws) int,
%typemap(throws, canthrow=1) int,
long,
short,
unsigned int,
@ -296,12 +296,12 @@ $1 = &temp; %}
SWIG_CSharpThrowException(SWIG_CSharpException, error_msg);
}
%typemap(throws) SWIGTYPE, SWIGTYPE &, SWIGTYPE *, SWIGTYPE [ANY] %{
%typemap(throws, canthrow=1) SWIGTYPE, SWIGTYPE &, SWIGTYPE *, SWIGTYPE [ANY] %{
(void)$1;
SWIG_CSharpThrowException(SWIG_CSharpException, "C++ $1_type exception thrown");
%}
%typemap(throws) char * %{
%typemap(throws, canthrow=1) char * %{
SWIG_CSharpThrowException(SWIG_CSharpException, $1);
%}
@ -330,39 +330,95 @@ $1 = &temp; %}
%typemap(csin) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) "$csclassname.getCPtr($csinput)"
/* The csout typemap is used for converting function return types from the return type
* used in the PInvoke class to the type returned by the proxy, module or type wrapper class. */
%typemap(csout) bool, const bool &,
char, const char &,
signed char, const signed char &,
unsigned char, const unsigned char &,
short, const short &,
unsigned short, const unsigned short &,
int, const int &,
unsigned int, const unsigned int &,
long, const long &,
unsigned long, const unsigned long &,
long long, const long long &,
unsigned long long, const unsigned long long &,
float, const float &,
double, const double & {
return $imcall;
* used in the PInvoke class to the type returned by the proxy, module or type wrapper class.
* The $excode special variable is replaced by the excode typemap attribute code if the
* method can throw any exceptions, otherwise replaced by nothing. */
// Macro used by the $excode special variable
%define SWIGEXCODE "\n if ($modulePINVOKE.ExceptionPending) throw $modulePINVOKE.RetrievePendingException();" %enddef
%typemap(csout, excode=SWIGEXCODE) bool, const bool & {
bool ret = $imcall;$excode
return ret;
}
%typemap(csout) char *, char[ANY], char[] {
return $imcall;
%typemap(csout, excode=SWIGEXCODE) char, const char & {
char ret = $imcall;$excode
return ret;
}
%typemap(csout) void {
$imcall;
%typemap(csout, excode=SWIGEXCODE) signed char, const signed char & {
sbyte ret = $imcall;$excode
return ret;
}
%typemap(csout) SWIGTYPE {
return new $&csclassname($imcall, true);
%typemap(csout, excode=SWIGEXCODE) unsigned char, const unsigned char & {
byte ret = $imcall;$excode
return ret;
}
%typemap(csout) SWIGTYPE & {
return new $csclassname($imcall, $owner);
%typemap(csout, excode=SWIGEXCODE) short, const short & {
short ret = $imcall;$excode
return ret;
}
%typemap(csout) SWIGTYPE *, SWIGTYPE [], SWIGTYPE (CLASS::*) {
%typemap(csout, excode=SWIGEXCODE) unsigned short, const unsigned short & {
ushort ret = $imcall;$excode
return ret;
}
%typemap(csout, excode=SWIGEXCODE) int, const int & {
int ret = $imcall;$excode
return ret;
}
%typemap(csout, excode=SWIGEXCODE) unsigned int, const unsigned int & {
uint ret = $imcall;$excode
return ret;
}
%typemap(csout, excode=SWIGEXCODE) long, const long & {
int ret = $imcall;$excode
return ret;
}
%typemap(csout, excode=SWIGEXCODE) unsigned long, const unsigned long & {
uint ret = $imcall;$excode
return ret;
}
%typemap(csout, excode=SWIGEXCODE) long long, const long long & {
long ret = $imcall;$excode
return ret;
}
%typemap(csout, excode=SWIGEXCODE) unsigned long long, const unsigned long long & {
ulong ret = $imcall;$excode
return ret;
}
%typemap(csout, excode=SWIGEXCODE) float, const float & {
float ret = $imcall;$excode
return ret;
}
%typemap(csout, excode=SWIGEXCODE) double, const double & {
double ret = $imcall;$excode
return ret;
}
%typemap(csout, excode=SWIGEXCODE) char *, char[ANY], char[] {
string ret = $imcall;$excode
return ret;
}
%typemap(csout, excode=SWIGEXCODE) void {
$imcall;$excode
}
%typemap(csout, excode=SWIGEXCODE) SWIGTYPE {
$&csclassname ret = new $&csclassname($imcall, true);$excode
return ret;
}
%typemap(csout, excode=SWIGEXCODE) SWIGTYPE & {
$csclassname ret = new $csclassname($imcall, $owner);$excode
return ret;
}
%typemap(csout, excode=SWIGEXCODE) SWIGTYPE *, SWIGTYPE [], SWIGTYPE (CLASS::*) {
IntPtr cPtr = $imcall;
return (cPtr == IntPtr.Zero) ? null : new $csclassname(cPtr, $owner);
$csclassname ret = (cPtr == IntPtr.Zero) ? null : new $csclassname(cPtr, $owner);$excode
return ret;
}
%typemap(csout, excode=SWIGEXCODE) SWIGTYPE *, SWIGTYPE [], SWIGTYPE (CLASS::*) {
IntPtr cPtr = $imcall;
$csclassname ret = (cPtr == IntPtr.Zero) ? null : new $csclassname(cPtr, $owner);$excode
return ret;
}
/* Properties */
%typemap(csvarin) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) %{
@ -484,8 +540,8 @@ $1 = &temp; %}
}
%}
%typemap(csconstruct) SWIGTYPE %{: this(IntPtr.Zero, false) {
swigSetup($imcall, true);
%typemap(csconstruct, excode=SWIGEXCODE) SWIGTYPE %{: this(IntPtr.Zero, false) {
swigSetup($imcall, true);$excode
}
%}
@ -514,6 +570,8 @@ $1 = &temp; %}
#define %csconstvalue(value) %feature("cs:constvalue",value)
#define %csenum(wrapapproach) %feature("cs:enum","wrapapproach")
#define %csmethodmodifiers %feature("cs:methodmodifiers")
#define %csexception %feature("except",canthrow=1)
#define %nocsexception %feature("except","")
%pragma(csharp) imclassclassmodifiers="class"
%pragma(csharp) moduleclassmodifiers="public class"
@ -555,8 +613,9 @@ using System.Runtime.InteropServices;
%typemap(imtype) char *, char[ANY], char[] "IntPtr"
%typemap(out) char[ANY], char[] %{ $result = $1; %}
%typemap(csin) char *, char[ANY], char[] "new $modulePINVOKE.SWIGStringMarshal($csinput).ptr"
%typemap(csout) char *, char[ANY], char[] {
return System.Runtime.InteropServices.Marshal.PtrToStringAnsi($imcall);
%typemap(csout, excode=SWIGEXCODE) char *, char[ANY], char[] {
string ret = System.Runtime.InteropServices.Marshal.PtrToStringAnsi($imcall);$excode
return ret;
}
%typemap(csvarin) char *, char[ANY], char[] %{
set {

View file

@ -122,6 +122,41 @@ DllExport void SWIGSTDCALL SWIGRegisterExceptionCallbacks_$module(SWIG_CSharpExc
}
static SWIGExceptionHelper exceptionHelper = new SWIGExceptionHelper();
[ThreadStatic]
private static Exception pendingException = null;
private static int numExceptionsPending = 0;
public static bool ExceptionPending {
get {
bool pending = false;
if (numExceptionsPending > 0)
if (pendingException != null)
pending = true;
return pending;
}
}
public static void SetPendingException(Exception e) {
pendingException = e;
lock(typeof($modulePINVOKE)) {
numExceptionsPending++;
}
}
public static Exception RetrievePendingException() {
Exception e = null;
if (numExceptionsPending > 0) {
if (pendingException != null) {
e = pendingException;
pendingException = null;
lock(typeof($modulePINVOKE)) {
numExceptionsPending--;
}
}
}
return e;
}
%}
%insert(runtime) %{

View file

@ -15,14 +15,15 @@
%typecheck(SWIG_TYPECHECK_POINTER) const enum SWIGTYPE & ""
%typemap(throws) const enum SWIGTYPE & %{
%typemap(throws, canthrow=1) const enum SWIGTYPE & %{
(void)$1;
SWIG_CSharpThrowException(SWIG_CSharpException, "C++ $1_type exception thrown");
%}
%typemap(csin) const enum SWIGTYPE & "(int)$csinput"
%typemap(csout) const enum SWIGTYPE & {
return ($*csclassname)$imcall;
%typemap(csout, excode=SWIGEXCODE) const enum SWIGTYPE & {
$*csclassname ret = ($*csclassname)$imcall;$excode
return ret;
}
%typemap(csvarout) const enum SWIGTYPE & %{
@ -41,14 +42,15 @@
%typecheck(SWIG_TYPECHECK_POINTER) enum SWIGTYPE ""
%typemap(throws) enum SWIGTYPE %{
%typemap(throws, canthrow=1) enum SWIGTYPE %{
(void)$1;
SWIG_CSharpThrowException(SWIG_CSharpException, "C++ $1_type exception thrown");
%}
%typemap(csin) enum SWIGTYPE "(int)$csinput"
%typemap(csout) enum SWIGTYPE {
return ($csclassname)$imcall;
%typemap(csout, excode=SWIGEXCODE) enum SWIGTYPE {
$csclassname ret = ($csclassname)$imcall;$excode
return ret;
}
%typemap(csvarout) enum SWIGTYPE %{

View file

@ -17,14 +17,15 @@
%typecheck(SWIG_TYPECHECK_INT32) const enum SWIGTYPE & ""
%typemap(throws) const enum SWIGTYPE & %{
%typemap(throws, canthrow=1) const enum SWIGTYPE & %{
(void)$1;
SWIG_CSharpThrowException(SWIG_CSharpException, "C++ $1_type exception thrown");
%}
%typemap(csin) const enum SWIGTYPE & "$csinput"
%typemap(csout) const enum SWIGTYPE & {
return $imcall;
%typemap(csout, excode=SWIGEXCODE) const enum SWIGTYPE & {
int ret = $imcall;$excode
return ret;
}
%typemap(csvarout) const enum SWIGTYPE & %{
@ -43,14 +44,15 @@
%typecheck(SWIG_TYPECHECK_INT32) enum SWIGTYPE ""
%typemap(throws) enum SWIGTYPE %{
%typemap(throws, canthrow=1) enum SWIGTYPE %{
(void)$1;
SWIG_CSharpThrowException(SWIG_CSharpException, "C++ $1_type exception thrown");
%}
%typemap(csin) enum SWIGTYPE "$csinput"
%typemap(csout) enum SWIGTYPE {
return $imcall;
%typemap(csout, excode=SWIGEXCODE) enum SWIGTYPE {
int ret = $imcall;$excode
return ret;
}
%typemap(csvarout) enum SWIGTYPE %{

View file

@ -16,14 +16,15 @@
%typecheck(SWIG_TYPECHECK_POINTER) const enum SWIGTYPE & ""
%typemap(throws) const enum SWIGTYPE & %{
%typemap(throws, canthrow=1) const enum SWIGTYPE & %{
(void)$1;
SWIG_CSharpThrowException(SWIG_CSharpException, "C++ $1_type exception thrown");
%}
%typemap(csin) const enum SWIGTYPE & "$csinput.swigValue"
%typemap(csout) const enum SWIGTYPE & {
return $*csclassname.swigToEnum($imcall);
%typemap(csout, excode=SWIGEXCODE) const enum SWIGTYPE & {
$*csclassname ret = $*csclassname.swigToEnum($imcall);$excode
return ret;
}
%typemap(csvarout) const enum SWIGTYPE & %{
@ -42,14 +43,15 @@
%typecheck(SWIG_TYPECHECK_POINTER) enum SWIGTYPE ""
%typemap(throws) enum SWIGTYPE %{
%typemap(throws, canthrow=1) enum SWIGTYPE %{
(void)$1;
SWIG_CSharpThrowException(SWIG_CSharpException, "C++ $1_type exception thrown");
%}
%typemap(csin) enum SWIGTYPE "$csinput.swigValue"
%typemap(csout) enum SWIGTYPE {
return $csclassname.swigToEnum($imcall);
%typemap(csout, excode=SWIGEXCODE) enum SWIGTYPE {
$csclassname ret = $csclassname.swigToEnum($imcall);$excode
return ret;
}
%typemap(csvarout) enum SWIGTYPE %{

View file

@ -26,14 +26,15 @@ class string;
%typemap(imtype) string "string"
%typemap(cstype) string "string"
%typemap(in) string
%typemap(in, canthrow=1) string
%{ if (!$input) SWIG_CSharpThrowException(SWIG_CSharpNullReferenceException, "null string");
$1 = std::string($input); %}
%typemap(out) string %{ $result = SWIG_csharp_string_callback($1.c_str()); %}
%typemap(csin) string "$csinput"
%typemap(csout) string {
return $imcall;
%typemap(csout, excode=SWIGEXCODE) string {
string ret = $imcall;$excode
return ret;
}
%typemap(csvarin) string %{
@ -47,7 +48,7 @@ class string;
%typemap(typecheck) string = char *;
%typemap(throws) string %{
%typemap(throws, canthrow=1) string %{
SWIG_CSharpThrowException(SWIG_CSharpException, $1.c_str());
%}
@ -56,15 +57,16 @@ class string;
%typemap(imtype) const string & "string"
%typemap(cstype) const string & "string"
%typemap(in) const string &
%typemap(in, canthrow=1) const string &
%{ if (!$input) SWIG_CSharpThrowException(SWIG_CSharpNullReferenceException, "null string");
std::string $1_str($input);
$1 = &$1_str; %}
%typemap(out) const string & %{ $result = SWIG_csharp_string_callback($1->c_str()); %}
%typemap(csin) const string & "$csinput"
%typemap(csout) const string & {
return $imcall;
%typemap(csout, excode=SWIGEXCODE) const string & {
string ret = $imcall;$excode
return ret;
}
%typemap(csvarin) const string & %{
@ -78,7 +80,7 @@ class string;
%typemap(typecheck) const string & = char *;
%typemap(throws) const string & %{
%typemap(throws, canthrow=1) const string & %{
SWIG_CSharpThrowException(SWIG_CSharpException, $1.c_str());
%}

View file

@ -327,7 +327,7 @@ namespace std {
// Methods which can throw an Exception
%exception std::vector::vector(int capacity) {
%csexception std::vector::vector(int capacity) {
try {
$action
} catch (std::out_of_range& e) {
@ -335,7 +335,7 @@ namespace std {
}
}
%exception std::vector::getitemcopy {
%csexception std::vector::getitemcopy {
try {
$action
} catch (std::out_of_range& e) {
@ -343,7 +343,7 @@ namespace std {
}
}
%exception std::vector::getitem {
%csexception std::vector::getitem {
try {
$action
} catch (std::out_of_range& e) {
@ -351,7 +351,7 @@ namespace std {
}
}
%exception std::vector::setitem {
%csexception std::vector::setitem {
try {
$action
} catch (std::out_of_range& e) {
@ -359,7 +359,7 @@ namespace std {
}
}
%exception std::vector::GetRange {
%csexception std::vector::GetRange {
try {
$action
} catch (std::out_of_range& e) {
@ -369,7 +369,7 @@ namespace std {
}
}
%exception std::vector::Insert {
%csexception std::vector::Insert {
try {
$action
} catch (std::out_of_range& e) {
@ -377,7 +377,7 @@ namespace std {
}
}
%exception std::vector::InsertRange {
%csexception std::vector::InsertRange {
try {
$action
} catch (std::out_of_range& e) {
@ -385,7 +385,7 @@ namespace std {
}
}
%exception std::vector::RemoveAt {
%csexception std::vector::RemoveAt {
try {
$action
} catch (std::out_of_range& e) {
@ -393,7 +393,7 @@ namespace std {
}
}
%exception std::vector::Repeat {
%csexception std::vector::Repeat {
try {
$action
} catch (std::out_of_range& e) {
@ -401,7 +401,7 @@ namespace std {
}
}
%exception std::vector::RemoveRange {
%csexception std::vector::RemoveRange {
try {
$action
} catch (std::out_of_range& e) {
@ -411,7 +411,7 @@ namespace std {
}
}
%exception std::vector::Reverse(int index, int count) {
%csexception std::vector::Reverse(int index, int count) {
try {
$action
} catch (std::out_of_range& e) {
@ -421,7 +421,7 @@ namespace std {
}
}
%exception std::vector::SetRange {
%csexception std::vector::SetRange {
try {
$action
} catch (std::out_of_range& e) {