virtualbox-com 0.9.9 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. data/LICENSE +339 -19
  2. data/examples/simple.rb +2 -0
  3. data/ext/virtualbox-com/4.1/extconf.rb +4 -0
  4. data/ext/virtualbox-com/4.1/generated.inc +17345 -0
  5. data/ext/virtualbox-com/4.1/vbox.c +858 -0
  6. data/ext/virtualbox-com/4.2/extconf.rb +4 -0
  7. data/ext/virtualbox-com/4.2/generated.inc +19751 -0
  8. data/ext/virtualbox-com/4.2/vbox.c +858 -0
  9. data/ext/virtualbox-com/helpers.h +62 -0
  10. data/ext/virtualbox-com/loader/extconf.rb +3 -0
  11. data/ext/virtualbox-com/loader/vbox-loader.c +187 -0
  12. data/ext/virtualbox-com/types.h +34 -0
  13. data/ext/virtualbox-com/vbox.c +858 -0
  14. data/lib/virtualbox/com.rb +4 -26
  15. data/lib/virtualbox/com/{abstract_enum.rb → abstracts.rb} +22 -18
  16. data/lib/virtualbox/com/exceptions.rb +29 -3
  17. data/lib/virtualbox/com/model/4.1-generated.rb +2141 -0
  18. data/lib/virtualbox/com/model/4.2-generated.rb +141 -432
  19. data/lib/virtualbox/com/model/4.2.rb +4 -4
  20. data/lib/virtualbox/com/util.rb +2 -1
  21. data/lib/virtualbox/com/version.rb +1 -1
  22. data/lib/virtualbox/com/xpcomc-ffi.rb +5 -19
  23. data/lib/virtualbox/com/xpcomc-ffi/abstracts.rb +103 -0
  24. data/lib/virtualbox/com/{iid.rb → xpcomc-ffi/iid.rb} +18 -0
  25. data/lib/virtualbox/com/xpcomc-ffi/lib.rb +6 -0
  26. data/lib/virtualbox/com/xpcomc-ffi/model-types.rb +1 -0
  27. data/lib/virtualbox/com/xpcomc-native.rb +8 -0
  28. data/scripts/abstracts.rb +84 -0
  29. data/scripts/sig.rb +201 -0
  30. data/scripts/spec.rb +56 -0
  31. data/scripts/to_c.rb +157 -0
  32. data/scripts/xidl-conv.rb +110 -50
  33. data/virtualbox-com.gemspec +18 -11
  34. metadata +49 -47
  35. data/.gitignore +0 -9
  36. data/README.md +0 -89
  37. data/Rakefile +0 -8
  38. data/lib/virtualbox/com/abstract_interface.rb +0 -144
  39. data/lib/virtualbox/com/abstract_model.rb +0 -14
@@ -1,4 +1,4 @@
1
- require_relative '4.2-generated'
1
+
2
2
  require 'set'
3
3
 
4
4
  module VirtualBox
@@ -6,7 +6,7 @@ module COM
6
6
  module Model
7
7
 
8
8
 
9
- class Machine < AbstractInterface
9
+ class Machine < NSISupports
10
10
  ONLINE_STATES = Set.new [ :running,
11
11
  :paused,
12
12
  :stuck,
@@ -30,7 +30,7 @@ end
30
30
 
31
31
 
32
32
 
33
- class Progress < AbstractInterface
33
+ class Progress < NSISupports
34
34
  # This method blocks the execution while the operations represented
35
35
  # by this {Progress} object execute, but yields a block every `x`
36
36
  # percent (interval given in parameters).
@@ -62,7 +62,7 @@ class Progress < AbstractInterface
62
62
  end
63
63
 
64
64
 
65
- class EventSource < AbstractInterface
65
+ class EventSource < NSISupports
66
66
  MODEL_MAP = {
67
67
  :machine_event => :MachineEvent,
68
68
  :snapshot_event => :SnapshotEvent,
@@ -60,6 +60,7 @@ module Util
60
60
  "bios" => "BIOS",
61
61
  "csam" => "CSAM",
62
62
  "dhcp" => "DHCP",
63
+ "ehci" => "EHCI",
63
64
  "fifo" => "FIFO",
64
65
  "hpet" => "HPET",
65
66
  "ich6" => "ICH6",
@@ -75,6 +76,7 @@ module Util
75
76
  "tftp" => "TFTP",
76
77
  "uuid" => "UUID",
77
78
  "vbox" => "VBox",
79
+ "vhwa" => "VHWA",
78
80
  "vpid" => "VPID",
79
81
  "vram" => "VRAM",
80
82
  "vrde" => "VRDE",
@@ -127,7 +129,6 @@ module Util
127
129
  "vm" => "VM",
128
130
  "vd" => "VD",
129
131
  }
130
-
131
132
  end
132
133
 
133
134
  end
@@ -1,5 +1,5 @@
1
1
  module VirtualBox
2
2
  module COM
3
- VERSION = "0.9.9"
3
+ VERSION = "0.10.0"
4
4
  end
5
5
  end
@@ -10,31 +10,17 @@ require_relative 'xpcomc-ffi/model-types'
10
10
 
11
11
  module VirtualBox
12
12
  module COM
13
- class IID
14
- class FFIStruct < ::FFI::Struct
15
- layout :m0, :uint32,
16
- :m1, :uint16,
17
- :m2, :uint16,
18
- :m3, [:uint8, 8]
19
- end
20
-
21
- def to_ffi
22
- @ffi ||= begin
23
- data = FFIStruct.new
24
- data[:m0] = to_a[0]
25
- data[:m1] = to_a[1]
26
- data[:m2] = to_a[2]
27
- to_a[3..-1].each_index{|i| data[:m3][i] = to_a[3..-1][i] }
28
- data.freeze
29
- end
13
+ module Model
14
+ def self.create(name, *args)
15
+ self.get(name).new(*args)
30
16
  end
31
17
  end
32
18
  end
33
19
  end
34
20
 
35
-
36
-
37
21
  # Load FFI implementation
22
+ require_relative 'xpcomc-ffi/iid'
23
+ require_relative 'xpcomc-ffi/abstracts'
38
24
  require_relative 'xpcomc-ffi/xpcomc-vbox'
39
25
  require_relative 'xpcomc-ffi/binding'
40
26
  require_relative 'xpcomc-ffi/implementer'
@@ -0,0 +1,103 @@
1
+ module VirtualBox
2
+ module COM
3
+
4
+ class AbstractModel
5
+ def self.iid(str)
6
+ const_set(:IID, IID.new(str))
7
+ end
8
+ end
9
+
10
+
11
+ #
12
+ # # Defining an Interface
13
+ #
14
+ # Defining an interface is done by subclassing AbstractInterface and
15
+ # using the provided class methods to define the COM methods and
16
+ # properties. A small example class is shown below:
17
+ #
18
+ # class Time < AbstractInterface
19
+ # function :now, [[:out, :uint]]
20
+ # property :hour, :uint
21
+ # end
22
+ #
23
+ # # Accessing an Interface
24
+ #
25
+ #
26
+ # # Assume `time` was retrieved already
27
+ # puts time.foo.to_s
28
+ # time.hour = 20
29
+ # x = time.now
30
+ #
31
+ # The above example shows how the properties and functions can be used
32
+ # with a given interface.
33
+ #
34
+ class AbstractInterface < AbstractModel
35
+ attr_reader :implementer
36
+
37
+ class << self
38
+ # Adds a function to the interface
39
+ def function(name, type, args, opts={})
40
+ h[name] = Spec::Function.new(name, type, args, opts)
41
+ define_method(name) { |*args|
42
+ @implementer.call_function(spec, *args)
43
+ } unless spec.hide?
44
+ end
45
+
46
+ # Adds a property to the interface
47
+ def property(name, type, opts={})
48
+ h[name] = Spec::Property.new(name, type, opts)
49
+ define_method(name) {
50
+ @implementer.read_property(spec)
51
+ } unless spec.hide?
52
+ define_method(:"#{name}=") { |value|
53
+ @implementer.write_property(spec, value)
54
+ } unless spec.hide? || spec.readonly?
55
+ end
56
+
57
+ # Get a member by name
58
+ def member(name)
59
+ h[name]
60
+ end
61
+
62
+ # List of members (Spec::*)
63
+ def members
64
+ h.values
65
+ end
66
+
67
+ # List of functions (Spec::Function)
68
+ def functions
69
+ members.select {|s| s.kind_of?(Spec::Function) }
70
+ end
71
+
72
+ # List if properties (Spec::Property)
73
+ def properties
74
+ members.select {|s| s.kind_of?(Spec::Property) }
75
+ end
76
+
77
+
78
+ private
79
+ def h ; @h ||= {} ; end
80
+ end
81
+
82
+
83
+ # Initializes the interface with the given implementer
84
+ def initialize(*args)
85
+ @args = args
86
+ @implementer = Implementer.new(self, *args)
87
+ end
88
+
89
+
90
+ # Cast to another model
91
+ def cast(name)
92
+ @implementer.cast(name, *@args)
93
+ end
94
+
95
+ # Concise inspect
96
+ def inspect
97
+ "#<#{self.class.name}>"
98
+ end
99
+ end
100
+
101
+
102
+ end
103
+ end
@@ -2,6 +2,13 @@ module VirtualBox
2
2
  module COM
3
3
 
4
4
  class IID
5
+ class FFIStruct < ::FFI::Struct
6
+ layout :m0, :uint32,
7
+ :m1, :uint16,
8
+ :m2, :uint16,
9
+ :m3, [:uint8, 8]
10
+ end
11
+
5
12
  def initialize(obj)
6
13
  @i = case obj
7
14
  when String
@@ -37,6 +44,17 @@ class IID
37
44
  ((@i & 0x000000000000000000000000000000ff) >> 0)]
38
45
  .freeze
39
46
  end
47
+
48
+ def to_ffi
49
+ @ffi ||= begin
50
+ data = FFIStruct.new
51
+ data[:m0] = to_a[0]
52
+ data[:m1] = to_a[1]
53
+ data[:m2] = to_a[2]
54
+ to_a[3..-1].each_index{|i| data[:m3][i] = to_a[3..-1][i] }
55
+ data.freeze
56
+ end
57
+ end
40
58
  end
41
59
 
42
60
  end
@@ -6,6 +6,11 @@ module XPCOMC
6
6
 
7
7
 
8
8
  module Lib
9
+ SUPPORTED_VERSIONS = {
10
+ "4.2" => [ "3b2f08eb-b810-4715-bee0-bb06b9880ad2",
11
+ "12F4DCDB-12B2-4EC1-B7CD-DDD9F6C5BF4D" ]
12
+ }
13
+
9
14
  extend ::FFI::Library
10
15
 
11
16
  # Constant with default library path and name
@@ -71,6 +76,7 @@ module Lib
71
76
  next if virtualbox_ptr.null? || session_ptr.null?
72
77
 
73
78
  # Load the interface description
79
+ require "virtualbox/com/model/#{version}-generated"
74
80
  require "virtualbox/com/model/#{version}"
75
81
 
76
82
  #
@@ -11,6 +11,7 @@ module COM
11
11
  UINT16 = :uint16
12
12
  UINT32 = :uint32
13
13
  UINT64 = :uint64
14
+ PTR = :pointer
14
15
  end
15
16
  end
16
17
 
@@ -0,0 +1,8 @@
1
+ require_relative 'xpcomc-native/vbox_loader'
2
+
3
+ module VirtualBox
4
+ module COM
5
+ def self.virtualbox ; VIRTUALBOX ; end
6
+ def self.session ; SESSION ; end
7
+ end
8
+ end
@@ -0,0 +1,84 @@
1
+ module VirtualBox
2
+ module COM
3
+
4
+ class IID
5
+ def initialize(iid)
6
+ @iid = iid
7
+ end
8
+
9
+ def to_s
10
+ @iid
11
+ end
12
+
13
+ def to_struct
14
+ hex = @iid.gsub('-', '')
15
+ '{' + ([ hex[0,8], hex[8,4], hex[12,4] ].map{|e| "0x#{e}" } +
16
+ [ '{' + [ hex[16,2], hex[18,2], hex[20,2], hex[22,2],
17
+ hex[24,2], hex[26,2], hex[28,2], hex[30,2] ]
18
+ .map{|e| "0x#{e}" }.join(', ') + '}' ]).join(', ') + '}'
19
+ end
20
+ end
21
+
22
+ class AbstractModel
23
+ def self.iid(str)
24
+ const_set(:IID, IID.new(str))
25
+ end
26
+
27
+
28
+ def self.nickname
29
+ self.name.split('::')[-1]
30
+ end
31
+ end
32
+
33
+ class AbstractInterface < AbstractModel
34
+ class << self
35
+
36
+ # Extends the current model with another one.
37
+ # Note that redefining functions or properties is not supported.
38
+ def extends(model = nil)
39
+ if model.nil?
40
+ then @model
41
+ else @model = Model.get(model)
42
+ end
43
+ rescue ModelNotFoundException
44
+ raise "trying to extend an unknown model (#{model})"
45
+ end
46
+
47
+
48
+ # Adds a function to the interface
49
+ def function(name, type, args, opts={})
50
+ h[name] = Spec::Function.new(name, type, args, opts)
51
+ end
52
+
53
+ # Adds a property to the interface
54
+ def property(name, type, opts={})
55
+ h[name] = Spec::Property.new(name, type, opts)
56
+ end
57
+
58
+ # Get a member by name
59
+ def member(name)
60
+ h[name]
61
+ end
62
+
63
+ # List of members (Spec::*)
64
+ def members
65
+ h.values
66
+ end
67
+
68
+ # List of functions (Spec::Function)
69
+ def functions
70
+ members.select {|s| s.kind_of?(Spec::Function) }
71
+ end
72
+
73
+ # List if properties (Spec::Property)
74
+ def properties
75
+ members.select {|s| s.kind_of?(Spec::Property) }
76
+ end
77
+
78
+ private
79
+ def h ; @h ||= {} ; end
80
+ end
81
+ end
82
+
83
+ end
84
+ end
data/scripts/sig.rb ADDED
@@ -0,0 +1,201 @@
1
+ module VirtualBox
2
+ module COM
3
+
4
+
5
+ class Sig
6
+ # Store and normalize signatures
7
+ def initialize(sig)
8
+ @sig = sig.map {|item|
9
+ if item.is_a?(Array) && item[0] == :out
10
+ then [ item[1], :out ]
11
+ else [ item, :in ]
12
+ end
13
+ }.freeze.each{|type, way|
14
+ # Sanity check: only `[type]` or `type`
15
+ if type.is_a?(Array) && type.length != 1
16
+ raise ArgumentError, "only arrays of simple type are supported"
17
+ end
18
+ }
19
+ end
20
+
21
+
22
+ def size
23
+ @sig.size
24
+ end
25
+
26
+ def in ; @sig.select {|type, way| way == :in } ; end
27
+ def out ; @sig.select {|type, way| way == :out } ; end
28
+
29
+ def to_c
30
+ @sig.map {|type, way| is_array = type.is_a?(Array)
31
+ case way
32
+ when :out
33
+ if is_array
34
+ then [PTR, PTR]
35
+ else PTR
36
+ end
37
+ when :in
38
+ if is_array then [UINT32, PTR]
39
+ elsif model = Model.fetch(type)
40
+ if model <= COM::AbstractInterface then PTR
41
+ elsif model <= COM::AbstractEnum then UINT32
42
+ end
43
+ else type
44
+ end
45
+ end
46
+ }.unshift(PTR).flatten # Add `this` element
47
+ end
48
+
49
+
50
+
51
+ # Enhance signature by adding variable declarations
52
+ def with_var_decl
53
+ i = 0
54
+ @sig.map {|type, way| is_array = type.is_a?(Array)
55
+ v = "v#{i+=1}"
56
+ vdecl = if is_array then [["#{v}_size", UINT32], [v, PTR]]
57
+ elsif model = Model.fetch(type)
58
+ if model <= AbstractInterface then [[v, PTR]]
59
+ elsif model <= AbstractEnum then [[v, UINT32]]
60
+ end
61
+ else [[v, type]]
62
+ end
63
+ [type, way] + vdecl
64
+ }
65
+ end
66
+
67
+
68
+
69
+
70
+
71
+
72
+ def to_c_func(name, vtbl, fun)
73
+ ins = self.in;
74
+
75
+ args= ([ 'self' ] + ins.size.times.map {|i| "i#{i}"})
76
+ .map {|v| "VALUE #{v}"}.join(', ')
77
+
78
+ OUT << "static VALUE #{name}(#{args}) {\n"
79
+ OUT << " VALUE res = Qundef;\n"
80
+ OUT << " struct obj *obj = DATA_PTR(self);\n"
81
+ OUT << " struct #{vtbl} *vtbl = obj->vtbl;\n"
82
+
83
+ args = self.with_var_decl
84
+
85
+ args.each{|type, way, *vdecl|
86
+ vdecl.each{|var, decl|
87
+ OUT << " #{decl} #{var};\n"
88
+ }
89
+ }
90
+
91
+ ins.each_index{|i| type, = ins[i]
92
+ OUT << " i#{i} = " << do_prepare(type, "i#{i}") << ";\n"
93
+ }
94
+
95
+ i = 0;
96
+ args.each {|type, way, *vdec| is_array = type.is_a?(Array)
97
+ if way == :in
98
+ OUT << " " << get_extract(type, "i#{i}", vdec.map{|var, dec|
99
+ "&#{var}"}) << ";\n"
100
+ end
101
+ i += 1
102
+ }
103
+
104
+ a = args.map {|type, way, *vdec| vdec.map{|var, dec|
105
+ if way == :out then "&#{var}" else var end } }.flatten
106
+ a.unshift('obj');
107
+ OUT << " NS_CHECK(vtbl->#{fun}(" << a.join(', ') << "));\n"
108
+
109
+
110
+
111
+ OUT << " res = rb_ary_new();\n"
112
+ i = 0
113
+ o = 0
114
+ args.each {|type, way, *vdec| is_array = type.is_a?(Array)
115
+ if way == :out
116
+ OUT << " rb_ary_push(res, " << get_convert(type, vdec.map{|var, dec|
117
+ "#{var}"}) << ");\n"
118
+ o += 1
119
+ end
120
+ i += 1
121
+ }
122
+
123
+ OUT << " res = rb_ary_entry(res, 0);\n" if o == 1
124
+ OUT << " return res;\n"
125
+ OUT << "}\n"
126
+
127
+ end
128
+
129
+
130
+
131
+ def get_convert(type, *args)
132
+ is_array = type.is_a?(Array)
133
+ type = type[0] if is_array
134
+
135
+ m, *a = to_converter(type)
136
+ m = "array_#{m}" if is_array && type != OCTET
137
+ m = "convert_#{m}"
138
+ m + '(' + (args + a).join(', ') + ')'
139
+ end
140
+
141
+ def get_extract(type, src, *args)
142
+ is_array = type.is_a?(Array)
143
+ type = type[0] if is_array
144
+ a = []
145
+
146
+ if is_array && type == OCTET
147
+ m = :blob
148
+ elsif is_array
149
+ m = :carray
150
+ else
151
+ m, *a = to_converter(type)
152
+ end
153
+ m = "extract_#{m}"
154
+ m + '(' + ([src] + args + a).join(', ') + ')'
155
+ end
156
+
157
+ def get_in_and_out(prefix, type, src, *args)
158
+ end
159
+
160
+ def do_prepare(type, src)
161
+ is_array = type.is_a?(Array)
162
+ type = type[0] if is_array
163
+
164
+ m, *a = to_converter(type)
165
+ m = "array_#{m}" if is_array && type != OCTET
166
+ m = "prepare_#{m}"
167
+ m + '(' + ([src] + a).join(', ') + ')'
168
+ end
169
+
170
+
171
+
172
+ def to_converter(type)
173
+ is_array = type.is_a?(Array)
174
+ type = type[0] if is_array
175
+
176
+ case type
177
+ when BOOL then :bool
178
+ when PTR then :ptr
179
+ when OCTET then :blob
180
+ when INT16 then :int16
181
+ when INT32 then :int32
182
+ when INT64 then :int64
183
+ when UINT16 then :uint16
184
+ when UINT32 then :uint32
185
+ when UINT64 then :uint64
186
+ when WSTRING then :wstring
187
+ else
188
+ if model = Model.fetch(type)
189
+ kind = if model <= AbstractInterface then :interface
190
+ elsif model <= AbstractEnum then :enum
191
+ else raise "unknown model #{mode.class}"
192
+ end
193
+ [ kind, "c#{type}" ]
194
+ else raise "unknown type #{type}"
195
+ end
196
+ end
197
+ end
198
+ end
199
+
200
+ end
201
+ end