summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Examples/test-suite/php/overload_simple_runme.php7
-rw-r--r--Lib/php/phprun.swg19
-rw-r--r--Source/Modules/php.cxx13
3 files changed, 35 insertions, 4 deletions
diff --git a/Examples/test-suite/php/overload_simple_runme.php b/Examples/test-suite/php/overload_simple_runme.php
index 3cba1d35b..949de9d98 100644
--- a/Examples/test-suite/php/overload_simple_runme.php
+++ b/Examples/test-suite/php/overload_simple_runme.php
@@ -187,8 +187,9 @@ check("' 11 '", 'char *');
# Check TypeError is thrown when the wrong type is passed.
check("array()", NULL);
-# FIXME: These need fixing
-#check("function(){}", NULL);
-#check("new stdClass()", NULL);
+check("function(){}", NULL);
+check("new stdClass()", NULL);
+class NotASwigWrappedClass { };
+check("new NotASwigWrappedClass()", NULL);
check::done();
diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg
index a24b2551c..97d17d9ca 100644
--- a/Lib/php/phprun.swg
+++ b/Lib/php/phprun.swg
@@ -93,6 +93,12 @@ static int default_error_code = E_ERROR;
#define SWIG_GetModule(clientdata) SWIG_Php_GetModule()
#define SWIG_SetModule(clientdata, pointer) SWIG_Php_SetModule(pointer, *(int*)clientdata)
+static zend_class_entry SWIG_Php_swig_wrapped_interface_ce;
+
+#if PHP_MAJOR_VERSION == 7
+# define zend_class_implements_interface(C, I) instanceof_function_ex(C, I, 1)
+#endif
+
/* used to wrap returned objects in so we know whether they are newobject
and need freeing, or not */
typedef struct {
@@ -156,7 +162,18 @@ SWIG_ConvertPtrAndOwn(zval *z, void **ptr, swig_type_info *ty, int flags, swig_o
switch (Z_TYPE_P(z)) {
case IS_OBJECT: {
- swig_object_wrapper *value = SWIG_Z_FETCH_OBJ_P(z);
+ zend_object *obj = Z_OBJ_P(z);
+ swig_object_wrapper *value;
+ if (ty && ty->clientdata == (void*)obj->ce) {
+ // Object is exactly the class asked for - this handles common cases cheaply,
+ // and in particular the PHP classes we use to wrap a pointer to a non-class.
+ } else if (!zend_class_implements_interface(obj->ce, &SWIG_Php_swig_wrapped_interface_ce)) {
+ // Not an object we've wrapped.
+ return -1;
+ }
+
+ /* convert and cast value->ptr from value->type to ptr as ty. */
+ value = swig_php_fetch_object(obj);
if (!ty) {
/* They don't care about the target type, so just pass on the pointer! */
*ptr = value->ptr;
diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx
index 1887bba3c..533ea2fc6 100644
--- a/Source/Modules/php.cxx
+++ b/Source/Modules/php.cxx
@@ -87,6 +87,15 @@ static String *fake_class_name() {
return result;
}
+static String *swig_wrapped_interface_ce() {
+ static String *result = NULL;
+ if (!result) {
+ result = NewStringf("SWIG_Php_swig_wrapped_interface_ce");
+ Printf(s_oinit, " INIT_CLASS_ENTRY(%s, \"SWIG\\\\wrapped\", NULL);\n", result);
+ }
+ return result;
+}
+
/* To reduce code size (generated and compiled) we only want to emit each
* different arginfo once, so we need to track which have been used.
*/
@@ -163,12 +172,14 @@ static void SwigPHP_emit_pointer_type_registrations() {
while (ki.key) {
String *type = ki.key;
+ String *swig_wrapped = swig_wrapped_interface_ce();
Printf(s_creation, "/* class entry for pointer to %s */\n", type);
Printf(s_creation, "static zend_class_entry *SWIG_Php_ce_%s;\n\n", type);
Printf(s_oinit, " INIT_CLASS_ENTRY(internal_ce, \"%s\\\\%s\", NULL);\n", "SWIG", type);
Printf(s_oinit, " SWIG_Php_ce_%s = zend_register_internal_class(&internal_ce);\n", type);
Printf(s_oinit, " SWIG_Php_ce_%s->create_object = swig_ptr_object_new;\n", type);
+ Printv(s_oinit, " zend_do_implement_interface(SWIG_Php_ce_", type, ", &", swig_wrapped, ");\n", NIL);
Printf(s_oinit, " SWIG_TypeClientData(SWIGTYPE%s,SWIG_Php_ce_%s);\n", type, type);
Printf(s_oinit, "\n");
@@ -1633,6 +1644,8 @@ public:
if (Getattr(n, "abstracts") && !GetFlag(n, "feature:notabstract")) {
Printf(s_oinit, " SWIG_Php_ce_%s->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;\n", class_name);
}
+ String *swig_wrapped = swig_wrapped_interface_ce();
+ Printv(s_oinit, " zend_do_implement_interface(SWIG_Php_ce_", class_name, ", &", swig_wrapped, ");\n", NIL);
{
Node *node = NewHash();