Skip to content

Commit fa9c7a7

Browse files
committed
Add PHP support for std::unique_ptr and std::auto_ptr
Equivalent to Python/Ruby implementations.
1 parent d4b1152 commit fa9c7a7

File tree

7 files changed

+265
-5
lines changed

7 files changed

+265
-5
lines changed

Examples/test-suite/cpp11_std_unique_ptr.i

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
%module cpp11_std_unique_ptr
22

3-
#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD)
3+
#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD) || defined(SWIGPHP)
44

55
%include "std_string.i"
66
%include "std_unique_ptr.i"
@@ -68,6 +68,10 @@ std::string takeKlassUniquePtr(std::unique_ptr<Klass> k) {
6868
return s;
6969
}
7070

71+
Klass *make_null() {
72+
return nullptr;
73+
}
74+
7175
bool is_nullptr(Klass *p) {
7276
return p == nullptr;
7377
}

Examples/test-suite/li_std_auto_ptr.i

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#endif
1313
%}
1414

15-
#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD)
15+
#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD) || (SWIGPHP)
1616

1717
%include "std_string.i"
1818
//#include <iostream>
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
require "tests.php";
4+
5+
function checkCount($expected_count) {
6+
$actual_count = Klass::getTotal_count();
7+
check::equal($actual_count, $expected_count, "Counts incorrect");
8+
}
9+
10+
# Test raw pointer handling involving virtual inheritance
11+
$kini = new KlassInheritance("KlassInheritanceInput");
12+
checkCount(1);
13+
$s = takeKlassUniquePtr($kini);
14+
check::equal($s, "KlassInheritanceInput", "Incorrect string: $s");
15+
$kini = NULL;
16+
checkCount(0);
17+
18+
19+
# unique_ptr as input
20+
$kin = new Klass("KlassInput");
21+
checkCount(1);
22+
$s = takeKlassUniquePtr($kin);
23+
checkCount(0);
24+
check::equal($s, "KlassInput", "Incorrect string: $s");
25+
try {
26+
is_nullptr($kin);
27+
check::fail("is_nullptr check");
28+
} catch (TypeError $e) {
29+
}
30+
$kin = NULL; # Should not fail, even though already deleted
31+
checkCount(0);
32+
33+
$kin = new Klass("KlassInput");
34+
checkCount(1);
35+
$s = takeKlassUniquePtr($kin);
36+
checkCount(0);
37+
check::equal($s, "KlassInput", "Incorrect string: $s");
38+
try {
39+
is_nullptr($kin);
40+
check::fail("is_nullptr check");
41+
} catch (TypeError $e) {
42+
}
43+
try {
44+
} catch (TypeError $e) {
45+
check::equal($e->getMessage(), "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' of takeKlassUniquePtr", "Unexpected exception: {$e->getMessage()}");
46+
}
47+
$kin = NULL; # Should not fail, even though already deleted
48+
checkCount(0);
49+
50+
$kin = new Klass("KlassInput");
51+
$notowned = get_not_owned_ptr($kin);
52+
try {
53+
takeKlassUniquePtr($notowned);
54+
} catch (TypeError $e) {
55+
check::equal($e->getMessage(), "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' of takeKlassUniquePtr", "Unexpected exception: {$e->getMessage()}");
56+
}
57+
checkCount(1);
58+
$kin = NULL;
59+
checkCount(0);
60+
61+
$kini = new KlassInheritance("KlassInheritanceInput");
62+
checkCount(1);
63+
$s = takeKlassUniquePtr($kini);
64+
checkCount(0);
65+
check::equal($s, "KlassInheritanceInput", "Incorrect string: $s");
66+
try {
67+
is_nullptr($kini);
68+
check::fail("is_nullptr check");
69+
} catch (TypeError $e) {
70+
}
71+
72+
$kini = NULL; # Should not fail, even though already deleted
73+
checkCount(0);
74+
75+
# unique_ptr as output
76+
$k1 = makeKlassUniquePtr("first");
77+
$k2 = makeKlassUniquePtr("second");
78+
checkCount(2);
79+
80+
$k1 = NULL;
81+
checkCount(1);
82+
83+
check::equal($k2->getLabel(), "second", "proper label");
84+
85+
$k2 = NULL;
86+
checkCount(0);
87+
88+
check::done();
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
require "tests.php";
4+
5+
function checkCount($expected_count) {
6+
$actual_count = Klass::getTotal_count();
7+
check::equal($actual_count, $expected_count, "Counts incorrect");
8+
}
9+
10+
# Test raw pointer handling involving virtual inheritance
11+
$kini = new KlassInheritance("KlassInheritanceInput");
12+
checkCount(1);
13+
$s = takeKlassAutoPtr($kini);
14+
check::equal($s, "KlassInheritanceInput", "Incorrect string: $s");
15+
$kini = NULL;
16+
checkCount(0);
17+
18+
19+
# auto_ptr as input
20+
$kin = new Klass("KlassInput");
21+
checkCount(1);
22+
$s = takeKlassAutoPtr($kin);
23+
checkCount(0);
24+
check::equal($s, "KlassInput", "Incorrect string: $s");
25+
try {
26+
is_nullptr($kin);
27+
check::fail("is_nullptr check");
28+
} catch (TypeError $e) {
29+
}
30+
$kin = NULL; # Should not fail, even though already deleted
31+
checkCount(0);
32+
33+
$kin = new Klass("KlassInput");
34+
checkCount(1);
35+
$s = takeKlassAutoPtr($kin);
36+
checkCount(0);
37+
check::equal($s, "KlassInput", "Incorrect string: $s");
38+
try {
39+
is_nullptr($kin);
40+
check::fail("is_nullptr check");
41+
} catch (TypeError $e) {
42+
}
43+
try {
44+
} catch (TypeError $e) {
45+
check::equal($e->getMessage(), "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' of takeKlassAutoPtr", "Unexpected exception: {$e->getMessage()}");
46+
}
47+
$kin = NULL; # Should not fail, even though already deleted
48+
checkCount(0);
49+
50+
$kin = new Klass("KlassInput");
51+
$notowned = get_not_owned_ptr($kin);
52+
try {
53+
takeKlassAutoPtr($notowned);
54+
} catch (TypeError $e) {
55+
check::equal($e->getMessage(), "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' of takeKlassAutoPtr", "Unexpected exception: {$e->getMessage()}");
56+
}
57+
checkCount(1);
58+
$kin = NULL;
59+
checkCount(0);
60+
61+
$kini = new KlassInheritance("KlassInheritanceInput");
62+
checkCount(1);
63+
$s = takeKlassAutoPtr($kini);
64+
checkCount(0);
65+
check::equal($s, "KlassInheritanceInput", "Incorrect string: $s");
66+
try {
67+
is_nullptr($kini);
68+
check::fail("is_nullptr check");
69+
} catch (TypeError $e) {
70+
}
71+
72+
$kini = NULL; # Should not fail, even though already deleted
73+
checkCount(0);
74+
75+
# auto_ptr as output
76+
$k1 = makeKlassAutoPtr("first");
77+
$k2 = makeKlassAutoPtr("second");
78+
checkCount(2);
79+
80+
$k1 = NULL;
81+
checkCount(1);
82+
83+
check::equal($k2->getLabel(), "second", "proper label");
84+
85+
$k2 = NULL;
86+
checkCount(0);
87+
88+
check::done();

Lib/php/phprun.swg

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,10 +208,20 @@ SWIG_ConvertPtrAndOwn(zval *z, void **ptr, swig_type_info *ty, int flags, swig_o
208208
*ptr = NULL;
209209
}
210210
}
211-
if (*ptr == NULL) return SWIG_ERROR;
212-
if (flags & SWIG_POINTER_DISOWN) {
213-
value->newobject = 0;
211+
212+
if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE) && !value->newobject) {
213+
return SWIG_ERROR_RELEASE_NOT_OWNED;
214+
} else {
215+
if (*ptr == NULL)
216+
return SWIG_ERROR; /* should be SWIG_NullReferenceError?? */
217+
if (flags & SWIG_POINTER_DISOWN) {
218+
value->newobject = 0;
219+
}
220+
if (flags & SWIG_POINTER_CLEAR) {
221+
value->ptr = 0;
222+
}
214223
}
224+
215225
return SWIG_OK;
216226
}
217227
case IS_NULL:

Lib/php/std_auto_ptr.i

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* -----------------------------------------------------------------------------
2+
* std_auto_ptr.i
3+
*
4+
* SWIG library file for handling std::auto_ptr.
5+
* Memory ownership is passed from the std::auto_ptr C++ layer to the proxy
6+
* class when returning a std::auto_ptr from a function.
7+
* Memory ownership is passed from the proxy class to the std::auto_ptr in the
8+
* C++ layer when passed as a parameter to a wrapped function.
9+
* ----------------------------------------------------------------------------- */
10+
11+
%define %auto_ptr(TYPE)
12+
%typemap(in, noblock=1) std::auto_ptr< TYPE > (void *argp = 0, int res = 0) {
13+
res = SWIG_ConvertPtr(&$input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE);
14+
if (!SWIG_IsOK(res)) {
15+
if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
16+
zend_type_error("Cannot release ownership as memory is not owned for argument $argnum of type 'TYPE *' of $symname");
17+
return;
18+
} else {
19+
zend_type_error("Expected TYPE * for argument $argnum of $symname");
20+
return;
21+
}
22+
}
23+
$1.reset((TYPE *)argp);
24+
}
25+
26+
%typemap (out) std::auto_ptr< TYPE > %{
27+
SWIG_SetPointerZval($result, (void *)$1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN);
28+
%}
29+
30+
%template() std::auto_ptr< TYPE >;
31+
%enddef
32+
33+
namespace std {
34+
template <class T> class auto_ptr {};
35+
}

Lib/php/std_unique_ptr.i

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* -----------------------------------------------------------------------------
2+
* std_unique_ptr.i
3+
*
4+
* SWIG library file for handling std::unique_ptr.
5+
* Memory ownership is passed from the std::unique_ptr C++ layer to the proxy
6+
* class when returning a std::unique_ptr from a function.
7+
* Memory ownership is passed from the proxy class to the std::unique_ptr in the
8+
* C++ layer when passed as a parameter to a wrapped function.
9+
* ----------------------------------------------------------------------------- */
10+
11+
%define %unique_ptr(TYPE)
12+
%typemap(in, noblock=1) std::unique_ptr< TYPE > (void *argp = 0, int res = 0) {
13+
res = SWIG_ConvertPtr(&$input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE);
14+
if (!SWIG_IsOK(res)) {
15+
if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
16+
zend_type_error("Cannot release ownership as memory is not owned for argument $argnum of type 'TYPE *' of $symname");
17+
return;
18+
} else {
19+
zend_type_error("Expected TYPE * for argument $argnum of $symname");
20+
return;
21+
}
22+
}
23+
$1.reset((TYPE *)argp);
24+
}
25+
26+
%typemap (out) std::unique_ptr< TYPE > %{
27+
SWIG_SetPointerZval($result, (void *)$1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN);
28+
%}
29+
30+
%template() std::unique_ptr< TYPE >;
31+
%enddef
32+
33+
namespace std {
34+
template <class T> class unique_ptr {};
35+
}

0 commit comments

Comments
 (0)