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 +4 -0
- data/History.txt +8 -0
- data/README.rdoc +14 -6
- data/Rakefile +8 -3
- data/ffi-generator.gemspec +39 -0
- data/lib/ffi-generator.rb +1 -1
- data/lib/generator/generator.rb +96 -56
- data/spec/generator/generator_spec.rb +41 -30
- data/spec/generator/swig/functions.i +7 -5
- data/spec/generator/swig/testlib.i +3 -2
- data/spec/generator/swig/types.i +1 -0
- metadata +4 -13
data/.gitignore
CHANGED
data/History.txt
CHANGED
|
@@ -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
|
data/README.rdoc
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
data/lib/ffi-generator.rb
CHANGED
data/lib/generator/generator.rb
CHANGED
|
@@ -43,65 +43,72 @@ module FFI
|
|
|
43
43
|
end
|
|
44
44
|
class Node
|
|
45
45
|
attr_reader :symname
|
|
46
|
-
def initialize(
|
|
47
|
-
|
|
48
|
-
@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
|
-
|
|
53
|
-
|
|
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(
|
|
60
|
+
def initialize(params = { })
|
|
58
61
|
super
|
|
59
|
-
@
|
|
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?(@
|
|
72
|
+
Generator::TYPES.has_key?(@statement)
|
|
69
73
|
end
|
|
70
74
|
def is_pointer?
|
|
71
|
-
@
|
|
75
|
+
@statement[/^p\./] and not is_callback?
|
|
72
76
|
end
|
|
73
77
|
def is_enum?
|
|
74
|
-
@
|
|
78
|
+
@statement[/^enum/]
|
|
75
79
|
end
|
|
76
80
|
def is_array?
|
|
77
|
-
@
|
|
81
|
+
@statement and @statement[/\w+\(\d+\)/]
|
|
78
82
|
end
|
|
79
83
|
def is_struct?
|
|
80
|
-
@
|
|
84
|
+
@statement[/^struct/]
|
|
81
85
|
end
|
|
82
86
|
def is_union?
|
|
83
|
-
@
|
|
87
|
+
@statement[/^union/]
|
|
84
88
|
end
|
|
85
89
|
def is_constant?
|
|
86
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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 @
|
|
103
|
-
@
|
|
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 = @
|
|
114
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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
|
-
@
|
|
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?(@
|
|
138
|
-
@
|
|
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 || "#{@
|
|
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, :
|
|
148
|
-
def initialize(
|
|
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(
|
|
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
|
-
@
|
|
171
|
+
@indent_str + "#{@name} = #{@value}"
|
|
161
172
|
end
|
|
162
173
|
end
|
|
163
174
|
class Enum < Node
|
|
164
|
-
def initialize(
|
|
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
|
-
@
|
|
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(
|
|
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 << @
|
|
217
|
+
str << @indent_str + ' ' * 9 << f.join(', ') << ",\n"
|
|
207
218
|
end
|
|
208
|
-
code = klass_string + @
|
|
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
|
-
@
|
|
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
|
-
@
|
|
234
|
+
@indent_str + "class #{@name} < FFI::Union\n"
|
|
224
235
|
end
|
|
225
236
|
end
|
|
226
|
-
class Function <
|
|
237
|
+
class Function < Type
|
|
227
238
|
class Argument < Type
|
|
228
|
-
def
|
|
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
|
-
@
|
|
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.
|
|
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, :
|
|
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')[
|
|
113
|
-
Generator::Type.new((@node / 'cdecl')[
|
|
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')[
|
|
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')[
|
|
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')[
|
|
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')[
|
|
126
|
-
Generator::Type.new((@node / 'cdecl')[
|
|
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 +
|
|
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
|
-
|
|
37
|
+
cb func;
|
|
37
38
|
union_t u;
|
|
38
39
|
};
|
|
39
40
|
|
data/spec/generator/swig/types.i
CHANGED
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.
|
|
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-
|
|
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.
|
|
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
|