virtualbox-com 0.9.9 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
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