class WIN32OLE::Variant
WIN32OLE::Variant 对象表示 OLE 变体。
当调用 OLE 方法时,Win32OLE 会自动将 Ruby 对象转换为 OLE 变体。如果 OLE 方法需要的参数与 Win32OLE 自动转换的变体不同,你可以使用 WIN32OLE::Variant 类来转换指定的变体类型。
param = WIN32OLE::Variant.new(10, WIN32OLE::VARIANT::VT_R4) oleobj.method(param)
WIN32OLE::Variant 不支持 VT_RECORD 变体。如果需要 VT_RECORD 变体,请使用 WIN32OLE::Record 类,而不是 WIN32OLE::Variant。
常量
- Empty
-
表示 VT_EMPTY OLE 对象。
- NoParam
-
表示带有 DISP_E_PARAMNOTFOUND 的 VT_ERROR 变体。此常量用于未指定的参数。
fso = WIN32OLE.new("Scripting.FileSystemObject") fso.openTextFile(filename, WIN32OLE::Variant::NoParam, false)
- Nothing
-
表示 VB.NET 或 VB 中的
Nothing。 - Null
-
表示 VT_NULL OLE 对象。
公共类方法
源
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 = RB_NUM2UINT(vvt);
vt = (vt | VT_ARRAY);
Check_Type(elems, T_ARRAY);
obj = folevariant_s_allocate(klass);
TypedData_Get_Struct(obj, struct olevariantdata, &olevariant_datatype, 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 = RB_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;
}
返回一个包装 OLE 变体的 Ruby 对象,其变体类型为 VT_ARRAY。第一个参数应该是 Array 对象,它指定 OLE 数组的维度和每个维度的大小。第二个参数指定 OLE 数组元素的变体类型。
以下代码创建一个二维 OLE 数组。第一个维度的大小为 3,第二个维度的大小为 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_initialize(VALUE self, VALUE args)
{
int len = 0;
VARIANT var;
VALUE val;
VALUE vvt;
VARTYPE vt;
struct olevariantdata *pvar;
len = RARRAY_LEN(args);
rb_check_arity(len, 1, 3);
VariantInit(&var);
val = rb_ary_entry(args, 0);
check_type_val2variant(val);
TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar);
if (len == 1) {
ole_val2variant(val, &(pvar->var));
} else {
vvt = rb_ary_entry(args, 1);
vt = RB_NUM2INT(vvt);
if ((vt & VT_TYPEMASK) == VT_RECORD) {
rb_raise(rb_eArgError, "not supported VT_RECORD WIN32OLE::Variant object");
}
ole_val2olevariantdata(val, vt, pvar);
}
return self;
}
返回一个包装 OLE 变体的 Ruby 对象。第一个参数指定要转换为 OLE 变体变量的 Ruby 对象。第二个参数指定 VARIANT 类型。在某些情况下,你需要 WIN32OLE::Variant 对象来传递 OLE 方法。
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_ary_aref(int argc, VALUE *argv, VALUE self)
{
struct olevariantdata *pvar;
SAFEARRAY *psa;
VALUE val = Qnil;
VARIANT variant;
LONG *pid;
HRESULT hr;
TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, 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 对象(OLE 数组)的元素。仅当 WIN32OLE::Variant 对象的变体类型为 VT_ARRAY 时,此方法才可用。
备注
The all indices should be 0 or natural number and lower than or equal to max indices. (This point is different with Ruby Array indices.) obj = WIN32OLE::Variant.new([[1,2,3],[4,5,6]]) p obj[0,0] # => 1 p obj[1,0] # => 4 p obj[2,0] # => WIN32OLE::RuntimeError p obj[0, -1] # => WIN32OLE::RuntimeError
源
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;
TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, 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];
}
将 WIN32OLE::Variant 对象(OLE 数组)的元素设置为 val。仅当 WIN32OLE::Variant 对象的变体类型为 VT_ARRAY 时,此方法才可用。
备注
The all indices should be 0 or natural number and lower than or equal to max indices. (This point is different with Ruby Array indices.) 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 # => WIN32OLE::RuntimeError obj[0, -1] = 9 # => WIN32OLE::RuntimeError
源
static VALUE
folevariant_value(VALUE self)
{
struct olevariantdata *pvar;
VALUE val = Qnil;
VARTYPE vt;
int dim;
SAFEARRAY *psa;
TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, 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;
}
从 OLE 变体返回 Ruby 对象值。
obj = WIN32OLE::Variant.new(1, WIN32OLE::VARIANT::VT_BSTR) obj.value # => "1" (not Integer object, but String object "1")
源
static VALUE
folevariant_set_value(VALUE self, VALUE val)
{
struct olevariantdata *pvar;
VARTYPE vt;
TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar);
vt = V_VT(&(pvar->var));
if (V_ISARRAY(&(pvar->var)) && ((vt & ~VT_BYREF) != (VT_UI1|VT_ARRAY) || !RB_TYPE_P(val, T_STRING))) {
rb_raise(eWIN32OLERuntimeError,
"`value=' is not available for this variant type object");
}
ole_val2olevariantdata(val, vt, pvar);
return Qnil;
}
将变体值设置为 val。如果 val 类型与变体值类型 (vartype) 不匹配,则在设置 val 之前将 val 更改为匹配变体值类型 (vartype)。当 vartype 为 VT_ARRAY(VT_UI1|VT_ARRAY 除外)时,此方法不可用。如果 vartype 为 VT_UI1|VT_ARRAY,则 val 应为 String 对象。
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_vartype(VALUE self)
{
struct olevariantdata *pvar;
TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar);
return RB_INT2FIX(V_VT(&pvar->var));
}
返回 OLE 变体类型。
obj = WIN32OLE::Variant.new("string") obj.vartype # => WIN32OLE::VARIANT::VT_BSTR