class WIN32OLE_VARIANT

Constants

Empty
Nothing
Null

Public Class Methods

array(ary, vt) click to toggle source

Returns Ruby object wrapping OLE variant whose variant type is VT_ARRAY. The first argument should be Array object which specifies dimensions and each size of dimensions of OLE array. The second argument specifies variant type of the element of OLE array.

The following create 2 dimensions OLE array. The first dimensions size is 3, and the second is 4.

ole_ary = WIN32OLE_VARIANT.array([3,4], VT_I4)
ruby_ary = ole_ary.value # => [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
static VALUE
folevariant_s_array(VALUE klass, VALUE elems, VALUE vvt)
{
    VALUE obj = Qnil;
    VARTYPE vt;
    struct olevariantdata *pvar;
    SAFEARRAYBOUND *psab = NULL;
    SAFEARRAY *psa = NULL;
    UINT dim = 0;
    UINT i = 0;

    ole_initialize();

    vt = NUM2UINT(vvt);
    vt = (vt | VT_ARRAY);
    Check_Type(elems, T_ARRAY);
    obj = folevariant_s_allocate(klass);

    Data_Get_Struct(obj, struct olevariantdata, pvar);
    dim = RARRAY_LEN(elems);

    psab = ALLOC_N(SAFEARRAYBOUND, dim);

    if(!psab) {
        rb_raise(rb_eRuntimeError, "memory allocation error");
    }

    for (i = 0; i < dim; i++) {
        psab[i].cElements = FIX2INT(rb_ary_entry(elems, i));
        psab[i].lLbound = 0;
    }

    psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab);
    if (psa == NULL) {
        if (psab) free(psab);
        rb_raise(rb_eRuntimeError, "memory allocation error(SafeArrayCreate)");
    }

    V_VT(&(pvar->var)) = vt;
    if (vt & VT_BYREF) {
        V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF);
        V_ARRAY(&(pvar->realvar)) = psa;
        V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
    } else {
        V_ARRAY(&(pvar->var)) = psa;
    }
    if (psab) free(psab);
    return obj;
}
new(val, vartype) #→ WIN32OLE_VARIANT object. click to toggle source

Returns Ruby object wrapping OLE variant. The first argument specifies Ruby object to convert OLE variant variable. The second argument specifies VARIANT type. In some situation, you need the WIN32OLE_VARIANT object to pass OLE method

shell = WIN32OLE.new("Shell.Application")
folder = shell.NameSpace("C:\\Windows")
item = folder.ParseName("tmp.txt")
# You can't use Ruby String object to call FolderItem.InvokeVerb.
# Instead, you have to use WIN32OLE_VARIANT object to call the method.
shortcut = WIN32OLE_VARIANT.new("Create Shortcut(\&S)")
item.invokeVerb(shortcut)
static VALUE
folevariant_initialize(VALUE self, VALUE args)
{
    int len = 0;
    VARIANT var;
    VALUE val;
    VALUE vvt;
    VARTYPE vt;
    struct olevariantdata *pvar;

    len = RARRAY_LEN(args);
    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);

    if(!rb_obj_is_kind_of(val, cWIN32OLE) &&
       !rb_obj_is_kind_of(val, cWIN32OLE_VARIANT) &&
       !rb_obj_is_kind_of(val, rb_cTime)) {
        switch (TYPE(val)) {
        case T_ARRAY:
        case T_STRING:
        case T_FIXNUM:
        case T_BIGNUM:
        case T_FLOAT:
        case T_TRUE:
        case T_FALSE:
        case T_NIL:
            break;
        default:
            rb_raise(rb_eTypeError, "can not convert WIN32OLE_VARIANT from type %s",
                     rb_obj_classname(val));
        }
    }

    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);
    }
    vt = V_VT(&pvar->var);
    return self;
}

Public Instance Methods

WIN32OLE_VARIANT[i,j,...] #→ element of OLE array. click to toggle source

Returns the element of WIN32OLE_VARIANT object(OLE array). This method is available only when the variant type of WIN32OLE_VARIANT object is VT_ARRAY.

REMARK:

The all indicies should be 0 or natural number and
lower than or equal to max indicies.
(This point is different with Ruby Array indicies.)

obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]])
p obj[0,0] # => 1
p obj[1,0] # => 4
p obj[2,0] # => WIN32OLERuntimeError
p obj[0, -1] # => WIN32OLERuntimeError
static VALUE
folevariant_ary_aref(int argc, VALUE *argv, VALUE self)
{
    struct olevariantdata *pvar;
    SAFEARRAY *psa;
    VALUE val = Qnil;
    VARIANT variant;
    long *pid;
    HRESULT hr;

    Data_Get_Struct(self, struct olevariantdata, pvar);
    if (!V_ISARRAY(&(pvar->var))) {
        rb_raise(eWIN32OLERuntimeError,
                 "`[]' is not available for this variant type object");
    }
    psa = get_locked_safe_array(self);
    if (psa == NULL) {
        return val;
    }

    pid = ary2safe_array_index(argc, argv, psa);

    VariantInit(&variant);
    V_VT(&variant) = (V_VT(&(pvar->var)) & ~VT_ARRAY) | VT_BYREF;
    hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant));
    if (FAILED(hr)) {
        ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPtrOfIndex");
    }
    val = ole_variant2val(&variant);

    unlock_safe_array(psa);
    if (pid) free(pid);
    return val;
}
WIN32OLE_VARIANT[i,j,...] = val #→ set the element of OLE array click to toggle source

Set the element of WIN32OLE_VARIANT object(OLE array) to val. This method is available only when the variant type of WIN32OLE_VARIANT object is VT_ARRAY.

REMARK:

The all indicies should be 0 or natural number and
lower than or equal to max indicies.
(This point is different with Ruby Array indicies.)

obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]])
obj[0,0] = 7
obj[1,0] = 8
p obj.value # => [[7,2,3], [8,5,6]]
obj[2,0] = 9 # => WIN32OLERuntimeError
obj[0, -1] = 9 # => WIN32OLERuntimeError
static VALUE
folevariant_ary_aset(int argc, VALUE *argv, VALUE self)
{
    struct olevariantdata *pvar;
    SAFEARRAY *psa;
    VARIANT var;
    VARTYPE vt;
    long *pid;
    HRESULT hr;
    VOID *p = NULL;

    Data_Get_Struct(self, struct olevariantdata, pvar);
    if (!V_ISARRAY(&(pvar->var))) {
        rb_raise(eWIN32OLERuntimeError,
                 "`[]' is not available for this variant type object");
    }
    psa = get_locked_safe_array(self);
    if (psa == NULL) {
        rb_raise(rb_eRuntimeError, "failed to get SafeArray pointer");
    }

    pid = ary2safe_array_index(argc-1, argv, psa);

    VariantInit(&var);
    vt = (V_VT(&(pvar->var)) & ~VT_ARRAY);
    p = val2variant_ptr(argv[argc-1], &var, vt);
    if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) ||
        (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) {
        rb_raise(eWIN32OLERuntimeError, "argument does not have IDispatch or IUnknown Interface");
    }
    hr = SafeArrayPutElement(psa, pid, p);
    if (FAILED(hr)) {
        ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPutElement");
    }

    unlock_safe_array(psa);
    if (pid) free(pid);
    return argv[argc-1];
}
value #→ Ruby object. click to toggle source

Returns Ruby object value from OLE variant.

obj = WIN32OLE_VARIANT.new(1, WIN32OLE::VARIANT::VT_BSTR)
obj.value # => "1" (not Fixnum object, but String object "1")
static VALUE
folevariant_value(VALUE self)
{
    struct olevariantdata *pvar;
    VALUE val = Qnil;
    VARTYPE vt;
    int dim;
    SAFEARRAY *psa;
    Data_Get_Struct(self, struct olevariantdata, pvar);

    val = ole_variant2val(&(pvar->var));
    vt = V_VT(&(pvar->var));

    if ((vt & ~VT_BYREF) == (VT_UI1|VT_ARRAY)) {
        if (vt & VT_BYREF) {
            psa = *V_ARRAYREF(&(pvar->var));
        } else {
            psa  = V_ARRAY(&(pvar->var));
        }
        if (!psa) {
            return val;
        }
        dim = SafeArrayGetDim(psa);
        if (dim == 1) {
            val = rb_funcall(val, rb_intern("pack"), 1, rb_str_new2("C*"));
        }
    }
    return val;
}
value = val #→ set WIN32OLE_VARIANT value to val. click to toggle source

Sets variant value to val. If the val type does not match variant value type(vartype), then val is changed to match variant value type(vartype) before setting val. Thie method is not available when vartype is VT_ARRAY(except VT_UI1|VT_ARRAY). If the vartype is VT_UI1|VT_ARRAY, the val should be String object.

obj = WIN32OLE_VARIANT.new(1) # obj.vartype is WIN32OLE::VARIANT::VT_I4
obj.value = 3.2 # 3.2 is changed to 3 when setting value.
p obj.value # => 3
static VALUE
folevariant_set_value(VALUE self, VALUE val)
{
    struct olevariantdata *pvar;
    VARTYPE vt;
    Data_Get_Struct(self, struct olevariantdata, pvar);
    vt = V_VT(&(pvar->var));
    if (V_ISARRAY(&(pvar->var)) && ((vt & ~VT_BYREF) != (VT_UI1|VT_ARRAY) || TYPE(val) != T_STRING)) {
        rb_raise(eWIN32OLERuntimeError,
                 "`value=' is not available for this variant type object");
    }
    ole_val2olevariantdata(val, vt, pvar);
    return Qnil;
}
vartype #→ OLE variant type. click to toggle source

Returns OLE variant type.

obj = WIN32OLE_VARIANT.new("string")
obj.vartype # => WIN32OLE::VARIANT::VT_BSTR
static VALUE
folevariant_vartype(VALUE self)
{
    struct olevariantdata *pvar;
    Data_Get_Struct(self, struct olevariantdata, pvar);
    return INT2FIX(V_VT(&pvar->var));
}