Class: VirtualBox::COM::FFI::Util

Inherits:
Object
  • Object
show all
Defined in:
lib/virtualbox/com/ffi/util.rb

Overview

Class which contains many class-level utility methods to assist with the FFI interface. These functions range from converting a function spec to a FFI parameter list to dereferencing pointers.

Class Method Summary (collapse)

Class Method Details

+ (String) camelize(string)

An "almost complete" camel-caser. Camel cases a string with a few exceptions. For example: `get_foo` becomes `GetFoo`, but `get_os_type` becomes `GetOSType` since `os` is a special case.



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/virtualbox/com/ffi/util.rb', line 80

def camelize(string)
  special_cases = {
    "os" => "OS",
    "dhcp" => "DHCP",
    "dvd" => "DVD",
    "usb" => "USB",
    "vram" => "VRAM",
    "3d" => "3D",
    "bios" => "BIOS",
    "vrdp" => "VRDP",
    "vrde" => "VRDE",
    "hw" => "HW",
    "png" => "PNG",
    "io" => "IO",
    "apic" => "APIC",
    "acpi" => "ACPI",
    "pxe" => "PXE",
    "nat" => "NAT",
    "ide" => "IDE",
    "vfs" => "VFS",
    "ip" => "IP",
    "vdi" => "VDI",
    "cpu" => "CPU",
    "ram" => "RAM",
    "hdd" => "HDD",
    "rtc" => "RTC",
    "utc" => "UTC",
    "io" => "IO",
    "vm" => "VM"
  }

  parts = string.to_s.split(/_/).collect do |part|
    special_cases[part] || part.capitalize
  end

  parts.join("")
end

+ (Class) interface_klass(type)

Finds and returns the `COM::Interface` class associated with the type. If the class does not exist, a `NameError` will be raised.



13
14
15
# File 'lib/virtualbox/com/ffi/util.rb', line 13

def interface_klass(type)
  ::VirtualBox::COM::Util.versioned_interface(type)
end

+ (Array) spec_to_ffi(spec)

Converts a function spec from AbstractInterface to an FFI function spec. This handles custom types (unicode strings, arrays, and out-parameters) and will return a perfectly valid array ready to be passed into `callback`.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/virtualbox/com/ffi/util.rb', line 31

def spec_to_ffi(spec)
  spec = spec.collect do |item|
    if item.is_a?(Array) && item[0] == :out
      if item[1].is_a?(Array)
        # The out is an array of items, so we add in two pointers:
        # one for size and one for the array
        [:pointer, :pointer]
      else
        # A regular out parameter is just a single pointer
        :pointer
      end
    elsif item.is_a?(Array) && item.length == 1
      # The parameter is an array of somethings
      [T_UINT32, :pointer]
    elsif item == WSTRING
      # Unicode strings are simply pointers
      :pointer
    elsif item.to_s[0,1] == item.to_s[0,1].upcase
      begin
        # Try to get the class from the interfaces
        interface = interface_klass(item.to_sym)

        if interface.superclass == COM::AbstractInterface
          :pointer
        elsif interface.superclass == COM::AbstractEnum
          T_UINT32
        end
      rescue NameError
        # Default to a pointer, since not all interfaces are implemented
        :pointer
      end
    else
      # Unknown items are simply passed as-is, hopefully FFI
      # will catch any problems
      item
    end
  end

  # Prepend a :pointer to represent the `this` parameter required
  # for the FFI parameter lists
  spec.unshift(:pointer).flatten
end

+ (Class) versioned_interface(interface)

Finds the versioned interface for the FFI module.



20
21
22
# File 'lib/virtualbox/com/ffi/util.rb', line 20

def versioned_interface(interface)
  ::VirtualBox::COM::FFI.const_get(::VirtualBox::COM::Util.version_const).const_get(interface)
end