From 8252f37ae8a50f299b2efb50fa9bde49dd75962a Mon Sep 17 00:00:00 2001 From: Nihal Date: Sat, 5 Aug 2017 10:22:51 +0530 Subject: [PATCH] Refactor code and introduce some functionalities. Also Fix some testcases. Code Refactor - Refactor code for return type of SWIGTYPE - Workaround for Namespaced classes. - Refactor code of SWIG_SetZval to take care of objects in class constructor. - Introduce SWIG_generalize_object to generalize each object to swig object wrapper. - Catch feature:immutable instead of feature:warnfilter - 462 for missing setter. - Refactor code to create PHP objects for all instances of value, reference and pointer return types of C++ objects. This applies for conversion operators too. - Introduce getAccessMode to get the Access Mode of a method for generating Wrapper. - Refactor free_object creation to include need_free condition. This is to check if there is a need to free. Example where it isn't required to free - (Virtual Protected Destructors). - Support for feature:exceptionclass. Extends class Exception. - Improve condition check in Director class constructor to distinguish between, extended class creation or not. Swig::Director::swig_is_overridden_method is used. --- Lib/php/factory.i | 4 +- Lib/php/php.swg | 106 +++++++++++---------------- Lib/php/phprun.swg | 40 +++++++--- Source/Modules/php.cxx | 163 +++++++++++++++++++++++++++-------------- 4 files changed, 184 insertions(+), 129 deletions(-) diff --git a/Lib/php/factory.i b/Lib/php/factory.i index 6a6b504ec..565383c40 100644 --- a/Lib/php/factory.i +++ b/Lib/php/factory.i @@ -103,7 +103,7 @@ if (!dcast) { else { std = $zend_obj; } - SWIG_SetZval(return_value, $newobj , $c_obj, SWIG_as_voidptr(dobj), $descriptor(Type *), std); + SWIG_SetZval(return_value, $classZv, $owner, $newobj, $c_obj, SWIG_as_voidptr(dobj), $descriptor(Type *), std); } }%enddef @@ -112,6 +112,6 @@ if (!dcast) { int dcast = 0; %formacro(%_factory_dispatch, Types) if (!dcast) { - SWIG_SetZval(return_value, $newobj , $c_obj, SWIG_as_voidptr($1), $descriptor, $zend_obj); + SWIG_SetZval(return_value, $classZv, $owner, $newobj, $c_obj, SWIG_as_voidptr($1), $descriptor, $zend_obj); } }%enddef diff --git a/Lib/php/php.swg b/Lib/php/php.swg index 1ababd48b..b521d452e 100644 --- a/Lib/php/php.swg +++ b/Lib/php/php.swg @@ -85,30 +85,30 @@ /* Object passed by value. Convert to a pointer */ %typemap(in) SWIGTYPE ($&1_ltype tmp) %{ - if (zend_lookup_class(zend_string_init("$lower_param",sizeof("$lower_param")-1,0))) { + if (zend_lookup_class(zend_string_init("$lower_param",sizeof("$lower_param")-1,0))) { $1 = *$obj_value; } else { if (SWIG_ConvertPtr(&$input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) - SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1&_descriptor"); $1 = *tmp; } %} %typemap(directorout) SWIGTYPE ($&1_ltype tmp) %{ - /* If exit was via exception, PHP NULL is returned so skip the conversion. */ - if (!EG(exception)) { - if (SWIG_ConvertPtr($input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) - SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); - $result = *tmp; - } + /* If exit was via exception, PHP NULL is returned so skip the conversion. */ + if (!EG(exception)) { + if (SWIG_ConvertPtr($input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); + $result = *tmp; + } %} %typemap(in) SWIGTYPE *, SWIGTYPE [] %{ - if (zend_lookup_class(zend_string_init("$lower_param",sizeof("$lower_param")-1,0))) { + if (zend_lookup_class(zend_string_init("$lower_param",sizeof("$lower_param")-1,0))) { $1 = $obj_value; } else { @@ -119,30 +119,40 @@ %typemap(in) SWIGTYPE & %{ - if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) + if (zend_lookup_class(zend_string_init("$lower_param",sizeof("$lower_param")-1,0))) { + $1 = $obj_value; + } + else { + if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); + } %} %typemap(in) SWIGTYPE && %{ - if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) { - SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); - } + if (zend_lookup_class(zend_string_init("$lower_param",sizeof("$lower_param")-1,0))) { + $1 = $obj_value; + } + else { + if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) { + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); + } + } %} %typemap(in) SWIGTYPE *const& ($*ltype temp) %{ - if (SWIG_ConvertPtr(&$input, (void **) &temp, $*1_descriptor, 0) < 0) { - SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $*1_descriptor"); - } - $1 = ($1_ltype)&temp; + if (SWIG_ConvertPtr(&$input, (void **) &temp, $*1_descriptor, 0) < 0) { + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $*1_descriptor"); + } + $1 = ($1_ltype)&temp; %} %typemap(in) SWIGTYPE *DISOWN %{ if (zend_lookup_class(zend_string_init("$lower_param",sizeof("$lower_param")-1,0))) { - Z_FETCH_OBJ_P(&$input)->newobject = 0; - $1 = ($lower_param *)Z_FETCH_OBJ_P(&$input)->ptr; + SWIG_Z_FETCH_OBJ_P(&$input)->newobject = 0; + $1 = ($lower_param *)SWIG_Z_FETCH_OBJ_P(&$input)->ptr; } else { if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, SWIG_POINTER_DISOWN ) < 0) @@ -157,12 +167,12 @@ %typemap(in) void * %{ - if (SWIG_ConvertPtr(&$input, (void **) &$1, 0, 0) < 0) { - /* Allow NULL from php for void* */ - if (Z_ISNULL($input)) $1=0; - else - SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); - } + if (SWIG_ConvertPtr(&$input, (void **) &$1, 0, 0) < 0) { + /* Allow NULL from php for void* */ + if (Z_ISNULL($input)) $1=0; + else + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); + } %} /* Special case when void* is passed by reference so it can be made to point @@ -381,12 +391,12 @@ SWIGTYPE &, SWIGTYPE && %{ - SWIG_SetZval($result, $newobj , $c_obj, (void *)result, $1_descriptor, $zend_obj); + SWIG_SetZval($result, $classZv, $owner, $newobj, $c_obj, (void *)result, $1_descriptor, $zend_obj); %} %typemap(out) SWIGTYPE *const& %{ - SWIG_SetPointerZval(return_value, (void *)*$1, $*1_descriptor, $owner); + SWIG_SetZval(return_value, $classZv, $owner, $newobj, $c_obj, (void *)*$1, $*1_descriptor, $zend_obj); %} %typemap(directorin) SWIGTYPE *, @@ -421,45 +431,13 @@ #ifdef __cplusplus { $&1_ltype resultobj = new $1_ltype((const $1_ltype &) $1); - SWIG_SetZval(return_value, $newobj , $c_obj, (void *)resultobj, $&1_descriptor, $zend_obj); - swig_object_wrapper *obj = NULL; - - HashTable * ht = NULL; - - obj = (swig_object_wrapper *) Z_FETCH_OBJ_P(return_value); - obj->ptr = (void *)resultobj; - ht = Z_OBJ_HT_P(return_value)->get_properties(return_value); - if(ht) { - zval zv; - ZVAL_RES(&zv,zend_register_resource(resultobj,*(int *)($&1_descriptor->clientdata))); - zend_hash_str_add(ht, "_cPtr", sizeof("_cPtr") - 1, &zv); - } - if ($newobj == 1) - obj->newobject = 1; - else - obj->newobject = 0; + SWIG_SetZval(return_value, $classZv, $owner, $newobj, $c_obj, (void *)resultobj, $&1_descriptor, $zend_obj); } #else { $&1_ltype resultobj = ($&1_ltype) emalloc(sizeof($1_type)); memcpy(resultobj, &$1, sizeof($1_type)); - SWIG_SetZval(return_value, $newobj , $c_obj, (void *)resultobj, $&1_descriptor, $zend_obj); - swig_object_wrapper *obj = NULL; - - HashTable * ht = NULL; - - obj = (swig_object_wrapper *) Z_FETCH_OBJ_P(return_value); - obj->ptr = (void *)resultobj; - ht = Z_OBJ_HT_P(return_value)->get_properties(return_value); - if(ht) { - zval zv; - ZVAL_RES(&zv,zend_register_resource(resultobj,*(int *)($&1_descriptor->clientdata))); - zend_hash_str_add(ht, "_cPtr", sizeof("_cPtr") - 1, &zv); - } - if ($newobj) - obj->newobject = 1; - else - obj->newobject = 0; + SWIG_SetZval(return_value, $classZv, $owner, $newobj, $c_obj, (void *)resultobj, $&1_descriptor, $zend_obj); } #endif @@ -514,7 +492,7 @@ %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE { void *tmp; - _v = (SWIG_ConvertPtr(&$input, (void **)&tmp, $1_descriptor, 0) >= 0); + _v = (SWIG_ConvertPtr(&$input, (void **)&tmp, $&1_descriptor, 0) >= 0); } %typecheck(SWIG_TYPECHECK_POINTER) @@ -531,13 +509,13 @@ %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *const& { void *tmp; - _v = (SWIG_ConvertPtr(&$input, (void **)&tmp, $1_descriptor, 0) >= 0); + _v = (SWIG_ConvertPtr(&$input, (void **)&tmp, $*1_descriptor, 0) >= 0); } %typecheck(SWIG_TYPECHECK_VOIDPTR) void * { void *tmp; - _v = (SWIG_ConvertPtr(&$input, (void **)&tmp, $1_descriptor, 0) >= 0); + _v = (SWIG_ConvertPtr(&$input, (void **)&tmp, 0, 0) >= 0); } /* Exception handling */ diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg index e6d361c8d..b048dc569 100644 --- a/Lib/php/phprun.swg +++ b/Lib/php/phprun.swg @@ -225,11 +225,37 @@ SWIG_ConvertPtr(zval *z, void **ptr, swig_type_info *ty, int flags) { return -1; } -static void -SWIG_SetZval( zval *zv, int object, int class_obj ,void *ptr, swig_type_info *type, zend_object *std) { +#define SWIG_Z_FETCH_OBJ_P(zv) php_fetch_object(Z_OBJ_P(zv)) - if (class_obj) +static inline +swig_object_wrapper * php_fetch_object(zend_object *obj) { + return (swig_object_wrapper *)((char *)obj - XtOffsetOf(swig_object_wrapper, std)); +} + +static void +SWIG_generalize_object(zval *zval_obj, void *ptr, int class_obj, int userNewObj ,swig_type_info *type) { + swig_object_wrapper *obj = NULL; + + HashTable * ht = NULL; + + obj = (swig_object_wrapper *) SWIG_Z_FETCH_OBJ_P(zval_obj); + obj->ptr = (void *)ptr; + ht = Z_OBJ_HT_P(zval_obj)->get_properties(zval_obj); + if(ht) { + zval zv; + ZVAL_RES(&zv,zend_register_resource(ptr,*(int *)(type->clientdata))); + zend_hash_str_add(ht, "_cPtr", sizeof("_cPtr") - 1, &zv); + } + obj->newobject = userNewObj; +} + +static void +SWIG_SetZval( zval *zv, zval *class_zv, int userNewObj ,int object, int class_obj ,void *ptr, swig_type_info *type, zend_object *std) { + + if (class_obj) { + SWIG_generalize_object(class_zv, ptr, class_obj, userNewObj ,type); return; + } if (!ptr) { ZVAL_NULL(zv); @@ -238,6 +264,7 @@ SWIG_SetZval( zval *zv, int object, int class_obj ,void *ptr, swig_type_info *ty if (object == 1) { ZVAL_OBJ(zv,std); + SWIG_generalize_object(zv, ptr, class_obj, userNewObj, type); } if (object == 2) { @@ -245,13 +272,6 @@ SWIG_SetZval( zval *zv, int object, int class_obj ,void *ptr, swig_type_info *ty } } -#define Z_FETCH_OBJ_P(zv) php_fetch_object(Z_OBJ_P(zv)) - -static inline -swig_object_wrapper * php_fetch_object(zend_object *obj) { - return (swig_object_wrapper *)((char *)obj - XtOffsetOf(swig_object_wrapper, std)); -} - static char const_name[] = "swig_runtime_data_type_pointer"; static swig_module_info *SWIG_Php_GetModule() { zval *pointer = zend_get_constant_str(const_name, sizeof(const_name) - 1); diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 4b79868ed..2370aa161 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -105,6 +105,7 @@ static String *class_name = NULL; static String *class_type = NULL; static List *classes = NewList(); static List *class_types = NewList(); +static List *class_need_free = NewList(); static String *magic_set = NULL; static String *magic_get = NULL; static String *magic_isset = NULL; @@ -146,6 +147,9 @@ static void print_creation_free_wrapper(int item_index) { class_name = Getitem(classes, item_index); class_type = Getitem(class_types, item_index); + bool need_free = false; + if (Cmp(Getitem(class_need_free, item_index), "1") == 0) + need_free = true; Printf(s_header, "/* class entry for %s */\n",class_name); Printf(s_header, "zend_class_entry *%s_ce;\n\n",class_name); @@ -162,8 +166,12 @@ static void print_creation_free_wrapper(int item_index) { Printf(s_header, " if(!object)\n\t return;\n"); Printf(s_header, " swig_object_wrapper *obj = (swig_object_wrapper *)php_fetch_object(object);\n"); Printf(s_header, " if(!obj->newobject)\n\t return;\n"); - Printf(s_header, " if(obj->ptr)\n"); - Printf(s_header, " SWIG_remove((%s *)obj->ptr);\n",class_type); + + if (need_free) { + Printf(s_header, " if(obj->ptr)\n"); + Printf(s_header, " SWIG_remove((%s *)obj->ptr);\n",class_type); + } + Printf(s_header, " if(obj->extras) {\n"); Printf(s_header, " zend_hash_destroy(obj->extras);\n"); Printf(s_header, " FREE_HASHTABLE(obj->extras);\n }\n\n"); @@ -944,6 +952,18 @@ public: } + /* Helper method to remove class prefix on method names. + * Ex- Class_method_name -> method_name + */ + String *getWrapperMethodName(String *className, String *methodName) { + String *wrapper_class_name = NewString(className); + Append(wrapper_class_name, "_"); + String *wrapper_method_name = NewString(methodName); + Replace(wrapper_method_name, wrapper_class_name, "", DOH_REPLACE_FIRST); + Delete(wrapper_class_name); + return wrapper_method_name; + } + /* ------------------------------------------------------------ * dispatchFunction() * ------------------------------------------------------------ */ @@ -972,7 +992,7 @@ public: String *modes = NULL; if (class_name) - wname = Getattr(n, "name"); + wname = getWrapperMethodName(Getattr(n, "name"), symname); else wname = Swig_name_wrapper(symname); @@ -1011,7 +1031,6 @@ public: DelWrapper(f); Delete(dispatch); Delete(tmp); - Delete(wname); } /* ------------------------------------------------------------ @@ -1050,11 +1069,12 @@ public: } /* Is special return type */ - bool is_return(SwigType *t) { + bool is_param_type_pointer(SwigType *t) { if (SwigType_ispointer(t) || SwigType_ismemberpointer(t) || - SwigType_isarray(t)) + SwigType_isreference(t) || + SwigType_isarray(t)) return true; return false; @@ -1104,7 +1124,7 @@ public: Printf(all_cs_entry, " PHP_ME(%s,__set,swig_arginfo_00,ZEND_ACC_PUBLIC)\n", class_name); Printf(f->code, "PHP_METHOD(%s,__set) {\n",class_name); - Printf(f->code, " swig_object_wrapper *arg = (swig_object_wrapper *)Z_FETCH_OBJ_P(getThis());\n"); + Printf(f->code, " swig_object_wrapper *arg = (swig_object_wrapper *)SWIG_Z_FETCH_OBJ_P(getThis());\n"); Printf(f->code, " %s *arg1 = (%s *)(arg->ptr);\n", class_type, class_type); Printf(f->code, " zval args[2];\n zend_string *arg2 = 0;\n\n"); Printf(f->code, " if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {\n"); @@ -1136,7 +1156,7 @@ public: Printf(all_cs_entry, " PHP_ME(%s,__get,swig_arginfo_0,ZEND_ACC_PUBLIC)\n", class_name); Printf(f->code, "PHP_METHOD(%s,__get) {\n",class_name); - Printf(f->code, " swig_object_wrapper *arg = (swig_object_wrapper *)Z_FETCH_OBJ_P(getThis());\n", class_name); + Printf(f->code, " swig_object_wrapper *arg = (swig_object_wrapper *)SWIG_Z_FETCH_OBJ_P(getThis());\n", class_name); Printf(f->code, " %s *arg1 = (%s *)(arg->ptr);\n", class_type, class_type); Printf(f->code, " zval args[1];\n zend_string *arg2 = 0;\n\n"); Printf(f->code, " if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {\n"); @@ -1167,7 +1187,7 @@ public: Printf(all_cs_entry, " PHP_ME(%s,__isset,swig_arginfo_0,ZEND_ACC_PUBLIC)\n", class_name); Printf(f->code, "PHP_METHOD(%s,__isset) {\n",class_name); - Printf(f->code, " swig_object_wrapper *arg = (swig_object_wrapper *)Z_FETCH_OBJ_P(getThis());\n", class_name); + Printf(f->code, " swig_object_wrapper *arg = (swig_object_wrapper *)SWIG_Z_FETCH_OBJ_P(getThis());\n", class_name); Printf(f->code, " %s *arg1 = (%s *)(arg->ptr);\n", class_type, class_type); Printf(f->code, " zval args[1];\n zend_string *arg2 = 0;\n\n"); Printf(f->code, " int newSize = 1;\nchar *method_name = 0;\n\n"); @@ -1222,7 +1242,15 @@ public: Printf(magic_get, "zval zv;\nZVAL_STRING(&zv, \"%s_get\");\n",v_name); Printf(magic_get, "CALL_METHOD(zv, return_value, getThis());\n}\n"); - } + } + + String *getAccessMode(String *access) { + if (Cmp(access, "protected") == 0) + return NewString("ZEND_ACC_PROTECTED"); + else if (Cmp(access, "private") == 0) + return NewString("ZEND_ACC_PRIVATE"); + return NewString("ZEND_ACC_PUBLIC"); + } virtual int functionWrapper(Node *n) { String *name = GetChar(n, "name"); @@ -1246,13 +1274,13 @@ public: bool static_setter = false; bool static_getter = false; + modes = getAccessMode(Getattr(n, "access")); + if (constructor) { - modes = NewString("ZEND_ACC_PUBLIC | ZEND_ACC_CTOR"); + Append(modes,"| ZEND_ACC_CTOR"); } else if (wrapperType == staticmemberfn || Cmp(Getattr(n, "storage"),"static") == 0) - modes = NewString("ZEND_ACC_PUBLIC | ZEND_ACC_STATIC"); - else - modes = NewString("ZEND_ACC_PUBLIC"); + Append(modes,"| ZEND_ACC_STATIC"); if (Getattr(n, "sym:overloaded")) { overloaded = 1; @@ -1270,11 +1298,23 @@ public: else if (constructor) { wname = NewString("__construct"); } - else if (wrapperType == membervar || wrapperType == globalvar) { + else if (wrapperType == membervar) { char *ptr = Char(iname); ptr+= strlen(Char(iname)) - 4 - strlen(Char(name)); wname = (String*) ptr; } + else if (wrapperType == globalvar) { + //check for namespaces + String *nameSpace = getNameSpace(GetChar(n, "name")); + if (nameSpace == NULL) { + char *ptr = Char(iname); + ptr+= strlen(Char(iname)) - 4 - strlen(Char(name)); + wname = (String*) ptr; + } + else { + wname = iname; + } + } else if (wrapperType == staticmembervar) { // Shape::nshapes -> nshapes char *ptr = Char(strrchr(GetChar(n, "name"),':')); @@ -1290,7 +1330,7 @@ public: static_setter = true; else if (Cmp(strrchr(GetChar(n, "sym:name"),'_'),"_get") == 0) { // This is to overcome types that can't be set and hence no setter. - if (Cmp(Getattr(n, "feature:warnfilter"),"462") != 0) + if (Cmp(Getattr(n, "feature:immutable"),"1") != 0) static_getter = true; } } @@ -1301,13 +1341,7 @@ public: } else { if (class_name) { - String *intermediate_name = NewString(class_name); - Append(intermediate_name, "_"); - String *intermediate_method_name = NewString(iname); - Replace(intermediate_method_name, intermediate_name, "", DOH_REPLACE_FIRST); - wname = intermediate_method_name; - //Printf(s_oinit, "ASd %s %s %s\n", iname, name ,wname); - Delete(intermediate_name); + wname = getWrapperMethodName(class_name, iname); } else wname = iname; @@ -1368,7 +1402,7 @@ public: //Wrapper_add_local(f, "arg0", "zval * arg0;"); if ((wrapperType == memberfn || wrapperType == membervar)) { num_arguments--; //To remove This Pointer - Printf(args, "arg1 = (%s *)((Z_FETCH_OBJ_P(getThis()))->ptr);\n", class_type); + Printf(args, "arg1 = (%s *)((SWIG_Z_FETCH_OBJ_P(getThis()))->ptr);\n", class_type); } Printf(args, "zval args[%d]", num_arguments); Wrapper_add_local(f, "args", args); @@ -1480,12 +1514,12 @@ public: Printf(param_zval, "getThis()"); else Printf(param_zval, "&%s", source); - Printf(param_value, "(%s *) Z_FETCH_OBJ_P(%s)->ptr", paramType_type , param_zval); + Printf(param_value, "(%s *) SWIG_Z_FETCH_OBJ_P(%s)->ptr", paramType_type , param_zval); Replaceall(tm, "$obj_value", param_value); } String *temp_obj = NewStringEmpty(); Printf(temp_obj, "&%s", ln); - Replaceall(tm, "$obj_value", is_return(resolved ? resolved : pt) ? "NULL" : temp_obj); // Adding this to compile. It won't reach this if $obj_val is required. + Replaceall(tm, "$obj_value", is_param_type_pointer(resolved ? resolved : pt) ? "NULL" : temp_obj); // Adding this to compile. It won't reach this if $obj_val is required. Replaceall(tm, "$lower_param", paramType_class); Setattr(p, "emit:input", source); Printf(f->code, "%s\n", tm); @@ -1568,12 +1602,10 @@ public: String *retType_class = NULL; bool retType_valid = is_class(d); - bool retType_operator = false; if (retType_valid) { retType_class = get_class_name(d); Chop(retType_class); - retType_operator = Getattr(n, "conversion_operator") ? true : false; } /* emit function call */ @@ -1585,13 +1617,11 @@ public: Replaceall(tm, "$target", "return_value"); Replaceall(tm, "$result", "return_value"); Replaceall(tm, "$owner", newobject ? "1" : "0"); - Replaceall(tm, "$swig_type", SwigType_manglestr(d)); + Replaceall(tm, "$classZv", constructor ? "getThis()" : "NULL"); if (retType_class) { String *retZend_obj = NewStringEmpty(); Printf(retZend_obj, "%s_object_new(%s_ce)", retType_class, retType_class); - String *ret_other_Zend_obj = NewStringEmpty(); - Printf(ret_other_Zend_obj, "zend_objects_new(%s_ce)", retType_class); - Replaceall(tm, "$zend_obj", retType_valid ? (constructor ? "NULL" : (newobject ? retZend_obj : (retType_operator ? retZend_obj : ret_other_Zend_obj))) : "NULL"); + Replaceall(tm, "$zend_obj", retType_valid ? (constructor ? "NULL" : retZend_obj) : "NULL"); } Replaceall(tm, "$zend_obj", "NULL"); Replaceall(tm, "$newobj", retType_valid ? "1" : "2"); @@ -1610,20 +1640,6 @@ public: Printv(f->code, cleanup, NIL); } - String *zval_ret_obj = constructor ? NewString("getThis()") : NewString("return_value"); - - if (retType_valid && !SwigType_issimple(d)) { - Printf(f->code, "\n{\nswig_object_wrapper *obj = NULL;\n"); - Printf(f->code, "\nHashTable * ht = NULL;\n\n"); - Printf(f->code, "obj = (swig_object_wrapper *) Z_FETCH_OBJ_P(%s);\n", zval_ret_obj); - Printf(f->code, "obj->ptr = (void *)result;\n"); - Printf(f->code, "ht = Z_OBJ_HT_P(%s)->get_properties(%s);\n", zval_ret_obj, zval_ret_obj); - Printf(f->code, "if(ht) {\nzval zv;\n"); - Printf(f->code, "ZVAL_RES(&zv,zend_register_resource(result,*(int *)(SWIGTYPE%s->clientdata)));\n", SwigType_manglestr(d)); - Printf(f->code, "zend_hash_str_add(ht, \"_cPtr\", sizeof(\"_cPtr\") - 1, &zv);\n}\n\n"); - Printf(f->code, "if (obj)\nobj->newobject = %d;\n}\n\n", newobject ? 1 : 0); - } - /* Look to see if there is any newfree cleanup code */ if (GetFlag(n, "feature:new")) { if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) { @@ -2681,6 +2697,15 @@ done: return Language::classDeclaration(n); } + /* class helper method to get namespace + */ + String *getNameSpace(char *name) { + String *present_name = NewString(name); + String *second_half = NewString(strchr(name, ':')); + Replace(present_name, second_half, "", DOH_REPLACE_FIRST); + return present_name; + } + /* ------------------------------------------------------------ * classHandler() * ------------------------------------------------------------ */ @@ -2690,10 +2715,24 @@ done: current_class = n; String *className = Getattr(n, "name"); String *symname = Getattr(n, "sym:name"); + String *nameSpace = NULL; + String *baseClassExtend = NULL; + + //check for namespaces + if (Strstr(className, ":")) + nameSpace = getNameSpace(GetChar(n, "name")); + + class_type = Getattr(n, "classtype"); Append(class_types, class_type); + Append(class_need_free, "0"); Printf(s_oinit, "\nzend_class_entry %s_internal_ce;\n", class_name); + + // namespace code to introduce namespaces into wrapper classes. + //if (nameSpace != NULL) + //Printf(s_oinit, "INIT_CLASS_ENTRY(%s_internal_ce, \"%s\\\\%s\", class_%s_functions);\n", class_name, nameSpace ,class_name, class_name); + //else Printf(s_oinit, "INIT_CLASS_ENTRY(%s_internal_ce, \"%s\", class_%s_functions);\n", class_name, class_name, class_name); if (shadow) { @@ -2713,8 +2752,7 @@ done: while (base.item && GetFlag(base.item, "feature:ignore")) { base = Next(base); } - Printf(s_oinit, "%s_ce = zend_register_internal_class_ex(&%s_internal_ce, %s_ce);\n", class_name , class_name, Getattr(base.item, "sym:name")); - + baseClassExtend = Getattr(base.item, "sym:name"); base = Next(base); if (base.item) { /* Warn about multiple inheritance for additional base class(es) */ @@ -2731,8 +2769,24 @@ done: } } } - else - Printf(s_oinit, "%s_ce = zend_register_internal_class(&%s_internal_ce);\n", class_name , class_name); + } + + if (Cmp(Getattr(n, "feature:exceptionclass"), "1") == 0 && Getattr(n, "feature:except")) { + if (baseClassExtend) { + Swig_warning(WARN_PHP_MULTIPLE_INHERITANCE, input_file, line_number, + "Warning for %s, base %s ignored. Multiple inheritance is not supported in PHP.\n", class_name, baseClassExtend); + } + baseClassExtend = NewString(class_name); + Append(baseClassExtend, "_Exception"); + + Printf(s_oinit, "zend_class_entry *%s_ce = zend_lookup_class(zend_string_init(\"Exception\", sizeof(\"Exception\") - 1, 0));\n", baseClassExtend); + } + + if (baseClassExtend) { + Printf(s_oinit, "%s_ce = zend_register_internal_class_ex(&%s_internal_ce, %s_ce);\n", class_name , class_name, baseClassExtend); + } + else { + Printf(s_oinit, "%s_ce = zend_register_internal_class(&%s_internal_ce);\n", class_name , class_name); } if (Cmp(symname,className) != 0) { @@ -2753,7 +2807,7 @@ done: for(int Iterator = 1; Iterator <= num_interfaces; Iterator++) { String *interface = Getitem(interface_list, Iterator-1); String *interface_ce = NewStringEmpty(); - Printf(interface_ce, "php_interface_ce_%d" , Iterator); + Printf(interface_ce, "php_%s_interface_ce_%d" , class_name , Iterator); Printf(s_oinit, "zend_class_entry *%s = zend_lookup_class(zend_string_init(\"%s\", sizeof(\"%s\") - 1, 0));\n", interface_ce , interface, interface); Append(append_interface, interface_ce); Append(append_interface, " "); @@ -3034,8 +3088,8 @@ done: Delete(director_ctor_code); director_ctor_code = NewStringEmpty(); director_prot_ctor_code = NewStringEmpty(); - Printf(director_ctor_code, "if (Z_TYPE_P(arg0) == IS_NULL) { /* not subclassed */\n"); - Printf(director_prot_ctor_code, "if (Z_TYPE_P(arg0) == IS_NULL) { /* not subclassed */\n"); + Printf(director_ctor_code, "if (Swig::Director::swig_is_overridden_method(\"%s\", arg0)) { /* not subclassed */\n", class_name); + Printf(director_prot_ctor_code, "if (Swig::Director::swig_is_overridden_method(\"%s\", arg0)) { /* not subclassed */\n", class_name); Printf(director_ctor_code, " %s = (%s *)new %s(%s);\n", Swig_cresult_name(), ctype, ctype, args); Printf(director_prot_ctor_code, " SWIG_PHP_Error(E_ERROR, \"accessing abstract class or protected constructor\");\n", name, name, args); if (i) { @@ -3064,6 +3118,9 @@ done: String *iname = GetChar(n, "sym:name"); ParmList *l = Getattr(n, "parms"); + Delitem(class_need_free, Len(class_need_free) - 1); + Append(class_need_free, "1"); + String *name_prefix = NewString("delete_"); String *intermediate_name = NewString(iname); Replace(intermediate_name, name_prefix, "", DOH_REPLACE_FIRST);