diff options
author | William S Fulton <wsf@fultondesigns.co.uk> | 2022-09-16 08:36:25 +0100 |
---|---|---|
committer | William S Fulton <wsf@fultondesigns.co.uk> | 2022-09-16 08:36:25 +0100 |
commit | dad7c93ca0a923e7d2671347cee711d180dd0338 (patch) | |
tree | e4f527a56b5a1e044213ebe1f07200cedcde8153 /Lib | |
parent | de65875955b236ee2644014e41bdeb1d574acc93 (diff) | |
download | swig-dad7c93ca0a923e7d2671347cee711d180dd0338.tar.gz |
Provide SWIGTYPE MOVE typemaps in swigmove.i
For implementing full move semantics when passing parameters by value.
Based on SWIGTYPE && and std::unique_ptr typemaps which implement move
semantics.
Added for all languages, but untested for: Go, Ocaml, R, Scilab (and
unlikely to be fully functional for same reasons as for std::unique_ptr
support).
Issue #999
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/csharp/swigmove.i | 16 | ||||
-rw-r--r-- | Lib/d/swigmove.i | 16 | ||||
-rw-r--r-- | Lib/go/swigmove.i | 15 | ||||
-rw-r--r-- | Lib/guile/swigmove.i | 19 | ||||
-rw-r--r-- | Lib/java/swigmove.i | 16 | ||||
-rw-r--r-- | Lib/javascript/jsc/swigmove.i | 1 | ||||
-rw-r--r-- | Lib/javascript/v8/swigmove.i | 1 | ||||
-rw-r--r-- | Lib/lua/swigmove.i | 18 | ||||
-rw-r--r-- | Lib/mzscheme/swigmove.i | 19 | ||||
-rw-r--r-- | Lib/ocaml/swigmove.i | 11 | ||||
-rw-r--r-- | Lib/octave/swigmove.i | 1 | ||||
-rw-r--r-- | Lib/perl5/swigmove.i | 1 | ||||
-rw-r--r-- | Lib/php/swigmove.i | 24 | ||||
-rw-r--r-- | Lib/python/swigmove.i | 1 | ||||
-rw-r--r-- | Lib/r/swigmove.i | 1 | ||||
-rw-r--r-- | Lib/ruby/swigmove.i | 1 | ||||
-rw-r--r-- | Lib/scilab/swigmove.i | 1 | ||||
-rw-r--r-- | Lib/swig.swg | 12 | ||||
-rw-r--r-- | Lib/tcl/swigmove.i | 1 | ||||
-rw-r--r-- | Lib/typemaps/swigmove.swg | 19 |
20 files changed, 194 insertions, 0 deletions
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/d/swigmove.i b/Lib/d/swigmove.i new file mode 100644 index 000000000..e2eb83406 --- /dev/null +++ b/Lib/d/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) SWIGTYPE MOVE ($&1_type argp) +%{ argp = ($&1_ltype)$input; + if (!argp) { + SWIG_DSetPendingException(SWIG_DIllegalArgumentException, "Attempt to dereference null $1_type"); + return $null; + } + SwigValueWrapper< $1_ltype >::reset($1, argp); %} + +%typemap(din) SWIGTYPE MOVE "$dclassname.swigRelease($dinput)" diff --git a/Lib/go/swigmove.i b/Lib/go/swigmove.i new file mode 100644 index 000000000..e1984b6ea --- /dev/null +++ b/Lib/go/swigmove.i @@ -0,0 +1,15 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in) SWIGTYPE MOVE ($&1_type argp) +%{ + argp = ($&1_ltype)$input; + if (argp == NULL) { + _swig_gopanic("Attempt to dereference null $1_type"); + } + SwigValueWrapper< $1_ltype >::reset($1, argp); +%} diff --git a/Lib/guile/swigmove.i b/Lib/guile/swigmove.i new file mode 100644 index 000000000..87ab91ead --- /dev/null +++ b/Lib/guile/swigmove.i @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in, noblock=1) SWIGTYPE MOVE (void *argp = 0, int res = 0) { + res = SWIG_ConvertPtr($input, &argp, $&1_descriptor, SWIG_POINTER_RELEASE); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "$1_type", $symname, $argnum); + } else { + %argument_fail(res, "$1_type", $symname, $argnum); + } + } + if (!argp) { %argument_nullref("$1_type", $symname, $argnum); } + SwigValueWrapper< $1_ltype >::reset($1, ($&1_type)argp); +} diff --git a/Lib/java/swigmove.i b/Lib/java/swigmove.i new file mode 100644 index 000000000..671b988af --- /dev/null +++ b/Lib/java/swigmove.i @@ -0,0 +1,16 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in) SWIGTYPE MOVE ($&1_type argp) +%{ argp = *($&1_ltype*)&$input; + if (!argp) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Attempt to dereference null $1_type"); + return $null; + } + SwigValueWrapper< $1_ltype >::reset($1, argp); %} + +%typemap(javain) SWIGTYPE MOVE "$&javaclassname.swigRelease($javainput)" diff --git a/Lib/javascript/jsc/swigmove.i b/Lib/javascript/jsc/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/javascript/jsc/swigmove.i @@ -0,0 +1 @@ +%include <typemaps/swigmove.swg> diff --git a/Lib/javascript/v8/swigmove.i b/Lib/javascript/v8/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/javascript/v8/swigmove.i @@ -0,0 +1 @@ +%include <typemaps/swigmove.swg> diff --git a/Lib/lua/swigmove.i b/Lib/lua/swigmove.i new file mode 100644 index 000000000..d130e797a --- /dev/null +++ b/Lib/lua/swigmove.i @@ -0,0 +1,18 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in, checkfn="lua_isuserdata", noblock=1) SWIGTYPE MOVE (void *argp = 0, int res = 0) { + res = SWIG_ConvertPtr(L, $input, &argp, $&1_descriptor, SWIG_POINTER_RELEASE); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + lua_pushfstring(L, "Cannot release ownership as memory is not owned for argument $argnum of type '$1_type' in $symname"); SWIG_fail; + } else { + SWIG_fail_ptr("$symname", $argnum, $&1_descriptor); + } + } + SwigValueWrapper< $1_ltype >::reset($1, ($&1_type)argp); +} diff --git a/Lib/mzscheme/swigmove.i b/Lib/mzscheme/swigmove.i new file mode 100644 index 000000000..bbfcdcb16 --- /dev/null +++ b/Lib/mzscheme/swigmove.i @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in, noblock=1) SWIGTYPE MOVE (void *argp = 0, int res = 0) { + res = SWIG_ConvertPtr($input, &argp, $&1_descriptor, SWIG_POINTER_RELEASE); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + scheme_signal_error(FUNC_NAME ": cannot release ownership as memory is not owned for argument $argnum of type '$1_type'"); + } else { + %argument_fail(res, "$1_type", $symname, $argnum); + } + } + if (argp == NULL) scheme_signal_error(FUNC_NAME ": swig-type-error (null reference)"); + SwigValueWrapper< $1_ltype >::reset($1, ($&1_type)argp); +} diff --git a/Lib/ocaml/swigmove.i b/Lib/ocaml/swigmove.i new file mode 100644 index 000000000..32f9903bd --- /dev/null +++ b/Lib/ocaml/swigmove.i @@ -0,0 +1,11 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in, noblock=1) SWIGTYPE MOVE (void *argp = 0) { + argp1 = ($&1_ltype) caml_ptr_val($input,$&1_descriptor); + SwigValueWrapper< $1_ltype >::reset($1, ($&1_type)argp); +} diff --git a/Lib/octave/swigmove.i b/Lib/octave/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/octave/swigmove.i @@ -0,0 +1 @@ +%include <typemaps/swigmove.swg> diff --git a/Lib/perl5/swigmove.i b/Lib/perl5/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/perl5/swigmove.i @@ -0,0 +1 @@ +%include <typemaps/swigmove.swg> diff --git a/Lib/php/swigmove.i b/Lib/php/swigmove.i new file mode 100644 index 000000000..b16a3c544 --- /dev/null +++ b/Lib/php/swigmove.i @@ -0,0 +1,24 @@ +/* ----------------------------------------------------------------------------- + * swigmove.i + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in, noblock=1) SWIGTYPE MOVE (void *argp = 0, int res = 0) { + res = SWIG_ConvertPtr(&$input, &argp, $&1_descriptor, SWIG_POINTER_RELEASE); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + zend_type_error("Cannot release ownership as memory is not owned for argument $argnum of $&1_descriptor of $symname"); + return; + } else { + zend_type_error("Expected $&1_descriptor for argument $argnum of $symname"); + return; + } + } + if (!argp) { + zend_type_error("Invalid null reference for argument $argnum of $&1_descriptor of $symname"); + return; + } + SwigValueWrapper< $1_ltype >::reset($1, ($&1_type)argp); +} diff --git a/Lib/python/swigmove.i b/Lib/python/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/python/swigmove.i @@ -0,0 +1 @@ +%include <typemaps/swigmove.swg> diff --git a/Lib/r/swigmove.i b/Lib/r/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/r/swigmove.i @@ -0,0 +1 @@ +%include <typemaps/swigmove.swg> diff --git a/Lib/ruby/swigmove.i b/Lib/ruby/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/ruby/swigmove.i @@ -0,0 +1 @@ +%include <typemaps/swigmove.swg> diff --git a/Lib/scilab/swigmove.i b/Lib/scilab/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/scilab/swigmove.i @@ -0,0 +1 @@ +%include <typemaps/swigmove.swg> diff --git a/Lib/swig.swg b/Lib/swig.swg index 6cac0e377..9f9d53349 100644 --- a/Lib/swig.swg +++ b/Lib/swig.swg @@ -656,6 +656,16 @@ namespace std { * arg1 = *inarg1; // Assignment from a pointer * arg1 = Vector(1,2,3); // Assignment from a value * + * SwigValueWrapper is a drop in replacement to modify normal value semantics by + * using the heap instead of the stack to copy/move the underlying object it is + * managing. Smart pointers also manage an underlying object on the heap, so + * SwigValueWrapper has characteristics of a smart pointer. The reset function + * is specific smart pointer functionality, but cannot be a non-static member as + * when SWIG modifies typemap code it assumes non-static member function calls + * are routed to the underlying object, changing for example $1.f() to (&x)->f(). + * The reset function was added as an optimisation to avoid some copying/moving + * and to take ownership of an object already created on the heap. + * * The class offers a strong guarantee of exception safety. * With regards to the implementation, the private SwigSmartPointer nested class is * a simple smart pointer providing exception safety, much like std::auto_ptr. @@ -677,6 +687,7 @@ template<typename T> class SwigValueWrapper { SwigSmartPointer(T *p) : ptr(p) { } ~SwigSmartPointer() { delete ptr; } SwigSmartPointer& operator=(SwigSmartPointer& rhs) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = rhs.ptr; rhs.ptr = 0; return *this; } + void reset(T *p) { T* oldptr = ptr; ptr = 0; delete oldptr; ptr = p; } } pointer; SwigValueWrapper& operator=(const SwigValueWrapper<T>& rhs); SwigValueWrapper(const SwigValueWrapper<T>& rhs); @@ -690,6 +701,7 @@ public: operator T&() const { return *pointer.ptr; } #endif T *operator&() const { return pointer.ptr; } + static void reset(SwigValueWrapper& t, T *p) { t.pointer.reset(p); } }; /* diff --git a/Lib/tcl/swigmove.i b/Lib/tcl/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/tcl/swigmove.i @@ -0,0 +1 @@ +%include <typemaps/swigmove.swg> diff --git a/Lib/typemaps/swigmove.swg b/Lib/typemaps/swigmove.swg new file mode 100644 index 000000000..b0a296850 --- /dev/null +++ b/Lib/typemaps/swigmove.swg @@ -0,0 +1,19 @@ +/* ----------------------------------------------------------------------------- + * swigmove.swg + * + * Input typemaps library for implementing full move semantics when passing + * parameters by value. + * ----------------------------------------------------------------------------- */ + +%typemap(in, noblock=1) SWIGTYPE MOVE (void *argp = 0, int res = 0) { + res = SWIG_ConvertPtr($input, &argp, $&1_descriptor, SWIG_POINTER_RELEASE); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "$1_type", $symname, $argnum); + } else { + %argument_fail(res, "$1_type", $symname, $argnum); + } + } + if (!argp) { %argument_nullref("$1_type", $symname, $argnum); } + SwigValueWrapper< $1_ltype >::reset($1, ($&1_type)argp); +} |