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
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
- io = $stdout
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
- io << <<-EOT
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
- io << "module VirtualBox\n"
20
- io << "module COM\n"
21
- io << "\n"
22
- io << "MODEL_VERSION = \"4.2\"\n"
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
- io << <<-EOT
55
+ OUT << <<-EOT
29
56
  class NSISupports < AbstractInterface
30
57
  iid "00000000-0000-0000-c000-000000000046"
31
- function :QueryInterface, :pointer, [ :pointer ], :hide => true
32
- function :AddRef, nil, [], :hide => true
33
- function :Release, nil, [], :hide => true
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
- def uncamelize(string)
40
- VirtualBox::COM::Util.uncamelize(string)
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 ':pointer' if ptr
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
- else ':'+ name.gsub(/^I/, '')
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
- io << "class #{enum[:name]} < AbstractEnum\n"
67
- io << " iid \"#{enum[:uuid]}\"\n"
68
- io << " map({\n"
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
- io << " :%-40s => %s,\n" % [ uncamelize(c[:name]), c[:value] ] }
71
- io << " })\n"
72
- io << " setup\n"
73
- io << "end\n"
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
- io << "class #{interface[:name][1..-1]} < AbstractInterface\n"
80
- io << " iid \"#{interface[:uuid]}\"\n"
81
-
82
- case e=interface[:extends]
83
- when nil
84
- when '$errorinfo'
85
- when '$unknown' then io << " extends :NSISupports\n"
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 = ':' + uncamelize(a[:name])
93
- type = cnv_type(a[:type], a[:safearray])
94
- opts = [ ':readonly => true' ] if a[:readonly]
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
- io << " property " << args.join(', ') << "\n"
159
+ OUT << " property " << args.join(', ') << "\n"
99
160
  }
100
161
  interface.xpath('method').each {|m|
101
- name = ':' + uncamelize(m[: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
- io << " function " << [name, ret, param].join(', ') << "\n"
173
+ OUT << " function " << [name, ret, param].join(', ') << "\n"
113
174
  }
114
175
 
115
- io << " setup\n"
116
- io << "end\n"
117
- io << "\n"
176
+ OUT << "end\n"
177
+ OUT << "\n"
118
178
  end
119
179
 
120
180
 
121
- io << "end\n"
122
- io << "end\n"
123
- io << "end\n"
181
+ OUT << "end\n"
182
+ OUT << "end\n"
183
+ OUT << "end\n"
124
184
 
125
- io.flush
185
+ OUT.flush
@@ -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.platform = Gem::Platform::RUBY
9
- s.authors = ["Stephane D'Alu", "Mitchell Hashimoto"]
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 interraction using pure ruby"
13
- s.description = "Low level VirtualBox interraction using pure ruby"
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
- s.required_rubygems_version = ">= 1.3.6"
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 = `git ls-files`.split("\n")
24
- s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
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