ffi-swig-generator 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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