[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
This commit is contained in:
Olly Betts 2012-05-18 02:43:52 +00:00
commit de9d01dbcd
5 changed files with 78 additions and 20 deletions

View file

@ -5,6 +5,9 @@ See the RELEASENOTES file for a summary of changes in each release.
Version 2.0.7 (in progress) Version 2.0.7 (in progress)
=========================== ===========================
2012-05-18: olly
[PHP] Fix getters for template members. (SF#3428833)
2012-05-14: wsfulton 2012-05-14: wsfulton
Fix some language's std::map wrappers to recognise difference_type, size_type, key_type Fix some language's std::map wrappers to recognise difference_type, size_type, key_type
and mapped_type. and mapped_type.

View file

@ -475,6 +475,7 @@ CPP_STD_TEST_CASES += \
li_std_string \ li_std_string \
li_std_vector \ li_std_vector \
li_std_vector_enum \ li_std_vector_enum \
li_std_vector_member_var\
naturalvar \ naturalvar \
smart_pointer_inherit \ smart_pointer_inherit \
template_typedef_fnc \ template_typedef_fnc \

View file

@ -0,0 +1,23 @@
%module li_std_vector_member_var
%include "std_vector.i"
%template(vectorDbl) std::vector<double>;
%inline %{
#include <vector>
typedef std::vector<double> DblVector;
struct Test {
DblVector v;
int x;
Test() : x(0) { }
void f(int n) {
x += n;
v.push_back(1.0 / n);
}
};
%}

View file

@ -0,0 +1,24 @@
<?php
require "tests.php";
require "li_std_vector_member_var.php";
$t = new Test();
check::equal($t->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();
?>

View file

@ -1032,7 +1032,7 @@ public:
p += strlen(p) - 4; p += strlen(p) - 4;
String *varname = Getattr(n, "membervariableHandler:sym:name"); String *varname = Getattr(n, "membervariableHandler:sym:name");
if (strcmp(p, "_get") == 0) { 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) { } else if (strcmp(p, "_set") == 0) {
Setattr(shadow_set_vars, varname, iname); Setattr(shadow_set_vars, varname, iname);
} }
@ -2012,7 +2012,6 @@ done:
classnode = 0; classnode = 0;
if (shadow) { if (shadow) {
DOH *key;
List *baselist = Getattr(n, "bases"); List *baselist = Getattr(n, "bases");
Iterator ki, base; Iterator ki, base;
@ -2055,10 +2054,10 @@ done:
// FIXME: tune this threshold... // FIXME: tune this threshold...
if (Len(shadow_set_vars) <= 2) { if (Len(shadow_set_vars) <= 2) {
// Not many setters, so avoid call_user_func. // Not many setters, so avoid call_user_func.
while (ki.key) { for (; ki.key; ki = Next(ki)) {
key = ki.key; DOH *key = ki.key;
Printf(s_phpclasses, "\t\tif ($var === '%s') return %s($this->%s,$value);\n", key, ki.item, SWIG_PTR); String *iname = ki.item;
ki = Next(ki); Printf(s_phpclasses, "\t\tif ($var === '%s') return %s($this->%s,$value);\n", key, iname, SWIG_PTR);
} }
} else { } else {
Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_set';\n", shadow_classname); Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_set';\n", shadow_classname);
@ -2106,21 +2105,29 @@ done:
if (ki.key) { if (ki.key) {
// This class has getters. // This class has getters.
Printf(s_phpclasses, "\n\tfunction __get($var) {\n"); Printf(s_phpclasses, "\n\tfunction __get($var) {\n");
// FIXME: Currently we always use call_user_func for __get, so we can int non_class_getters = 0;
// check and wrap the result. This is needless if all the properties for (; ki.key; ki = Next(ki)) {
// are primitive types. Also this doesn't handle all the cases which DOH *key = ki.key;
// a method returning an object does. SwigType *d = ki.item;
Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_get';\n", shadow_classname); if (!is_class(d)) {
Printf(s_phpclasses, "\t\tif (function_exists($func)) {\n"); ++non_class_getters;
Printf(s_phpclasses, "\t\t\t$r = call_user_func($func,$this->%s);\n", SWIG_PTR); continue;
Printf(s_phpclasses, "\t\t\tif (!is_resource($r)) return $r;\n"); }
if (Len(prefix) == 0) { Printv(s_phpclasses, "\t\tif ($var === '", key, "') return new ", prefix, Getattr(classLookup(d), "sym:name"), "(", shadow_classname, "_", key, "_get($this->", SWIG_PTR, "));\n", NIL);
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 { // FIXME: tune this threshold...
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); 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); Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_get_newobject($this->%s);\n", module, SWIG_PTR);
if (baseclass) { if (baseclass) {
Printf(s_phpclasses, "\t\treturn %s%s::__get($var);\n", prefix, baseclass); Printf(s_phpclasses, "\t\treturn %s%s::__get($var);\n", prefix, baseclass);