[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)
===========================
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.

View file

@ -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 \

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;
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);