summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlly Betts <olly@survex.com>2021-05-03 16:00:30 +1200
committerOlly Betts <olly@survex.com>2021-05-03 16:00:30 +1200
commit04bacf689b5c9ddc5b6d3ef84c281c3a499a00ad (patch)
tree673bd72d946826b11be23dbe55fccec1098d6748
parent3c4342e66ae5c0c59869772377ca78d9ec4668d0 (diff)
downloadswig-04bacf689b5c9ddc5b6d3ef84c281c3a499a00ad.tar.gz
Implement director-disown for PHP
-rw-r--r--Lib/php/director.swg22
-rw-r--r--Source/Modules/php.cxx28
2 files changed, 42 insertions, 8 deletions
diff --git a/Lib/php/director.swg b/Lib/php/director.swg
index 7a81cd518..ead731a48 100644
--- a/Lib/php/director.swg
+++ b/Lib/php/director.swg
@@ -8,6 +8,8 @@
#ifndef SWIG_DIRECTOR_PHP_HEADER_
#define SWIG_DIRECTOR_PHP_HEADER_
+#define SWIG_DIRECTOR_CAST(ARG) dynamic_cast<Swig::Director *>(ARG)
+
#include <string>
#include <exception>
#include <map>
@@ -76,16 +78,34 @@ namespace Swig {
};
class Director {
+ private:
+ /* flag indicating whether the object is owned by PHP or C++ */
+ mutable bool swig_disown_flag;
+
protected:
// "mutable" so we can get a non-const pointer to it in const methods.
mutable zval swig_self;
typedef std::map<void *, GCItem_var> swig_ownership_map;
mutable swig_ownership_map swig_owner;
+
public:
- Director(zval *self) {
+ Director(zval *self) : swig_disown_flag(false) {
ZVAL_COPY_VALUE(&swig_self, self);
}
+ ~Director() {
+ if (swig_disown_flag) {
+ Z_DELREF(swig_self);
+ }
+ }
+
+ void swig_disown() const {
+ if (!swig_disown_flag) {
+ swig_disown_flag = true;
+ Z_ADDREF(swig_self);
+ }
+ }
+
static bool swig_is_overridden_method(const char *cname, zval *z) {
zend_string * cname_str = zend_string_init(cname, strlen(cname), 0);
zend_class_entry *ce = zend_lookup_class(cname_str);
diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx
index 9e52400b7..79c2bd567 100644
--- a/Source/Modules/php.cxx
+++ b/Source/Modules/php.cxx
@@ -110,7 +110,8 @@ static enum {
membervar,
staticmembervar,
constructor,
- directorconstructor
+ directorconstructor,
+ directordisown
} wrapperType = standard;
extern "C" {
@@ -904,7 +905,7 @@ public:
return false;
}
- void generate_magic_property_methods(String *baseClassExtend) {
+ void generate_magic_property_methods(Node *class_node, String *baseClassExtend) {
if (Cmp(baseClassExtend, "Exception") == 0 || !is_class_wrapped(baseClassExtend)) {
baseClassExtend = NULL;
}
@@ -944,8 +945,14 @@ public:
Append(f->code, magic_set);
}
Printf(f->code, "\nelse if (strcmp(ZSTR_VAL(arg2),\"thisown\") == 0) {\n");
- Printf(f->code, "arg->newobject = zval_get_long(&args[1]);\n}\n\n");
- Printf(f->code, "else {\n");
+ Printf(f->code, "arg->newobject = zval_get_long(&args[1]);\n");
+ if (Swig_directorclass(class_node)) {
+ Printv(f->code, "if (arg->newobject == 0) {\n",
+ " Swig::Director *director = SWIG_DIRECTOR_CAST((", Getattr(class_node, "classtypeobj"), "*)(arg->ptr));\n",
+ " if (director) director->swig_disown();\n",
+ "}\n", NIL);
+ }
+ Printf(f->code, "} else {\n");
if (baseClassExtend) {
Printf(f->code, "PHP_MN(%s___set)(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n}\n", baseClassExtend);
} else {
@@ -1074,6 +1081,10 @@ public:
}
virtual int functionWrapper(Node *n) {
+ if (wrapperType == directordisown) {
+ // Handled via __set magic method - no explicit wrapper method wanted.
+ return SWIG_OK;
+ }
String *name = GetChar(n, "name");
String *iname = GetChar(n, "sym:name");
SwigType *d = Getattr(n, "type");
@@ -1673,7 +1684,7 @@ public:
Language::classHandler(n);
print_creation_free_wrapper(n);
- generate_magic_property_methods(baseClassExtend);
+ generate_magic_property_methods(n, baseClassExtend);
Printf(all_cs_entry, " ZEND_FE_END\n};\n\n");
class_name = NULL;
@@ -2190,8 +2201,11 @@ public:
return status;
}
- int classDirectorDisown(Node *) {
- return SWIG_OK;
+ int classDirectorDisown(Node *n) {
+ wrapperType = directordisown;
+ int result = Language::classDirectorDisown(n);
+ wrapperType = standard;
+ return result;
}
}; /* class PHP */