remogatto-ffi-generator 0.1.0 → 0.2.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/.gitignore CHANGED
@@ -1,4 +1,8 @@
1
1
  pkg/
2
2
  generated/
3
3
  *.gem
4
+ *.xml
5
+ *#
6
+ .#*
7
+ announcement.txt
4
8
 
@@ -1,3 +1,11 @@
1
+ == 0.2.0 / 2009-03-05
2
+
3
+ * 1 major enhancement
4
+ * Added support for callbacks.
5
+ * 1 minor enhancement
6
+ * C functions with one void argument are correctly generated as FFI
7
+ functions with no arguments.
8
+
1
9
  == 0.1.0 / 2009-02-16
2
10
 
3
11
  * a bunch of minor fixes
@@ -5,10 +5,10 @@ ffi-generator
5
5
  == DESCRIPTION:
6
6
 
7
7
  ffi-generator is a ruby-ffi wrapper code generator based on SWIG
8
- interfaces.
8
+ interface files.
9
9
 
10
10
  ffi-generator is able to traverse a XML parse tree file generated by
11
- SWIG and to produce a ruby file with ruby-ffi wrapper code inside.
11
+ SWIG and to produce a ruby-ffi interface file from it.
12
12
 
13
13
  ffi-generator is shipped with a command line tool (ffi-gen) and a rake
14
14
  task that automates the code generation process.
@@ -17,12 +17,13 @@ ffi-generator XML capabilities are provided by nokogiri.
17
17
 
18
18
  == FEATURES/PROBLEMS:
19
19
 
20
- * support for
20
+ * The program is able to generate:
21
21
  * all C native types
22
22
  * #define constants
23
23
  * typedefs
24
- * struct, union, array and enum types
25
- * naive indentation of the generated code
24
+ * struct, union, array and enum types
25
+ * callbacks (pointers to functions)
26
+ * Naive indentation of the generated code
26
27
 
27
28
  == SYNOPSIS:
28
29
 
@@ -40,7 +41,14 @@ From a Rakefile:
40
41
  * rake >= 0.8.3
41
42
  * nokogiri >= 1.1.1
42
43
 
43
- == INSTALL:
44
+ == DOWNLOAD/INSTALL:
45
+
46
+ To download and install the gem from github:
47
+
48
+ [sudo] gem sources -a http://gems.github.com
49
+ [sudo] gem install remogatto-ffi-generator
50
+
51
+ To download the develpment trunk:
44
52
 
45
53
  git clone git://github.com/remogatto/ffi-generator.git
46
54
 
data/Rakefile CHANGED
@@ -25,12 +25,17 @@ PROJ.url = 'http://github.com/remogatto/dokkit-core/tree/master'
25
25
  PROJ.version = FFI::Generator::VERSION
26
26
  PROJ.rubyforge.name = 'ffi-generator'
27
27
 
28
- depend_on 'rake'
29
- depend_on 'nokogiri'
30
-
31
28
  PROJ.readme_file = 'README.rdoc'
32
29
 
30
+ PROJ.ann.paragraphs << 'FEATURES' << 'SYNOPSIS' << 'REQUIREMENTS' << 'DOWNLOAD' << 'EXAMPLES'
31
+ PROJ.ann.email[:from] = 'andrea.fazzi@alca.le.it'
32
+ PROJ.ann.email[:to] << 'dev@ruby-ffi.kenai.com' << 'users@ruby-ffi.kenai.com'
33
+ PROJ.ann.email[:server] = 'smtp.gmail.com'
34
+
33
35
  PROJ.ruby_opts = []
34
36
  PROJ.spec.opts << '--color'
35
37
 
38
+ depend_on 'rake'
39
+ depend_on 'nokogiri'
40
+
36
41
  # EOF
@@ -0,0 +1,39 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{ffi-generator}
5
+ s.version = "0.2.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Andrea Fazzi"]
9
+ s.date = %q{2009-03-05}
10
+ s.default_executable = %q{ffi-gen}
11
+ s.description = %q{ffi-generator is a ruby-ffi wrapper code generator based on SWIG interfaces. ffi-generator is able to traverse a XML parse tree file generated by SWIG and to produce a ruby file with ruby-ffi wrapper code inside. ffi-generator is shipped with a command line tool (ffi-gen) and a rake task that automates the code generation process. ffi-generator XML capabilities are provided by nokogiri.}
12
+ s.email = %q{andrea.fazzi@alcacoop.it}
13
+ s.executables = ["ffi-gen"]
14
+ s.extra_rdoc_files = ["History.txt", "README.rdoc", "bin/ffi-gen"]
15
+ s.files = [".gitignore", "History.txt", "README.rdoc", "Rakefile", "bin/ffi-gen", "examples/Rakefile", "examples/generated/libc_wrap.rb", "examples/generated/libc_wrap.xml", "examples/generated/wiiuse_wrap.rb", "examples/generated/wiiuse_wrap.xml", "examples/interfaces/libc.i", "examples/interfaces/wiiuse.i", "ffi-generator.gemspec", "lib/ffi-generator.rb", "lib/generator/application.rb", "lib/generator/generator.rb", "lib/generator/generatortask.rb", "spec/ffi-generator_spec.rb", "spec/generator/generator_spec.rb", "spec/generator/swig/constants.i", "spec/generator/swig/enums.i", "spec/generator/swig/functions.i", "spec/generator/swig/structs.i", "spec/generator/swig/testlib.i", "spec/generator/swig/typedefs.i", "spec/generator/swig/types.i", "spec/generator/swig/unions.i", "spec/spec.opts", "spec/spec_helper.rb", "tasks/ann.rake", "tasks/bones.rake", "tasks/gem.rake", "tasks/git.rake", "tasks/notes.rake", "tasks/post_load.rake", "tasks/rdoc.rake", "tasks/rubyforge.rake", "tasks/setup.rb", "tasks/spec.rake", "tasks/svn.rake", "tasks/test.rake"]
16
+ s.has_rdoc = true
17
+ s.homepage = %q{http://github.com/remogatto/dokkit-core/tree/master}
18
+ s.rdoc_options = ["--main", "README.rdoc"]
19
+ s.require_paths = ["lib"]
20
+ s.rubyforge_project = %q{ffi-generator}
21
+ s.rubygems_version = %q{1.3.1}
22
+ s.summary = %q{ffi-generator is a ruby-ffi wrapper code generator based on SWIG interfaces}
23
+
24
+ if s.respond_to? :specification_version then
25
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
26
+ s.specification_version = 2
27
+
28
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
29
+ s.add_runtime_dependency(%q<rake>, [">= 0.8.3"])
30
+ s.add_runtime_dependency(%q<nokogiri>, [">= 1.2.1"])
31
+ else
32
+ s.add_dependency(%q<rake>, [">= 0.8.3"])
33
+ s.add_dependency(%q<nokogiri>, [">= 1.2.1"])
34
+ end
35
+ else
36
+ s.add_dependency(%q<rake>, [">= 0.8.3"])
37
+ s.add_dependency(%q<nokogiri>, [">= 1.2.1"])
38
+ end
39
+ end
@@ -2,7 +2,7 @@
2
2
  module FFI
3
3
  module Generator
4
4
  # :stopdoc:
5
- VERSION = '0.1.0'
5
+ VERSION = '0.2.0'
6
6
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
7
7
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
8
8
  # :startdoc:
@@ -43,65 +43,72 @@ module FFI
43
43
  end
44
44
  class Node
45
45
  attr_reader :symname
46
- def initialize(node, indent = 0)
47
- @node = node
48
- @indent = ' ' * indent
46
+ def initialize(params = { })
47
+ params = { :indent => 0 }.merge(params)
48
+ @node, @indent = params[:node], params[:indent]
49
+ @indent_str = ' ' * @indent
49
50
  @symname = get_attr('name')
50
51
  end
51
52
  def get_attr(name)
52
- attr = (@node / "./attributelist/attribute[@name='#{name}']").first
53
- attr['value'] if attr
53
+ if @node
54
+ attr = (@node / "./attributelist/attribute[@name='#{name}']").first
55
+ attr['value'] if attr
56
+ end
54
57
  end
55
58
  end
56
59
  class Type < Node
57
- def initialize(node, indent = 0)
60
+ def initialize(params = { })
58
61
  super
59
- @type = get_attr('type')
60
- @decl = get_attr('decl')
61
- @statement = @type.to_s + @decl.to_s
62
+ @statement = params[:statement] || get_statement
62
63
  end
63
64
  def to_s
64
65
  get_type
65
66
  end
66
67
  private
68
+ def get_statement
69
+ get_attr('decl').to_s + get_attr('type').to_s if @node
70
+ end
67
71
  def is_native?
68
- Generator::TYPES.has_key?(@type)
72
+ Generator::TYPES.has_key?(@statement)
69
73
  end
70
74
  def is_pointer?
71
- @decl and @decl[/(\)\.p|^p)\./]
75
+ @statement[/^p\./] and not is_callback?
72
76
  end
73
77
  def is_enum?
74
- @type[/^enum/]
78
+ @statement[/^enum/]
75
79
  end
76
80
  def is_array?
77
- @decl and @decl[/\w+\(\d+\)/]
81
+ @statement and @statement[/\w+\(\d+\)/]
78
82
  end
79
83
  def is_struct?
80
- @type[/^struct/]
84
+ @statement[/^struct/]
81
85
  end
82
86
  def is_union?
83
- @type[/^union/]
87
+ @statement[/^union/]
84
88
  end
85
89
  def is_constant?
86
- @type[/^q\(const\)/]
90
+ @statement[/^q\(const\)/]
91
+ end
92
+ def is_callback?
93
+ @statement[/^p.f\(/]
87
94
  end
88
95
  def native
89
96
  if is_native?
90
- @type = Generator::TYPES[@type]
97
+ @statement = Generator::TYPES[@statement]
91
98
  get_type
92
99
  end
93
100
  end
94
101
  def constant
95
102
  if is_constant?
96
- @type = @type.scan(/^q\(const\)\.(.+)/).flatten[0]
103
+ @statement = @statement.scan(/^q\(const\)\.(.+)/).flatten[0]
97
104
  get_type
98
105
  end
99
106
  end
100
107
  def pointer
101
108
  if is_pointer?
102
- if @type[/char/]
103
- @type = ':string'
104
- @decl.gsub!(/p./, '')
109
+ if @statement[/char/] and @statement.scan(/p\./).size == 1
110
+ @statement = ':string'
111
+ # @decl.gsub!(/p\./, '')
105
112
  get_type
106
113
  else
107
114
  return ':pointer'
@@ -110,58 +117,62 @@ module FFI
110
117
  end
111
118
  def array
112
119
  if is_array?
113
- num = @decl.scan(/\w+\((\d+)\)/).flatten[0]
114
- @decl.gsub!(/\w+\(\d+\)/, '')
120
+ num = @statement.scan(/\w+\((\d+)\)/).flatten[0]
121
+ @statement.gsub!(/\w+\(\d+\)\./, '')
115
122
  "[#{get_type}, #{num}]"
116
123
  end
117
124
  end
118
125
  def struct
119
126
  if is_struct?
120
- @type = Structure.camelcase(@type.scan(/^struct\s(\w+)/).flatten[0])
127
+ @statement = Structure.camelcase(@statement.scan(/^struct\s(\w+)/).flatten[0])
121
128
  get_type
122
129
  end
123
130
  end
124
131
  def union
125
132
  if is_union?
126
- @type = Union.camelcase(@type.scan(/^union\s(\w+)/).flatten[0])
133
+ @statement = Union.camelcase(@statement.scan(/^union\s(\w+)/).flatten[0])
127
134
  get_type
128
135
  end
129
136
  end
130
137
  def enum
131
138
  if is_enum?
132
- @type = Generator::TYPES['int']
139
+ @statement = Generator::TYPES['int']
133
140
  get_type
134
141
  end
135
142
  end
143
+ def callback
144
+ Callback.new(:node => @node).to_s if is_callback?
145
+ end
136
146
  def typedef
137
- if Generator.typedefs.has_key?(@type)
138
- @type = Generator.typedefs[@type]
147
+ if Generator.typedefs.has_key?(@statement)
148
+ @statement = Generator.typedefs[@statement]
139
149
  get_type
140
150
  end
141
151
  end
142
152
  def get_type
143
- constant || pointer || enum || typedef || native || struct || union || array || "#{@type}"
153
+ constant || pointer || enum || typedef || native || struct || union || array || callback || "#{@statement}"
144
154
  end
145
155
  end
146
156
  class Typedef < Type
147
- attr_reader :symname, :type
148
- def initialize(node, indent = 0)
157
+ attr_reader :symname, :statement
158
+ def initialize(params = { })
149
159
  super
150
160
  @symname = get_attr('name')
151
- @type = is_pointer? ? ':pointer' : get_attr('type')
161
+ # @type = is_pointer? ? ':pointer' : get_attr('type')
162
+ # p @statement
152
163
  end
153
164
  end
154
165
  class Constant < Node
155
- def initialize(node, indent = 0)
166
+ def initialize(params = { })
156
167
  super
157
168
  @name, @value = get_attr('sym_name'), get_attr('value')
158
169
  end
159
170
  def to_s
160
- @indent + "#{@name} = #{@value}"
171
+ @indent_str + "#{@name} = #{@value}"
161
172
  end
162
173
  end
163
174
  class Enum < Node
164
- def initialize(node, indent = 0)
175
+ def initialize(params = { })
165
176
  super
166
177
  eval_items
167
178
  end
@@ -172,7 +183,7 @@ module FFI
172
183
  end
173
184
  private
174
185
  def assignment_str(name, value)
175
- @indent + "#{name} = #{value}"
186
+ @indent_str + "#{name} = #{value}"
176
187
  end
177
188
  def eval_expr(expr)
178
189
  if expr.include?('+')
@@ -184,7 +195,7 @@ module FFI
184
195
  def eval_items
185
196
  @items = {}
186
197
  get_items.each do |i|
187
- node = Node.new(i)
198
+ node = Node.new(:node => i)
188
199
  @items[node.get_attr('name')] = node.get_attr('enumvalueex') ? eval_expr(node.get_attr('enumvalueex')) : node.get_attr('enumvalue')
189
200
  end
190
201
  @items
@@ -197,49 +208,70 @@ module FFI
197
208
  def self.camelcase(name)
198
209
  name.gsub(/^\w|\_\w/).each {|c| c.upcase }.delete('_')
199
210
  end
200
- def initialize(node, indent = 0)
211
+ def initialize(params = { })
201
212
  super
202
213
  @name = self.class.camelcase(@symname)
203
214
  end
204
215
  def to_s
205
216
  fields_str = fields.inject("") do |str, f|
206
- str << @indent + ' ' * 9 << f.join(', ') << ",\n"
217
+ str << @indent_str + ' ' * 9 << f.join(', ') << ",\n"
207
218
  end
208
- code = klass_string + @indent + " layout(\n" + fields_str.chomp.chomp(',') + "\n" + @indent + " )\n" + @indent + "end\n"
219
+ code = klass_string + @indent_str + " layout(\n" + fields_str.chomp.chomp(',') + "\n" + @indent_str + " )\n" + @indent_str + "end\n"
209
220
  end
210
221
  private
211
222
  def klass_string
212
- @indent + "class #{@name} < FFI::Struct\n"
223
+ @indent_str + "class #{@name} < FFI::Struct\n"
213
224
  end
214
225
  def fields
215
226
  (@node / 'cdecl').inject([]) do |array, field|
216
- array << [":#{Node.new(field).symname}", "#{Type.new(field)}"]
227
+ array << [":#{Node.new(:node => field).symname}", "#{Type.new(:node => field)}"]
217
228
  end
218
229
  end
219
230
  end
220
231
  class Union < Structure
221
232
  private
222
233
  def klass_string
223
- @indent + "class #{@name} < FFI::Union\n"
234
+ @indent_str + "class #{@name} < FFI::Union\n"
224
235
  end
225
236
  end
226
- class Function < Node
237
+ class Function < Type
227
238
  class Argument < Type
228
- def initialize(node, indent = 0)
229
- super
230
- @decl = @type
239
+ def to_s
240
+ get_attr('type') == 'void' ? nil : super
231
241
  end
232
242
  end
243
+ def initialize(params = { })
244
+ super
245
+ @type = get_attr('type')
246
+ end
233
247
  def to_s
234
248
  params = get_params(@node).inject([]) do |array, node|
235
- array << Argument.new(node).to_s
249
+ array << Argument.new(:node => node).to_s
236
250
  end.collect { |p| "#{p}" }
237
- @indent + "attach_function :#{@symname}, [ #{params.join(', ')} ], #{Type.new(@node).to_s}"
251
+ @indent_str + "attach_function :#{@symname}, [ #{params.join(', ')} ], #{get_rvalue}"
238
252
  end
239
253
  private
240
254
  def get_params(node)
241
255
  parmlist = node / './attributelist/parmlist/parm'
242
256
  end
257
+ def get_rvalue
258
+ Type.new(:node => @node, :statement => @statement.scan(/^f\(.*\)\.(.+)/).flatten[0]).to_s
259
+ end
260
+ end
261
+ class Callback < Type
262
+ def to_s
263
+ params = get_params.inject([]) do |array, type|
264
+ array << (type == 'void' ? '' : Type.new(:statement => type).to_s)
265
+ end
266
+ @indent_str + "callback(:#{@symname}, [ #{params.join(', ')} ], #{get_rtype})"
267
+ end
268
+ private
269
+ def get_params
270
+ @statement.scan(/p.f\((.*)\)/).flatten[0].split(',')
271
+ end
272
+ def get_rtype
273
+ Type.new(:statement => @statement.scan(/\)\.(\w+)/).flatten[0]).to_s
274
+ end
243
275
  end
244
276
  class Parser
245
277
  @indent = 2
@@ -269,28 +301,36 @@ module FFI
269
301
  def is_typedef?(node)
270
302
  node.name == 'cdecl' and (node / "./attributelist/attribute[@name='kind']").first['value'] == 'typedef'
271
303
  end
304
+ def is_callback?(node)
305
+ (node / "./attributelist/attribute[@name='decl']").first['value'] =~ /^p\.f\(/
306
+ end
272
307
  def generate(node)
273
308
  result = ""
274
309
  node.traverse do |node|
275
310
  if is_constant?(node)
276
- result << Constant.new(node, @indent).to_s << "\n"
311
+ result << Constant.new(:node => node, :indent => @indent).to_s << "\n"
277
312
  elsif is_typedef?(node)
278
- typedef = Typedef.new(node)
279
- Generator.add_type(typedef.symname, typedef.type)
313
+ typedef = Typedef.new(:node => node)
314
+ Generator.add_type(typedef.symname, typedef.statement)
315
+ if is_callback?(node)
316
+ cb = Callback.new(:node => node, :indent => @indent).to_s << "\n"
317
+ Generator.add_type(typedef.symname, ":#{typedef.symname}")
318
+ result << cb.to_s
319
+ end
280
320
  elsif is_enum?(node)
281
- e = Enum.new(node, @indent)
321
+ e = Enum.new(:node => node, :indent => @indent)
282
322
  Generator.add_type(e.symname, Generator::TYPES['int'])
283
323
  result << e.to_s << "\n"
284
324
  elsif is_struct?(node)
285
- s = Structure.new(node, @indent)
325
+ s = Structure.new(:node => node, :indent => @indent)
286
326
  Generator.add_type(s.symname, "struct #{s.symname}")
287
327
  result << s.to_s
288
328
  elsif is_union?(node)
289
- s = Union.new(node, @indent)
329
+ s = Union.new(:node => node, :indent => @indent)
290
330
  Generator.add_type(s.symname, "union #{s.symname}")
291
331
  result << s.to_s
292
332
  elsif is_function_decl?(node)
293
- result << Function.new(node, @indent).to_s << "\n"
333
+ result << Function.new(:node => node, :indent => @indent).to_s << "\n"
294
334
  elsif node.name == 'insert' and not is_insert_runtime?(node)
295
335
  result << get_verbatim(node)
296
336
  end
@@ -42,12 +42,13 @@ module TestLib
42
42
  :c, :char
43
43
  )
44
44
  end
45
+ callback(:cb, [ :string, :string ], :void)
45
46
  class TestStruct2 < FFI::Struct
46
47
  layout(
47
48
  :s, TestStruct,
48
49
  :s_3, TestStruct3,
49
50
  :e, :int,
50
- :func, :pointer,
51
+ :func, :cb,
51
52
  :u, UnionT
52
53
  )
53
54
  end
@@ -68,7 +69,7 @@ describe Generator::Constant do
68
69
  @node = generate_xml_wrap_from('constants')
69
70
  end
70
71
  it 'should return a ruby constant assignment' do
71
- Generator::Constant.new(@node / 'constant').to_s.should == "CONST_1 = 0x10"
72
+ Generator::Constant.new(:node => @node / 'constant').to_s.should == "CONST_1 = 0x10"
72
73
  end
73
74
  end
74
75
 
@@ -77,19 +78,19 @@ describe Generator::Enum do
77
78
  @node = generate_xml_wrap_from('enums')
78
79
  end
79
80
  it 'should generate constants' do
80
- Generator::Enum.new((@node / 'enum')[0]).to_s.should == <<EOE
81
+ Generator::Enum.new(:node => (@node / 'enum')[0]).to_s.should == <<EOE
81
82
  ENUM_1 = 0
82
83
  ENUM_2 = 1
83
84
  ENUM_3 = 2
84
85
  EOE
85
86
  end
86
87
  it 'should generate constants starting from the latest assignment' do
87
- Generator::Enum.new((@node / 'enum')[1]).to_s.should == <<EOE
88
+ Generator::Enum.new(:node => (@node / 'enum')[1]).to_s.should == <<EOE
88
89
  ENUM_21 = 2
89
90
  ENUM_22 = 3
90
91
  ENUM_23 = 4
91
92
  EOE
92
- Generator::Enum.new((@node / 'enum')[2]).to_s.should == <<EOE
93
+ Generator::Enum.new(:node => (@node / 'enum')[2]).to_s.should == <<EOE
93
94
  ENUM_31 = 0
94
95
  ENUM_32 = 5
95
96
  ENUM_33 = 6
@@ -103,31 +104,32 @@ describe Generator::Type do
103
104
  @node = generate_xml_wrap_from('types')
104
105
  end
105
106
  it 'should generate string type' do
106
- Generator::Type.new((@node / 'cdecl')[0]).to_s.should == ':string'
107
+ Generator::Type.new(:node => (@node / 'cdecl')[0]).to_s.should == ':string'
107
108
  end
108
109
  it 'should generate pointer type' do
109
- Generator::Type.new((@node / 'cdecl')[1]).to_s.should == ':pointer'
110
+ Generator::Type.new(:node => (@node / 'cdecl')[1]).to_s.should == ':pointer'
111
+ Generator::Type.new(:node => (@node / 'cdecl')[2]).to_s.should == ':pointer'
110
112
  end
111
113
  it 'should generate array type' do
112
- Generator::Type.new((@node / 'cdecl')[2]).to_s.should == '[:int, 5]'
113
- Generator::Type.new((@node / 'cdecl')[3]).to_s.should == '[:string, 5]'
114
+ Generator::Type.new(:node => (@node / 'cdecl')[3]).to_s.should == '[:int, 5]'
115
+ Generator::Type.new(:node => (@node / 'cdecl')[4]).to_s.should == '[:string, 5]'
114
116
  end
115
117
  it 'should generate struct type' do
116
- Generator::Type.new((@node / 'cdecl')[5]).to_s.should == 'TestStruct'
118
+ Generator::Type.new(:node => (@node / 'cdecl')[6]).to_s.should == 'TestStruct'
117
119
  end
118
120
  it 'should generate struct array type' do
119
- Generator::Type.new((@node / 'cdecl')[6]).to_s.should == '[TestStruct, 5]'
121
+ Generator::Type.new(:node => (@node / 'cdecl')[7]).to_s.should == '[TestStruct, 5]'
120
122
  end
121
123
  it 'should generate enum array type' do
122
- Generator::Type.new((@node / 'cdecl')[7]).to_s.should == '[:int, 5]'
124
+ Generator::Type.new(:node => (@node / 'cdecl')[8]).to_s.should == '[:int, 5]'
123
125
  end
124
126
  it 'should generate const type' do
125
- Generator::Type.new((@node / 'cdecl')[8]).to_s.should == ':int'
126
- Generator::Type.new((@node / 'cdecl')[9]).to_s.should == ':string'
127
+ Generator::Type.new(:node => (@node / 'cdecl')[9]).to_s.should == ':int'
128
+ Generator::Type.new(:node => (@node / 'cdecl')[10]).to_s.should == ':string'
127
129
  end
128
130
  Generator::TYPES.sort.each_with_index do |type, i|
129
131
  it "should generate #{type[0]} type" do
130
- Generator::Type.new((@node / 'cdecl')[i + 10]).to_s.should == type[1]
132
+ Generator::Type.new(:node => (@node / 'cdecl')[i + 11]).to_s.should == type[1]
131
133
  end
132
134
  end
133
135
  end
@@ -138,34 +140,43 @@ describe Generator::Function do
138
140
  @node = generate_xml_wrap_from('functions')
139
141
  end
140
142
  it 'should return a properly generated attach_method' do
141
- Generator::Function.new((@node / 'cdecl')[0]).to_s.should == "attach_function :func_1, [ :char, :int ], :int"
143
+ Generator::Function.new(:node => (@node / 'cdecl')[0]).to_s.should == "attach_function :func_1, [ :char, :int ], :int"
142
144
  end
143
145
  it 'should properly generate pointer arguments' do
144
- Generator::Function.new((@node / 'cdecl')[1]).to_s.should == "attach_function :func_2, [ :pointer, :pointer ], :uint"
146
+ Generator::Function.new(:node => (@node / 'cdecl')[1]).to_s.should == "attach_function :func_2, [ :pointer, :pointer, :pointer ], :uint"
145
147
  end
146
148
  it 'should properly generate string arguments' do
147
- Generator::Function.new((@node / 'cdecl')[2]).to_s.should == "attach_function :func_3, [ :string ], :void"
149
+ Generator::Function.new(:node => (@node / 'cdecl')[2]).to_s.should == "attach_function :func_3, [ :string ], :void"
148
150
  end
149
151
  it 'should properly generate return type' do
150
- Generator::Function.new((@node / 'cdecl')[3]).to_s.should == "attach_function :func_4, [ :int ], :string"
152
+ Generator::Function.new(:node => (@node / 'cdecl')[3]).to_s.should == "attach_function :func_4, [ :int ], :string"
151
153
  end
152
154
  it 'should properly generate void return type' do
153
- Generator::Function.new((@node / 'cdecl')[4]).to_s.should == "attach_function :func_5, [ ], :void"
155
+ Generator::Function.new(:node => (@node / 'cdecl')[4]).to_s.should == "attach_function :func_5, [ ], :void"
154
156
  end
155
157
  it 'should properly generate pointer of pointer arguments' do
156
- Generator::Function.new((@node / 'cdecl')[5]).to_s.should == "attach_function :func_6, [ :pointer ], :void"
158
+ Generator::Function.new(:node => (@node / 'cdecl')[5]).to_s.should == "attach_function :func_6, [ :pointer ], :void"
157
159
  end
158
160
  it 'should properly generate enum arguments' do
159
- Generator::Function.new((@node / 'cdecl')[6]).to_s.should == "attach_function :func_7, [ :int ], :void"
161
+ Generator::Function.new(:node => (@node / 'cdecl')[6]).to_s.should == "attach_function :func_7, [ :int ], :void"
160
162
  end
161
163
  it 'should properly generate enum return type' do
162
- Generator::Function.new((@node / 'cdecl')[7]).to_s.should == "attach_function :func_8, [ ], :int"
164
+ Generator::Function.new(:node => (@node / 'cdecl')[7]).to_s.should == "attach_function :func_8, [ ], :int"
163
165
  end
164
166
  it 'should properly generate struct arguments' do
165
- Generator::Function.new((@node / 'cdecl')[9]).to_s.should == "attach_function :func_9, [ TestStruct ], :void"
167
+ Generator::Function.new(:node => (@node / 'cdecl')[9]).to_s.should == "attach_function :func_9, [ TestStruct ], :void"
166
168
  end
167
169
  it 'should properly generate struct return type' do
168
- Generator::Function.new((@node / 'cdecl')[10]).to_s.should == "attach_function :func_10, [ ], TestStruct"
170
+ Generator::Function.new(:node => (@node / 'cdecl')[10]).to_s.should == "attach_function :func_10, [ ], TestStruct"
171
+ end
172
+ it 'should properly generate a function with no parameters' do
173
+ Generator::Function.new(:node => (@node / 'cdecl')[11]).to_s.should == "attach_function :func_11, [ ], :void"
174
+ end
175
+ it 'should properly generate a function that takes a callback as argument' do
176
+ Generator::Function.new(:node => (@node / 'cdecl')[12]).to_s.should == "attach_function :func_12, [ callback(:callback, [ :float ], :void) ], :void"
177
+ Generator::Function.new(:node => (@node / 'cdecl')[13]).to_s.should == "attach_function :func_13, [ callback(:callback, [ :double, :float ], :int) ], :void"
178
+ Generator::Function.new(:node => (@node / 'cdecl')[14]).to_s.should == "attach_function :func_14, [ callback(:callback, [ :string ], :void) ], :void"
179
+ Generator::Function.new(:node => (@node / 'cdecl')[15]).to_s.should == "attach_function :func_15, [ callback(:callback, [ ], :void) ], :void"
169
180
  end
170
181
  end
171
182
 
@@ -175,7 +186,7 @@ describe Generator::Structure do
175
186
  @node = generate_xml_wrap_from('structs')
176
187
  end
177
188
  it 'should properly generate the layout of a FFI::Struct class' do
178
- Generator::Structure.new((@node / 'class')[0]).to_s.should == <<EOC
189
+ Generator::Structure.new(:node => (@node / 'class')[0]).to_s.should == <<EOC
179
190
  class TestStruct1 < FFI::Struct
180
191
  layout(
181
192
  :i, :int,
@@ -188,7 +199,7 @@ EOC
188
199
 
189
200
  end
190
201
  it 'should properly generate the layout of a FFI::Struct containing pointer field' do
191
- Generator::Structure.new((@node / 'class')[1]).to_s.should == <<EOC
202
+ Generator::Structure.new(:node => (@node / 'class')[1]).to_s.should == <<EOC
192
203
  class TestStruct2 < FFI::Struct
193
204
  layout(
194
205
  :ptr, :pointer
@@ -197,7 +208,7 @@ end
197
208
  EOC
198
209
  end
199
210
  it 'should properly generate the layout of a FFI::Struct containing array field' do
200
- Generator::Structure.new((@node / 'class')[2]).to_s.should == <<EOC
211
+ Generator::Structure.new(:node => (@node / 'class')[2]).to_s.should == <<EOC
201
212
  class TestStruct3 < FFI::Struct
202
213
  layout(
203
214
  :c, [:char, 5]
@@ -207,7 +218,7 @@ EOC
207
218
 
208
219
  end
209
220
  it 'should properly generate the layout of a FFI::Struct containing array field' do
210
- Generator::Structure.new((@node / 'class')[3]).to_s.should == <<EOC
221
+ Generator::Structure.new(:node => (@node / 'class')[3]).to_s.should == <<EOC
211
222
  class TestStruct4 < FFI::Struct
212
223
  layout(
213
224
  :s, [TestStruct3, 5]
@@ -224,7 +235,7 @@ describe Generator::Union do
224
235
  @node = generate_xml_wrap_from('unions')
225
236
  end
226
237
  it 'should properly generate the layout of a FFI::Union class' do
227
- Generator::Union.new((@node / 'class')[0]).to_s.should == <<EOC
238
+ Generator::Union.new(:node => (@node / 'class')[0]).to_s.should == <<EOC
228
239
  class UnionT < FFI::Union
229
240
  layout(
230
241
  :c, :char,
@@ -1,22 +1,24 @@
1
1
  %module function_testlib
2
2
 
3
3
  int func_1(char c, int i);
4
- unsigned int func_2(int* p1, int* p2);
4
+ unsigned int func_2(int* p1, int* p2, char** p3);
5
5
  void func_3(char* str);
6
6
  char *func_4(int i);
7
7
  extern void func_5();
8
8
  void func_6(void** ptr);
9
9
  void func_7(enum e e1);
10
-
11
10
  enum e { E_1, E_2 };
12
-
13
11
  enum e func_8();
14
-
15
12
  struct test_struct {
16
13
  char c;
17
14
  };
18
-
19
15
  void func_9(struct test_struct s);
20
16
  struct test_struct func_10();
17
+ void func_11(void);
18
+ void func_12(void (*callback)(float));
19
+ void func_13(int (*callback)(double, float));
20
+ void func_14(void (*callback)(char* str));
21
+ void func_15(void (*callback)(void));
22
+
21
23
 
22
24
 
@@ -9,7 +9,6 @@ module TestLib
9
9
  #define CONST_2 0x20
10
10
 
11
11
  typedef unsigned char byte;
12
- typedef void (*PFI)(char*, char*);
13
12
  typedef enum e_1 {
14
13
  ENUM_1, ENUM_2, ENUM_3
15
14
  } enum_t;
@@ -29,11 +28,13 @@ typedef struct {
29
28
  char c;
30
29
  } test_struct_3;
31
30
 
31
+ typedef void (*cb)(char*, char*);
32
+
32
33
  struct test_struct_2 {
33
34
  struct test_struct s;
34
35
  test_struct_3 s_3;
35
36
  enum_t e;
36
- PFI func;
37
+ cb func;
37
38
  union_t u;
38
39
  };
39
40
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  char *string;
4
4
  void *ptr;
5
+ char **ptr_2;
5
6
 
6
7
  int array[5];
7
8
  char* ptr_array[5];
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: remogatto-ffi-generator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrea Fazzi
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-02-16 00:00:00 -08:00
12
+ date: 2009-03-05 00:00:00 -08:00
13
13
  default_executable: ffi-gen
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -30,17 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 1.1.1
34
- version:
35
- - !ruby/object:Gem::Dependency
36
- name: bones
37
- type: :development
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- version: 2.4.0
33
+ version: 1.2.1
44
34
  version:
45
35
  description: ffi-generator is a ruby-ffi wrapper code generator based on SWIG interfaces. ffi-generator is able to traverse a XML parse tree file generated by SWIG and to produce a ruby file with ruby-ffi wrapper code inside. ffi-generator is shipped with a command line tool (ffi-gen) and a rake task that automates the code generation process. ffi-generator XML capabilities are provided by nokogiri.
46
36
  email: andrea.fazzi@alcacoop.it
@@ -65,6 +55,7 @@ files:
65
55
  - examples/generated/wiiuse_wrap.xml
66
56
  - examples/interfaces/libc.i
67
57
  - examples/interfaces/wiiuse.i
58
+ - ffi-generator.gemspec
68
59
  - lib/ffi-generator.rb
69
60
  - lib/generator/application.rb
70
61
  - lib/generator/generator.rb