wez Mon Jan 12 19:40:15 2004 EDT Modified files: /php-src/ext/com_dotnet com_com.c com_handlers.c php_com_dotnet_internal.h Log: Support automatic handling of byref parameters Index: php-src/ext/com_dotnet/com_com.c diff -u php-src/ext/com_dotnet/com_com.c:1.8 php-src/ext/com_dotnet/com_com.c:1.9 --- php-src/ext/com_dotnet/com_com.c:1.8 Thu Jan 8 03:14:20 2004 +++ php-src/ext/com_dotnet/com_com.c Mon Jan 12 19:40:14 2004 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: com_com.c,v 1.8 2004/01/08 08:14:20 andi Exp $ */ +/* $Id: com_com.c,v 1.9 2004/01/13 00:40:14 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -377,6 +377,127 @@ } /* the core of COM */ +int php_com_do_invoke_byref(php_com_dotnet_object *obj, char *name, int namelen, + WORD flags, VARIANT *v, int nargs, zval ***args TSRMLS_DC) +{ + DISPID dispid, altdispid; + DISPPARAMS disp_params; + HRESULT hr; + VARIANT *vargs = NULL, *byref_vals = NULL; + int i, byref_count = 0, j; + zend_internal_function *f = (zend_internal_function*)EG(function_state_ptr)->function; + + /* assumption: that the active function (f) is the function we generated for the engine */ + if (!f || f->type != ZEND_OVERLOADED_FUNCTION_TEMPORARY || f->arg_info == NULL) { + f = NULL; + } + + hr = php_com_get_id_of_name(obj, name, namelen, &dispid TSRMLS_CC); + + if (FAILED(hr)) { + char *winerr = NULL; + char *msg = NULL; + winerr = php_win_err(hr); + spprintf(&msg, 0, "Unable to lookup `%s': %s", name, winerr); + LocalFree(winerr); + php_com_throw_exception(hr, msg TSRMLS_CC); + efree(msg); + return FAILURE; + } + + + if (nargs) { + vargs = (VARIANT*)safe_emalloc(sizeof(VARIANT), nargs, 0); + } + + if (f) { + for (i = 0; i < nargs; i++) { + if (f->arg_info[nargs - i - 1].pass_by_reference) { + byref_count++; + } + } + } + + if (byref_count) { + byref_vals = (VARIANT*)safe_emalloc(sizeof(VARIANT), byref_count, 0); + for (j = 0, i = 0; i < nargs; i++) { + if (f->arg_info[nargs - i - 1].pass_by_reference) { + /* put the value into byref_vals instead */ + php_com_variant_from_zval(&byref_vals[j], *args[nargs - i - 1], obj->code_page TSRMLS_CC); + + /* if it is already byref, "move" it into the vargs array, otherwise + * make vargs a reference to this value */ + if (V_VT(&byref_vals[j]) & VT_BYREF) { + memcpy(&vargs[i], &byref_vals[j], sizeof(vargs[i])); + VariantInit(&byref_vals[j]); /* leave the variant slot empty to simplify cleanup */ + } else { + VariantInit(&vargs[i]); + V_VT(&vargs[i]) = V_VT(&byref_vals[j]) | VT_BYREF; + /* union magic ensures that this works out */ + vargs[i].byref = &V_UINT(&byref_vals[j]); + } + j++; + } else { + php_com_variant_from_zval(&vargs[i], *args[nargs - i - 1], obj->code_page TSRMLS_CC); + } + } + + } else { + /* Invoke'd args are in reverse order */ + for (i = 0; i < nargs; i++) { + php_com_variant_from_zval(&vargs[i], *args[nargs - i - 1], obj->code_page TSRMLS_CC); + } + } + + disp_params.cArgs = nargs; + disp_params.cNamedArgs = 0; + disp_params.rgvarg = vargs; + disp_params.rgdispidNamedArgs = NULL; + + if (flags & DISPATCH_PROPERTYPUT) { + altdispid = DISPID_PROPERTYPUT; + disp_params.rgdispidNamedArgs = &altdispid; + disp_params.cNamedArgs = 1; + } + + /* this will create an exception if needed */ + hr = php_com_invoke_helper(obj, dispid, flags, &disp_params, v TSRMLS_CC); + + /* release variants */ + if (vargs) { + for (i = 0, j = 0; i < nargs; i++) { + /* if this was byref, update the zval */ + if (f && f->arg_info[nargs - i - 1].pass_by_reference) { + SEPARATE_ZVAL_IF_NOT_REF(args[nargs - i - 1]); + + /* if the variant is pointing at the byref_vals, we need to map + * the pointee value as a zval; otherwise, the value is pointing + * into an existing PHP variant record */ + if (V_VT(&vargs[i]) & VT_BYREF) { + if (vargs[i].byref == &V_UINT(&byref_vals[j])) { + /* copy that value */ + php_com_zval_from_variant(*args[nargs - i - 1], &byref_vals[j], + obj->code_page TSRMLS_CC); + } + } else { + /* not sure if this can ever happen; the variant we marked as BYREF + * is no longer BYREF - copy its value */ + php_com_zval_from_variant(*args[nargs - i - 1], &vargs[i], + obj->code_page TSRMLS_CC); + } + VariantClear(&byref_vals[j]); + j++; + } + VariantClear(&vargs[i]); + } + efree(vargs); + } + + return SUCCEEDED(hr) ? SUCCESS : FAILURE; +} + + + int php_com_do_invoke_by_id(php_com_dotnet_object *obj, DISPID dispid, WORD flags, VARIANT *v, int nargs, zval **args TSRMLS_DC) { Index: php-src/ext/com_dotnet/com_handlers.c diff -u php-src/ext/com_dotnet/com_handlers.c:1.9 php-src/ext/com_dotnet/com_handlers.c:1.10 --- php-src/ext/com_dotnet/com_handlers.c:1.9 Thu Jan 8 03:14:20 2004 +++ php-src/ext/com_dotnet/com_handlers.c Mon Jan 12 19:40:14 2004 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: com_handlers.c,v 1.9 2004/01/08 08:14:20 andi Exp $ */ +/* $Id: com_handlers.c,v 1.10 2004/01/13 00:40:14 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -306,7 +306,7 @@ static int com_call_method(char *method, INTERNAL_FUNCTION_PARAMETERS) { - zval **args = NULL; + zval ***args = NULL; php_com_dotnet_object *obj; int nargs; VARIANT v; @@ -321,13 +321,13 @@ nargs = ZEND_NUM_ARGS(); if (nargs) { - args = (zval **)safe_emalloc(sizeof(zval *), nargs, 0); - zend_get_parameters_array(ht, nargs, args); + args = (zval ***)safe_emalloc(sizeof(zval *), nargs, 0); + zend_get_parameters_array_ex(nargs, args); } VariantInit(&v); - if (SUCCESS == php_com_do_invoke(obj, method, -1, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, nargs, args TSRMLS_CC)) { + if (SUCCESS == php_com_do_invoke_byref(obj, method, -1, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v, nargs, args TSRMLS_CC)) { php_com_zval_from_variant(return_value, &v, obj->code_page TSRMLS_CC); ret = SUCCESS; VariantClear(&v); Index: php-src/ext/com_dotnet/php_com_dotnet_internal.h diff -u php-src/ext/com_dotnet/php_com_dotnet_internal.h:1.6 php-src/ext/com_dotnet/php_com_dotnet_internal.h:1.7 --- php-src/ext/com_dotnet/php_com_dotnet_internal.h:1.6 Thu Jan 8 12:31:51 2004 +++ php-src/ext/com_dotnet/php_com_dotnet_internal.h Mon Jan 12 19:40:14 2004 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_com_dotnet_internal.h,v 1.6 2004/01/08 17:31:51 sniper Exp $ */ +/* $Id: php_com_dotnet_internal.h,v 1.7 2004/01/13 00:40:14 wez Exp $ */ #ifndef PHP_COM_DOTNET_INTERNAL_H #define PHP_COM_DOTNET_INTERNAL_H @@ -103,6 +103,8 @@ WORD flags, VARIANT *v, int nargs, zval **args TSRMLS_DC); int php_com_do_invoke(php_com_dotnet_object *obj, char *name, int namelen, WORD flags, VARIANT *v, int nargs, zval **args TSRMLS_DC); +int php_com_do_invoke_byref(php_com_dotnet_object *obj, char *name, int namelen, + WORD flags, VARIANT *v, int nargs, zval ***args TSRMLS_DC); /* com_wrapper.c */ int php_com_wrapper_minit(INIT_FUNC_ARGS);
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php