ffi-swig-generator 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/.hg/branch.cache +2 -0
  2. data/.hg/dirstate +0 -0
  3. data/.hg/store/00changelog.i +0 -0
  4. data/.hg/store/00manifest.i +0 -0
  5. data/.hg/store/data/.hgignore.i +0 -0
  6. data/.hg/store/data/.hgtags.i +0 -0
  7. data/.hg/store/data/_history.txt.i +0 -0
  8. data/.hg/store/data/_r_e_a_d_m_e.rdoc.i +0 -0
  9. data/.hg/store/data/_rakefile.i +0 -0
  10. data/.hg/store/data/cucumber.yml.i +0 -0
  11. data/.hg/store/data/examples/_rakefile.i +0 -0
  12. data/.hg/store/data/features/generate.feature.i +0 -0
  13. data/.hg/store/data/features/step__definitions/generate.rb.i +0 -0
  14. data/.hg/store/data/features/support/env.rb.i +0 -0
  15. data/.hg/store/data/features/support/results.rb.i +0 -0
  16. data/.hg/store/data/features/support/templates.rb.i +0 -0
  17. data/.hg/store/data/lib/ffi-swig-generator.rb.i +0 -0
  18. data/.hg/store/data/lib/generator/application.rb.i +0 -0
  19. data/.hg/store/data/lib/generator/constant.rb.i +0 -0
  20. data/.hg/store/data/lib/generator/enum.rb.i +0 -0
  21. data/.hg/store/data/lib/generator/function.rb.i +0 -0
  22. data/.hg/store/data/lib/generator/generator.rb.i +0 -0
  23. data/.hg/store/data/lib/generator/generatortask.rb.i +0 -0
  24. data/.hg/store/data/lib/generator/logger.rb.i +0 -0
  25. data/.hg/store/data/lib/generator/node.rb.i +0 -0
  26. data/.hg/store/data/lib/generator/parser.rb.i +0 -0
  27. data/.hg/store/data/lib/generator/struct.rb.i +0 -0
  28. data/.hg/store/data/lib/generator/type.rb.i +0 -0
  29. data/.hg/store/data/lib/generator/types.rb.i +0 -0
  30. data/.hg/store/data/spec/generator/constant__spec.rb.i +0 -0
  31. data/.hg/store/data/spec/generator/enum__spec.rb.i +0 -0
  32. data/.hg/store/data/spec/generator/function__spec.rb.i +0 -0
  33. data/.hg/store/data/spec/generator/generator__spec.rb.i +0 -0
  34. data/.hg/store/data/spec/generator/node__spec.rb.i +0 -0
  35. data/.hg/store/data/spec/generator/parser__spec.rb.i +0 -0
  36. data/.hg/store/data/spec/generator/struct__spec.rb.i +0 -0
  37. data/.hg/store/data/spec/generator/swig/constants.i.i +0 -0
  38. data/.hg/store/data/spec/generator/swig/functions.i.i +0 -0
  39. data/.hg/store/data/spec/generator/swig/testlib.i.i +0 -0
  40. data/.hg/store/data/spec/generator/swig/typedefs.i.i +0 -0
  41. data/.hg/store/data/spec/generator/swig/types.i.i +0 -0
  42. data/.hg/store/data/spec/generator/type__spec.rb.i +0 -0
  43. data/.hg/store/data/spec/spec__helper.rb.i +0 -0
  44. data/.hg/store/data/tasks/cucumber.rake.i +0 -0
  45. data/.hg/store/undo +0 -0
  46. data/.hg/undo.dirstate +0 -0
  47. data/.hgignore +3 -0
  48. data/.hgtags +1 -0
  49. data/History.txt +22 -2
  50. data/README.rdoc +26 -22
  51. data/Rakefile +2 -3
  52. data/cucumber.yml +1 -0
  53. data/examples/Rakefile +5 -3
  54. data/examples/generated/libc_wrap.rb +18 -0
  55. data/examples/generated/libc_wrap.xml +597 -0
  56. data/examples/generated/wiiuse_wrap.rb +322 -0
  57. data/examples/generated/wiiuse_wrap.xml +9025 -0
  58. data/features/generate.feature +45 -0
  59. data/features/step_definitions/generate.rb +32 -0
  60. data/features/support/env.rb +4 -0
  61. data/features/support/templates.rb +381 -0
  62. data/lib/ffi-swig-generator.rb +1 -1
  63. data/lib/generator/application.rb +1 -1
  64. data/lib/generator/constant.rb +24 -0
  65. data/lib/generator/enum.rb +38 -0
  66. data/lib/generator/function.rb +71 -0
  67. data/lib/generator/generatortask.rb +21 -9
  68. data/lib/generator/logger.rb +29 -0
  69. data/lib/generator/node.rb +19 -0
  70. data/lib/generator/parser.rb +168 -0
  71. data/lib/generator/struct.rb +76 -0
  72. data/lib/generator/type.rb +128 -0
  73. data/lib/generator/types.rb +36 -0
  74. data/spec/generator/constant_spec.rb +17 -0
  75. data/spec/generator/enum_spec.rb +29 -0
  76. data/spec/generator/function_spec.rb +66 -0
  77. data/spec/generator/parser_spec.rb +250 -0
  78. data/spec/generator/struct_spec.rb +77 -0
  79. data/spec/generator/swig/constants.i +5 -0
  80. data/spec/generator/swig/functions.i +8 -0
  81. data/spec/generator/swig/testlib.i +42 -0
  82. data/spec/generator/swig/typedefs.i +1 -0
  83. data/spec/generator/swig/types.i +1 -0
  84. data/spec/generator/type_spec.rb +38 -0
  85. data/spec/spec_helper.rb +6 -0
  86. data/tasks/cucumber.rake +8 -0
  87. metadata +58 -18
  88. data/lib/generator/generator.rb +0 -344
  89. data/spec/generator/generator_spec.rb +0 -248
@@ -0,0 +1,45 @@
1
+ Feature: Generate FFI glue code from SWIG interface.
2
+
3
+ In order to generate ruby-ffi glue code.
4
+ As a developer of ruby-ffi bindings.
5
+ I want the generator to automagically produce code for me.
6
+
7
+ Scenario: Generate code using default configuration
8
+ Given we are in a project directory
9
+ And the project directory is configured for the 'Scenario1'
10
+ When rake task 'ffi:generate' is invoked
11
+ Then rake task 'ffi:generate' succeeded
12
+ And the file 'generated/interface_wrap.rb' is created
13
+ And the file 'generated/interface_wrap.xml' is created
14
+ And the file 'generated/interface_wrap.rb' contains ffi glue code
15
+ And the tmp directory is removed
16
+
17
+ Scenario: Generate code using a configuration hash
18
+ Given we are in a project directory
19
+ And the project directory is configured for the 'Scenario2'
20
+ When rake task 'ffi:generate' is invoked
21
+ Then rake task 'ffi:generate' succeeded
22
+ And the file 'generated/interface_wrap.rb' is created
23
+ And the file 'generated/interface_wrap.xml' is created
24
+ And the file 'generated/interface_wrap.rb' contains ffi glue code
25
+ And the tmp directory is removed
26
+
27
+ Scenario: Generate code using a configuration block
28
+ Given we are in a project directory
29
+ And the project directory is configured for the 'Scenario3'
30
+ When rake task 'ffi:generate' is invoked
31
+ Then rake task 'ffi:generate' succeeded
32
+ And the file 'generated/interface_wrap.rb' is created
33
+ And the file 'generated/interface_wrap.xml' is created
34
+ And the file 'generated/interface_wrap.rb' contains ffi glue code
35
+ And the tmp directory is removed
36
+
37
+ Scenario: Generate code using a configuration file
38
+ Given we are in a project directory
39
+ And the project directory is configured for the 'Scenario4'
40
+ When rake task 'ffi:generate' is invoked
41
+ Then rake task 'ffi:generate' succeeded
42
+ And the file 'generated/interface_wrap.rb' is created
43
+ And the file 'generated/interface_wrap.xml' is created
44
+ And the file 'generated/interface_wrap.rb' contains ffi glue code
45
+ And the tmp directory is removed
@@ -0,0 +1,32 @@
1
+ Given /^we are in a project directory$/ do
2
+ FileUtils.mkdir_p('tmp')
3
+ Dir.chdir('tmp')
4
+ end
5
+
6
+ Given /^the project directory is configured for the '(.+)'$/ do |mod|
7
+ @scenario = eval(mod)
8
+ @scenario.generate
9
+ end
10
+
11
+ When /^rake task 'ffi:generate' is invoked$/ do
12
+ @output = `rake ffi:generate 2>&1`
13
+ @result = $?.success?
14
+ end
15
+
16
+ Then /^rake task 'ffi:generate' succeeded$/ do
17
+ @result.should be_true
18
+ end
19
+
20
+ Then /^the file '(.+)' is created/ do |fn|
21
+ File.exists?(fn).should be_true
22
+ end
23
+
24
+ Then /^the file '(.+)' contains ffi glue code$/ do |fn|
25
+ File.read(fn).should == @scenario.result_template
26
+ end
27
+
28
+ Then /^the tmp directory is removed$/ do
29
+ Dir.chdir('..')
30
+ FileUtils.rm_rf 'tmp'
31
+ File.exists?('tmp').should be_false
32
+ end
@@ -0,0 +1,4 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ ROOT_PATH = File.expand_path(File.join(File.dirname(__FILE__), '../..'))
@@ -0,0 +1,381 @@
1
+ class Scenario1
2
+
3
+ class << self
4
+
5
+ def interface_dir
6
+ '.'
7
+ end
8
+
9
+ def create_file(fn, &blk)
10
+ File.open(fn, 'w') do |file|
11
+ yield file
12
+ end
13
+ end
14
+
15
+ def generate
16
+ FileUtils.mkdir interface_dir unless File.exists?(interface_dir)
17
+ create_file(File.join(interface_dir, 'interface.i')) { |file| file << interface_template }
18
+ create_file('Rakefile') { |file| file << rakefile_template }
19
+ end
20
+
21
+ def interface_template
22
+ <<-EOF
23
+ %module testlib
24
+
25
+ %{
26
+ module TestLib
27
+ extend FFI::Library
28
+ %}
29
+
30
+ #define CONST_1 0x10
31
+ #define CONST_2 0x20
32
+
33
+ typedef unsigned char byte;
34
+ typedef enum e_1 {
35
+ ENUM_1, ENUM_2, ENUM_3
36
+ } enum_t;
37
+
38
+ union union_t {
39
+ char c;
40
+ float f;
41
+ };
42
+
43
+ struct test_struct {
44
+ int i;
45
+ char c;
46
+ byte b;
47
+ };
48
+
49
+ struct CamelCaseStruct {
50
+ int i;
51
+ char c;
52
+ byte b;
53
+ };
54
+
55
+ typedef struct {
56
+ char c;
57
+ } test_struct_3;
58
+
59
+ typedef void (*cb)(char*, char*);
60
+ typedef void * (*cb_2)(char*, const char *);
61
+ typedef CamelCaseStruct (*cb_3)(char*, CamelCaseStruct);
62
+
63
+ struct test_struct_2 {
64
+ struct test_struct s;
65
+ CamelCaseStruct camel_case_struct;
66
+ test_struct_3 s_3;
67
+ enum_t e;
68
+ cb func;
69
+ union_t u;
70
+ cb callback;
71
+ void (*inline_callback)();
72
+ };
73
+
74
+ // struct with getter/setter method for strings and callbacks
75
+
76
+ struct _test_struct_4 {
77
+ char* string;
78
+ void (*inline_callback)();
79
+ };
80
+
81
+ struct test_struct_5 {
82
+ int i;
83
+ union {
84
+ struct {
85
+ int a;
86
+ int b;
87
+ } nested_struct_field_1;
88
+ struct {
89
+ int c;
90
+ int d;
91
+ } nested_struct_field_2;
92
+ struct {
93
+ int e;
94
+ int f;
95
+ } nested_struct_field_3;
96
+ union {
97
+ long l;
98
+ long long ll;
99
+ } union_field;
100
+ float f;
101
+ } big_union_field;
102
+ char c;
103
+ };
104
+
105
+ int get_int(struct test_struct* s);
106
+ char get_char(struct test_struct* s);
107
+ int func_with_enum(enum e_1 e);
108
+ int func_with_enum_2(enum_t e);
109
+ byte func_with_typedef();
110
+ %{
111
+ end
112
+ %}
113
+ EOF
114
+ end
115
+
116
+ def result_template
117
+ <<-EOF
118
+
119
+ module TestLib
120
+ extend FFI::Library
121
+ CONST_1 = 0x10
122
+ CONST_2 = 0x20
123
+ ENUM_1 = 0
124
+ ENUM_2 = 1
125
+ ENUM_3 = 2
126
+
127
+ class UnionT < FFI::Union
128
+ layout(
129
+ :c, :char,
130
+ :f, :float
131
+ )
132
+ end
133
+ class TestStruct < FFI::Struct
134
+ layout(
135
+ :i, :int,
136
+ :c, :char,
137
+ :b, :uchar
138
+ )
139
+ end
140
+ class CamelCaseStruct < FFI::Struct
141
+ layout(
142
+ :i, :int,
143
+ :c, :char,
144
+ :b, :uchar
145
+ )
146
+ end
147
+ class TestStruct3 < FFI::Struct
148
+ layout(
149
+ :c, :char
150
+ )
151
+ end
152
+ callback(:cb, [ :string, :string ], :void)
153
+ callback(:cb_2, [ :string, :string ], :pointer)
154
+ callback(:cb_3, [ :string, CamelCaseStruct ], CamelCaseStruct)
155
+ class TestStruct2 < FFI::Struct
156
+ layout(
157
+ :s, TestStruct,
158
+ :camel_case_struct, CamelCaseStruct,
159
+ :s_3, TestStruct3,
160
+ :e, :int,
161
+ :func, :cb,
162
+ :u, UnionT,
163
+ :callback, :cb,
164
+ :inline_callback, callback([ ], :void)
165
+ )
166
+ def func=(cb)
167
+ @func = cb
168
+ self[:func] = @func
169
+ end
170
+ def func
171
+ @func
172
+ end
173
+ def callback=(cb)
174
+ @callback = cb
175
+ self[:callback] = @callback
176
+ end
177
+ def callback
178
+ @callback
179
+ end
180
+ def inline_callback=(cb)
181
+ @inline_callback = cb
182
+ self[:inline_callback] = @inline_callback
183
+ end
184
+ def inline_callback
185
+ @inline_callback
186
+ end
187
+
188
+ end
189
+ class TestStruct4 < FFI::Struct
190
+ layout(
191
+ :string, :pointer,
192
+ :inline_callback, callback([ ], :void)
193
+ )
194
+ def string=(str)
195
+ @string = FFI::MemoryPointer.from_string(str)
196
+ self[:string] = @string
197
+ end
198
+ def string
199
+ @string.get_string(0)
200
+ end
201
+ def inline_callback=(cb)
202
+ @inline_callback = cb
203
+ self[:inline_callback] = @inline_callback
204
+ end
205
+ def inline_callback
206
+ @inline_callback
207
+ end
208
+
209
+ end
210
+ class TestStruct5BigUnionFieldNestedStructField1 < FFI::Struct
211
+ layout(
212
+ :a, :int,
213
+ :b, :int
214
+ )
215
+ end
216
+ class TestStruct5BigUnionFieldNestedStructField2 < FFI::Struct
217
+ layout(
218
+ :c, :int,
219
+ :d, :int
220
+ )
221
+ end
222
+ class TestStruct5BigUnionFieldNestedStructField3 < FFI::Struct
223
+ layout(
224
+ :e, :int,
225
+ :f, :int
226
+ )
227
+ end
228
+ class TestStruct5BigUnionFieldUnionField < FFI::Union
229
+ layout(
230
+ :l, :long,
231
+ :ll, :long_long
232
+ )
233
+ end
234
+ # FIXME: Nested structures are not correctly supported at the moment.
235
+ # Please check the order of the declarations in the structure below.
236
+ # class TestStruct5BigUnionField < FFI::Union
237
+ # layout(
238
+ # :f, :float,
239
+ # :union_field, TestStruct5BigUnionFieldUnionField,
240
+ # :nested_struct_field_3, TestStruct5BigUnionFieldNestedStructField3,
241
+ # :nested_struct_field_2, TestStruct5BigUnionFieldNestedStructField2,
242
+ # :nested_struct_field_1, TestStruct5BigUnionFieldNestedStructField1
243
+ # )
244
+ # end
245
+ # FIXME: Nested structures are not correctly supported at the moment.
246
+ # Please check the order of the declarations in the structure below.
247
+ # class TestStruct5 < FFI::Struct
248
+ # layout(
249
+ # :i, :int,
250
+ # :c, :char,
251
+ # :big_union_field, TestStruct5BigUnionField
252
+ # )
253
+ # end
254
+ attach_function :get_int, [ :pointer ], :int
255
+ attach_function :get_char, [ :pointer ], :char
256
+ attach_function :func_with_enum, [ :int ], :int
257
+ attach_function :func_with_enum_2, [ :int ], :int
258
+ attach_function :func_with_typedef, [ ], :uchar
259
+
260
+ end
261
+ EOF
262
+ end
263
+
264
+ def rakefile_template
265
+ <<-EOF
266
+ require '../lib/ffi-swig-generator'
267
+
268
+ FFI::Generator::Task.new
269
+ EOF
270
+ end
271
+
272
+ end
273
+
274
+ end
275
+
276
+ class Scenario2 < Scenario1
277
+
278
+ class << self
279
+
280
+ def interface_dir
281
+ 'interfaces'
282
+ end
283
+
284
+ def rakefile_template
285
+ <<-EOF
286
+ require 'rubygems'
287
+ require '../lib/ffi-swig-generator'
288
+
289
+ FFI::Generator::Task.new :input_fn => 'interfaces/*.i', :output_dir => 'generated/'
290
+
291
+ EOF
292
+ end
293
+
294
+ end
295
+
296
+ end
297
+
298
+ class Scenario3 < Scenario2
299
+
300
+ class << self
301
+
302
+ def rakefile_template
303
+ <<-EOF
304
+ require 'rubygems'
305
+ require '../lib/ffi-swig-generator'
306
+
307
+ FFI::Generator::Task.new do |task|
308
+ task.input_fn = 'interfaces/*.i'
309
+ task.output_dir = 'generated/'
310
+ end
311
+
312
+ EOF
313
+ end
314
+
315
+ end
316
+
317
+ end
318
+
319
+ class Scenario4 < Scenario3
320
+
321
+ class << self
322
+
323
+ def generate
324
+ super
325
+ create_file(File.join(interface_dir, 'interface.rb')) { |file| file << config_template }
326
+ end
327
+
328
+ def rakefile_template
329
+ <<-EOF
330
+ require 'rubygems'
331
+ require '../lib/ffi-swig-generator'
332
+
333
+ FFI::Generator::Task.new do |task|
334
+ task.input_fn = 'interfaces/*.i'
335
+ task.output_dir = 'generated/'
336
+ end
337
+
338
+ EOF
339
+ end
340
+
341
+ def interface_template
342
+ <<-EOF
343
+ %module my_interface
344
+
345
+ #define CONST_1 0xff1;
346
+ #define CONST_2 0Xff2;
347
+
348
+ typedef struct {
349
+ char a;
350
+ char b;
351
+ } my_struct_1;
352
+
353
+ typedef struct {
354
+ char c;
355
+ char d;
356
+ } my_struct_2;
357
+
358
+ EOF
359
+ end
360
+
361
+ def result_template
362
+ <<-EOF
363
+ CONST_1 = 0xff1
364
+ class MyStruct1 < FFI::Struct
365
+ layout(
366
+ :a, :char,
367
+ :b, :char
368
+ )
369
+ end
370
+ EOF
371
+ end
372
+
373
+ def config_template
374
+ <<-EOF
375
+ ignore 'my_struct_2', 'CONST_2'
376
+ EOF
377
+ end
378
+
379
+ end
380
+
381
+ end