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