diff options
Diffstat (limited to 'Lib/csharp')
-rw-r--r-- | Lib/csharp/argcargv.i | 76 | ||||
-rw-r--r-- | Lib/csharp/arrays_csharp.i | 37 | ||||
-rw-r--r-- | Lib/csharp/boost_intrusive_ptr.i | 4 | ||||
-rw-r--r-- | Lib/csharp/boost_shared_ptr.i | 6 | ||||
-rw-r--r-- | Lib/csharp/csharp.swg | 89 | ||||
-rw-r--r-- | Lib/csharp/csharphead.swg | 2 | ||||
-rw-r--r-- | Lib/csharp/csharpkw.swg | 4 | ||||
-rw-r--r-- | Lib/csharp/std_array.i | 71 | ||||
-rw-r--r-- | Lib/csharp/std_auto_ptr.i | 51 | ||||
-rw-r--r-- | Lib/csharp/std_list.i | 2 | ||||
-rw-r--r-- | Lib/csharp/std_map.i | 30 | ||||
-rw-r--r-- | Lib/csharp/std_set.i | 11 | ||||
-rw-r--r-- | Lib/csharp/std_string.i | 8 | ||||
-rw-r--r-- | Lib/csharp/std_string_view.i | 116 | ||||
-rw-r--r-- | Lib/csharp/std_unique_ptr.i | 38 | ||||
-rw-r--r-- | Lib/csharp/std_unordered_map.i | 306 | ||||
-rw-r--r-- | Lib/csharp/std_unordered_set.i | 320 | ||||
-rw-r--r-- | Lib/csharp/std_vector.i | 29 | ||||
-rw-r--r-- | Lib/csharp/std_wstring.i | 66 | ||||
-rw-r--r-- | Lib/csharp/swigmove.i | 16 | ||||
-rw-r--r-- | Lib/csharp/typemaps.i | 49 | ||||
-rw-r--r-- | Lib/csharp/wchar.i | 266 |
22 files changed, 1433 insertions, 164 deletions
diff --git a/Lib/csharp/argcargv.i b/Lib/csharp/argcargv.i new file mode 100644 index 000000000..2dae1f6dc --- /dev/null +++ b/Lib/csharp/argcargv.i @@ -0,0 +1,76 @@ +/* ------------------------------------------------------------- + * SWIG library containing argc and argv multi-argument typemaps + * ------------------------------------------------------------- */ + +%typemap(cstype) (int ARGC, char **ARGV) "string[]" +%typemap(imtype) (int ARGC, char **ARGV) "global::System.IntPtr" +%typemap(ctype) (int ARGC, char **ARGV) "void*" +%typemap(csin) (int ARGC, char **ARGV) "$modulePINVOKE.SWIG_csharp_string_array_to_c($csinput.Length, $csinput)" +%pragma(csharp) imclasscode=%{ + [global::System.Runtime.InteropServices.DllImport("$module", EntryPoint="SWIG_csharp_string_array_to_c")] + public static extern global::System.IntPtr SWIG_csharp_string_array_to_c(int len, [global::System.Runtime.InteropServices.In,global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPArray, ArraySubType=global::System.Runtime.InteropServices.UnmanagedType.LPStr, SizeParamIndex=0)] string[] array); +%} +%fragment("SWIG_csharp_string_array", "header") %{ +#ifdef __cplusplus +extern "C" { +#endif +typedef struct { int len; char* array[1]; } SWIG_csharp_string_array; + +static void* SWIG_csharp_string_array_free(SWIG_csharp_string_array *arr) { + if (arr != SWIG_NULLPTR) { + int i; + for(i = 0; i < arr->len; i++) { + free(arr->array[i]); + } + free(arr); + } + return SWIG_NULLPTR; +} + +SWIGEXPORT void* SWIGSTDCALL SWIG_csharp_string_array_to_c(int len, void *array) { + int i; + size_t alen, slen; + char *p, **ptr; + SWIG_csharp_string_array *ret; + /* We don't need to add one to len for the terminating NULL here because + * SWIG_csharp_string_array includes one element already. + */ + alen = sizeof(SWIG_csharp_string_array) + sizeof(char *) * len; + ret = (SWIG_csharp_string_array *)malloc(alen); + if (ret == SWIG_NULLPTR) { + SWIG_CSharpSetPendingException(SWIG_CSharpOutOfMemoryException, "fail to duplicate array."); + return SWIG_NULLPTR; + } + memset(ret, 0, alen); + ret->len = len; + ptr = (char **)array; + for(i = 0; i < len; i++) { + slen = strlen(ptr[i]) + 1; + p = (char*)malloc(slen); + if (p == SWIG_NULLPTR) { + SWIG_CSharpSetPendingException(SWIG_CSharpOutOfMemoryException, "fail to alloc a string."); + return SWIG_csharp_string_array_free(ret); + } + memcpy(p, ptr[i], slen); + ret->array[i] = p; + } + ret->array[i] = SWIG_NULLPTR; + return ret; +} + +#ifdef __cplusplus +} +#endif +%} + +%typemap(in, canthrow=1, fragment="SWIG_csharp_string_array") (int ARGC, char **ARGV) %{ + SWIG_csharp_string_array *arr = (SWIG_csharp_string_array*)$input; + if (arr != SWIG_NULLPTR) { + $1 = ($1_ltype)arr->len; + $2 = ($2_ltype)arr->array; + } +%} + +%typemap(freearg, fragment="SWIG_csharp_string_array") (int ARGC, char **ARGV) %{ + SWIG_csharp_string_array_free((SWIG_csharp_string_array*)$input); +%} diff --git a/Lib/csharp/arrays_csharp.i b/Lib/csharp/arrays_csharp.i index 861da8386..00ded7187 100644 --- a/Lib/csharp/arrays_csharp.i +++ b/Lib/csharp/arrays_csharp.i @@ -49,8 +49,17 @@ * %csmethodmodifiers myArrayCopy "public unsafe"; * void myArrayCopy( int *sourceArray, int* targetArray, int nitems ); * + * long type + * --------- + * Unlike other primitive types, the sizeof(long) varies considerably from one + * platform to another. The sizeof(long) in the unmanaged layer must match the + * number of bytes used in the managed layer. A check is implemented via the + * "long_check_wordsize" fragment which results in a compile time error upon an + * inconsistent match. Use the SWIGWORDSIZE64 macro to target 64-bit long. + * For easiest portability, avoid using long! * ----------------------------------------------------------------------------- */ + %define CSHARP_ARRAYS( CTYPE, CSTYPE ) // input only arrays @@ -94,16 +103,23 @@ CSHARP_ARRAYS(short, short) CSHARP_ARRAYS(unsigned short, ushort) CSHARP_ARRAYS(int, int) CSHARP_ARRAYS(unsigned int, uint) -// FIXME - on Unix 64 bit, long is 8 bytes but is 4 bytes on Windows 64 bit. -// How can this be handled sensibly? -// See e.g. http://www.xml.com/ldd/chapter/book/ch10.html -CSHARP_ARRAYS(long, int) -CSHARP_ARRAYS(unsigned long, uint) CSHARP_ARRAYS(long long, long) CSHARP_ARRAYS(unsigned long long, ulong) CSHARP_ARRAYS(float, float) CSHARP_ARRAYS(double, double) +// 32-bit/64-bit architecture specific typemaps - special handling to ensure sizeof(long) on C side matches size used on C# side +#if !defined(SWIGWORDSIZE64) +CSHARP_ARRAYS(long, int) +CSHARP_ARRAYS(unsigned long, uint) +#else +CSHARP_ARRAYS(long, long) +CSHARP_ARRAYS(unsigned long, ulong) +#endif +%typemap(in, fragment="long_check_wordsize") long INPUT[], unsigned long INPUT[] "$1 = $input;" +%typemap(in, fragment="long_check_wordsize") long OUTPUT[], unsigned long OUTPUT[] "$1 = $input;" +%typemap(in, fragment="long_check_wordsize") long INOUT[], unsigned long INOUT[] "$1 = $input;" + // By default C# will marshal bools as 4 bytes // UnmanagedType.I1 will change this to 1 byte // FIXME - When running on mono ArraySubType appears to be ignored and bools will be marshalled as 4-byte @@ -169,11 +185,18 @@ CSHARP_ARRAYS_FIXED(short, short) CSHARP_ARRAYS_FIXED(unsigned short, ushort) CSHARP_ARRAYS_FIXED(int, int) CSHARP_ARRAYS_FIXED(unsigned int, uint) -CSHARP_ARRAYS_FIXED(long, int) -CSHARP_ARRAYS_FIXED(unsigned long, uint) CSHARP_ARRAYS_FIXED(long long, long) CSHARP_ARRAYS_FIXED(unsigned long long, ulong) CSHARP_ARRAYS_FIXED(float, float) CSHARP_ARRAYS_FIXED(double, double) CSHARP_ARRAYS_FIXED(bool, bool) +// 32-bit/64-bit architecture specific typemaps - special handling to ensure sizeof(long) on C side matches size used on C# side +#ifdef !SWIGWORDSIZE64 +CSHARP_ARRAYS_FIXED(long, int) +CSHARP_ARRAYS_FIXED(unsigned long, uint) +#else +CSHARP_ARRAYS_FIXED(long, long) +CSHARP_ARRAYS_FIXED(unsigned long, ulong) +#endif +%typemap(in, fragment="long_check_wordsize") long FIXED[], unsigned long FIXED[] "$1 = $input;" diff --git a/Lib/csharp/boost_intrusive_ptr.i b/Lib/csharp/boost_intrusive_ptr.i index fa3f53a20..355a910cf 100644 --- a/Lib/csharp/boost_intrusive_ptr.i +++ b/Lib/csharp/boost_intrusive_ptr.i @@ -32,7 +32,7 @@ %} %typemap(out, fragment="SWIG_intrusive_deleter") CONST TYPE %{ //plain value(out) - $1_ltype* resultp = new $1_ltype(($1_ltype &)$1); + $1_ltype* resultp = new $1_ltype($1); intrusive_ptr_add_ref(resultp); *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(resultp, SWIG_intrusive_deleter< CONST TYPE >()); %} @@ -372,7 +372,7 @@ } $1 = *argp; %} %typemap(out) CONST TYPE -%{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); %} +%{ *(SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > **)&$result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %} // plain pointer %typemap(in) CONST TYPE * (SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > *smartarg = 0) %{ diff --git a/Lib/csharp/boost_shared_ptr.i b/Lib/csharp/boost_shared_ptr.i index 508c0ec14..d47fab558 100644 --- a/Lib/csharp/boost_shared_ptr.i +++ b/Lib/csharp/boost_shared_ptr.i @@ -29,10 +29,10 @@ } $1 = *argp; %} %typemap(out) CONST TYPE -%{ $result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype(($1_ltype &)$1)); %} +%{ $result = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE >(new $1_ltype($1)); %} %typemap(directorin) CONST TYPE -%{ $input = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (new $1_ltype((const $1_ltype &)$1)); %} +%{ $input = new SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > (new $1_ltype(SWIG_STD_MOVE($1))); %} %typemap(directorout) CONST TYPE %{ if (!$input) { @@ -122,7 +122,7 @@ %typemap(in) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * ($*1_ltype tempnull) %{ $1 = $input ? ($1_ltype)$input : &tempnull; %} %typemap(out, fragment="SWIG_null_deleter") SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * -%{ $result = ($1 && *$1) ? new $*1_ltype(*($1_ltype)$1) : 0; +%{ $result = ($1 && *$1) ? new $*1_ltype(*$1) : 0; if ($owner) delete $1; %} %typemap(directorin) SWIG_SHARED_PTR_QNAMESPACE::shared_ptr< CONST TYPE > * diff --git a/Lib/csharp/csharp.swg b/Lib/csharp/csharp.swg index 832206386..fffde505c 100644 --- a/Lib/csharp/csharp.swg +++ b/Lib/csharp/csharp.swg @@ -82,8 +82,8 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %typemap(ctype) unsigned short, const unsigned short & "unsigned short" %typemap(ctype) int, const int & "int" %typemap(ctype) unsigned int, const unsigned int & "unsigned int" -%typemap(ctype) long, const long & "long" -%typemap(ctype) unsigned long, const unsigned long & "unsigned long" +%typemap(ctype) long, const long & "int" +%typemap(ctype) unsigned long, const unsigned long & "unsigned int" %typemap(ctype) long long, const long long & "long long" %typemap(ctype) unsigned long long, const unsigned long long & "unsigned long long" %typemap(ctype) float, const float & "float" @@ -201,9 +201,9 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %typemap(directorin) short "$input = $1;" %typemap(directorin) unsigned short "$input = $1;" %typemap(directorin) int "$input = $1;" -%typemap(directorin) unsigned int "$input = $1;" +%typemap(directorin) unsigned int "$input = (unsigned int)$1;" %typemap(directorin) long "$input = $1;" -%typemap(directorin) unsigned long "$input = (unsigned long)$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;" @@ -246,9 +246,9 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %typemap(out) short %{ $result = $1; %} %typemap(out) unsigned short %{ $result = $1; %} %typemap(out) int %{ $result = $1; %} -%typemap(out) unsigned int %{ $result = $1; %} +%typemap(out) unsigned int %{ $result = (unsigned int)$1; %} %typemap(out) long %{ $result = $1; %} -%typemap(out) unsigned long %{ $result = (unsigned long)$1; %} +%typemap(out) unsigned long %{ $result = $1; %} %typemap(out) long long %{ $result = $1; %} %typemap(out) unsigned long long %{ $result = $1; %} %typemap(out) float %{ $result = $1; %} @@ -327,7 +327,7 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %typemap(directorin) const short & "$input = $1;" %typemap(directorin) const unsigned short & "$input = $1;" %typemap(directorin) const int & "$input = $1;" -%typemap(directorin) const unsigned int & "$input = $1;" +%typemap(directorin) const unsigned int & "$input = (unsigned int)$1;" %typemap(directorin) const long & "$input = $1;" %typemap(directorin) const unsigned long & "$input = $1;" %typemap(directorin) const long long & "$input = $1;" @@ -373,9 +373,9 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %typemap(out) const short & %{ $result = *$1; %} %typemap(out) const unsigned short & %{ $result = *$1; %} %typemap(out) const int & %{ $result = *$1; %} -%typemap(out) const unsigned int & %{ $result = *$1; %} +%typemap(out) const unsigned int & %{ $result = (unsigned int)*$1; %} %typemap(out) const long & %{ $result = *$1; %} -%typemap(out) const unsigned long & %{ $result = (unsigned long)*$1; %} +%typemap(out) const unsigned long & %{ $result = *$1; %} %typemap(out) const long long & %{ $result = *$1; %} %typemap(out) const unsigned long long & %{ $result = *$1; %} %typemap(out) const float & %{ $result = *$1; %} @@ -399,7 +399,7 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %typemap(out) SWIGTYPE #ifdef __cplusplus -%{ $result = new $1_ltype((const $1_ltype &)$1); %} +%{ $result = new $1_ltype($1); %} #else { $&1_ltype $1ptr = ($&1_ltype) malloc(sizeof($1_ltype)); @@ -409,7 +409,7 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { #endif %typemap(directorin) SWIGTYPE -%{ $input = (void *)new $1_ltype((const $1_ltype &)$1); %} +%{ $input = (void *)new $1_ltype(SWIG_STD_MOVE($1)); %} %typemap(csdirectorin) SWIGTYPE "new $&csclassname($iminput, true)" %typemap(csdirectorout) SWIGTYPE "$&csclassname.getCPtr($cscall).Handle" @@ -420,14 +420,15 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %} %typemap(in, canthrow=1) SWIGTYPE & %{ $1 = ($1_ltype)$input; if (!$1) { - SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "$1_type type is null", 0); + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "$1_type is null", 0); return $null; } %} -%typemap(in, canthrow=1) SWIGTYPE && %{ $1 = ($1_ltype)$input; +%typemap(in, canthrow=1, fragment="<memory>") SWIGTYPE && (std::unique_ptr<$*1_ltype> rvrdeleter) %{ $1 = ($1_ltype)$input; if (!$1) { - SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "$1_type type is null", 0); + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "$1_type is null", 0); return $null; - } %} + } + rvrdeleter.reset($1); %} %typemap(out) SWIGTYPE * %{ $result = (void *)$1; %} %typemap(out, fragment="SWIG_PackData") SWIGTYPE (CLASS::*) %{ char buf[128]; @@ -578,7 +579,7 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { unsigned long, unsigned short %{ char error_msg[256]; - sprintf(error_msg, "C++ $1_type exception thrown, value: %d", $1); + SWIG_snprintf(error_msg, sizeof(error_msg), "C++ $1_type exception thrown, value: %d", $1); SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, error_msg); return $null; %} @@ -613,7 +614,8 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { "$csinput" %typemap(csin) char *, char *&, char[ANY], char[] "$csinput" %typemap(csin) SWIGTYPE "$&csclassname.getCPtr($csinput)" -%typemap(csin) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] "$csclassname.getCPtr($csinput)" +%typemap(csin) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] "$csclassname.getCPtr($csinput)" +%typemap(csin) SWIGTYPE && "$csclassname.swigRelease($csinput)" %typemap(csin) SWIGTYPE (CLASS::*) "$csclassname.getCMemberPtr($csinput)" /* The csout typemap is used for converting function return types from the return type @@ -875,6 +877,15 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { global::System.IntPtr ret = $imcall;$excode return ret; } +%typemap(csvarin, excode=SWIGEXCODE2) void *VOID_INT_PTR %{ + set { + $imcall;$excode + } %} +%typemap(csvarout, excode=SWIGEXCODE2) void *VOID_INT_PTR %{ + get { + global::System.IntPtr ret = $imcall;$excode + return ret; + } %} %typemap(csdirectorin) void *VOID_INT_PTR "$iminput" %typemap(csdirectorout) void *VOID_INT_PTR "$cscall" @@ -885,6 +896,7 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { %typemap(csinterfaces) SWIGTYPE "global::System.IDisposable" %typemap(csinterfaces) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [], SWIGTYPE (CLASS::*) "" %typemap(csinterfaces_derived) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [], SWIGTYPE (CLASS::*) "" +%typemap(csinterfacemodifiers) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [], SWIGTYPE (CLASS::*) "public interface" // csbody typemaps... these are in macros so that the visibility of the methods can be easily changed by users. @@ -903,6 +915,19 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef getCPtr($csclassname obj) { return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; } + + CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef swigRelease($csclassname obj) { + if (obj != null) { + if (!obj.swigCMemOwn) + throw new global::System.ApplicationException("Cannot release ownership as memory is not owned"); + global::System.Runtime.InteropServices.HandleRef ptr = obj.swigCPtr; + obj.swigCMemOwn = false; + obj.Dispose(); + return ptr; + } else { + return new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + } %} // Derived proxy classes @@ -916,6 +941,19 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef getCPtr($csclassname obj) { return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; } + + CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef swigRelease($csclassname obj) { + if (obj != null) { + if (!obj.swigCMemOwn) + throw new global::System.ApplicationException("Cannot release ownership as memory is not owned"); + global::System.Runtime.InteropServices.HandleRef ptr = obj.swigCPtr; + obj.swigCMemOwn = false; + obj.Dispose(); + return ptr; + } else { + return new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero); + } + } %} %enddef @@ -935,6 +973,10 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) { CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef getCPtr($csclassname obj) { return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; } + + CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef swigRelease($csclassname obj) { + return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; + } %} %typemap(csbody) TYPE (CLASS::*) %{ @@ -1020,10 +1062,17 @@ SWIG_CSBODY_TYPEWRAPPER(internal, protected, internal, SWIGTYPE) %pragma(csharp) imclassclassmodifiers="class" %pragma(csharp) moduleclassmodifiers="public class" -/* Some ANSI C typemaps */ +/* 64-bit architecture specific typemaps */ +#if defined(SWIGWORDSIZE64) +%apply long long { long }; +%apply unsigned long long { unsigned long }; +%apply const long long & { const long & }; +%apply const unsigned long long & { const unsigned long & }; +#endif -%apply unsigned long { size_t }; -%apply const unsigned long & { const size_t & }; +/* size_t maps to C# 32-bit uint type */ +%apply unsigned int { size_t }; +%apply const unsigned int & { const size_t & }; /* Array reference typemaps */ %apply SWIGTYPE & { SWIGTYPE ((&)[ANY]) } diff --git a/Lib/csharp/csharphead.swg b/Lib/csharp/csharphead.swg index 7db4c0e3c..56a019bd5 100644 --- a/Lib/csharp/csharphead.swg +++ b/Lib/csharp/csharphead.swg @@ -335,5 +335,5 @@ SWIGEXPORT void SWIGSTDCALL SWIGRegisterStringCallback_$module(SWIG_CSharpString %insert(runtime) %{ /* Contract support */ -#define SWIG_contract_assert(nullreturn, expr, msg) if (!(expr)) {SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentOutOfRangeException, msg, ""); return nullreturn; } else +#define SWIG_contract_assert(nullreturn, expr, msg) do { if (!(expr)) {SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentOutOfRangeException, msg, ""); return nullreturn; } } while (0) %} diff --git a/Lib/csharp/csharpkw.swg b/Lib/csharp/csharpkw.swg index 824f61874..1904fce94 100644 --- a/Lib/csharp/csharpkw.swg +++ b/Lib/csharp/csharpkw.swg @@ -2,9 +2,9 @@ #define CSHARP_CSHARPKW_SWG_ /* Warnings for C# keywords */ -#define CSHARPKW(x) %keywordwarn("'" `x` "' is a C# keyword, renaming to '" `x` "_'",rename="%s_") `x` +#define CSHARPKW(x) %keywordwarn("'" `x` "' is a C# keyword",rename="%s_") `x` -#define CSHARPCLASSKW(x) %keywordwarn("'" `x` "' is a special method name used in the C# wrapper classes, class renamed to '" `x` "_'",%$isclass,rename="%s_") `x` +#define CSHARPCLASSKW(x) %keywordwarn("'" `x` "' is a special method name used in the C# wrapper classes",%$isclass,rename="%s_") `x` /* from diff --git a/Lib/csharp/std_array.i b/Lib/csharp/std_array.i index a4f0f9640..87b1b8956 100644 --- a/Lib/csharp/std_array.i +++ b/Lib/csharp/std_array.i @@ -6,37 +6,37 @@ * The C# wrapper is made to look and feel like a C# System.Collections.Generic.IReadOnlyList<> collection. * ----------------------------------------------------------------------------- */ -%{ -#include <algorithm> -#include <array> -#include <stdexcept> -%} - %include <std_common.i> -%define SWIG_STD_ARRAY_INTERNAL(T, N) -%typemap(csinterfaces) std::array< T, N > "global::System.IDisposable, global::System.Collections.IEnumerable\n , global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)>\n"; +%define SWIG_STD_ARRAY_INTERNAL(CTYPE, N) +%typemap(csinterfaces) std::array< CTYPE, N > "global::System.IDisposable, global::System.Collections.IEnumerable\n , global::System.Collections.Generic.IEnumerable<$typemap(cstype, CTYPE)>\n" %proxycode %{ public $csclassname(global::System.Collections.ICollection c) : this() { if (c == null) throw new global::System.ArgumentNullException("c"); - int end = global::System.Math.Min(this.Count, c.Count); + int count = this.Count; int i = 0; - foreach ($typemap(cstype, T) elem in c) { - if (i >= end) + foreach ($typemap(cstype, CTYPE) element in c) { + if (i >= count) break; - this[i++] = elem; + this[i++] = element; } } - public int Count { + public bool IsFixedSize { get { - return (int)size(); + return true; } } - public $typemap(cstype, T) this[int index] { + public bool IsReadOnly { + get { + return false; + } + } + + public $typemap(cstype, CTYPE) this[int index] { get { return getitem(index); } @@ -51,17 +51,29 @@ } } - public void CopyTo($typemap(cstype, T)[] array) + public int Count { + get { + return (int)size(); + } + } + + public bool IsSynchronized { + get { + return false; + } + } + + public void CopyTo($typemap(cstype, CTYPE)[] array) { CopyTo(0, array, 0, this.Count); } - public void CopyTo($typemap(cstype, T)[] array, int arrayIndex) + public void CopyTo($typemap(cstype, CTYPE)[] array, int arrayIndex) { CopyTo(0, array, arrayIndex, this.Count); } - public void CopyTo(int index, $typemap(cstype, T)[] array, int arrayIndex, int count) + public void CopyTo(int index, $typemap(cstype, CTYPE)[] array, int arrayIndex, int count) { if (array == null) throw new global::System.ArgumentNullException("array"); @@ -79,7 +91,13 @@ array.SetValue(getitemcopy(index+i), arrayIndex+i); } - global::System.Collections.Generic.IEnumerator<$typemap(cstype, T)> global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)>.GetEnumerator() { + public $typemap(cstype, CTYPE)[] ToArray() { + $typemap(cstype, CTYPE)[] array = new $typemap(cstype, CTYPE)[this.Count]; + this.CopyTo(array); + return array; + } + + global::System.Collections.Generic.IEnumerator<$typemap(cstype, CTYPE)> global::System.Collections.Generic.IEnumerable<$typemap(cstype, CTYPE)>.GetEnumerator() { return new $csclassnameEnumerator(this); } @@ -97,7 +115,7 @@ /// collection but not when one of the elements of the collection is modified as it is a bit /// tricky to detect unmanaged code that modifies the collection under our feet. public sealed class $csclassnameEnumerator : global::System.Collections.IEnumerator - , global::System.Collections.Generic.IEnumerator<$typemap(cstype, T)> + , global::System.Collections.Generic.IEnumerator<$typemap(cstype, CTYPE)> { private $csclassname collectionRef; private int currentIndex; @@ -112,7 +130,7 @@ } // Type-safe iterator Current - public $typemap(cstype, T) Current { + public $typemap(cstype, CTYPE) Current { get { if (currentIndex == -1) throw new global::System.InvalidOperationException("Enumeration not started."); @@ -120,7 +138,7 @@ throw new global::System.InvalidOperationException("Enumeration finished."); if (currentObject == null) throw new global::System.InvalidOperationException("Collection modified."); - return ($typemap(cstype, T))currentObject; + return ($typemap(cstype, CTYPE))currentObject; } } @@ -161,7 +179,7 @@ public: typedef size_t size_type; typedef ptrdiff_t difference_type; - typedef T value_type; + typedef CTYPE value_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type& reference; @@ -180,7 +198,7 @@ void swap(array& other); %extend { - T getitemcopy(int index) throw (std::out_of_range) { + CTYPE getitemcopy(int index) throw (std::out_of_range) { if (index>=0 && index<(int)$self->size()) return (*$self)[index]; else @@ -213,6 +231,11 @@ } %enddef +%{ +#include <array> +#include <algorithm> +#include <stdexcept> +%} %csmethodmodifiers std::array::empty "private" %csmethodmodifiers std::array::getitemcopy "private" diff --git a/Lib/csharp/std_auto_ptr.i b/Lib/csharp/std_auto_ptr.i index d7e5f167e..da15df3e9 100644 --- a/Lib/csharp/std_auto_ptr.i +++ b/Lib/csharp/std_auto_ptr.i @@ -1,25 +1,38 @@ -/* - The typemaps here allow to handle functions returning std::auto_ptr<>, - which is the most common use of this type. If you have functions taking it - as parameter, these typemaps can't be used for them and you need to do - something else (e.g. use shared_ptr<> which SWIG supports fully). - */ +/* ----------------------------------------------------------------------------- + * std_auto_ptr.i + * + * SWIG library file for handling std::auto_ptr. + * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy + * class when returning a std::auto_ptr from a function. + * Memory ownership is passed from the proxy class to the std::auto_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ %define %auto_ptr(TYPE) -%typemap (ctype) std::auto_ptr<TYPE > "void *" -%typemap (imtype, out="System.IntPtr") std::auto_ptr<TYPE > "HandleRef" -%typemap (cstype) std::auto_ptr<TYPE > "$typemap(cstype, TYPE)" -%typemap (out) std::auto_ptr<TYPE > %{ - $result = (void *)$1.release(); +%typemap (ctype) std::auto_ptr< TYPE > "void *" +%typemap (imtype, out="System.IntPtr") std::auto_ptr< TYPE > "global::System.Runtime.InteropServices.HandleRef" +%typemap (cstype) std::auto_ptr< TYPE > "$typemap(cstype, TYPE)" + +%typemap(in) std::auto_ptr< TYPE > +%{ $1.reset((TYPE *)$input); %} + +%typemap(csin) std::auto_ptr< TYPE > "$typemap(cstype, TYPE).swigRelease($csinput)" + +%typemap (out) std::auto_ptr< TYPE > %{ + $result = (void *)$1.release(); %} -%typemap(csout, excode=SWIGEXCODE) std::auto_ptr<TYPE > { - System.IntPtr cPtr = $imcall; - $typemap(cstype, TYPE) ret = (cPtr == System.IntPtr.Zero) ? null : new $typemap(cstype, TYPE)(cPtr, true);$excode - return ret; - } -%template() std::auto_ptr<TYPE >; + +%typemap(csout, excode=SWIGEXCODE) std::auto_ptr< TYPE > { + System.IntPtr cPtr = $imcall; + $typemap(cstype, TYPE) ret = (cPtr == System.IntPtr.Zero) ? null : new $typemap(cstype, TYPE)(cPtr, true);$excode + return ret; + } + +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") std::auto_ptr< TYPE > "" + +%template() std::auto_ptr< TYPE >; %enddef namespace std { - template <class T> class auto_ptr {}; -} + template <class T> class auto_ptr {}; +} diff --git a/Lib/csharp/std_list.i b/Lib/csharp/std_list.i index 674aba0ab..cf6f20238 100644 --- a/Lib/csharp/std_list.i +++ b/Lib/csharp/std_list.i @@ -19,7 +19,7 @@ // MACRO for use within the std::list class body %define SWIG_STD_LIST_MINIMUM_INTERNAL(CSINTERFACE, CTYPE...) -%typemap(csinterfaces) std::list< CTYPE > "global::System.IDisposable, global::System.Collections.IEnumerable, global::System.Collections.Generic.CSINTERFACE<$typemap(cstype, CTYPE)>\n"; +%typemap(csinterfaces) std::list< CTYPE > "global::System.IDisposable, global::System.Collections.IEnumerable, global::System.Collections.Generic.CSINTERFACE<$typemap(cstype, CTYPE)>\n" %apply void *VOID_INT_PTR { std::list< CTYPE >::iterator * }; diff --git a/Lib/csharp/std_map.i b/Lib/csharp/std_map.i index e538a03a1..4f447422a 100644 --- a/Lib/csharp/std_map.i +++ b/Lib/csharp/std_map.i @@ -26,7 +26,7 @@ /* K is the C++ key type, T is the C++ value type */ %define SWIG_STD_MAP_INTERNAL(K, T, C) -%typemap(csinterfaces) std::map< K, T, C > "global::System.IDisposable \n , global::System.Collections.Generic.IDictionary<$typemap(cstype, K), $typemap(cstype, T)>\n"; +%typemap(csinterfaces) std::map< K, T, C > "global::System.IDisposable \n , global::System.Collections.Generic.IDictionary<$typemap(cstype, K), $typemap(cstype, T)>\n" %proxycode %{ public $typemap(cstype, T) this[$typemap(cstype, K) key] { @@ -48,6 +48,12 @@ return false; } + public bool IsEmpty { + get { + return empty(); + } + } + public int Count { get { return (int)size(); @@ -236,7 +242,11 @@ } void setitem(const key_type& key, const mapped_type& x) { +%#ifdef __cpp_lib_map_try_emplace + (*$self).insert_or_assign(key, x); +%#else (*$self)[key] = x; +%#endif } bool ContainsKey(const key_type& key) { @@ -269,12 +279,14 @@ } const key_type& get_next_key(std::map< K, T, C >::iterator *swigiterator) { + (void)$self; std::map< K, T, C >::iterator iter = *swigiterator; (*swigiterator)++; return (*iter).first; } void destroy_iterator(std::map< K, T, C >::iterator *swigiterator) { + (void)$self; delete swigiterator; } } @@ -282,6 +294,7 @@ %enddef +%csmethodmodifiers std::map::empty "private" %csmethodmodifiers std::map::size "private" %csmethodmodifiers std::map::getitem "private" %csmethodmodifiers std::map::setitem "private" @@ -295,18 +308,3 @@ namespace std { SWIG_STD_MAP_INTERNAL(K, T, C) }; } - - -// Legacy macros (deprecated) -%define specialize_std_map_on_key(K,CHECK,CONVERT_FROM,CONVERT_TO) -#warning "specialize_std_map_on_key ignored - macro is deprecated and no longer necessary" -%enddef - -%define specialize_std_map_on_value(T,CHECK,CONVERT_FROM,CONVERT_TO) -#warning "specialize_std_map_on_value ignored - macro is deprecated and no longer necessary" -%enddef - -%define specialize_std_map_on_both(K,CHECK_K,CONVERT_K_FROM,CONVERT_K_TO, T,CHECK_T,CONVERT_T_FROM,CONVERT_T_TO) -#warning "specialize_std_map_on_both ignored - macro is deprecated and no longer necessary" -%enddef - diff --git a/Lib/csharp/std_set.i b/Lib/csharp/std_set.i index 82f010aff..480a24cc7 100644 --- a/Lib/csharp/std_set.i +++ b/Lib/csharp/std_set.i @@ -16,6 +16,7 @@ #include <stdexcept> %} +%csmethodmodifiers std::set::empty "private" %csmethodmodifiers std::set::size "private" %csmethodmodifiers std::set::getitem "private" %csmethodmodifiers std::set::create_iterator_begin "private" @@ -28,7 +29,7 @@ namespace std { template <class T> class set { -%typemap(csinterfaces) std::set<T> "global::System.IDisposable, global::System.Collections.Generic.ISet<$typemap(cstype, T)>\n"; +%typemap(csinterfaces) std::set<T> "global::System.IDisposable, global::System.Collections.Generic.ISet<$typemap(cstype, T)>\n" %proxycode %{ void global::System.Collections.Generic.ICollection<$typemap(cstype, T)>.Add($typemap(cstype, T) item) { ((global::System.Collections.Generic.ISet<$typemap(cstype, T)>)this).Add(item); @@ -44,6 +45,12 @@ class set { } } + public bool IsEmpty { + get { + return empty(); + } + } + public int Count { get { return (int)size(); @@ -297,12 +304,14 @@ class set { } const key_type& get_next(std::set<T>::iterator *swigiterator) { + (void)$self; std::set<T>::iterator iter = *swigiterator; (*swigiterator)++; return *iter; } void destroy_iterator(std::set<T>::iterator *swigiterator) { + (void)$self; delete swigiterator; } } diff --git a/Lib/csharp/std_string.i b/Lib/csharp/std_string.i index 5f8fa44cb..c8920c09e 100644 --- a/Lib/csharp/std_string.i +++ b/Lib/csharp/std_string.i @@ -20,7 +20,7 @@ namespace std { class string; // string -%typemap(ctype) string "char *" +%typemap(ctype) string "const char *" %typemap(imtype) string "string" %typemap(cstype) string "string" @@ -42,7 +42,7 @@ class string; } $result.assign($input); %} -%typemap(directorin) string %{ $input = SWIG_csharp_string_callback($1.c_str()); %} +%typemap(directorin) string %{ $input = $1.c_str(); %} %typemap(csin) string "$csinput" %typemap(csout, excode=SWIGEXCODE) string { @@ -57,7 +57,7 @@ class string; return $null; %} // const string & -%typemap(ctype) const string & "char *" +%typemap(ctype) const string & "const char *" %typemap(imtype) const string & "string" %typemap(cstype) const string & "string" @@ -89,7 +89,7 @@ class string; $1_str = $input; $result = &$1_str; %} -%typemap(directorin) const string & %{ $input = SWIG_csharp_string_callback($1.c_str()); %} +%typemap(directorin) const string & %{ $input = $1.c_str(); %} %typemap(csvarin, excode=SWIGEXCODE2) const string & %{ set { diff --git a/Lib/csharp/std_string_view.i b/Lib/csharp/std_string_view.i new file mode 100644 index 000000000..3b6cd40ef --- /dev/null +++ b/Lib/csharp/std_string_view.i @@ -0,0 +1,116 @@ +/* ----------------------------------------------------------------------------- + * std_string_view.i + * + * Typemaps for std::string_view and const std::string_view& + * These are mapped to a C# String and are passed around by value. + * + * To use non-const std::string_view references use the following %apply. Note + * that they are passed by value. + * %apply const std::string_view & {std::string_view &}; + * ----------------------------------------------------------------------------- */ + +%{ +#include <string_view> +#include <string> +%} + +namespace std { + +%naturalvar string_view; + +class string_view; + +// string_view +%typemap(ctype) string_view "const char *" +%typemap(imtype) string_view "string" +%typemap(cstype) string_view "string" + +%typemap(csdirectorin) string_view "$iminput" +%typemap(csdirectorout) string_view "$cscall" + +%typemap(in, canthrow=1) string_view +%{ if (!$input) { + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null string", 0); + return $null; + } + $1 = std::string_view($input); %} +%typemap(out) string_view %{ $result = SWIG_csharp_string_callback(std::string($1).c_str()); %} + +%typemap(directorout, canthrow=1, warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) string_view +%{ if (!$input) { + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null string", 0); + return $null; + } + /* possible thread/reentrant code problem */ + static std::string $1_str; + $1_str = $input; + $result = std::string_view($1_str); %} + +%typemap(directorin) string_view %{ $input = std::string($1).c_str(); %} + +%typemap(csin) string_view "$csinput" +%typemap(csout, excode=SWIGEXCODE) string_view { + string ret = $imcall;$excode + return ret; + } + +%typemap(typecheck) string_view = char *; + +%typemap(throws, canthrow=1) string_view +%{ SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, std::string($1).c_str()); + return $null; %} + +// const string_view & +%typemap(ctype) const string_view & "const char *" +%typemap(imtype) const string_view & "string" +%typemap(cstype) const string_view & "string" + +%typemap(csdirectorin) const string_view & "$iminput" +%typemap(csdirectorout) const string_view & "$cscall" + +%typemap(in, canthrow=1) const string_view & +%{ if (!$input) { + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null string", 0); + return $null; + } + $*1_ltype $1_str($input); + $1 = &$1_str; %} +%typemap(out) const string_view & %{ $result = SWIG_csharp_string_callback(std::string(*$1).c_str()); %} + +%typemap(csin) const string_view & "$csinput" +%typemap(csout, excode=SWIGEXCODE) const string_view & { + string ret = $imcall;$excode + return ret; + } + +%typemap(directorout, canthrow=1, warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) const string_view & +%{ if (!$input) { + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null string", 0); + return $null; + } + /* possible thread/reentrant code problem */ + static std::string $1_str; + $1_str = $input; + static $*1_ltype $1_strview; + $1_strview = $1_str; + $result = &$1_strview; %} + +%typemap(directorin) const string_view & %{ $input = std::string($1).c_str(); %} + +%typemap(csvarin, excode=SWIGEXCODE2) const string_view & %{ + set { + $imcall;$excode + } %} +%typemap(csvarout, excode=SWIGEXCODE2) const string_view & %{ + get { + string ret = $imcall;$excode + return ret; + } %} + +%typemap(typecheck) const string_view & = char *; + +%typemap(throws, canthrow=1) const string_view & +%{ SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, std::string($1).c_str()); + return $null; %} + +} diff --git a/Lib/csharp/std_unique_ptr.i b/Lib/csharp/std_unique_ptr.i new file mode 100644 index 000000000..0a4caafbc --- /dev/null +++ b/Lib/csharp/std_unique_ptr.i @@ -0,0 +1,38 @@ +/* ----------------------------------------------------------------------------- + * std_unique_ptr.i + * + * SWIG library file for handling std::unique_ptr. + * Memory ownership is passed from the std::unique_ptr C++ layer to the proxy + * class when returning a std::unique_ptr from a function. + * Memory ownership is passed from the proxy class to the std::unique_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%define %unique_ptr(TYPE) +%typemap (ctype) std::unique_ptr< TYPE > "void *" +%typemap (imtype, out="System.IntPtr") std::unique_ptr< TYPE > "global::System.Runtime.InteropServices.HandleRef" +%typemap (cstype) std::unique_ptr< TYPE > "$typemap(cstype, TYPE)" + +%typemap(in) std::unique_ptr< TYPE > +%{ $1.reset((TYPE *)$input); %} + +%typemap(csin) std::unique_ptr< TYPE > "$typemap(cstype, TYPE).swigRelease($csinput)" + +%typemap (out) std::unique_ptr< TYPE > %{ + $result = (void *)$1.release(); +%} + +%typemap(csout, excode=SWIGEXCODE) std::unique_ptr< TYPE > { + System.IntPtr cPtr = $imcall; + $typemap(cstype, TYPE) ret = (cPtr == System.IntPtr.Zero) ? null : new $typemap(cstype, TYPE)(cPtr, true);$excode + return ret; + } + +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *") std::unique_ptr< TYPE > "" + +%template() std::unique_ptr< TYPE >; +%enddef + +namespace std { + template <class T> class unique_ptr {}; +} diff --git a/Lib/csharp/std_unordered_map.i b/Lib/csharp/std_unordered_map.i new file mode 100644 index 000000000..f8145e372 --- /dev/null +++ b/Lib/csharp/std_unordered_map.i @@ -0,0 +1,306 @@ +/* ----------------------------------------------------------------------------- + * std_unordered_map.i + * + * SWIG typemaps for std::unordered_map< K, T, H > + * + * The C# wrapper is made to look and feel like a C# System.Collections.Generic.IDictionary<>. + * + * Using this wrapper is fairly simple. For example, to create an unordered_map from integers to doubles use: + * + * %include <std_unordered_map.i> + * %template(MapIntDouble) std::unordered_map<int, double> + * + * Notes: + * 1) IEnumerable<> is implemented in the proxy class which is useful for using LINQ with + * C++ std::unordered_map wrappers. + * + * Warning: heavy macro usage in this file. Use swig -E to get a sane view on the real file contents! + * ----------------------------------------------------------------------------- */ + +%{ +#include <unordered_map> +#include <algorithm> +#include <stdexcept> +%} + +/* K is the C++ key type, T is the C++ value type */ +%define SWIG_STD_UNORDERED_MAP_INTERNAL(K, T, H) + +%typemap(csinterfaces) std::unordered_map< K, T, H > "global::System.IDisposable \n , global::System.Collections.Generic.IDictionary<$typemap(cstype, K), $typemap(cstype, T)>\n" +%proxycode %{ + + public $typemap(cstype, T) this[$typemap(cstype, K) key] { + get { + return getitem(key); + } + + set { + setitem(key, value); + } + } + + public bool TryGetValue($typemap(cstype, K) key, out $typemap(cstype, T) value) { + if (this.ContainsKey(key)) { + value = this[key]; + return true; + } + value = default($typemap(cstype, T)); + return false; + } + + public bool IsEmpty { + get { + return empty(); + } + } + + public int Count { + get { + return (int)size(); + } + } + + public bool IsReadOnly { + get { + return false; + } + } + + public global::System.Collections.Generic.ICollection<$typemap(cstype, K)> Keys { + get { + global::System.Collections.Generic.ICollection<$typemap(cstype, K)> keys = new global::System.Collections.Generic.List<$typemap(cstype, K)>(); + int size = this.Count; + if (size > 0) { + global::System.IntPtr iter = create_iterator_begin(); + for (int i = 0; i < size; i++) { + keys.Add(get_next_key(iter)); + } + destroy_iterator(iter); + } + return keys; + } + } + + public global::System.Collections.Generic.ICollection<$typemap(cstype, T)> Values { + get { + global::System.Collections.Generic.ICollection<$typemap(cstype, T)> vals = new global::System.Collections.Generic.List<$typemap(cstype, T)>(); + foreach (global::System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)> pair in this) { + vals.Add(pair.Value); + } + return vals; + } + } + + public void Add(global::System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)> item) { + Add(item.Key, item.Value); + } + + public bool Remove(global::System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)> item) { + if (Contains(item)) { + return Remove(item.Key); + } else { + return false; + } + } + + public bool Contains(global::System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)> item) { + if (this[item.Key] == item.Value) { + return true; + } else { + return false; + } + } + + public void CopyTo(global::System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>[] array) { + CopyTo(array, 0); + } + + public void CopyTo(global::System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>[] array, int arrayIndex) { + if (array == null) + throw new global::System.ArgumentNullException("array"); + if (arrayIndex < 0) + throw new global::System.ArgumentOutOfRangeException("arrayIndex", "Value is less than zero"); + if (array.Rank > 1) + throw new global::System.ArgumentException("Multi dimensional array.", "array"); + if (arrayIndex+this.Count > array.Length) + throw new global::System.ArgumentException("Number of elements to copy is too large."); + + global::System.Collections.Generic.IList<$typemap(cstype, K)> keyList = new global::System.Collections.Generic.List<$typemap(cstype, K)>(this.Keys); + for (int i = 0; i < keyList.Count; i++) { + $typemap(cstype, K) currentKey = keyList[i]; + array.SetValue(new global::System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>(currentKey, this[currentKey]), arrayIndex+i); + } + } + + global::System.Collections.Generic.IEnumerator<global::System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>> global::System.Collections.Generic.IEnumerable<global::System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>>.GetEnumerator() { + return new $csclassnameEnumerator(this); + } + + global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() { + return new $csclassnameEnumerator(this); + } + + public $csclassnameEnumerator GetEnumerator() { + return new $csclassnameEnumerator(this); + } + + // Type-safe enumerator + /// Note that the IEnumerator documentation requires an InvalidOperationException to be thrown + /// whenever the collection is modified. This has been done for changes in the size of the + /// collection but not when one of the elements of the collection is modified as it is a bit + /// tricky to detect unmanaged code that modifies the collection under our feet. + public sealed class $csclassnameEnumerator : global::System.Collections.IEnumerator, + global::System.Collections.Generic.IEnumerator<global::System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>> + { + private $csclassname collectionRef; + private global::System.Collections.Generic.IList<$typemap(cstype, K)> keyCollection; + private int currentIndex; + private object currentObject; + private int currentSize; + + public $csclassnameEnumerator($csclassname collection) { + collectionRef = collection; + keyCollection = new global::System.Collections.Generic.List<$typemap(cstype, K)>(collection.Keys); + currentIndex = -1; + currentObject = null; + currentSize = collectionRef.Count; + } + + // Type-safe iterator Current + public global::System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)> Current { + get { + if (currentIndex == -1) + throw new global::System.InvalidOperationException("Enumeration not started."); + if (currentIndex > currentSize - 1) + throw new global::System.InvalidOperationException("Enumeration finished."); + if (currentObject == null) + throw new global::System.InvalidOperationException("Collection modified."); + return (global::System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>)currentObject; + } + } + + // Type-unsafe IEnumerator.Current + object global::System.Collections.IEnumerator.Current { + get { + return Current; + } + } + + public bool MoveNext() { + int size = collectionRef.Count; + bool moveOkay = (currentIndex+1 < size) && (size == currentSize); + if (moveOkay) { + currentIndex++; + $typemap(cstype, K) currentKey = keyCollection[currentIndex]; + currentObject = new global::System.Collections.Generic.KeyValuePair<$typemap(cstype, K), $typemap(cstype, T)>(currentKey, collectionRef[currentKey]); + } else { + currentObject = null; + } + return moveOkay; + } + + public void Reset() { + currentIndex = -1; + currentObject = null; + if (collectionRef.Count != currentSize) { + throw new global::System.InvalidOperationException("Collection modified."); + } + } + + public void Dispose() { + currentIndex = -1; + currentObject = null; + } + } + +%} + + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef K key_type; + typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + unordered_map(); + unordered_map(const unordered_map& other); + size_type size() const; + bool empty() const; + %rename(Clear) clear; + void clear(); + %extend { + const mapped_type& getitem(const key_type& key) throw (std::out_of_range) { + std::unordered_map< K, T, H >::iterator iter = $self->find(key); + if (iter != $self->end()) + return iter->second; + else + throw std::out_of_range("key not found"); + } + + void setitem(const key_type& key, const mapped_type& x) { + (*$self)[key] = x; + } + + bool ContainsKey(const key_type& key) { + std::unordered_map< K, T, H >::iterator iter = $self->find(key); + return iter != $self->end(); + } + + void Add(const key_type& key, const mapped_type& value) throw (std::out_of_range) { + std::unordered_map< K, T, H >::iterator iter = $self->find(key); + if (iter != $self->end()) + throw std::out_of_range("key already exists"); + $self->insert(std::pair< K, T >(key, value)); + } + + bool Remove(const key_type& key) { + std::unordered_map< K, T, H >::iterator iter = $self->find(key); + if (iter != $self->end()) { + $self->erase(iter); + return true; + } + return false; + } + + // create_iterator_begin(), get_next_key() and destroy_iterator work together to provide a collection of keys to C# + %apply void *VOID_INT_PTR { std::unordered_map< K, T, H >::iterator *create_iterator_begin } + %apply void *VOID_INT_PTR { std::unordered_map< K, T, H >::iterator *swigiterator } + + std::unordered_map< K, T, H >::iterator *create_iterator_begin() { + return new std::unordered_map< K, T, H >::iterator($self->begin()); + } + + const key_type& get_next_key(std::unordered_map< K, T, H >::iterator *swigiterator) { + (void)self; + std::unordered_map< K, T, H >::iterator iter = *swigiterator; + (*swigiterator)++; + return (*iter).first; + } + + void destroy_iterator(std::unordered_map< K, T, H >::iterator *swigiterator) { + (void)self; + delete swigiterator; + } + } + + +%enddef + +%csmethodmodifiers std::unordered_map::empty "private" +%csmethodmodifiers std::unordered_map::size "private" +%csmethodmodifiers std::unordered_map::getitem "private" +%csmethodmodifiers std::unordered_map::setitem "private" +%csmethodmodifiers std::unordered_map::create_iterator_begin "private" +%csmethodmodifiers std::unordered_map::get_next_key "private" +%csmethodmodifiers std::unordered_map::destroy_iterator "private" + +// Default implementation +namespace std { + template<class K, class T, class H = std::hash<K> > class unordered_map { + SWIG_STD_UNORDERED_MAP_INTERNAL(K, T, H) + }; +} diff --git a/Lib/csharp/std_unordered_set.i b/Lib/csharp/std_unordered_set.i new file mode 100644 index 000000000..d6f6a18f3 --- /dev/null +++ b/Lib/csharp/std_unordered_set.i @@ -0,0 +1,320 @@ +/* ----------------------------------------------------------------------------- + * std_unordered_set.i + * + * SWIG typemaps for std::unordered_set<T>. + * + * Note that ISet<> used here requires .NET 4 or later. + * + * The C# wrapper implements ISet<> interface and is similar in + * characteristics to the C# System.Collections.Generic.HashSet<> class, but + * doesn't provide quite all of its methods. + * ----------------------------------------------------------------------------- */ + +%{ +#include <unordered_set> +#include <algorithm> +#include <stdexcept> +%} + +%csmethodmodifiers std::unordered_set::empty "private" +%csmethodmodifiers std::unordered_set::size "private" +%csmethodmodifiers std::unordered_set::getitem "private" +%csmethodmodifiers std::unordered_set::create_iterator_begin "private" +%csmethodmodifiers std::unordered_set::get_next "private" +%csmethodmodifiers std::unordered_set::destroy_iterator "private" + +namespace std { + +// TODO: Add support for comparator and allocator template parameters. +template <class T> +class unordered_set { + +%typemap(csinterfaces) std::unordered_set<T> "global::System.IDisposable, global::System.Collections.Generic.ISet<$typemap(cstype, T)>\n" +%proxycode %{ + void global::System.Collections.Generic.ICollection<$typemap(cstype, T)>.Add($typemap(cstype, T) item) { + ((global::System.Collections.Generic.ISet<$typemap(cstype, T)>)this).Add(item); + } + + public bool TryGetValue($typemap(cstype, T) equalValue, out $typemap(cstype, T) actualValue) { + try { + actualValue = getitem(equalValue); + return true; + } catch { + actualValue = default($typemap(cstype, T)); + return false; + } + } + + public bool IsEmpty { + get { + return empty(); + } + } + + public int Count { + get { + return (int)size(); + } + } + + public bool IsReadOnly { + get { + return false; + } + } + + public void CopyTo($typemap(cstype, T)[] array) { + CopyTo(array, 0); + } + + public void CopyTo($typemap(cstype, T)[] array, int arrayIndex) { + if (array == null) + throw new global::System.ArgumentNullException("array"); + if (arrayIndex < 0) + throw new global::System.ArgumentOutOfRangeException("arrayIndex", "Value is less than zero"); + if (array.Rank > 1) + throw new global::System.ArgumentException("Multi dimensional array.", "array"); + if (arrayIndex+this.Count > array.Length) + throw new global::System.ArgumentException("Number of elements to copy is too large."); + + foreach ($typemap(cstype, T) item in this) { + array.SetValue(item, arrayIndex++); + } + } + + public void ExceptWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + foreach ($typemap(cstype, T) item in other) { + Remove(item); + } + } + + public void IntersectWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + $csclassname old = new $csclassname(this); + + Clear(); + foreach ($typemap(cstype, T) item in other) { + if (old.Contains(item)) + Add(item); + } + } + + private static int count_enum(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + int count = 0; + foreach ($typemap(cstype, T) item in other) { + count++; + } + + return count; + } + + public bool IsProperSubsetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + return IsSubsetOf(other) && Count < count_enum(other); + } + + public bool IsProperSupersetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + return IsSupersetOf(other) && Count > count_enum(other); + } + + public bool IsSubsetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + int countContained = 0; + + foreach ($typemap(cstype, T) item in other) { + if (Contains(item)) + countContained++; + } + + return countContained == Count; + } + + public bool IsSupersetOf(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + foreach ($typemap(cstype, T) item in other) { + if (!Contains(item)) + return false; + } + + return true; + } + + public bool Overlaps(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + foreach ($typemap(cstype, T) item in other) { + if (Contains(item)) + return true; + } + + return false; + } + + public bool SetEquals(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + return IsSupersetOf(other) && Count == count_enum(other); + } + + public void SymmetricExceptWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + foreach ($typemap(cstype, T) item in other) { + if (!Remove(item)) + Add(item); + } + } + + public void UnionWith(global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)> other) { + foreach ($typemap(cstype, T) item in other) { + Add(item); + } + } + + private global::System.Collections.Generic.ICollection<$typemap(cstype, T)> Items { + get { + global::System.Collections.Generic.ICollection<$typemap(cstype, T)> items = new global::System.Collections.Generic.List<$typemap(cstype, T)>(); + int size = this.Count; + if (size > 0) { + global::System.IntPtr iter = create_iterator_begin(); + for (int i = 0; i < size; i++) { + items.Add(get_next(iter)); + } + destroy_iterator(iter); + } + return items; + } + } + + global::System.Collections.Generic.IEnumerator<$typemap(cstype, T)> global::System.Collections.Generic.IEnumerable<$typemap(cstype, T)>.GetEnumerator() { + return new $csclassnameEnumerator(this); + } + + global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() { + return new $csclassnameEnumerator(this); + } + + public $csclassnameEnumerator GetEnumerator() { + return new $csclassnameEnumerator(this); + } + + // Type-safe enumerator + /// Note that the IEnumerator documentation requires an InvalidOperationException to be thrown + /// whenever the collection is modified. This has been done for changes in the size of the + /// collection but not when one of the elements of the collection is modified as it is a bit + /// tricky to detect unmanaged code that modifies the collection under our feet. + public sealed class $csclassnameEnumerator : global::System.Collections.IEnumerator, + global::System.Collections.Generic.IEnumerator<$typemap(cstype, T)> + { + private $csclassname collectionRef; + private global::System.Collections.Generic.IList<$typemap(cstype, T)> ItemsCollection; + private int currentIndex; + private object currentObject; + private int currentSize; + + public $csclassnameEnumerator($csclassname collection) { + collectionRef = collection; + ItemsCollection = new global::System.Collections.Generic.List<$typemap(cstype, T)>(collection.Items); + currentIndex = -1; + currentObject = null; + currentSize = collectionRef.Count; + } + + // Type-safe iterator Current + public $typemap(cstype, T) Current { + get { + if (currentIndex == -1) + throw new global::System.InvalidOperationException("Enumeration not started."); + if (currentIndex > currentSize - 1) + throw new global::System.InvalidOperationException("Enumeration finished."); + if (currentObject == null) + throw new global::System.InvalidOperationException("Collection modified."); + return ($typemap(cstype, T))currentObject; + } + } + + // Type-unsafe IEnumerator.Current + object global::System.Collections.IEnumerator.Current { + get { + return Current; + } + } + + public bool MoveNext() { + int size = collectionRef.Count; + bool moveOkay = (currentIndex+1 < size) && (size == currentSize); + if (moveOkay) { + currentIndex++; + currentObject = ItemsCollection[currentIndex]; + } else { + currentObject = null; + } + return moveOkay; + } + + public void Reset() { + currentIndex = -1; + currentObject = null; + if (collectionRef.Count != currentSize) { + throw new global::System.InvalidOperationException("Collection modified."); + } + } + + public void Dispose() { + currentIndex = -1; + currentObject = null; + } + } + +%} + + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T key_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + unordered_set(); + unordered_set(const unordered_set& other); + size_type size() const; + bool empty() const; + %rename(Clear) clear; + void clear(); + %extend { + bool Add(const value_type& item) { + return $self->insert(item).second; + } + + bool Contains(const value_type& item) { + return $self->count(item) != 0; + } + + bool Remove(const value_type& item) { + return $self->erase(item) != 0; + } + + const value_type& getitem(const value_type& item) throw (std::out_of_range) { + std::unordered_set<T>::iterator iter = $self->find(item); + if (iter == $self->end()) + throw std::out_of_range("item not found"); + + return *iter; + } + + // create_iterator_begin(), get_next() and destroy_iterator work together to provide a collection of items to C# + %apply void *VOID_INT_PTR { std::unordered_set<T>::iterator *create_iterator_begin } + %apply void *VOID_INT_PTR { std::unordered_set<T>::iterator *swigiterator } + + std::unordered_set<T>::iterator *create_iterator_begin() { + return new std::unordered_set<T>::iterator($self->begin()); + } + + const key_type& get_next(std::unordered_set<T>::iterator *swigiterator) { + (void)$self; + std::unordered_set<T>::iterator iter = *swigiterator; + (*swigiterator)++; + return *iter; + } + + void destroy_iterator(std::unordered_set<T>::iterator *swigiterator) { + (void)$self; + delete swigiterator; + } + } +}; + +} diff --git a/Lib/csharp/std_vector.i b/Lib/csharp/std_vector.i index e2811290c..982306e0d 100644 --- a/Lib/csharp/std_vector.i +++ b/Lib/csharp/std_vector.i @@ -19,7 +19,7 @@ // MACRO for use within the std::vector class body %define SWIG_STD_VECTOR_MINIMUM_INTERNAL(CSINTERFACE, CONST_REFERENCE, CTYPE...) -%typemap(csinterfaces) std::vector< CTYPE > "global::System.IDisposable, global::System.Collections.IEnumerable, global::System.Collections.Generic.CSINTERFACE<$typemap(cstype, CTYPE)>\n"; +%typemap(csinterfaces) std::vector< CTYPE > "global::System.IDisposable, global::System.Collections.IEnumerable, global::System.Collections.Generic.CSINTERFACE<$typemap(cstype, CTYPE)>\n" %proxycode %{ public $csclassname(global::System.Collections.IEnumerable c) : this() { if (c == null) @@ -63,12 +63,18 @@ return (int)capacity(); } set { - if (value < size()) + if (value < 0 || ($typemap(cstype, size_t))value < size()) throw new global::System.ArgumentOutOfRangeException("Capacity"); reserve(($typemap(cstype, size_t))value); } } + public bool IsEmpty { + get { + return empty(); + } + } + public int Count { get { return (int)size(); @@ -203,19 +209,20 @@ typedef value_type& reference; typedef CONST_REFERENCE const_reference; + vector(); + vector(const vector &other); + %rename(Clear) clear; void clear(); %rename(Add) push_back; void push_back(CTYPE const& x); size_type size() const; + bool empty() const; size_type capacity() const; void reserve(size_type n); %newobject GetRange(int index, int count); %newobject Repeat(CTYPE const& value, int count); - vector(); - vector(const vector &other); - %extend { vector(int capacity) throw (std::out_of_range) { std::vector< CTYPE >* pv = 0; @@ -357,22 +364,13 @@ namespace std { } %enddef -// Legacy macros -%define SWIG_STD_VECTOR_SPECIALIZE(CSTYPE, CTYPE...) -#warning SWIG_STD_VECTOR_SPECIALIZE macro deprecated, please see csharp/std_vector.i and switch to SWIG_STD_VECTOR_ENHANCED -SWIG_STD_VECTOR_ENHANCED(CTYPE) -%enddef - -%define SWIG_STD_VECTOR_SPECIALIZE_MINIMUM(CSTYPE, CTYPE...) -#warning SWIG_STD_VECTOR_SPECIALIZE_MINIMUM macro deprecated, it is no longer required -%enddef - %{ #include <vector> #include <algorithm> #include <stdexcept> %} +%csmethodmodifiers std::vector::empty "private" %csmethodmodifiers std::vector::getitemcopy "private" %csmethodmodifiers std::vector::getitem "private" %csmethodmodifiers std::vector::setitem "private" @@ -415,4 +413,3 @@ SWIG_STD_VECTOR_ENHANCED(float) SWIG_STD_VECTOR_ENHANCED(double) SWIG_STD_VECTOR_ENHANCED(std::string) // also requires a %include <std_string.i> SWIG_STD_VECTOR_ENHANCED(std::wstring) // also requires a %include <std_wstring.i> - diff --git a/Lib/csharp/std_wstring.i b/Lib/csharp/std_wstring.i index 162b90e80..c7fef41a5 100644 --- a/Lib/csharp/std_wstring.i +++ b/Lib/csharp/std_wstring.i @@ -2,7 +2,9 @@ * std_wstring.i * * Typemaps for std::wstring and const std::wstring& - * These are mapped to a C# String and are passed around by value. + * std::wstring is mapped to a C# Unicode string (UTF16) and is passed around by value. + * std::wstring support includes wchar_t as a 2 byte type (Windows) and a 4 byte type + * (most Unix systems). * * To use non-const std::wstring references use the following %apply. Note * that they are passed by value. @@ -15,6 +17,28 @@ #include <string> %} +%fragment("Swig_csharp_UTF16ToWString", "header") %{ +/* For converting from .NET UTF16 (2 byte unicode) strings. wchar_t is 2 bytes on Windows, 4 bytes on Linux. */ +static std::wstring Swig_csharp_UTF16ToWString(const unsigned short *str) { + if (sizeof(wchar_t) == 2) { + return std::wstring((wchar_t *)str); + } else { + const unsigned short *pBegin(str); + const unsigned short *ptr(pBegin); + + while (*ptr != 0) + ++ptr; + + std::wstring result; + result.reserve(ptr - pBegin); + while(pBegin != ptr) + result.push_back(*pBegin++); + + return result; + } +} +%} + namespace std { %naturalvar wstring; @@ -22,31 +46,33 @@ namespace std { class wstring; // wstring -%typemap(ctype, out="void *") wstring "wchar_t *" +%typemap(ctype, out="void *") wstring "unsigned short *" %typemap(imtype, inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", - outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" + outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", + directorinattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", + directoroutattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" ) wstring "string" %typemap(cstype) wstring "string" %typemap(csdirectorin) wstring "$iminput" %typemap(csdirectorout) wstring "$cscall" -%typemap(in, canthrow=1) wstring +%typemap(in, canthrow=1, fragment="Swig_csharp_UTF16ToWString") wstring %{ if (!$input) { SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null wstring", 0); return $null; } - $1.assign($input); %} -%typemap(out) wstring %{ $result = SWIG_csharp_wstring_callback($1.c_str()); %} + $1 = Swig_csharp_UTF16ToWString($input); %} +%typemap(out) wstring %{ $result = SWIG_csharp_wstring_with_length_callback($1.data(), (int)$1.size()); %} -%typemap(directorout, canthrow=1) wstring +%typemap(directorout, canthrow=1) wstring %{ if (!$input) { SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null wstring", 0); return $null; } - $result.assign($input); %} + $result = Swig_csharp_UTF16ToWString($input); %} -%typemap(directorin) wstring %{ $input = SWIG_csharp_wstring_callback($1.c_str()); %} +%typemap(directorin) wstring %{ $input = SWIG_csharp_wstring_with_length_callback($1.data(), (int)$1.size()); %} %typemap(csin) wstring "$csinput" %typemap(csout, excode=SWIGEXCODE) wstring { @@ -57,29 +83,30 @@ class wstring; %typemap(typecheck) wstring = wchar_t *; %typemap(throws, canthrow=1) wstring -%{ std::string message($1.begin(), $1.end()); - SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, message.c_str()); +%{ SWIG_csharp_ApplicationException_callback($1.data(), (int)$1.size()); return $null; %} // const wstring & -%typemap(ctype, out="void *") const wstring & "wchar_t *" +%typemap(ctype, out="void *") const wstring & "unsigned short *" %typemap(imtype, inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", - outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" + outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", + directorinattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", + directoroutattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" ) const wstring & "string" %typemap(cstype) const wstring & "string" %typemap(csdirectorin) const wstring & "$iminput" %typemap(csdirectorout) const wstring & "$cscall" -%typemap(in, canthrow=1) const wstring & +%typemap(in, canthrow=1, fragment="Swig_csharp_UTF16ToWString") const wstring & %{ if (!$input) { SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null wstring", 0); return $null; } - std::wstring $1_str($input); + std::wstring $1_str(Swig_csharp_UTF16ToWString($input)); $1 = &$1_str; %} -%typemap(out) const wstring & %{ $result = SWIG_csharp_wstring_callback($1->c_str()); %} +%typemap(out) const wstring & %{ $result = SWIG_csharp_wstring_with_length_callback($1->data(), (int)$1->size()); %} %typemap(csin) const wstring & "$csinput" %typemap(csout, excode=SWIGEXCODE) const wstring & { @@ -94,10 +121,10 @@ class wstring; } /* possible thread/reentrant code problem */ static std::wstring $1_str; - $1_str = $input; + $1_str = Swig_csharp_UTF16ToWString($input); $result = &$1_str; %} -%typemap(directorin) const wstring & %{ $input = SWIG_csharp_wstring_callback($1.c_str()); %} +%typemap(directorin) const wstring & %{ $input = SWIG_csharp_wstring_with_length_callback($1.data(), (int)$1.size()); %} %typemap(csvarin, excode=SWIGEXCODE2) const wstring & %{ set { @@ -112,8 +139,7 @@ class wstring; %typemap(typecheck) const wstring & = wchar_t *; %typemap(throws, canthrow=1) const wstring & -%{ std::string message($1.begin(), $1.end()); - SWIG_CSharpSetPendingException(SWIG_CSharpApplicationException, message.c_str()); +%{ SWIG_csharp_ApplicationException_callback($1.data(), (int)$1.size()); return $null; %} } diff --git a/Lib/csharp/swigmove.i b/Lib/csharp/swigmove.i new file mode 100644 index 000000000..2f21bd6f7 --- /dev/null +++ b/Lib/csharp/swigmove.i @@ -0,0 +1,16 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in, canthrow=1, fragment="<memory>") SWIGTYPE MOVE ($&1_type argp) +%{ argp = ($&1_ltype)$input; + if (!argp) { + SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null $1_type", 0); + return $null; + } + SwigValueWrapper< $1_ltype >::reset($1, argp); %} + +%typemap(csin) SWIGTYPE MOVE "$&csclassname.swigRelease($csinput)" diff --git a/Lib/csharp/typemaps.i b/Lib/csharp/typemaps.i index b6f9bddbd..80a5cb545 100644 --- a/Lib/csharp/typemaps.i +++ b/Lib/csharp/typemaps.i @@ -74,15 +74,11 @@ INPUT_TYPEMAP(short, short, short) INPUT_TYPEMAP(unsigned short, unsigned short, ushort) INPUT_TYPEMAP(int, int, int) INPUT_TYPEMAP(unsigned int, unsigned int, uint) -INPUT_TYPEMAP(long, long, int) -INPUT_TYPEMAP(unsigned long, unsigned long, uint) INPUT_TYPEMAP(long long, long long, long) INPUT_TYPEMAP(unsigned long long, unsigned long long, ulong) INPUT_TYPEMAP(float, float, float) INPUT_TYPEMAP(double, double, double) -#undef INPUT_TYPEMAP - /* OUTPUT typemaps --------------- @@ -153,15 +149,11 @@ OUTPUT_TYPEMAP(short, short, short, INT16_PTR) OUTPUT_TYPEMAP(unsigned short, unsigned short, ushort, UINT16_PTR) OUTPUT_TYPEMAP(int, int, int, INT32_PTR) OUTPUT_TYPEMAP(unsigned int, unsigned int, uint, UINT32_PTR) -OUTPUT_TYPEMAP(long, long, int, INT32_PTR) -OUTPUT_TYPEMAP(unsigned long, unsigned long, uint, UINT32_PTR) OUTPUT_TYPEMAP(long long, long long, long, INT64_PTR) OUTPUT_TYPEMAP(unsigned long long, unsigned long long, ulong, UINT64_PTR) OUTPUT_TYPEMAP(float, float, float, FLOAT_PTR) OUTPUT_TYPEMAP(double, double, double, DOUBLE_PTR) -#undef OUTPUT_TYPEMAP - %typemap(in) bool *OUTPUT, bool &OUTPUT %{ *$input = 0; $1 = ($1_ltype)$input; %} @@ -242,12 +234,47 @@ INOUT_TYPEMAP(short, short, short, INT16_PTR) INOUT_TYPEMAP(unsigned short, unsigned short, ushort, UINT16_PTR) INOUT_TYPEMAP(int, int, int, INT32_PTR) INOUT_TYPEMAP(unsigned int, unsigned int, uint, UINT32_PTR) -INOUT_TYPEMAP(long, long, int, INT32_PTR) -INOUT_TYPEMAP(unsigned long, unsigned long, uint, UINT32_PTR) INOUT_TYPEMAP(long long, long long, long, INT64_PTR) INOUT_TYPEMAP(unsigned long long, unsigned long long, ulong, UINT64_PTR) INOUT_TYPEMAP(float, float, float, FLOAT_PTR) INOUT_TYPEMAP(double, double, double, DOUBLE_PTR) -#undef INOUT_TYPEMAP +// 32-bit/64-bit architecture specific typemaps - marshal as 32-bit by default +#if !defined(SWIGWORDSIZE64) +INPUT_TYPEMAP(long, int, int) +INPUT_TYPEMAP(unsigned long, unsigned int, uint) + +OUTPUT_TYPEMAP(long, int, int, INT32_PTR) +OUTPUT_TYPEMAP(unsigned long, unsigned int, uint, UINT32_PTR) + +INOUT_TYPEMAP(long, int, int, INT32_PTR) +INOUT_TYPEMAP(unsigned long, unsigned int, uint, UINT32_PTR) +#else +INPUT_TYPEMAP(long, long long, int) +INPUT_TYPEMAP(unsigned long, unsigned long long, uint) + +OUTPUT_TYPEMAP(long, long long, int, INT64_PTR) +OUTPUT_TYPEMAP(unsigned long, unsigned long long, uint, UINT64_PTR) + +INOUT_TYPEMAP(long, long long, int, INT64_PTR) +INOUT_TYPEMAP(unsigned long, unsigned long long, uint, UINT64_PTR) +#endif +%typemap(in) long INPUT[] ($*1_ltype tempinput), unsigned long INPUT[] ($*1_ltype tempinput) +%{tempinput = ($*1_ltype)*$input; + $1 = &tempinput;%} + +%typemap(in) long OUTPUT[] ($*1_ltype tempoutput), unsigned long OUTPUT[] ($*1_ltype tempoutput) +%{$1 = &tempoutput;%} + +%typemap(in) long INOUT[] ($*1_ltype tempinout), unsigned long INOUT[] ($*1_ltype tempinout) +%{tempinout = ($*1_ltype)*$input; + $1 = &tempinout;%} + +%typemap(argout) long OUTPUT[], unsigned long OUTPUT[] "*$input = *$1;" +%typemap(argout) long INOUT[], unsigned long INOUT[] "*$input = *$1;" + + +#undef INPUT_TYPEMAP +#undef OUTPUT_TYPEMAP +#undef INOUT_TYPEMAP diff --git a/Lib/csharp/wchar.i b/Lib/csharp/wchar.i index 798194114..f1e0d5a26 100644 --- a/Lib/csharp/wchar.i +++ b/Lib/csharp/wchar.i @@ -2,37 +2,58 @@ * wchar.i * * Typemaps for the wchar_t type - * These are mapped to a C# String and are passed around by value. + * wchar_t * is mapped to a C# Unicode string (UTF16) and is passed around by value. + * wchar_t * support includes wchar_t as a 2 byte type (Windows) and a 4 byte type + * (most Unix systems). * * Support code for wide strings can be turned off by defining SWIG_CSHARP_NO_WSTRING_HELPER - * * ----------------------------------------------------------------------------- */ #if !defined(SWIG_CSHARP_NO_WSTRING_HELPER) #if !defined(SWIG_CSHARP_WSTRING_HELPER_) #define SWIG_CSHARP_WSTRING_HELPER_ + +%fragment("<wchar.h>"); // TODO: %fragment("<wchar.h", "runtime"); + %insert(runtime) %{ /* Callback for returning strings to C# without leaking memory */ -typedef void * (SWIGSTDCALL* SWIG_CSharpWStringHelperCallback)(const wchar_t *); -static SWIG_CSharpWStringHelperCallback SWIG_csharp_wstring_callback = NULL; +typedef void * (SWIGSTDCALL* SWIG_CSharpWStringHelperCallback)(const wchar_t *, int length); +static SWIG_CSharpWStringHelperCallback SWIG_csharp_wstring_with_length_callback = NULL; +%} + +%insert(header) %{ +static void * SWIG_csharp_wstring_callback(const wchar_t *s) { + return SWIG_csharp_wstring_with_length_callback(s, (int)wcslen(s)); +} %} + %pragma(csharp) imclasscode=%{ protected class SWIGWStringHelper { [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)] - public delegate string SWIGWStringDelegate(global::System.IntPtr message); - static SWIGWStringDelegate wstringDelegate = new SWIGWStringDelegate(CreateWString); + public delegate string SWIGWStringDelegate(global::System.IntPtr message, int length); + static SWIGWStringDelegate wstringUTF16Delegate = new SWIGWStringDelegate(CreateWStringFromUTF16); + static SWIGWStringDelegate wstringUTF32Delegate = new SWIGWStringDelegate(CreateWStringFromUTF32); [global::System.Runtime.InteropServices.DllImport("$dllimport", EntryPoint="SWIGRegisterWStringCallback_$module")] - public static extern void SWIGRegisterWStringCallback_$module(SWIGWStringDelegate wstringDelegate); + public static extern void SWIGRegisterWStringCallback_$module(SWIGWStringDelegate wstringUTF16Delegate, SWIGWStringDelegate wstringUTF32Delegate); - static string CreateWString([global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]global::System.IntPtr cString) { - return global::System.Runtime.InteropServices.Marshal.PtrToStringUni(cString); + public static string CreateWStringFromUTF16([global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]global::System.IntPtr cString, int length) { + return global::System.Runtime.InteropServices.Marshal.PtrToStringUni(cString, length); + } + + public static string CreateWStringFromUTF32([global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]global::System.IntPtr cString, int length) { + if (length == 0) + return string.Empty; + + byte[] buffer = new byte[length * 4]; + global::System.Runtime.InteropServices.Marshal.Copy(cString, buffer, 0, buffer.Length); + return global::System.Text.Encoding.UTF32.GetString(buffer); } static SWIGWStringHelper() { - SWIGRegisterWStringCallback_$module(wstringDelegate); + SWIGRegisterWStringCallback_$module(wstringUTF16Delegate, wstringUTF32Delegate); } } @@ -43,13 +64,76 @@ static SWIG_CSharpWStringHelperCallback SWIG_csharp_wstring_callback = NULL; #ifdef __cplusplus extern "C" #endif -SWIGEXPORT void SWIGSTDCALL SWIGRegisterWStringCallback_$module(SWIG_CSharpWStringHelperCallback callback) { - SWIG_csharp_wstring_callback = callback; +SWIGEXPORT void SWIGSTDCALL SWIGRegisterWStringCallback_$module(SWIG_CSharpWStringHelperCallback callback_utf16, SWIG_CSharpWStringHelperCallback callback_utf32) { + SWIG_csharp_wstring_with_length_callback = sizeof(wchar_t) == 2 ? callback_utf16 : callback_utf32; } %} #endif // SWIG_CSHARP_WSTRING_HELPER_ #endif // SWIG_CSHARP_NO_WSTRING_HELPER +#if !defined(SWIG_CSHARP_NO_WSTRING_EXCEPTION_HELPER) +#if !defined(SWIG_CSHARP_WSTRING_EXCEPTION_HELPER_) +#define SWIG_CSHARP_WSTRING_EXCEPTION_HELPER_ + +%insert(runtime) %{ +/* Callback for returning strings to C# without leaking memory */ +typedef void (SWIGSTDCALL* SWIG_CSharpWStringExceptionHelperCallback)(const wchar_t *, int length); +static SWIG_CSharpWStringExceptionHelperCallback SWIG_csharp_ApplicationException_callback = NULL; +%} + +%pragma(csharp) imclasscode=%{ + protected class SWIGWStringExceptionHelper { + + [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)] + public delegate void SWIGWStringExceptionDelegate(global::System.IntPtr message, int length); + static SWIGWStringExceptionDelegate applicationExceptionUTF16Delegate = new SWIGWStringExceptionDelegate(SetPendingApplicationExceptionUTF16); + static SWIGWStringExceptionDelegate applicationExceptionUTF32Delegate = new SWIGWStringExceptionDelegate(SetPendingApplicationExceptionUTF32); + + [global::System.Runtime.InteropServices.DllImport("$dllimport", EntryPoint="SWIGRegisterWStringExceptionCallback_$module")] + public static extern void SWIGRegisterWStringExceptionCallback_$module(SWIGWStringExceptionDelegate applicationExceptionUTF16Delegate, SWIGWStringExceptionDelegate applicationExceptionUTF32Delegate); + + static string CreateWStringFromUTF16([global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]global::System.IntPtr cString, int length) { + return global::System.Runtime.InteropServices.Marshal.PtrToStringUni(cString, length); + } + + public static string CreateWStringFromUTF32([global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]global::System.IntPtr cString, int length) { + if (length == 0) + return string.Empty; + + byte[] buffer = new byte[length * 4]; + return global::System.Text.Encoding.UTF32.GetString(buffer); + } + + static void SetPendingApplicationExceptionUTF16([global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]global::System.IntPtr cString, int length) { + string message = SWIGWStringHelper.CreateWStringFromUTF16(cString, length); + SWIGPendingException.Set(new global::System.ApplicationException(message, SWIGPendingException.Retrieve())); + } + + static void SetPendingApplicationExceptionUTF32([global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]global::System.IntPtr cString, int length) { + string message = SWIGWStringHelper.CreateWStringFromUTF32(cString, length); + SWIGPendingException.Set(new global::System.ApplicationException(message, SWIGPendingException.Retrieve())); + } + + static SWIGWStringExceptionHelper() { + SWIGRegisterWStringExceptionCallback_$module(applicationExceptionUTF16Delegate, applicationExceptionUTF32Delegate); + } + } + + static protected SWIGWStringExceptionHelper swigWStringExceptionHelper = new SWIGWStringExceptionHelper(); +%} + +%insert(runtime) %{ +#ifdef __cplusplus +extern "C" +#endif +SWIGEXPORT void SWIGSTDCALL SWIGRegisterWStringExceptionCallback_$module(SWIG_CSharpWStringExceptionHelperCallback callback_utf16, SWIG_CSharpWStringExceptionHelperCallback callback_utf32) { + SWIG_csharp_ApplicationException_callback = sizeof(wchar_t) == 2 ? callback_utf16 : callback_utf32; +} +%} + +#endif // SWIG_CSHARP_WSTRING_EXCEPTION_HELPER_ +#endif // SWIG_CSHARP_NO_WSTRING_EXCEPTION_HELPER + // wchar_t %typemap(ctype) wchar_t "wchar_t" @@ -77,13 +161,64 @@ SWIGEXPORT void SWIGSTDCALL SWIGRegisterWStringCallback_$module(SWIG_CSharpWStri %typemap(typecheck) wchar_t = char; // wchar_t * -%typemap(ctype) wchar_t * "wchar_t *" -%typemap(imtype, inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", out="global::System.IntPtr" ) wchar_t * "string" + +%fragment("Swig_csharp_UTF16ToWCharPtr", "header") %{ +/* For converting from .NET UTF16 (2 byte unicode) strings. wchar_t is 2 bytes on Windows, 4 bytes on Linux. */ +static wchar_t * Swig_csharp_UTF16ToWCharPtr(const unsigned short *str) { + if (sizeof(wchar_t) == 2) { + return (wchar_t *)str; + } else { + wchar_t *result = 0; + + if (str) { + const unsigned short *pBegin(str); + const unsigned short *pEnd(pBegin); + wchar_t *ptr = 0; + + while (*pEnd != 0) + ++pEnd; + +#ifdef __cplusplus + result = ptr = new wchar_t[pEnd - pBegin + 1]; +#else + result = ptr = (wchar_t *)malloc(sizeof(wchar_t) * (pEnd - pBegin + 1)); +#endif + while(pBegin != pEnd) + *ptr++ = *pBegin++; + *ptr++ = 0; + } + + return result; + } +} +%} + +%fragment("Swig_csharp_UTF16ToWCharPtrFree", "header") %{ +static void Swig_csharp_UTF16ToWCharPtrFree(wchar_t *str) { + if (sizeof(wchar_t) != 2) { +#ifdef __cplusplus + delete [] str; +#else + free(str); +#endif + } +} +%} + +%typemap(ctype, out="void *") wchar_t * "unsigned short *" +%typemap(imtype, + inattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", + outattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", + directorinattributes="[global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]", + directoroutattributes="[return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.LPWStr)]" + ) wchar_t * "string" %typemap(cstype) wchar_t * "string" +%typemap(csdirectorin) wchar_t * "$iminput" +%typemap(csdirectorout) wchar_t * "$cscall" %typemap(csin) wchar_t * "$csinput" %typemap(csout, excode=SWIGEXCODE) wchar_t * { - string ret = global::System.Runtime.InteropServices.Marshal.PtrToStringUni($imcall);$excode + string ret = $imcall;$excode return ret; } %typemap(csvarin, excode=SWIGEXCODE2) wchar_t * %{ @@ -96,8 +231,105 @@ SWIGEXPORT void SWIGSTDCALL SWIGRegisterWStringCallback_$module(SWIG_CSharpWStri return ret; } %} -%typemap(in) wchar_t * %{ $1 = ($1_ltype)$input; %} -%typemap(out) wchar_t * %{ $result = (wchar_t *)$1; %} +%typemap(in, fragment="Swig_csharp_UTF16ToWCharPtr") wchar_t * +%{ $1 = Swig_csharp_UTF16ToWCharPtr($input); %} + +%typemap(out) wchar_t * %{ $result = $1 ? SWIG_csharp_wstring_callback($1) : 0; %} + +%typemap(freearg, fragment="Swig_csharp_UTF16ToWCharPtrFree") wchar_t * +%{ Swig_csharp_UTF16ToWCharPtrFree($1); %} + +%typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) wchar_t * +%{ $result = Swig_csharp_UTF16ToWCharPtr($input); %} + +%typemap(directorin) wchar_t * %{ $input = SWIG_csharp_wstring_with_length_callback($1, (int)wcslen($1)); %} %typemap(typecheck) wchar_t * = char *; +%typemap(throws, canthrow=1, fragment="<wchar.h>") wchar_t * +%{ SWIG_csharp_ApplicationException_callback($1, (int)wcslen($1)); + return $null; %} + + +/* Default typemap for handling wchar_t * members (based on char * in swig.swg) */ + +#ifdef __cplusplus +%typemap(memberin,fragment="<wchar.h>") wchar_t * { + delete [] $1; + if ($input && sizeof(wchar_t) == 2) { + $1 = ($1_type) (new wchar_t[wcslen((const wchar_t *)$input)+1]); + wcscpy((wchar_t *)$1, (const wchar_t *)$input); + } else { + $1 = $input; + $input = 0; + } +} +%typemap(memberin,warning=SWIGWARN_TYPEMAP_WCHARLEAK_MSG,fragment="<wchar.h>") const wchar_t * { + if ($input && sizeof(wchar_t) == 2) { + $1 = ($1_type) (new wchar_t[wcslen((const wchar_t *)$input)+1]); + wcscpy((wchar_t *)$1, (const wchar_t *)$input); + } else { + $1 = $input; + $input = 0; + } +} +%typemap(globalin,fragment="<wchar.h>") wchar_t * { + delete [] $1; + if ($input && sizeof(wchar_t) == 2) { + $1 = ($1_type) (new wchar_t[wcslen((const wchar_t *)$input)+1]); + wcscpy((wchar_t *)$1, (const wchar_t *)$input); + } else { + $1 = $input; + $input = 0; + } +} +%typemap(globalin,warning=SWIGWARN_TYPEMAP_WCHARLEAK_MSG,fragment="<wchar.h>") const wchar_t * { + if ($input && sizeof(wchar_t) == 2) { + $1 = ($1_type) (new wchar_t[wcslen((const wchar_t *)$input)+1]); + wcscpy((wchar_t *)$1, (const wchar_t *)$input); + } else { + $1 = $input; + $input = 0; + } +} +#else +%typemap(memberin,fragment="<wchar.h>") wchar_t * { + free($1); + if ($input && sizeof(wchar_t) == 2) { + $1 = ($1_type) malloc(wcslen((const wchar_t *)$input)+1); + wcscpy((wchar_t *)$1, (const wchar_t *)$input); + } else { + $1 = $input; + $input = 0; + } +} +%typemap(memberin,warning=SWIGWARN_TYPEMAP_WCHARLEAK_MSG,fragment="<wchar.h>") const wchar_t * { + if ($input && sizeof(wchar_t) == 2) { + $1 = ($1_type) malloc(wcslen((const wchar_t *)$input)+1); + wcscpy((wchar_t *)$1, (const wchar_t *)$input); + } else { + $1 = $input; + $input = 0; + } +} +%typemap(globalin,fragment="<wchar.h>") wchar_t * { + free($1); + if ($input && sizeof(wchar_t) == 2) { + $1 = ($1_type) malloc(wcslen((const wchar_t *)$input)+1); + wcscpy((wchar_t *)$1, (const wchar_t *)$input); + } else { + $1 = $input; + $input = 0; + } +} +%typemap(globalin,warning=SWIGWARN_TYPEMAP_WCHARLEAK_MSG,fragment="<wchar.h>") const wchar_t * { + if ($input && sizeof(wchar_t) == 2) { + $1 = ($1_type) malloc(wcslen((const wchar_t *)$input)+1); + wcscpy((wchar_t *)$1, (const wchar_t *)$input); + } else { + $1 = $input; + $input = 0; + } +} + +#endif |