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,128 @@
1
+ module FFI
2
+ module Generator
3
+ require libpath('generator/node')
4
+ class Type < Node
5
+ attr_reader :full_decl
6
+ class Declaration
7
+ def initialize(declaration)
8
+ @full_decl = declaration
9
+ end
10
+ def is_native?
11
+ Generator::TYPES.has_key?(@full_decl)
12
+ end
13
+ def is_pointer?
14
+ @full_decl[/^p\./] and not is_inline_callback?
15
+ end
16
+ def is_enum?
17
+ @full_decl[/^enum/]
18
+ end
19
+ def is_array?
20
+ @full_decl and @full_decl[/\w+\(\d+\)/]
21
+ end
22
+ def is_struct?
23
+ @full_decl[/^struct/]
24
+ end
25
+ def is_union?
26
+ @full_decl[/^union/]
27
+ end
28
+ def is_constant?
29
+ @full_decl[/^q\(const\)/]
30
+ end
31
+ def is_volatile?
32
+ @full_decl[/^q\(volatile\)/]
33
+ end
34
+ def is_callback?
35
+ @full_decl[/^callback/]
36
+ end
37
+ def is_inline_callback?
38
+ @full_decl[/^p.f\(/]
39
+ end
40
+ end
41
+ def initialize(params = { })
42
+ super
43
+ params = { :declaration => get_full_decl, :typedefs => { } }.merge(params)
44
+ @full_decl = params[:declaration]
45
+ @typedefs = params[:typedefs] || { }
46
+ @declaration = Declaration.new(@full_decl)
47
+ @is_pointer = 0
48
+ end
49
+ def to_s
50
+ ffi_type_from(@full_decl)
51
+ end
52
+ private
53
+ def get_full_decl
54
+ get_attr('decl').to_s + get_attr('type').to_s if @node
55
+ end
56
+ def decl
57
+ get_attr('decl').to_s
58
+ end
59
+ def type
60
+ get_attr('type').to_s
61
+ end
62
+ def native
63
+ ffi_type_from(Generator::TYPES[@full_decl]) if @declaration.is_native?
64
+ end
65
+ def constant
66
+ ffi_type_from(@full_decl.scan(/^q\(const\)\.(.+)/).flatten[0]) if @declaration.is_constant?
67
+ end
68
+ def volatile
69
+ ffi_type_from(@full_decl.scan(/^q\(volatile\)\.(.+)/).flatten[0]) if @declaration.is_volatile?
70
+ end
71
+ def pointer
72
+ if @declaration.is_pointer? or @is_pointer > 0
73
+ @is_pointer += 1
74
+ if @full_decl.scan(/^p\.(.+)/).flatten[0]
75
+ ffi_type_from(@full_decl.scan(/^p\.(.+)/).flatten[0])
76
+ elsif @full_decl == 'char' and @is_pointer == 2
77
+ ':string'
78
+ else
79
+ ':pointer'
80
+ end
81
+ end
82
+ end
83
+ def array
84
+ if @declaration.is_array?
85
+ num = @full_decl.scan(/\w+\((\d+)\)/).flatten[0]
86
+ "[#{ffi_type_from(@full_decl.gsub!(/\w+\(\d+\)\./, ''))}, #{num}]"
87
+ end
88
+ end
89
+ def struct
90
+ Struct.camelcase(@full_decl.scan(/^struct\s(\w+)/).flatten[0]) if @declaration.is_struct?
91
+ end
92
+ def union
93
+ Union.camelcase(@full_decl.scan(/^union\s(\w+)/).flatten[0]) if @declaration.is_union?
94
+ end
95
+ def enum
96
+ ffi_type_from(Generator::TYPES['int']) if @declaration.is_enum?
97
+ end
98
+ def callback
99
+ ":#{@full_decl.scan(/^callback\s(\w+)/).flatten[0]}" if @declaration.is_callback?
100
+ end
101
+ def inline_callback
102
+ Callback.new(:node => @node, :inline => true, :typedefs => @typedefs).to_s if @declaration.is_inline_callback?
103
+ end
104
+ def typedef
105
+ ffi_type_from(@typedefs[@full_decl]) if @typedefs.has_key?(@full_decl)
106
+ end
107
+ def undefined(type)
108
+ "#{type}"
109
+ end
110
+ def ffi_type_from(full_decl)
111
+ @full_decl = full_decl
112
+ @declaration = Declaration.new(full_decl)
113
+ constant || \
114
+ volatile || \
115
+ typedef || \
116
+ pointer || \
117
+ enum || \
118
+ native || \
119
+ struct || \
120
+ union || \
121
+ array || \
122
+ inline_callback || \
123
+ callback || \
124
+ undefined(full_decl)
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,36 @@
1
+ module FFI
2
+ module Generator
3
+ TYPES = {
4
+ 'char' => ':char',
5
+ 'double' => ':double',
6
+ 'float' => ':float',
7
+ 'unsigned long' => ':ulong',
8
+ 'unsigned char' => ':uchar',
9
+ 'signed char' => ':char',
10
+ 'unsigned char' => ':uchar',
11
+ 'short' => ':short',
12
+ 'signed short' => ':short',
13
+ 'signed short int' => ':short',
14
+ 'unsigned short' => ':ushort',
15
+ 'unsigned short int' => ':ushort',
16
+ 'int' => ':int',
17
+ 'signed int' => ':int',
18
+ 'unsigned int' => ':uint',
19
+ 'long' => ':long',
20
+ 'long int' => ':long',
21
+ 'signed long' => ':long',
22
+ 'signed long int' => ':long',
23
+ 'unsigned long' => ':ulong',
24
+ 'unsigned long int' => ':ulong',
25
+ 'long unsigned int' => ':ulong',
26
+ 'long long' => ':long_long',
27
+ 'long long int' => ':long_long',
28
+ 'signed long long' => ':long_long',
29
+ 'signed long long int' => ':long_long',
30
+ 'size_t' => ':uint',
31
+ 'unsigned long long' => ':ulong_long',
32
+ 'unsigned long long int' => ':ulong_long',
33
+ 'void' => ':void'
34
+ }
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ require File.join(File.dirname(__FILE__), %w[.. spec_helper])
2
+ include FFI
3
+
4
+ describe Generator::Constant do
5
+ it_should_behave_like 'All specs'
6
+ before :all do
7
+ @node = generate_xml_wrap_from('constants')
8
+ end
9
+ it 'should return a ruby constant assignment' do
10
+ Generator::Constant.new(:node => (@node / 'constant')[0]).to_s.should == "CONST_1 = 0x10"
11
+ end
12
+ it 'should ignore constant qualifiers' do
13
+ Generator::Constant.new(:node => (@node / 'constant')[1]).to_s.should == "CONST_2 = 1234"
14
+ Generator::Constant.new(:node => (@node / 'constant')[2]).to_s.should == "CONST_3 = 1234"
15
+ Generator::Constant.new(:node => (@node / 'constant')[3]).to_s.should == "CONST_4 = 1234"
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ require File.join(File.dirname(__FILE__), %w[.. spec_helper])
2
+ include FFI
3
+
4
+ describe Generator::Enum do
5
+ it_should_behave_like 'All specs'
6
+ before :all do
7
+ @node = generate_xml_wrap_from('enums')
8
+ end
9
+ it 'should generate constants' do
10
+ Generator::Enum.new(:node => (@node / 'enum')[0]).to_s.should == <<EOE
11
+ ENUM_1 = 0
12
+ ENUM_2 = 1
13
+ ENUM_3 = 2
14
+ EOE
15
+ end
16
+ it 'should generate constants starting from the latest assignment' do
17
+ Generator::Enum.new(:node => (@node / 'enum')[1]).to_s.should == <<EOE
18
+ ENUM_21 = 2
19
+ ENUM_22 = 3
20
+ ENUM_23 = 4
21
+ EOE
22
+ Generator::Enum.new(:node => (@node / 'enum')[2]).to_s.should == <<EOE
23
+ ENUM_31 = 0
24
+ ENUM_32 = 5
25
+ ENUM_33 = 6
26
+ EOE
27
+ end
28
+ end
29
+
@@ -0,0 +1,66 @@
1
+ require File.join(File.dirname(__FILE__), %w[.. spec_helper])
2
+ include FFI
3
+
4
+ describe Generator::Function do
5
+ it_should_behave_like 'All specs'
6
+ before :all do
7
+ @node = generate_xml_wrap_from('functions')
8
+ end
9
+ it 'should return a properly generated attach_method' do
10
+ Generator::Function.new(:node => (@node / 'cdecl')[0]).to_s.should == "attach_function :func_1, [ :char, :int ], :int"
11
+ end
12
+ it 'should properly generate pointer arguments' do
13
+ Generator::Function.new(:node => (@node / 'cdecl')[1]).to_s.should == "attach_function :func_2, [ :pointer, :pointer, :pointer ], :uint"
14
+ end
15
+ it 'should properly generate string arguments' do
16
+ Generator::Function.new(:node => (@node / 'cdecl')[2]).to_s.should == "attach_function :func_3, [ :string ], :void"
17
+ end
18
+ it 'should properly generate string return type' do
19
+ Generator::Function.new(:node => (@node / 'cdecl')[3]).to_s.should == "attach_function :func_4, [ :int ], :string"
20
+ end
21
+ it 'should generate string type only in case of pointer of type char (char *)' do
22
+ Generator::Function.new(:node => (@node / 'cdecl')[17]).to_s.should == "attach_function :func_17, [ ], :pointer"
23
+ end
24
+ it 'should properly generate void return type' do
25
+ Generator::Function.new(:node => (@node / 'cdecl')[4]).to_s.should == "attach_function :func_5, [ ], :void"
26
+ end
27
+ it 'should properly generate pointer of pointer arguments' do
28
+ Generator::Function.new(:node => (@node / 'cdecl')[5]).to_s.should == "attach_function :func_6, [ :pointer ], :void"
29
+ end
30
+ it 'should properly generate enum arguments' do
31
+ Generator::Function.new(:node => (@node / 'cdecl')[6]).to_s.should == "attach_function :func_7, [ :int ], :void"
32
+ end
33
+ it 'should properly generate enum return type' do
34
+ Generator::Function.new(:node => (@node / 'cdecl')[7]).to_s.should == "attach_function :func_8, [ ], :int"
35
+ end
36
+ it 'should properly generate struct arguments' do
37
+ Generator::Function.new(:node => (@node / 'cdecl')[9]).to_s.should == "attach_function :func_9, [ TestStruct ], :void"
38
+ end
39
+ it 'should properly generate struct return type' do
40
+ Generator::Function.new(:node => (@node / 'cdecl')[10]).to_s.should == "attach_function :func_10, [ ], TestStruct"
41
+ end
42
+ it 'should properly generate a function with no parameters' do
43
+ Generator::Function.new(:node => (@node / 'cdecl')[11]).to_s.should == "attach_function :func_11, [ ], :void"
44
+ end
45
+ it 'should properly generate a function that takes a callback as argument' do
46
+ Generator::Function.new(:node => (@node / 'cdecl')[12]).to_s.should == "attach_function :func_12, [ callback([ :float ], :void) ], :void"
47
+ Generator::Function.new(:node => (@node / 'cdecl')[13]).to_s.should == "attach_function :func_13, [ callback([ :double, :float ], :int) ], :void"
48
+ Generator::Function.new(:node => (@node / 'cdecl')[14]).to_s.should == "attach_function :func_14, [ callback([ :string ], :void) ], :void"
49
+ Generator::Function.new(:node => (@node / 'cdecl')[15]).to_s.should == "attach_function :func_15, [ callback([ ], :void) ], :void"
50
+ end
51
+ it 'should handle const qualifier return type' do
52
+ Generator::Function.new(:node => (@node / 'cdecl')[16]).to_s.should == "attach_function :func_16, [ ], :string"
53
+ end
54
+ it 'should generate a function with variadic args' do
55
+ Generator::Function.new(:node => (@node / 'cdecl')[18]).to_s.should == "attach_function :func_18, [ :varargs ], :void"
56
+ end
57
+ it 'should generate a function with volatile args' do
58
+ Generator::Function.new(:node => (@node / 'cdecl')[19]).to_s.should == "attach_function :func_19, [ :int ], :void"
59
+ end
60
+ it 'should properly generate func_20' do
61
+ Generator::Function.new(:node => (@node / 'cdecl')[20]).to_s.should == "attach_function :func_20, [ :pointer, callback([ :string, :pointer, :pointer ], :void), :pointer ], :void"
62
+ end
63
+ it 'should properly generate func_20' do
64
+ Generator::Function.new(:node => (@node / 'cdecl')[21]).to_s.should == "attach_function :func_21, [ :pointer, callback([ :uchar, :pointer, :pointer ], :void), :pointer ], :void"
65
+ end
66
+ end
@@ -0,0 +1,250 @@
1
+ require File.join(File.dirname(__FILE__), %w[.. spec_helper])
2
+
3
+ include FFI
4
+
5
+ describe Generator::Parser do
6
+ it_should_behave_like 'All specs'
7
+ before do
8
+ @node = generate_xml_wrap_from('testlib')
9
+ end
10
+ it 'should generate ruby ffi wrap code' do
11
+ Generator::Parser.new.generate(@node).should == <<EOC
12
+
13
+ module TestLib
14
+ extend FFI::Library
15
+ CONST_1 = 0x10
16
+ CONST_2 = 0x20
17
+ ENUM_1 = 0
18
+ ENUM_2 = 1
19
+ ENUM_3 = 2
20
+
21
+ class UnionT < FFI::Union
22
+ layout(
23
+ :c, :char,
24
+ :f, :float
25
+ )
26
+ end
27
+ class TestStruct < FFI::Struct
28
+ layout(
29
+ :i, :int,
30
+ :c, :char,
31
+ :b, :uchar
32
+ )
33
+ end
34
+ class CamelCaseStruct < FFI::Struct
35
+ layout(
36
+ :i, :int,
37
+ :c, :char,
38
+ :b, :uchar
39
+ )
40
+ end
41
+ class TestStruct3 < FFI::Struct
42
+ layout(
43
+ :c, :char
44
+ )
45
+ end
46
+ callback(:cb, [ :string, :string ], :void)
47
+ callback(:cb_2, [ :string, :string ], :pointer)
48
+ callback(:cb_3, [ :string, CamelCaseStruct ], CamelCaseStruct)
49
+ class TestStruct2 < FFI::Struct
50
+ layout(
51
+ :s, TestStruct,
52
+ :camel_case_struct, CamelCaseStruct,
53
+ :s_3, TestStruct3,
54
+ :e, :int,
55
+ :func, :cb,
56
+ :u, UnionT,
57
+ :callback, :cb,
58
+ :inline_callback, callback([ ], :void)
59
+ )
60
+ def func=(cb)
61
+ @func = cb
62
+ self[:func] = @func
63
+ end
64
+ def func
65
+ @func
66
+ end
67
+ def callback=(cb)
68
+ @callback = cb
69
+ self[:callback] = @callback
70
+ end
71
+ def callback
72
+ @callback
73
+ end
74
+ def inline_callback=(cb)
75
+ @inline_callback = cb
76
+ self[:inline_callback] = @inline_callback
77
+ end
78
+ def inline_callback
79
+ @inline_callback
80
+ end
81
+
82
+ end
83
+ class TestStruct4 < FFI::Struct
84
+ layout(
85
+ :string, :pointer,
86
+ :inline_callback, callback([ ], :void)
87
+ )
88
+ def string=(str)
89
+ @string = FFI::MemoryPointer.from_string(str)
90
+ self[:string] = @string
91
+ end
92
+ def string
93
+ @string.get_string(0)
94
+ end
95
+ def inline_callback=(cb)
96
+ @inline_callback = cb
97
+ self[:inline_callback] = @inline_callback
98
+ end
99
+ def inline_callback
100
+ @inline_callback
101
+ end
102
+
103
+ end
104
+ class TestStruct5BigUnionFieldNestedStructField1 < FFI::Struct
105
+ layout(
106
+ :a, :int,
107
+ :b, :int
108
+ )
109
+ end
110
+ class TestStruct5BigUnionFieldNestedStructField2 < FFI::Struct
111
+ layout(
112
+ :c, :int,
113
+ :d, :int
114
+ )
115
+ end
116
+ class TestStruct5BigUnionFieldNestedStructField3 < FFI::Struct
117
+ layout(
118
+ :e, :int,
119
+ :f, :int
120
+ )
121
+ end
122
+ class TestStruct5BigUnionFieldUnionField < FFI::Union
123
+ layout(
124
+ :l, :long,
125
+ :ll, :long_long
126
+ )
127
+ end
128
+ # FIXME: Nested structures are not correctly supported at the moment.
129
+ # Please check the order of the declarations in the structure below.
130
+ # class TestStruct5BigUnionField < FFI::Union
131
+ # layout(
132
+ # :f, :float,
133
+ # :union_field, TestStruct5BigUnionFieldUnionField,
134
+ # :nested_struct_field_3, TestStruct5BigUnionFieldNestedStructField3,
135
+ # :nested_struct_field_2, TestStruct5BigUnionFieldNestedStructField2,
136
+ # :nested_struct_field_1, TestStruct5BigUnionFieldNestedStructField1
137
+ # )
138
+ # end
139
+ # FIXME: Nested structures are not correctly supported at the moment.
140
+ # Please check the order of the declarations in the structure below.
141
+ # class TestStruct5 < FFI::Struct
142
+ # layout(
143
+ # :i, :int,
144
+ # :c, :char,
145
+ # :big_union_field, TestStruct5BigUnionField
146
+ # )
147
+ # end
148
+ attach_function :get_int, [ :pointer ], :int
149
+ attach_function :get_char, [ :pointer ], :char
150
+ attach_function :func_with_enum, [ :int ], :int
151
+ attach_function :func_with_enum_2, [ :int ], :int
152
+ attach_function :func_with_typedef, [ ], :uchar
153
+
154
+ end
155
+ EOC
156
+ end
157
+ it 'should ignore given declarations' do
158
+ parser = Generator::Parser.new
159
+ parser.ignore 'CONST_1', 'e_1', 'test_struct', 'test_struct_5'
160
+ parser.ignore 'func_with_enum_2'
161
+ parser.generate(@node).should == <<EOC
162
+
163
+ module TestLib
164
+ extend FFI::Library
165
+ CONST_2 = 0x20
166
+ class UnionT < FFI::Union
167
+ layout(
168
+ :c, :char,
169
+ :f, :float
170
+ )
171
+ end
172
+ class CamelCaseStruct < FFI::Struct
173
+ layout(
174
+ :i, :int,
175
+ :c, :char,
176
+ :b, :uchar
177
+ )
178
+ end
179
+ class TestStruct3 < FFI::Struct
180
+ layout(
181
+ :c, :char
182
+ )
183
+ end
184
+ callback(:cb, [ :string, :string ], :void)
185
+ callback(:cb_2, [ :string, :string ], :pointer)
186
+ callback(:cb_3, [ :string, CamelCaseStruct ], CamelCaseStruct)
187
+ class TestStruct2 < FFI::Struct
188
+ layout(
189
+ :s, TestStruct,
190
+ :camel_case_struct, CamelCaseStruct,
191
+ :s_3, TestStruct3,
192
+ :e, :int,
193
+ :func, :cb,
194
+ :u, UnionT,
195
+ :callback, :cb,
196
+ :inline_callback, callback([ ], :void)
197
+ )
198
+ def func=(cb)
199
+ @func = cb
200
+ self[:func] = @func
201
+ end
202
+ def func
203
+ @func
204
+ end
205
+ def callback=(cb)
206
+ @callback = cb
207
+ self[:callback] = @callback
208
+ end
209
+ def callback
210
+ @callback
211
+ end
212
+ def inline_callback=(cb)
213
+ @inline_callback = cb
214
+ self[:inline_callback] = @inline_callback
215
+ end
216
+ def inline_callback
217
+ @inline_callback
218
+ end
219
+
220
+ end
221
+ class TestStruct4 < FFI::Struct
222
+ layout(
223
+ :string, :pointer,
224
+ :inline_callback, callback([ ], :void)
225
+ )
226
+ def string=(str)
227
+ @string = FFI::MemoryPointer.from_string(str)
228
+ self[:string] = @string
229
+ end
230
+ def string
231
+ @string.get_string(0)
232
+ end
233
+ def inline_callback=(cb)
234
+ @inline_callback = cb
235
+ self[:inline_callback] = @inline_callback
236
+ end
237
+ def inline_callback
238
+ @inline_callback
239
+ end
240
+
241
+ end
242
+ attach_function :get_int, [ :pointer ], :int
243
+ attach_function :get_char, [ :pointer ], :char
244
+ attach_function :func_with_enum, [ :int ], :int
245
+ attach_function :func_with_typedef, [ ], :uchar
246
+
247
+ end
248
+ EOC
249
+ end
250
+ end