Class: WIN32OLE_RECORD

Inherits:
Object
  • Object
show all
Defined in:
win32ole_record.c,
win32ole_record.c

Overview

WIN32OLE_RECORD objects represents VT_RECORD OLE variant.

Win32OLE returns WIN32OLE_RECORD object if the result value of invoking
OLE methods.

If COM server in VB.NET ComServer project is the following:

  Imports System.Runtime.InteropServices
  Public Class ComClass
      Public Structure Book
          <MarshalAs(UnmanagedType.BStr)> _
          Public title As String
          Public cost As Integer
      End Structure
      Public Function getBook() As Book
          Dim book As New Book
          book.title = "The Ruby Book"
          book.cost = 20
          Return book
      End Function
  End Class

then, you can retrieve getBook return value from the following
Ruby script:

  require 'win32ole'
  obj = WIN32OLE.new('ComServer.ComClass')
  book = obj.getBook
  book.class # => WIN32OLE_RECORD
  book.title # => "The Ruby Book"
  book.cost  # => 20

Instance Method Summary collapse

Constructor Details

#new(typename, obj) ⇒ WIN32OLE_RECORD object

Returns WIN32OLE_RECORD object. The first argument is struct name (String or Symbol). The second parameter obj should be WIN32OLE object or WIN32OLE_TYPELIB object. If COM server in VB.NET ComServer project is the following:

Imports System.Runtime.InteropServices
Public Class ComClass
    Public Structure Book
        <MarshalAs(UnmanagedType.BStr)> _
        Public title As String
        Public cost As Integer
    End Structure
End Class

then, you can create WIN32OLE_RECORD object is as following:

require 'win32ole'
obj = WIN32OLE.new('ComServer.ComClass')
book1 = WIN32OLE_RECORD.new('Book', obj) # => WIN32OLE_RECORD object
tlib = obj.ole_typelib
book2 = WIN32OLE_RECORD.new('Book', tlib) # => WIN32OLE_RECORD object


281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'win32ole_record.c', line 281

static VALUE
folerecord_initialize(VALUE self, VALUE typename, VALUE oleobj) {
    HRESULT hr;
    ITypeLib *pTypeLib = NULL;
    IRecordInfo *pri = NULL;

    if (!RB_TYPE_P(typename, T_STRING) && !RB_TYPE_P(typename, T_SYMBOL)) {
        rb_raise(rb_eArgError, "1st argument should be String or Symbol");
    }
    if (RB_TYPE_P(typename, T_SYMBOL)) {
        typename = rb_sym2str(typename);
    }

    hr = S_OK;
    if(rb_obj_is_kind_of(oleobj, cWIN32OLE)) {
        hr = typelib_from_val(oleobj, &pTypeLib);
    } else if (rb_obj_is_kind_of(oleobj, cWIN32OLE_TYPELIB)) {
        pTypeLib = itypelib(oleobj);
        OLE_ADDREF(pTypeLib);
        if (pTypeLib) {
            hr = S_OK;
        } else {
            hr = E_FAIL;
        }
    } else {
        rb_raise(rb_eArgError, "2nd argument should be WIN32OLE object or WIN32OLE_TYPELIB object");
    }

    if (FAILED(hr)) {
        ole_raise(hr, eWIN32OLERuntimeError, "fail to query ITypeLib interface");
    }

    hr = recordinfo_from_itypelib(pTypeLib, typename, &pri);
    OLE_RELEASE(pTypeLib);
    if (FAILED(hr)) {
        ole_raise(hr, eWIN32OLERuntimeError, "fail to query IRecordInfo interface for `%s'", StringValuePtr(typename));
    }

    olerecord_set_ivar(self, pri, NULL);

    return self;
}

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name) ⇒ Object

Returns value specified by the member name of VT_RECORD OLE variable. Or sets value specified by the member name of VT_RECORD OLE variable. If the member name is not correct, KeyError exception is raised.

If COM server in VB.NET ComServer project is the following:

Imports System.Runtime.InteropServices
Public Class ComClass
    Public Structure Book
        <MarshalAs(UnmanagedType.BStr)> _
        Public title As String
        Public cost As Integer
    End Structure
End Class

Then getting/setting value from Ruby is as the following:

obj = WIN32OLE.new('ComServer.ComClass')
book = WIN32OLE_RECORD.new('Book', obj)
book.title # => nil ( book.method_missing(:title) is invoked. )
book.title = "Ruby" # ( book.method_missing(:title=, "Ruby") is invoked. )


450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
# File 'win32ole_record.c', line 450

static VALUE
folerecord_method_missing(int argc, VALUE *argv, VALUE self)
{
    VALUE name;
    rb_check_arity(argc, 1, 2);
    name = rb_sym2str(argv[0]);

#if SIZEOF_SIZE_T > SIZEOF_LONG
    {
        size_t n = strlen(StringValueCStr(name));
        if (n >= LONG_MAX) {
            rb_raise(rb_eRuntimeError, "too long member name");
        }
    }
#endif

    if (argc == 1) {
        return olerecord_ivar_get(self, name);
    } else if (argc == 2) {
        return olerecord_ivar_set(self, name, argv[1]);
    }
    return Qnil;
}

Instance Method Details

#inspectString

Returns the OLE struct name and member name and the value of member

If COM server in VB.NET ComServer project is the following:

Imports System.Runtime.InteropServices
Public Class ComClass
    <MarshalAs(UnmanagedType.BStr)> _
    Public title As String
    Public cost As Integer
End Class

then

srver = WIN32OLE.new('ComServer.ComClass')
obj = WIN32OLE_RECORD.new('Book', server)
obj.inspect # => <WIN32OLE_RECORD(ComClass) {"title" => nil, "cost" => nil}>

Returns:

  • (String)


577
578
579
580
581
582
583
584
585
586
587
588
589
590
# File 'win32ole_record.c', line 577

static VALUE
folerecord_inspect(VALUE self)
{
    VALUE tname;
    VALUE field;
    tname = folerecord_typename(self);
    if (tname == Qnil) {
        tname = rb_inspect(tname);
    }
    field = rb_inspect(folerecord_to_h(self));
    return rb_sprintf("#<WIN32OLE_RECORD(%"PRIsVALUE") %"PRIsVALUE">",
                      tname,
                      field);
}

#ole_instance_variable_get(name) ⇒ Object

Returns value specified by the member name of VT_RECORD OLE object. If the member name is not correct, KeyError exception is raised. If you can’t access member variable of VT_RECORD OLE object directly, use this method.

If COM server in VB.NET ComServer project is the following:

Imports System.Runtime.InteropServices
Public Class ComClass
    Public Structure ComObject
        Public object_id As Ineger
    End Structure
End Class

and Ruby Object class has title attribute:

then accessing object_id of ComObject from Ruby is as the following:

srver = WIN32OLE.new('ComServer.ComClass')
obj = WIN32OLE_RECORD.new('ComObject', server)
# obj.object_id returns Ruby Object#object_id
obj.ole_instance_variable_get(:object_id) # => nil


502
503
504
505
506
507
508
509
510
511
512
513
514
# File 'win32ole_record.c', line 502

static VALUE
folerecord_ole_instance_variable_get(VALUE self, VALUE name)
{
    VALUE sname;
    if(!RB_TYPE_P(name, T_STRING) && !RB_TYPE_P(name, T_SYMBOL)) {
        rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
    }
    sname = name;
    if (RB_TYPE_P(name, T_SYMBOL)) {
        sname = rb_sym2str(name);
    }
    return olerecord_ivar_get(self, sname);
}

#ole_instance_variable_set(name, val) ⇒ Object

Sets value specified by the member name of VT_RECORD OLE object. If the member name is not correct, KeyError exception is raised. If you can’t set value of member of VT_RECORD OLE object directly, use this method.

If COM server in VB.NET ComServer project is the following:

Imports System.Runtime.InteropServices
Public Class ComClass
    <MarshalAs(UnmanagedType.BStr)> _
    Public title As String
    Public cost As Integer
End Class

then setting value of the ‘title’ member is as following:

srver = WIN32OLE.new('ComServer.ComClass')
obj = WIN32OLE_RECORD.new('Book', server)
obj.ole_instance_variable_set(:title, "The Ruby Book")


541
542
543
544
545
546
547
548
549
550
551
552
553
# File 'win32ole_record.c', line 541

static VALUE
folerecord_ole_instance_variable_set(VALUE self, VALUE name, VALUE val)
{
    VALUE sname;
    if(!RB_TYPE_P(name, T_STRING) && !RB_TYPE_P(name, T_SYMBOL)) {
        rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
    }
    sname = name;
    if (RB_TYPE_P(name, T_SYMBOL)) {
        sname = rb_sym2str(name);
    }
    return olerecord_ivar_set(self, sname, val);
}

#to_hObject

Returns Ruby Hash object which represents VT_RECORD variable. The keys of Hash object are member names of VT_RECORD OLE variable and the values of Hash object are values of VT_RECORD OLE variable.

If COM server in VB.NET ComServer project is the following:

Imports System.Runtime.InteropServices
Public Class ComClass
    Public Structure Book
        <MarshalAs(UnmanagedType.BStr)> _
        Public title As String
        Public cost As Integer
    End Structure
    Public Function getBook() As Book
        Dim book As New Book
        book.title = "The Ruby Book"
        book.cost = 20
        Return book
    End Function
End Class

then, the result of WIN32OLE_RECORD#to_h is the following:

require 'win32ole'
obj = WIN32OLE.new('ComServer.ComClass')
book = obj.getBook
book.to_h # => {"title"=>"The Ruby Book", "cost"=>20}


357
358
359
360
361
# File 'win32ole_record.c', line 357

static VALUE
folerecord_to_h(VALUE self)
{
    return rb_ivar_get(self, rb_intern("fields"));
}

#typenameObject

Returns the type name of VT_RECORD OLE variable.

If COM server in VB.NET ComServer project is the following:

Imports System.Runtime.InteropServices
Public Class ComClass
    Public Structure Book
        <MarshalAs(UnmanagedType.BStr)> _
        Public title As String
        Public cost As Integer
    End Structure
    Public Function getBook() As Book
        Dim book As New Book
        book.title = "The Ruby Book"
        book.cost = 20
        Return book
    End Function
End Class

then, the result of WIN32OLE_RECORD#typename is the following:

require 'win32ole'
obj = WIN32OLE.new('ComServer.ComClass')
book = obj.getBook
book.typename # => "Book"


394
395
396
397
398
# File 'win32ole_record.c', line 394

static VALUE
folerecord_typename(VALUE self)
{
    return rb_ivar_get(self, rb_intern("typename"));
}