From ba30d87a3687c22d7551968d28b2a4c4a252a57c Mon Sep 17 00:00:00 2001 From: suke Date: Sat, 13 Aug 2005 12:22:12 +0000 Subject: add WIN32OLE_VARIANT class. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8984 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 8 ++ ext/win32ole/win32ole.c | 337 +++++++++++++++++++++++++++++++++++++----------- 2 files changed, 268 insertions(+), 77 deletions(-) diff --git a/ChangeLog b/ChangeLog index 097ab406f2..288c344494 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +Sat Aug 13 21:11:05 2005 Masaki Suketa + + * ext/win32ole/win32ole.c: add WIN32OLE_VARIANT class. + + * ext/win32ole/tests/testall.rb: ditto. + + * ext/win32ole/tests/testOLEVARIANT.rb: ditto. + Sat Aug 13 18:51:26 2005 Nobuyoshi Nakada * eval.c (rb_block_pass): distinguish current block from others. diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c index fd7cb1a152..25984130ab 100644 --- a/ext/win32ole/win32ole.c +++ b/ext/win32ole/win32ole.c @@ -79,7 +79,7 @@ #define WC2VSTR(x) ole_wc2vstr((x), TRUE) -#define WIN32OLE_VERSION "0.6.7" +#define WIN32OLE_VERSION "0.6.8" typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX) (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*); @@ -144,6 +144,7 @@ VALUE cWIN32OLE_VARIABLE; VALUE cWIN32OLE_METHOD; VALUE cWIN32OLE_PARAM; VALUE cWIN32OLE_EVENT; +VALUE cWIN32OLE_VARIANT; VALUE eWIN32OLE_RUNTIME_ERROR; VALUE mWIN32OLE_VARIANT; @@ -192,6 +193,11 @@ struct oleparam { OLECHAR** pNamedArgs; }; +struct olevariantdata { + VARIANT realvar; + VARIANT var; +}; + static VALUE folemethod_s_allocate _((VALUE)); static VALUE olemethod_set_member _((VALUE, ITypeInfo *, ITypeInfo *, int, VALUE)); static VALUE foletype_s_allocate _((VALUE)); @@ -270,7 +276,9 @@ static HRESULT ( STDMETHODCALLTYPE GetIDsOfNames )( /* [in] */ LCID lcid, /* [size_is][out] */ DISPID __RPC_FAR *rgDispId) { + /* Win32OLEIDispatch* p = (Win32OLEIDispatch*)This; + */ char* psz = ole_wc2mb(*rgszNames); // support only one method *rgDispId = rb_intern(psz); free(psz); @@ -496,7 +504,7 @@ ole_hresult2msg(hr) DWORD dwCount; char strhr[100]; - sprintf(strhr, " HRESULT error code:0x%08x\n ", hr); + sprintf(strhr, " HRESULT error code:0x%08x\n ", (unsigned)hr); msg = rb_str_new2(strhr); dwCount = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | @@ -849,6 +857,178 @@ ole_val2variant(val, var) } } +static void +ole_val2ptr_variant(val, var) + VALUE val; + VARIANT *var; +{ + switch (TYPE(val)) { + case T_STRING: + if (V_VT(var) == (VT_BSTR | VT_BYREF)) { + *V_BSTRREF(var) = ole_mb2wc(StringValuePtr(val), -1); + } + break; + case T_FIXNUM: + switch(V_VT(var)) { + case (VT_UI1 | VT_BYREF) : + *V_UI1REF(var) = NUM2CHR(val); + break; + case (VT_I2 | VT_BYREF) : + *V_I2REF(var) = (short)NUM2INT(val); + break; + case (VT_I4 | VT_BYREF) : + *V_I4REF(var) = NUM2INT(val); + break; + case (VT_R4 | VT_BYREF) : + *V_R4REF(var) = (float)NUM2INT(val); + break; + case (VT_R8 | VT_BYREF) : + *V_R8REF(var) = NUM2INT(val); + break; + default: + break; + } + break; + case T_FLOAT: + switch(V_VT(var)) { + case (VT_I2 | VT_BYREF) : + *V_I2REF(var) = (short)NUM2INT(val); + break; + case (VT_I4 | VT_BYREF) : + *V_I4REF(var) = NUM2INT(val); + break; + case (VT_R4 | VT_BYREF) : + *V_R4REF(var) = (float)NUM2DBL(val); + break; + case (VT_R8 | VT_BYREF) : + *V_R8REF(var) = NUM2DBL(val); + break; + default: + break; + } + break; + case T_BIGNUM: + if (V_VT(var) == (VT_R8 | VT_BYREF)) { + *V_R8REF(var) = rb_big2dbl(val); + } + break; + case T_TRUE: + if (V_VT(var) == (VT_BOOL | VT_BYREF)) { + *V_BOOLREF(var) = VARIANT_TRUE; + } + break; + case T_FALSE: + if (V_VT(var) == (VT_BOOL | VT_BYREF)) { + *V_BOOLREF(var) = VARIANT_FALSE; + } + break; + default: + break; + } +} + +static void +ole_var2ptr_var(var, pvar) + VARIANT *var; + VARIANT *pvar; +{ + VARTYPE vt = V_VT(var); + V_VT(pvar) = V_VT(var) | VT_BYREF; + switch(vt) { + case VT_UI1: + V_UI1REF(pvar) = &V_UI1(var); + break; + case VT_I2: + V_I2REF(pvar) = &V_I2(var); + break; + case VT_I4: + V_I4REF(pvar) = &V_I4(var); + break; + case VT_UI4: + V_UI4REF(pvar) = &V_UI4(var); + break; +/* + case VT_I8: + V_I8REF(pvar) = &V_I8(var); + break; +*/ + case VT_R4: + V_R4REF(pvar) = &V_R4(var); + break; + case VT_R8: + V_R8REF(pvar) = &V_R8(var); + break; + case VT_CY: + V_CYREF(pvar) = &V_CY(var); + break; + case VT_DATE: + V_DATEREF(pvar) = &V_DATE(var); + break; + case VT_BSTR: + V_BSTRREF(pvar) = &V_BSTR(var); + break; + case VT_DISPATCH: + V_DISPATCHREF(pvar) = &V_DISPATCH(var); + break; + case VT_ERROR: + V_ERRORREF(pvar) = &V_ERROR(var); + break; + case VT_BOOL: + V_BOOLREF(pvar) = &V_BOOL(var); + break; +/* + case VT_VARIANT: + V_VARIANTREF(pvar) = &V_VARIANT(var); + break; +*/ + case VT_UNKNOWN: + V_UNKNOWNREF(pvar) = &V_UNKNOWN(var); + break; + case VT_ARRAY: + V_ARRAYREF(pvar) = &V_ARRAY(var); + break; + default: + break; + } +} + +static void +ole_val2olevariantdata(val, vtype, pvar) + VALUE val; + VARTYPE vtype; + struct olevariantdata *pvar; +{ + HRESULT hr = S_OK; + VARIANT var; + ole_val2variant(val, &(pvar->realvar)); + if (vtype & VT_BYREF) { + if ( (vtype & ~VT_BYREF) == V_VT(&(pvar->realvar))) { + ole_var2ptr_var(&(pvar->realvar), &(pvar->var)); + } else { + VariantInit(&var); + hr = VariantChangeTypeEx(&(var), &(pvar->realvar), + LOCALE_SYSTEM_DEFAULT, 0, vtype & ~VT_BYREF); + if (SUCCEEDED(hr)) { + VariantClear(&(pvar->realvar)); + hr = VariantCopy(&(pvar->realvar), &var); + VariantClear(&var); + ole_var2ptr_var(&(pvar->realvar), &(pvar->var)); + } + } + } else { + if (vtype == V_VT(&(pvar->realvar))) { + hr = VariantCopy(&(pvar->var), &(pvar->realvar)); + } else { + hr = VariantChangeTypeEx(&(pvar->var), &(pvar->realvar), + LOCALE_SYSTEM_DEFAULT, 0, vtype); + } + } + if (FAILED(hr)) { + ole_raise(hr, rb_eRuntimeError, "failed to change type"); + } +} + + static void ole_val2variant2(val, var) VALUE val; @@ -1997,6 +2177,7 @@ ole_invoke(argc, argv, self, wFlags) unsigned int cNamedArgs; int n; struct oleparam op; + struct olevariantdata *pvar; memset(&excepinfo, 0, sizeof(EXCEPINFO)); VariantInit(&result); @@ -2077,11 +2258,14 @@ ole_invoke(argc, argv, self, wFlags) VariantInit(&realargs[n]); VariantInit(&op.dp.rgvarg[n]); param = rb_ary_entry(paramS, i-cNamedArgs); - - ole_val2variant(param, &realargs[n]); - V_VT(&op.dp.rgvarg[n]) = VT_VARIANT | VT_BYREF; - V_VARIANTREF(&op.dp.rgvarg[n]) = &realargs[n]; - + if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) { + Data_Get_Struct(param, struct olevariantdata, pvar); + VariantCopy(&op.dp.rgvarg[n], &(pvar->var)); + } else { + ole_val2variant(param, &realargs[n]); + V_VT(&op.dp.rgvarg[n]) = VT_VARIANT | VT_BYREF; + V_VARIANTREF(&op.dp.rgvarg[n]) = &realargs[n]; + } } } /* apparent you need to call propput, you need this */ @@ -6105,75 +6289,6 @@ ole_search_event(ary, ev, is_default) return def_event; } -static void -val2ptr_variant(val, var) - VALUE val; - VARIANT *var; -{ - switch (TYPE(val)) { - case T_STRING: - if (V_VT(var) == (VT_BSTR | VT_BYREF)) { - *V_BSTRREF(var) = ole_mb2wc(StringValuePtr(val), -1); - } - break; - case T_FIXNUM: - switch(V_VT(var)) { - case (VT_UI1 | VT_BYREF) : - *V_UI1REF(var) = NUM2CHR(val); - break; - case (VT_I2 | VT_BYREF) : - *V_I2REF(var) = (short)NUM2INT(val); - break; - case (VT_I4 | VT_BYREF) : - *V_I4REF(var) = NUM2INT(val); - break; - case (VT_R4 | VT_BYREF) : - *V_R4REF(var) = (float)NUM2INT(val); - break; - case (VT_R8 | VT_BYREF) : - *V_R8REF(var) = NUM2INT(val); - break; - default: - break; - } - break; - case T_FLOAT: - switch(V_VT(var)) { - case (VT_I2 | VT_BYREF) : - *V_I2REF(var) = (short)NUM2INT(val); - break; - case (VT_I4 | VT_BYREF) : - *V_I4REF(var) = NUM2INT(val); - break; - case (VT_R4 | VT_BYREF) : - *V_R4REF(var) = (float)NUM2DBL(val); - break; - case (VT_R8 | VT_BYREF) : - *V_R8REF(var) = NUM2DBL(val); - break; - default: - break; - } - break; - case T_BIGNUM: - if (V_VT(var) == (VT_R8 | VT_BYREF)) { - *V_R8REF(var) = rb_big2dbl(val); - } - break; - case T_TRUE: - if (V_VT(var) == (VT_BOOL | VT_BYREF)) { - *V_BOOLREF(var) = VARIANT_TRUE; - } - break; - case T_FALSE: - if (V_VT(var) == (VT_BOOL | VT_BYREF)) { - *V_BOOLREF(var) = VARIANT_FALSE; - } - break; - default: - break; - } -} static void ary2ptr_dispparams(ary, pdispparams) @@ -6186,7 +6301,7 @@ ary2ptr_dispparams(ary, pdispparams) for(i = 0; i < RARRAY(ary)->len && (unsigned int) i < pdispparams->cArgs; i++) { v = rb_ary_entry(ary, i); pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1]; - val2ptr_variant(v, pvar); + ole_val2ptr_variant(v, pvar); } } @@ -6714,6 +6829,68 @@ fev_on_event_with_outargs(argc, argv, self) return ev_on_event(argc, argv, self, Qtrue); } +static void +olevariant_free(pvar) + struct olevariantdata *pvar; +{ + VariantClear(&(pvar->realvar)); + VariantClear(&(pvar->var)); +} + +static VALUE folevariant_s_allocate _((VALUE)); +static VALUE +folevariant_s_allocate(klass) + VALUE klass; +{ + struct olevariantdata *pvar; + VALUE obj; + ole_initialize(); + obj = Data_Make_Struct(klass,struct olevariantdata,0,olevariant_free,pvar); + VariantInit(&(pvar->var)); + VariantInit(&(pvar->realvar)); + return obj; +} + +static VALUE +folevariant_initialize(self, args) + VALUE self; + VALUE args; +{ + long len = 0; + VARIANT var; + VALUE val; + VALUE vvt; + VARTYPE vt; + HRESULT hr; + struct olevariantdata *pvar; + + len = RARRAY(args)->len; + if (len < 1 || len > 3) { + rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", len); + } + VariantInit(&var); + val = rb_ary_entry(args, 0); + Data_Get_Struct(self, struct olevariantdata, pvar); + if (len == 1) { + ole_val2variant(val, &(pvar->var)); + } else { + vvt = rb_ary_entry(args, 1); + vt = NUM2INT(vvt); + ole_val2olevariantdata(val, vt, pvar); + } + return self; +} + +static VALUE +folevariant_value(self) + VALUE self; +{ + struct olevariantdata *pvar; + VALUE val = Qnil; + Data_Get_Struct(self, struct olevariantdata, pvar); + val = ole_variant2val(&(pvar->var)); + return val; +} void Init_win32ole() @@ -6898,5 +7075,11 @@ Init_win32ole() rb_define_method(cWIN32OLE_EVENT, "on_event", fev_on_event, -1); rb_define_method(cWIN32OLE_EVENT, "on_event_with_outargs", fev_on_event_with_outargs, -1); + + cWIN32OLE_VARIANT = rb_define_class("WIN32OLE_VARIANT", rb_cObject); + rb_define_alloc_func(cWIN32OLE_VARIANT, folevariant_s_allocate); + rb_define_method(cWIN32OLE_VARIANT, "initialize", folevariant_initialize, -2); + rb_define_method(cWIN32OLE_VARIANT, "value", folevariant_value, 0); + eWIN32OLE_RUNTIME_ERROR = rb_define_class("WIN32OLERuntimeError", rb_eRuntimeError); } -- cgit v1.2.3