diff --git a/Examples/test-suite/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index 0549a7b45..285eedf5a 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -1,6 +1,6 @@ %module cpp11_std_unique_ptr -#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD) +#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD) || defined(SWIGPHP) %include "std_string.i" %include "std_unique_ptr.i" @@ -68,6 +68,10 @@ std::string takeKlassUniquePtr(std::unique_ptr k) { return s; } +Klass *make_null() { + return nullptr; +} + bool is_nullptr(Klass *p) { return p == nullptr; } diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index 5f3b7724f..49615e0b5 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -12,7 +12,7 @@ #endif %} -#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD) +#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD) || (SWIGPHP) %include "std_string.i" //#include diff --git a/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php b/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php new file mode 100644 index 000000000..5820592de --- /dev/null +++ b/Examples/test-suite/php/cpp11_std_unique_ptr_runme.php @@ -0,0 +1,88 @@ +getMessage(), "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' of takeKlassUniquePtr", "Unexpected exception: {$e->getMessage()}"); +} +$kin = NULL; # Should not fail, even though already deleted +checkCount(0); + +$kin = new Klass("KlassInput"); +$notowned = get_not_owned_ptr($kin); +try { + takeKlassUniquePtr($notowned); +} catch (TypeError $e) { + check::equal($e->getMessage(), "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' of takeKlassUniquePtr", "Unexpected exception: {$e->getMessage()}"); +} +checkCount(1); +$kin = NULL; +checkCount(0); + +$kini = new KlassInheritance("KlassInheritanceInput"); +checkCount(1); +$s = takeKlassUniquePtr($kini); +checkCount(0); +check::equal($s, "KlassInheritanceInput", "Incorrect string: $s"); +try { + is_nullptr($kini); + check::fail("is_nullptr check"); +} catch (TypeError $e) { +} + +$kini = NULL; # Should not fail, even though already deleted +checkCount(0); + +# unique_ptr as output +$k1 = makeKlassUniquePtr("first"); +$k2 = makeKlassUniquePtr("second"); +checkCount(2); + +$k1 = NULL; +checkCount(1); + +check::equal($k2->getLabel(), "second", "proper label"); + +$k2 = NULL; +checkCount(0); + +check::done(); diff --git a/Examples/test-suite/php/li_std_auto_ptr_runme.php b/Examples/test-suite/php/li_std_auto_ptr_runme.php new file mode 100644 index 000000000..c4992c1fe --- /dev/null +++ b/Examples/test-suite/php/li_std_auto_ptr_runme.php @@ -0,0 +1,88 @@ +getMessage(), "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' of takeKlassAutoPtr", "Unexpected exception: {$e->getMessage()}"); +} +$kin = NULL; # Should not fail, even though already deleted +checkCount(0); + +$kin = new Klass("KlassInput"); +$notowned = get_not_owned_ptr($kin); +try { + takeKlassAutoPtr($notowned); +} catch (TypeError $e) { + check::equal($e->getMessage(), "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' of takeKlassAutoPtr", "Unexpected exception: {$e->getMessage()}"); +} +checkCount(1); +$kin = NULL; +checkCount(0); + +$kini = new KlassInheritance("KlassInheritanceInput"); +checkCount(1); +$s = takeKlassAutoPtr($kini); +checkCount(0); +check::equal($s, "KlassInheritanceInput", "Incorrect string: $s"); +try { + is_nullptr($kini); + check::fail("is_nullptr check"); +} catch (TypeError $e) { +} + +$kini = NULL; # Should not fail, even though already deleted +checkCount(0); + +# auto_ptr as output +$k1 = makeKlassAutoPtr("first"); +$k2 = makeKlassAutoPtr("second"); +checkCount(2); + +$k1 = NULL; +checkCount(1); + +check::equal($k2->getLabel(), "second", "proper label"); + +$k2 = NULL; +checkCount(0); + +check::done(); diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg index a49683197..a81baf001 100644 --- a/Lib/php/phprun.swg +++ b/Lib/php/phprun.swg @@ -208,10 +208,20 @@ SWIG_ConvertPtrAndOwn(zval *z, void **ptr, swig_type_info *ty, int flags, swig_o *ptr = NULL; } } - if (*ptr == NULL) return SWIG_ERROR; - if (flags & SWIG_POINTER_DISOWN) { - value->newobject = 0; + + if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE) && !value->newobject) { + return SWIG_ERROR_RELEASE_NOT_OWNED; + } else { + if (*ptr == NULL) + return SWIG_ERROR; /* should be SWIG_NullReferenceError?? */ + if (flags & SWIG_POINTER_DISOWN) { + value->newobject = 0; + } + if (flags & SWIG_POINTER_CLEAR) { + value->ptr = 0; + } } + return SWIG_OK; } case IS_NULL: diff --git a/Lib/php/std_auto_ptr.i b/Lib/php/std_auto_ptr.i new file mode 100644 index 000000000..7df497e60 --- /dev/null +++ b/Lib/php/std_auto_ptr.i @@ -0,0 +1,35 @@ +/* ----------------------------------------------------------------------------- + * 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(in, noblock=1) std::auto_ptr< TYPE > (void *argp = 0, int res = 0) { + res = SWIG_ConvertPtr(&$input, &argp, $descriptor(TYPE *), 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 type 'TYPE *' of $symname"); + return; + } else { + zend_type_error("Expected TYPE * for argument $argnum of $symname"); + return; + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::auto_ptr< TYPE > %{ + SWIG_SetPointerZval($result, (void *)$1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN); +%} + +%template() std::auto_ptr< TYPE >; +%enddef + +namespace std { + template class auto_ptr {}; +} diff --git a/Lib/php/std_unique_ptr.i b/Lib/php/std_unique_ptr.i new file mode 100644 index 000000000..591f580cb --- /dev/null +++ b/Lib/php/std_unique_ptr.i @@ -0,0 +1,35 @@ +/* ----------------------------------------------------------------------------- + * 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(in, noblock=1) std::unique_ptr< TYPE > (void *argp = 0, int res = 0) { + res = SWIG_ConvertPtr(&$input, &argp, $descriptor(TYPE *), 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 type 'TYPE *' of $symname"); + return; + } else { + zend_type_error("Expected TYPE * for argument $argnum of $symname"); + return; + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::unique_ptr< TYPE > %{ + SWIG_SetPointerZval($result, (void *)$1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN); +%} + +%template() std::unique_ptr< TYPE >; +%enddef + +namespace std { + template class unique_ptr {}; +}