static zend_function *oop_get_indirection_func( zend_class_entry *ce, zend_function *fbc, zval *method, zval *obj ) { indirection_function *ind = emalloc(sizeof(indirection_function)); zend_function *fn = (zend_function *) &ind->fn; long keep_flags = ZEND_ACC_RETURN_REFERENCE; ind->fn.type = ZEND_INTERNAL_FUNCTION; ind->fn.module = (ce->type == ZEND_INTERNAL_CLASS) ? ce->info.internal.module : NULL; ind->fn.handler = oop_indirection_func; ind->fn.scope = ce; ind->fn.fn_flags = ZEND_ACC_CALL_VIA_HANDLER | (fbc->common.fn_flags & keep_flags); ind->fn.num_args = fbc->common.num_args - 1; ind->fbc = fbc; if (fbc->common.arg_info) { fn->common.arg_info = &fbc->common.arg_info[1]; } else { fn->common.arg_info = NULL; } ind->fn.function_name = zend_string_copy(Z_STR_P(method)); zend_set_function_arg_flags(fn); ZVAL_COPY_VALUE(&ind->obj, obj); return fn; }
static zend_function *zend_test_class_static_method_get(zend_class_entry *ce, zend_string *name) /* {{{ */ { zend_internal_function *fptr = emalloc(sizeof(zend_internal_function)); fptr->type = ZEND_OVERLOADED_FUNCTION; fptr->num_args = 1; fptr->arg_info = NULL; fptr->scope = ce; fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_STATIC; fptr->function_name = name; fptr->handler = ZEND_FN(zend_test_func); zend_set_function_arg_flags((zend_function*)fptr); return (zend_function*)fptr; }
static zend_function *zend_test_class_method_get(zend_object **object, zend_string *name, const zval *key) /* {{{ */ { zend_internal_function *fptr = emalloc(sizeof(zend_internal_function)); fptr->type = ZEND_OVERLOADED_FUNCTION_TEMPORARY; fptr->num_args = 1; fptr->arg_info = NULL; fptr->scope = (*object)->ce; fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER; fptr->function_name = zend_string_copy(name); fptr->handler = ZEND_FN(zend_test_func); zend_set_function_arg_flags((zend_function*)fptr); return (zend_function*)fptr; }
static union _zend_function *com_method_get(zend_object **object_ptr, zend_string *name, const zval *key) { zend_internal_function f, *fptr = NULL; union _zend_function *func; DISPID dummy; php_com_dotnet_object *obj = (php_com_dotnet_object*)*object_ptr; if (V_VT(&obj->v) != VT_DISPATCH) { return NULL; } if (FAILED(php_com_get_id_of_name(obj, name->val, name->len, &dummy))) { return NULL; } /* check cache */ if (obj->method_cache == NULL || NULL == (fptr = zend_hash_find_ptr(obj->method_cache, name))) { f.type = ZEND_OVERLOADED_FUNCTION; f.num_args = 0; f.arg_info = NULL; f.scope = obj->ce; f.fn_flags = ZEND_ACC_CALL_VIA_HANDLER; f.function_name = zend_string_copy(name); f.handler = PHP_FN(com_method_handler); fptr = &f; if (obj->typeinfo) { /* look for byref params */ ITypeComp *comp; ITypeInfo *TI = NULL; DESCKIND kind; BINDPTR bindptr; OLECHAR *olename; ULONG lhash; int i; if (SUCCEEDED(ITypeInfo_GetTypeComp(obj->typeinfo, &comp))) { olename = php_com_string_to_olestring(name->val, name->len, obj->code_page); lhash = LHashValOfNameSys(SYS_WIN32, LOCALE_SYSTEM_DEFAULT, olename); if (SUCCEEDED(ITypeComp_Bind(comp, olename, lhash, INVOKE_FUNC, &TI, &kind, &bindptr))) { switch (kind) { case DESCKIND_FUNCDESC: f.arg_info = ecalloc(bindptr.lpfuncdesc->cParams, sizeof(zend_arg_info)); for (i = 0; i < bindptr.lpfuncdesc->cParams; i++) { f.arg_info[i].allow_null = 1; if (bindptr.lpfuncdesc->lprgelemdescParam[i].paramdesc.wParamFlags & PARAMFLAG_FOUT) { f.arg_info[i].pass_by_reference = ZEND_SEND_BY_REF; } } f.num_args = bindptr.lpfuncdesc->cParams; ITypeInfo_ReleaseFuncDesc(TI, bindptr.lpfuncdesc); break; /* these should not happen, but *might* happen if the user * screws up; lets avoid a leak in that case */ case DESCKIND_VARDESC: ITypeInfo_ReleaseVarDesc(TI, bindptr.lpvardesc); break; case DESCKIND_TYPECOMP: ITypeComp_Release(bindptr.lptcomp); break; case DESCKIND_NONE: break; } if (TI) { ITypeInfo_Release(TI); } } ITypeComp_Release(comp); efree(olename); } } zend_set_function_arg_flags((zend_function*)&f); /* save this method in the cache */ if (!obj->method_cache) { ALLOC_HASHTABLE(obj->method_cache); zend_hash_init(obj->method_cache, 2, NULL, function_dtor, 0); } zend_hash_update_mem(obj->method_cache, name, &f, sizeof(f)); } if (fptr) { /* duplicate this into a new chunk of emalloc'd memory, * since the engine will efree it */ func = emalloc(sizeof(*fptr)); memcpy(func, fptr, sizeof(*fptr)); return func; } return NULL; }