From de9d01dbcdc3128e74ad290093dbf57e6df31bd5 Mon Sep 17 00:00:00 2001 From: Olly Betts Date: Fri, 18 May 2012 02:43:52 +0000 Subject: [PATCH] [PHP] Fix getters for template members. (SF#3428833) git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@13096 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- CHANGES.current | 3 ++ Examples/test-suite/common.mk | 1 + .../test-suite/li_std_vector_member_var.i | 23 +++++++++ .../php/li_std_vector_member_var_runme.php | 24 ++++++++++ Source/Modules/php.cxx | 47 +++++++++++-------- 5 files changed, 78 insertions(+), 20 deletions(-) create mode 100644 Examples/test-suite/li_std_vector_member_var.i create mode 100644 Examples/test-suite/php/li_std_vector_member_var_runme.php diff --git a/CHANGES.current b/CHANGES.current index 2092bd6e4..dd5132efa 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -5,6 +5,9 @@ See the RELEASENOTES file for a summary of changes in each release. Version 2.0.7 (in progress) =========================== +2012-05-18: olly + [PHP] Fix getters for template members. (SF#3428833) + 2012-05-14: wsfulton Fix some language's std::map wrappers to recognise difference_type, size_type, key_type and mapped_type. diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 9e7e21ac4..73c0c4254 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -475,6 +475,7 @@ CPP_STD_TEST_CASES += \ li_std_string \ li_std_vector \ li_std_vector_enum \ + li_std_vector_member_var\ naturalvar \ smart_pointer_inherit \ template_typedef_fnc \ diff --git a/Examples/test-suite/li_std_vector_member_var.i b/Examples/test-suite/li_std_vector_member_var.i new file mode 100644 index 000000000..b6e0727db --- /dev/null +++ b/Examples/test-suite/li_std_vector_member_var.i @@ -0,0 +1,23 @@ +%module li_std_vector_member_var + +%include "std_vector.i" + +%template(vectorDbl) std::vector; + +%inline %{ +#include + +typedef std::vector DblVector; + +struct Test { + DblVector v; + int x; + + Test() : x(0) { } + + void f(int n) { + x += n; + v.push_back(1.0 / n); + } +}; +%} diff --git a/Examples/test-suite/php/li_std_vector_member_var_runme.php b/Examples/test-suite/php/li_std_vector_member_var_runme.php new file mode 100644 index 000000000..96accf39f --- /dev/null +++ b/Examples/test-suite/php/li_std_vector_member_var_runme.php @@ -0,0 +1,24 @@ +x, 0, "Test::x != 0"); +check::equal($t->v->size(), 0, "Test::v.size() != 0"); + +$t->f(1); +check::equal($t->x, 1, "Test::x != 1"); +check::equal($t->v->size(), 1, "Test::v.size() != 1"); + +$t->f(2); +check::equal($t->x, 3, "Test::x != 3"); +check::equal($t->v->size(), 2, "Test::v.size() != 2"); + +$t->f(3); +check::equal($t->x, 6, "Test::x != 6"); +check::equal($t->v->size(), 3, "Test::v.size() != 3"); + +check::done(); +?> diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 1ac9e8b24..c5391a2e0 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -1032,7 +1032,7 @@ public: p += strlen(p) - 4; String *varname = Getattr(n, "membervariableHandler:sym:name"); if (strcmp(p, "_get") == 0) { - Setattr(shadow_get_vars, varname, iname); + Setattr(shadow_get_vars, varname, Getattr(n, "type")); } else if (strcmp(p, "_set") == 0) { Setattr(shadow_set_vars, varname, iname); } @@ -2012,7 +2012,6 @@ done: classnode = 0; if (shadow) { - DOH *key; List *baselist = Getattr(n, "bases"); Iterator ki, base; @@ -2055,10 +2054,10 @@ done: // FIXME: tune this threshold... if (Len(shadow_set_vars) <= 2) { // Not many setters, so avoid call_user_func. - while (ki.key) { - key = ki.key; - Printf(s_phpclasses, "\t\tif ($var === '%s') return %s($this->%s,$value);\n", key, ki.item, SWIG_PTR); - ki = Next(ki); + for (; ki.key; ki = Next(ki)) { + DOH *key = ki.key; + String *iname = ki.item; + Printf(s_phpclasses, "\t\tif ($var === '%s') return %s($this->%s,$value);\n", key, iname, SWIG_PTR); } } else { Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_set';\n", shadow_classname); @@ -2106,21 +2105,29 @@ done: if (ki.key) { // This class has getters. Printf(s_phpclasses, "\n\tfunction __get($var) {\n"); - // FIXME: Currently we always use call_user_func for __get, so we can - // check and wrap the result. This is needless if all the properties - // are primitive types. Also this doesn't handle all the cases which - // a method returning an object does. - Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_get';\n", shadow_classname); - Printf(s_phpclasses, "\t\tif (function_exists($func)) {\n"); - Printf(s_phpclasses, "\t\t\t$r = call_user_func($func,$this->%s);\n", SWIG_PTR); - Printf(s_phpclasses, "\t\t\tif (!is_resource($r)) return $r;\n"); - if (Len(prefix) == 0) { - Printf(s_phpclasses, "\t\t\t$c=substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));\n"); - } else { - Printf(s_phpclasses, "\t\t\t$c='%s'.substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));\n", prefix); + int non_class_getters = 0; + for (; ki.key; ki = Next(ki)) { + DOH *key = ki.key; + SwigType *d = ki.item; + if (!is_class(d)) { + ++non_class_getters; + continue; + } + Printv(s_phpclasses, "\t\tif ($var === '", key, "') return new ", prefix, Getattr(classLookup(d), "sym:name"), "(", shadow_classname, "_", key, "_get($this->", SWIG_PTR, "));\n", NIL); + } + // FIXME: tune this threshold... + if (non_class_getters <= 2) { + // Not many non-class getters, so avoid call_user_func. + for (ki = First(shadow_get_vars); non_class_getters && ki.key; --non_class_getters, ki = Next(ki)) { + DOH *key = ki.key; + SwigType *d = ki.item; + if (is_class(d)) continue; + Printv(s_phpclasses, "\t\tif ($var === '", key, "') return ", shadow_classname, "_", key, "_get($this->", SWIG_PTR, ");\n", NIL); + } + } else { + Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_get';\n", shadow_classname); + Printf(s_phpclasses, "\t\tif (function_exists($func)) return call_user_func($func,$this->%s);\n", SWIG_PTR); } - Printf(s_phpclasses, "\t\t\treturn new $c($r);\n"); - Printf(s_phpclasses, "\t\t}\n"); Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_get_newobject($this->%s);\n", module, SWIG_PTR); if (baseclass) { Printf(s_phpclasses, "\t\treturn %s%s::__get($var);\n", prefix, baseclass);