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.
- 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
data/scripts/spec.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative 'sig'
|
2
|
+
|
3
|
+
module VirtualBox
|
4
|
+
module COM
|
5
|
+
|
6
|
+
class Spec
|
7
|
+
attr_reader :name
|
8
|
+
|
9
|
+
def hide?
|
10
|
+
@opts[:hide]
|
11
|
+
end
|
12
|
+
|
13
|
+
class Function < Spec
|
14
|
+
def initialize(name, type, args, opts)
|
15
|
+
@name, @type, @args, @opts = name, type, args, opts
|
16
|
+
end
|
17
|
+
|
18
|
+
def signatures
|
19
|
+
{ name => to_call }
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_call
|
23
|
+
Sig.new( if @type.nil?
|
24
|
+
then @args
|
25
|
+
else @args + [ [ :out, @type ] ]
|
26
|
+
end)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Property < Spec
|
31
|
+
attr_reader :getter, :setter
|
32
|
+
|
33
|
+
def initialize(name, type, opts)
|
34
|
+
@name, @type, @opts = name, type, opts
|
35
|
+
end
|
36
|
+
|
37
|
+
def signatures
|
38
|
+
r = {}
|
39
|
+
r[getter] = to_read
|
40
|
+
r[setter] = to_write unless self.readonly?
|
41
|
+
r
|
42
|
+
end
|
43
|
+
|
44
|
+
def readonly?
|
45
|
+
@opts[:readonly]
|
46
|
+
end
|
47
|
+
|
48
|
+
def getter ; :"get_#{@name}" ; end
|
49
|
+
def setter ; :"set_#{@name}" ; end
|
50
|
+
def to_read ; Sig.new([[:out, @type]]) ; end
|
51
|
+
def to_write ; Sig.new([ @type ]) ; end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
data/scripts/to_c.rb
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'getoptlong'
|
3
|
+
|
4
|
+
module VirtualBox
|
5
|
+
module COM
|
6
|
+
WSTRING = 'wstring_t'
|
7
|
+
BOOL = 'bool_t'
|
8
|
+
OCTET = 'char'
|
9
|
+
PTR = 'void *'
|
10
|
+
INT8 = 'int8_t'
|
11
|
+
INT16 = 'int16_t'
|
12
|
+
INT32 = 'int32_t'
|
13
|
+
INT64 = 'int64_t'
|
14
|
+
UINT8 = 'uint8_t'
|
15
|
+
UINT16 = 'uint16_t'
|
16
|
+
UINT32 = 'uint32_t'
|
17
|
+
UINT64 = 'uint64_t'
|
18
|
+
|
19
|
+
module Model
|
20
|
+
def self.get(name)
|
21
|
+
self.const_get(name, false)
|
22
|
+
rescue NameError
|
23
|
+
raise ModelNotFoundException, name
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.fetch(name)
|
27
|
+
self.const_get(name, false)
|
28
|
+
rescue NameError
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class ModelNotFoundException < Exception
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
require 'virtualbox/com/abstracts'
|
39
|
+
require_relative 'abstracts'
|
40
|
+
require_relative 'sig'
|
41
|
+
require_relative 'spec'
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
opts = GetoptLong.new(
|
46
|
+
[ "--api", GetoptLong::REQUIRED_ARGUMENT ],
|
47
|
+
[ "--file", GetoptLong::REQUIRED_ARGUMENT ],
|
48
|
+
[ "--help", GetoptLong::NO_ARGUMENT ] )
|
49
|
+
|
50
|
+
api = nil
|
51
|
+
file = nil
|
52
|
+
|
53
|
+
begin
|
54
|
+
opts.each do |opt, arg|
|
55
|
+
case opt
|
56
|
+
when "--api" then api = arg
|
57
|
+
when "--file" then file = arg
|
58
|
+
when "--help" then raise
|
59
|
+
end
|
60
|
+
end
|
61
|
+
raise if api.nil?
|
62
|
+
rescue
|
63
|
+
$stderr.print <<EOT
|
64
|
+
usage: xidl-conv.rb: --api version [--file output]
|
65
|
+
--api Model description
|
66
|
+
--file path to generated output
|
67
|
+
--help Show this message.
|
68
|
+
|
69
|
+
EOT
|
70
|
+
exit 0
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
require "virtualbox/com/model/#{api}-generated"
|
75
|
+
OUT = file.nil? ? $stdout : File.open(file, 'w')
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
M = VirtualBox::COM::Model
|
82
|
+
|
83
|
+
|
84
|
+
M.constants.each {|name| model = VirtualBox::COM::Model.get(name)
|
85
|
+
next unless model <= VirtualBox::COM::AbstractInterface
|
86
|
+
OUT << "struct #{name} {\n"
|
87
|
+
if (s = model.superclass) < VirtualBox::COM::AbstractInterface
|
88
|
+
OUT << " struct #{s.nickname} #{s.nickname};\n"
|
89
|
+
end
|
90
|
+
model.members.each {|spec|
|
91
|
+
spec.signatures.each {|n, sig|
|
92
|
+
OUT << " uint32_t (*#{n})(#{sig.to_c.join(', ')});\n"
|
93
|
+
}
|
94
|
+
}
|
95
|
+
OUT << "};\n"
|
96
|
+
}
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
M.constants.each {|name| model = VirtualBox::COM::Model.get(name)
|
101
|
+
OUT << "static VALUE c#{name} = Qundef;\n"
|
102
|
+
}
|
103
|
+
|
104
|
+
|
105
|
+
M.constants.each {|name| model = VirtualBox::COM::Model.get(name)
|
106
|
+
next unless model <= VirtualBox::COM::AbstractInterface
|
107
|
+
|
108
|
+
model.functions.each {|spec|
|
109
|
+
spec.to_call.to_c_func("#{name}__#{spec.name}", name, spec.name);
|
110
|
+
}
|
111
|
+
|
112
|
+
model.properties.each {|spec|
|
113
|
+
spec.to_read.to_c_func("#{name}__#{spec.getter}", name, spec.getter);
|
114
|
+
next if spec.readonly?
|
115
|
+
spec.to_write.to_c_func("#{name}__#{spec.setter}", name, spec.setter);
|
116
|
+
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
|
121
|
+
OUT << "static void comclass_init(VALUE under) {\n"
|
122
|
+
M.constants.each {|name| model = VirtualBox::COM::Model.get(name)
|
123
|
+
kAbstract = 'c' + model.superclass.name.split('::')[-1]
|
124
|
+
|
125
|
+
OUT << " {\n"
|
126
|
+
OUT << " iid_t iid = #{model::IID.to_struct};\n"
|
127
|
+
OUT << " VALUE c = c#{name}\n"
|
128
|
+
OUT << " = rb_define_class_under(under, \"#{name}\", #{kAbstract});\n"
|
129
|
+
OUT << " no_instantiation(c);\n"
|
130
|
+
OUT << " rb_const_set(c, _IID, iid__new(&iid));\n"
|
131
|
+
|
132
|
+
if model <= VirtualBox::COM::AbstractEnum
|
133
|
+
OUT << " VALUE h = rb_hash_new();\n"
|
134
|
+
model.map.each {|sym, val|
|
135
|
+
OUT << " rb_funcall(h, _bracketseq, 2, SYM(\"#{sym}\"), ULL2NUM(#{val}));\n"
|
136
|
+
}
|
137
|
+
OUT << " rb_funcall(c, _map, 1, h);\n"
|
138
|
+
elsif model <= VirtualBox::COM::AbstractInterface
|
139
|
+
model.members.each {|spec|
|
140
|
+
next if spec.hide?
|
141
|
+
case spec
|
142
|
+
when VirtualBox::COM::Spec::Function
|
143
|
+
if spec.to_call.size > 15
|
144
|
+
warn "Binding for #{model.nickname}\##{spec.name} need to be handcrafted"
|
145
|
+
next
|
146
|
+
end
|
147
|
+
OUT << " rb_define_method(c, \"#{spec.name}\", #{model.nickname}__#{spec.name}, #{spec.to_call.in.size});\n"
|
148
|
+
when VirtualBox::COM::Spec::Property
|
149
|
+
OUT << " rb_define_method(c, \"#{spec.name}\", #{model.nickname}__#{spec.getter}, 0);\n"
|
150
|
+
|
151
|
+
OUT << " rb_define_method(c, \"#{spec.name}=\", #{model.nickname}__#{spec.setter}, 1);\n" if !spec.readonly?
|
152
|
+
end
|
153
|
+
}
|
154
|
+
end
|
155
|
+
OUT << " }\n"
|
156
|
+
}
|
157
|
+
OUT << "}\n"
|
data/scripts/xidl-conv.rb
CHANGED
@@ -1,47 +1,102 @@
|
|
1
1
|
require 'bundler/setup'
|
2
|
+
require 'getoptlong'
|
2
3
|
require 'nokogiri'
|
3
4
|
require 'virtualbox/com/util'
|
4
5
|
|
5
|
-
XIDL = Nokogiri::XML(File.new("../VirtualBox.xidl"))
|
6
|
-
LIB = XIDL.root.xpath('library')
|
7
6
|
|
7
|
+
# Parse command line
|
8
|
+
opts = GetoptLong.new(
|
9
|
+
[ "--xidl", GetoptLong::REQUIRED_ARGUMENT ],
|
10
|
+
[ "--file", GetoptLong::REQUIRED_ARGUMENT ],
|
11
|
+
[ "--help", GetoptLong::NO_ARGUMENT ] )
|
8
12
|
|
13
|
+
xidl = nil
|
14
|
+
file = nil
|
9
15
|
|
10
|
-
|
16
|
+
begin
|
17
|
+
opts.each do |opt, arg|
|
18
|
+
case opt
|
19
|
+
when "--xidl" then xidl = arg
|
20
|
+
when "--file" then file = arg
|
21
|
+
when "--help" then raise
|
22
|
+
end
|
23
|
+
end
|
24
|
+
raise if xidl.nil?
|
25
|
+
rescue
|
26
|
+
$stderr.print <<EOT
|
27
|
+
usage: xidl-conv.rb: --xidl file [--file output]
|
28
|
+
--xidl VirtualBox XIDL file
|
29
|
+
--file path to generated output
|
30
|
+
--help Show this message.
|
31
|
+
|
32
|
+
EOT
|
33
|
+
exit 0
|
34
|
+
end
|
11
35
|
|
12
|
-
|
36
|
+
|
37
|
+
XIDL = Nokogiri::XML(File.new(xidl))
|
38
|
+
LIB = XIDL.root.xpath('library')
|
39
|
+
OUT = file.nil? ? $stdout : File.open(file, 'w')
|
40
|
+
|
41
|
+
OUT << <<-EOT
|
13
42
|
#
|
14
43
|
# This file has been automatically generated from the VirtualBox.xidl
|
44
|
+
# NOTE: it is not always loaded.
|
15
45
|
#
|
16
46
|
|
17
47
|
EOT
|
18
48
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
io << "\n"
|
24
|
-
io << "module Model\n"
|
25
|
-
io << "\n"
|
49
|
+
OUT << "module VirtualBox\n"
|
50
|
+
OUT << "module COM\n"
|
51
|
+
OUT << "module Model\n"
|
52
|
+
OUT << "\n"
|
26
53
|
|
27
54
|
|
28
|
-
|
55
|
+
OUT << <<-EOT
|
29
56
|
class NSISupports < AbstractInterface
|
30
57
|
iid "00000000-0000-0000-c000-000000000046"
|
31
|
-
function :QueryInterface,
|
32
|
-
function :AddRef, nil, [],
|
33
|
-
function :Release, nil, [],
|
58
|
+
function :QueryInterface, PTR, [ PTR ], :hide => true
|
59
|
+
function :AddRef, nil, [], :hide => true
|
60
|
+
function :Release, nil, [], :hide => true
|
61
|
+
end
|
62
|
+
|
63
|
+
class NSIException < NSISupports
|
64
|
+
iid "f3a8d3b4-c424-4edc-8bf6-8974c983ba78"
|
65
|
+
property :message, WSTRING, :readonly => true
|
66
|
+
property :result, UINT32, :readonly => true
|
67
|
+
property :name, WSTRING, :readonly => true
|
68
|
+
property :filename, WSTRING, :readonly => true
|
69
|
+
property :line_number, UINT32, :readonly => true
|
70
|
+
property :column_number, UINT32, :readonly => true
|
71
|
+
property :location, PTR, :readonly => true
|
72
|
+
property :inner, :NSIException, :readonly => true
|
73
|
+
property :data, :NSISupports, :readonly => true
|
74
|
+
function :to_string, nil, [WSTRING]
|
34
75
|
end
|
35
76
|
|
36
77
|
EOT
|
37
78
|
|
38
79
|
|
39
|
-
|
40
|
-
|
80
|
+
class String
|
81
|
+
def uncamelize
|
82
|
+
VirtualBox::COM::Util.uncamelize(self)
|
83
|
+
end
|
84
|
+
|
85
|
+
def up1case
|
86
|
+
self[0].upcase + self[1..-1]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def origin_of(type)
|
91
|
+
if !LIB.xpath("interface[@name = '#{type}']").empty?
|
92
|
+
:interface
|
93
|
+
elsif !LIB.xpath("enum [@name = '#{type}']").empty?
|
94
|
+
:enum
|
95
|
+
end
|
41
96
|
end
|
42
97
|
|
43
98
|
def cnv_type(name, array=nil, ptr=nil)
|
44
|
-
return '
|
99
|
+
return 'PTR' if ptr
|
45
100
|
t = case name
|
46
101
|
when 'boolean' then 'BOOL'
|
47
102
|
when 'octet' then 'OCTET'
|
@@ -54,7 +109,13 @@ def cnv_type(name, array=nil, ptr=nil)
|
|
54
109
|
when 'uuid' then 'WSTRING'
|
55
110
|
when 'wstring' then 'WSTRING'
|
56
111
|
when '$unknown' then ':NSISupports'
|
57
|
-
|
112
|
+
when '$errorinfo' then ':NSIException'
|
113
|
+
else
|
114
|
+
case origin_of(name)
|
115
|
+
when :interface then ':' + name.gsub(/^I/, '')
|
116
|
+
when :enum then ':' + name
|
117
|
+
else raise "Unknown type #{name}"
|
118
|
+
end
|
58
119
|
end
|
59
120
|
t = '[' + t + ']' if array
|
60
121
|
t
|
@@ -63,42 +124,42 @@ end
|
|
63
124
|
|
64
125
|
# Enumeration
|
65
126
|
for enum in LIB.xpath('enum')
|
66
|
-
|
67
|
-
|
68
|
-
|
127
|
+
OUT << "class #{enum[:name]} < AbstractEnum\n"
|
128
|
+
OUT << " iid \"#{enum[:uuid]}\"\n"
|
129
|
+
OUT << " map({\n"
|
69
130
|
enum.xpath('const').each {|c|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
io << "\n"
|
131
|
+
OUT << " :%-40s => %s,\n" % [ c[:name].uncamelize, c[:value] ] }
|
132
|
+
OUT << " })\n"
|
133
|
+
OUT << "end\n"
|
134
|
+
OUT << "\n"
|
75
135
|
end
|
76
136
|
|
77
137
|
# Interface
|
78
138
|
for interface in LIB.xpath('interface')
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
when /^I/ then io << " extends :#{e[1..-1]}\n"
|
87
|
-
else raise "Unkown extension"
|
88
|
-
end
|
139
|
+
klass = case e=interface[:extends]
|
140
|
+
when 'AbstractInterface'
|
141
|
+
when '$errorinfo' then 'NSIException'
|
142
|
+
when '$unknown' then 'NSISupports'
|
143
|
+
when /^I/ then e[1..-1]
|
144
|
+
else raise "Unknown extension"
|
145
|
+
end
|
89
146
|
|
147
|
+
OUT << "class #{interface[:name][1..-1]} < #{klass}\n"
|
148
|
+
OUT << " iid \"#{interface[:uuid]}\"\n"
|
90
149
|
|
91
150
|
interface.xpath('attribute').each {|a|
|
92
|
-
name = ':' +
|
93
|
-
type = cnv_type(a[:type], a[:safearray])
|
94
|
-
opts =
|
151
|
+
name = ':' + a[:name].uncamelize
|
152
|
+
type = cnv_type(a[:type], a[:safearray], a[:mod] == 'ptr')
|
153
|
+
opts = if a[:readonly]
|
154
|
+
then [ ':readonly => true' ]
|
155
|
+
end
|
95
156
|
args = [ name, type ]
|
96
157
|
args << opts if opts && !opts.empty?
|
97
158
|
|
98
|
-
|
159
|
+
OUT << " property " << args.join(', ') << "\n"
|
99
160
|
}
|
100
161
|
interface.xpath('method').each {|m|
|
101
|
-
name = ':' +
|
162
|
+
name = ':' + m[:name].uncamelize
|
102
163
|
ret = if ret = m.xpath("param[@dir = 'return']")[0]
|
103
164
|
cnv_type(ret[:type], ret[:safearray], ret[:mod] == 'ptr')
|
104
165
|
else 'nil'
|
@@ -109,17 +170,16 @@ for interface in LIB.xpath('interface')
|
|
109
170
|
t
|
110
171
|
}.join(', ') + ']'
|
111
172
|
|
112
|
-
|
173
|
+
OUT << " function " << [name, ret, param].join(', ') << "\n"
|
113
174
|
}
|
114
175
|
|
115
|
-
|
116
|
-
|
117
|
-
io << "\n"
|
176
|
+
OUT << "end\n"
|
177
|
+
OUT << "\n"
|
118
178
|
end
|
119
179
|
|
120
180
|
|
121
|
-
|
122
|
-
|
123
|
-
|
181
|
+
OUT << "end\n"
|
182
|
+
OUT << "end\n"
|
183
|
+
OUT << "end\n"
|
124
184
|
|
125
|
-
|
185
|
+
OUT.flush
|
data/virtualbox-com.gemspec
CHANGED
@@ -5,23 +5,30 @@ require "virtualbox/com/version"
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "virtualbox-com"
|
7
7
|
s.version = VirtualBox::COM::VERSION
|
8
|
-
s.
|
9
|
-
s.
|
10
|
-
s.email = ["stephane.dalu@gmail.com", "mitchell.hashimoto@gmail.com"]
|
8
|
+
s.authors = [ "Stephane D'Alu" ]
|
9
|
+
s.email = [ "stephane.dalu@gmail.com" ]
|
11
10
|
s.homepage = "http://github.com/sdalu/virtualbox-com"
|
12
|
-
s.summary = "Low level VirtualBox
|
13
|
-
s.description = "Low level VirtualBox
|
11
|
+
s.summary = "Low level VirtualBox binding"
|
12
|
+
s.description = "Low level VirtualBox binding using native code"
|
13
|
+
s.extensions = [ "ext/virtualbox-com/loader/extconf.rb",
|
14
|
+
"ext/virtualbox-com/4.2/extconf.rb",
|
15
|
+
"ext/virtualbox-com/4.1/extconf.rb",
|
16
|
+
]
|
14
17
|
|
15
|
-
|
16
|
-
s.rubyforge_project = "virtualbox-com"
|
17
|
-
|
18
|
-
s.add_dependency "ffi"
|
18
|
+
# s.add_dependency "ffi"
|
19
19
|
s.add_development_dependency "rake"
|
20
20
|
s.add_development_dependency "nokogiri"
|
21
|
+
|
22
|
+
s.has_rdoc = false
|
23
|
+
|
24
|
+
s.license = 'GPL-2'
|
21
25
|
|
22
26
|
|
23
|
-
s.files =
|
24
|
-
|
27
|
+
s.files = %w[ LICENSE Gemfile virtualbox-com.gemspec ] +
|
28
|
+
Dir['scripts/*.rb'] +
|
29
|
+
Dir['examples/*.rb'] +
|
30
|
+
Dir['ext/**/*.{c,h,rb,inc}'] +
|
31
|
+
Dir['lib/**/*.rb']
|
25
32
|
s.require_path = 'lib'
|
26
33
|
end
|
27
34
|
|