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.
- data/LICENSE +339 -19
- data/examples/simple.rb +2 -0
- data/ext/virtualbox-com/4.1/extconf.rb +4 -0
- data/ext/virtualbox-com/4.1/generated.inc +17345 -0
- data/ext/virtualbox-com/4.1/vbox.c +858 -0
- data/ext/virtualbox-com/4.2/extconf.rb +4 -0
- data/ext/virtualbox-com/4.2/generated.inc +19751 -0
- data/ext/virtualbox-com/4.2/vbox.c +858 -0
- data/ext/virtualbox-com/helpers.h +62 -0
- data/ext/virtualbox-com/loader/extconf.rb +3 -0
- data/ext/virtualbox-com/loader/vbox-loader.c +187 -0
- data/ext/virtualbox-com/types.h +34 -0
- data/ext/virtualbox-com/vbox.c +858 -0
- data/lib/virtualbox/com.rb +4 -26
- data/lib/virtualbox/com/{abstract_enum.rb → abstracts.rb} +22 -18
- data/lib/virtualbox/com/exceptions.rb +29 -3
- data/lib/virtualbox/com/model/4.1-generated.rb +2141 -0
- data/lib/virtualbox/com/model/4.2-generated.rb +141 -432
- data/lib/virtualbox/com/model/4.2.rb +4 -4
- data/lib/virtualbox/com/util.rb +2 -1
- data/lib/virtualbox/com/version.rb +1 -1
- data/lib/virtualbox/com/xpcomc-ffi.rb +5 -19
- data/lib/virtualbox/com/xpcomc-ffi/abstracts.rb +103 -0
- data/lib/virtualbox/com/{iid.rb → xpcomc-ffi/iid.rb} +18 -0
- data/lib/virtualbox/com/xpcomc-ffi/lib.rb +6 -0
- data/lib/virtualbox/com/xpcomc-ffi/model-types.rb +1 -0
- data/lib/virtualbox/com/xpcomc-native.rb +8 -0
- data/scripts/abstracts.rb +84 -0
- data/scripts/sig.rb +201 -0
- data/scripts/spec.rb +56 -0
- data/scripts/to_c.rb +157 -0
- data/scripts/xidl-conv.rb +110 -50
- data/virtualbox-com.gemspec +18 -11
- metadata +49 -47
- data/.gitignore +0 -9
- data/README.md +0 -89
- data/Rakefile +0 -8
- data/lib/virtualbox/com/abstract_interface.rb +0 -144
- data/lib/virtualbox/com/abstract_model.rb +0 -14
@@ -1,4 +1,4 @@
|
|
1
|
-
|
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 <
|
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 <
|
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 <
|
65
|
+
class EventSource < NSISupports
|
66
66
|
MODEL_MAP = {
|
67
67
|
:machine_event => :MachineEvent,
|
68
68
|
:snapshot_event => :SnapshotEvent,
|
data/lib/virtualbox/com/util.rb
CHANGED
@@ -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
|
@@ -10,31 +10,17 @@ require_relative 'xpcomc-ffi/model-types'
|
|
10
10
|
|
11
11
|
module VirtualBox
|
12
12
|
module COM
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
#
|
@@ -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
|