remogatto-ffi-swig-generator 0.1.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 +8 -0
- data/History.txt +25 -0
- data/README.rdoc +99 -0
- data/Rakefile +42 -0
- data/bin/ffi-gen +7 -0
- data/examples/Rakefile +4 -0
- data/examples/interfaces/libc.i +26 -0
- data/examples/interfaces/wiiuse.i +672 -0
- data/lib/ffi-swig-generator.rb +48 -0
- data/lib/generator/application.rb +69 -0
- data/lib/generator/generator.rb +344 -0
- data/lib/generator/generatortask.rb +45 -0
- data/spec/ffi-swig-generator_spec.rb +7 -0
- data/spec/generator/generator_spec.rb +248 -0
- data/spec/generator/swig/constants.i +3 -0
- data/spec/generator/swig/enums.i +5 -0
- data/spec/generator/swig/functions.i +24 -0
- data/spec/generator/swig/structs.i +25 -0
- data/spec/generator/swig/testlib.i +48 -0
- data/spec/generator/swig/typedefs.i +5 -0
- data/spec/generator/swig/types.i +52 -0
- data/spec/generator/swig/unions.i +6 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +27 -0
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/gem.rake +201 -0
- data/tasks/git.rake +40 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +50 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +300 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- metadata +110 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rake/tasklib'
|
2
|
+
|
3
|
+
module FFI
|
4
|
+
module Generator
|
5
|
+
class Task < Rake::TaskLib
|
6
|
+
def initialize(options = {})
|
7
|
+
@options = { :input_fn => '*.i', :output_dir => 'generated/' }.merge(options)
|
8
|
+
namespace 'ffi' do
|
9
|
+
define_generate_task
|
10
|
+
define_clean_task
|
11
|
+
end
|
12
|
+
end
|
13
|
+
private
|
14
|
+
def define_file_task(fn, xml_fn, output_fn)
|
15
|
+
desc "Generate #{output_fn} from #{fn}"
|
16
|
+
file output_fn => fn do
|
17
|
+
mkdir_p @options[:output_dir], :verbose => false
|
18
|
+
puts "Generating #{xml_fn} from #{fn} using SWIG..."
|
19
|
+
`swig -xml #{xml_fn} #{fn}`
|
20
|
+
puts "Generating #{output_fn} from #{xml_fn}..."
|
21
|
+
File.open(output_fn, 'w') do |file|
|
22
|
+
file << Parser.generate(Nokogiri::XML(File.open(xml_fn)))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
def define_file_tasks
|
27
|
+
Dir.glob(@options[:input_fn]).inject([]) do |output_fns, fn|
|
28
|
+
output_fn = File.join(@options[:output_dir], "#{File.basename(fn, '.i')}_wrap.rb")
|
29
|
+
xml_fn = File.join(@options[:output_dir], "#{File.basename(fn, '.i')}_wrap.xml")
|
30
|
+
define_file_task(fn, xml_fn, output_fn)
|
31
|
+
output_fns << output_fn
|
32
|
+
end
|
33
|
+
end
|
34
|
+
def define_generate_task
|
35
|
+
(task :generate => define_file_tasks).add_description('Generate all files')
|
36
|
+
end
|
37
|
+
def define_clean_task
|
38
|
+
desc 'Remove all generated files'
|
39
|
+
task :clean do
|
40
|
+
rm_rf @options[:output_dir] unless @options[:output_dir] == '.'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. spec_helper])
|
2
|
+
|
3
|
+
include FFI
|
4
|
+
|
5
|
+
share_examples_for "All specs" do
|
6
|
+
after :all do
|
7
|
+
remove_xml
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Generator::Parser do
|
12
|
+
it_should_behave_like 'All specs'
|
13
|
+
before :all do
|
14
|
+
@node = generate_xml_wrap_from('testlib')
|
15
|
+
end
|
16
|
+
it 'should generate ruby ffi wrap code' do
|
17
|
+
Generator::Parser.generate(@node).should == <<EOC
|
18
|
+
|
19
|
+
module TestLib
|
20
|
+
extend FFI::Library
|
21
|
+
CONST_1 = 0x10
|
22
|
+
CONST_2 = 0x20
|
23
|
+
ENUM_1 = 0
|
24
|
+
ENUM_2 = 1
|
25
|
+
ENUM_3 = 2
|
26
|
+
|
27
|
+
class UnionT < FFI::Union
|
28
|
+
layout(
|
29
|
+
:c, :char,
|
30
|
+
:f, :float
|
31
|
+
)
|
32
|
+
end
|
33
|
+
class TestStruct < FFI::Struct
|
34
|
+
layout(
|
35
|
+
:i, :int,
|
36
|
+
:c, :char,
|
37
|
+
:b, :uchar
|
38
|
+
)
|
39
|
+
end
|
40
|
+
class TestStruct3 < FFI::Struct
|
41
|
+
layout(
|
42
|
+
:c, :char
|
43
|
+
)
|
44
|
+
end
|
45
|
+
callback(:cb, [ :string, :string ], :void)
|
46
|
+
class TestStruct2 < FFI::Struct
|
47
|
+
layout(
|
48
|
+
:s, TestStruct,
|
49
|
+
:s_3, TestStruct3,
|
50
|
+
:e, :int,
|
51
|
+
:func, :cb,
|
52
|
+
:u, UnionT
|
53
|
+
)
|
54
|
+
end
|
55
|
+
attach_function :get_int, [ :pointer ], :int
|
56
|
+
attach_function :get_char, [ :pointer ], :char
|
57
|
+
attach_function :func_with_enum, [ :int ], :int
|
58
|
+
attach_function :func_with_enum_2, [ :int ], :int
|
59
|
+
attach_function :func_with_typedef, [ ], :uchar
|
60
|
+
|
61
|
+
end
|
62
|
+
EOC
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe Generator::Constant do
|
67
|
+
it_should_behave_like 'All specs'
|
68
|
+
before :all do
|
69
|
+
@node = generate_xml_wrap_from('constants')
|
70
|
+
end
|
71
|
+
it 'should return a ruby constant assignment' do
|
72
|
+
Generator::Constant.new(:node => @node / 'constant').to_s.should == "CONST_1 = 0x10"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe Generator::Enum do
|
77
|
+
before :all do
|
78
|
+
@node = generate_xml_wrap_from('enums')
|
79
|
+
end
|
80
|
+
it 'should generate constants' do
|
81
|
+
Generator::Enum.new(:node => (@node / 'enum')[0]).to_s.should == <<EOE
|
82
|
+
ENUM_1 = 0
|
83
|
+
ENUM_2 = 1
|
84
|
+
ENUM_3 = 2
|
85
|
+
EOE
|
86
|
+
end
|
87
|
+
it 'should generate constants starting from the latest assignment' do
|
88
|
+
Generator::Enum.new(:node => (@node / 'enum')[1]).to_s.should == <<EOE
|
89
|
+
ENUM_21 = 2
|
90
|
+
ENUM_22 = 3
|
91
|
+
ENUM_23 = 4
|
92
|
+
EOE
|
93
|
+
Generator::Enum.new(:node => (@node / 'enum')[2]).to_s.should == <<EOE
|
94
|
+
ENUM_31 = 0
|
95
|
+
ENUM_32 = 5
|
96
|
+
ENUM_33 = 6
|
97
|
+
EOE
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe Generator::Type do
|
102
|
+
it_should_behave_like 'All specs'
|
103
|
+
before :all do
|
104
|
+
@node = generate_xml_wrap_from('types')
|
105
|
+
end
|
106
|
+
it 'should generate string type' do
|
107
|
+
Generator::Type.new(:node => (@node / 'cdecl')[0]).to_s.should == ':string'
|
108
|
+
end
|
109
|
+
it 'should generate pointer type' do
|
110
|
+
Generator::Type.new(:node => (@node / 'cdecl')[1]).to_s.should == ':pointer'
|
111
|
+
Generator::Type.new(:node => (@node / 'cdecl')[2]).to_s.should == ':pointer'
|
112
|
+
end
|
113
|
+
it 'should generate array type' do
|
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]'
|
116
|
+
end
|
117
|
+
it 'should generate struct type' do
|
118
|
+
Generator::Type.new(:node => (@node / 'cdecl')[6]).to_s.should == 'TestStruct'
|
119
|
+
end
|
120
|
+
it 'should generate struct array type' do
|
121
|
+
Generator::Type.new(:node => (@node / 'cdecl')[7]).to_s.should == '[TestStruct, 5]'
|
122
|
+
end
|
123
|
+
it 'should generate enum array type' do
|
124
|
+
Generator::Type.new(:node => (@node / 'cdecl')[8]).to_s.should == '[:int, 5]'
|
125
|
+
end
|
126
|
+
it 'should generate const type' do
|
127
|
+
Generator::Type.new(:node => (@node / 'cdecl')[9]).to_s.should == ':int'
|
128
|
+
Generator::Type.new(:node => (@node / 'cdecl')[10]).to_s.should == ':string'
|
129
|
+
end
|
130
|
+
Generator::TYPES.sort.each_with_index do |type, i|
|
131
|
+
it "should generate #{type[0]} type" do
|
132
|
+
Generator::Type.new(:node => (@node / 'cdecl')[i + 11]).to_s.should == type[1]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe Generator::Function do
|
138
|
+
it_should_behave_like 'All specs'
|
139
|
+
before :all do
|
140
|
+
@node = generate_xml_wrap_from('functions')
|
141
|
+
end
|
142
|
+
it 'should return a properly generated attach_method' do
|
143
|
+
Generator::Function.new(:node => (@node / 'cdecl')[0]).to_s.should == "attach_function :func_1, [ :char, :int ], :int"
|
144
|
+
end
|
145
|
+
it 'should properly generate pointer arguments' do
|
146
|
+
Generator::Function.new(:node => (@node / 'cdecl')[1]).to_s.should == "attach_function :func_2, [ :pointer, :pointer, :pointer ], :uint"
|
147
|
+
end
|
148
|
+
it 'should properly generate string arguments' do
|
149
|
+
Generator::Function.new(:node => (@node / 'cdecl')[2]).to_s.should == "attach_function :func_3, [ :string ], :void"
|
150
|
+
end
|
151
|
+
it 'should properly generate return type' do
|
152
|
+
Generator::Function.new(:node => (@node / 'cdecl')[3]).to_s.should == "attach_function :func_4, [ :int ], :string"
|
153
|
+
end
|
154
|
+
it 'should properly generate void return type' do
|
155
|
+
Generator::Function.new(:node => (@node / 'cdecl')[4]).to_s.should == "attach_function :func_5, [ ], :void"
|
156
|
+
end
|
157
|
+
it 'should properly generate pointer of pointer arguments' do
|
158
|
+
Generator::Function.new(:node => (@node / 'cdecl')[5]).to_s.should == "attach_function :func_6, [ :pointer ], :void"
|
159
|
+
end
|
160
|
+
it 'should properly generate enum arguments' do
|
161
|
+
Generator::Function.new(:node => (@node / 'cdecl')[6]).to_s.should == "attach_function :func_7, [ :int ], :void"
|
162
|
+
end
|
163
|
+
it 'should properly generate enum return type' do
|
164
|
+
Generator::Function.new(:node => (@node / 'cdecl')[7]).to_s.should == "attach_function :func_8, [ ], :int"
|
165
|
+
end
|
166
|
+
it 'should properly generate struct arguments' do
|
167
|
+
Generator::Function.new(:node => (@node / 'cdecl')[9]).to_s.should == "attach_function :func_9, [ TestStruct ], :void"
|
168
|
+
end
|
169
|
+
it 'should properly generate struct return type' do
|
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"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe Generator::Structure do
|
184
|
+
it_should_behave_like 'All specs'
|
185
|
+
before :all do
|
186
|
+
@node = generate_xml_wrap_from('structs')
|
187
|
+
end
|
188
|
+
it 'should properly generate the layout of a FFI::Struct class' do
|
189
|
+
Generator::Structure.new(:node => (@node / 'class')[0]).to_s.should == <<EOC
|
190
|
+
class TestStruct1 < FFI::Struct
|
191
|
+
layout(
|
192
|
+
:i, :int,
|
193
|
+
:c, :char,
|
194
|
+
:s, :string,
|
195
|
+
:a, [:char, 5]
|
196
|
+
)
|
197
|
+
end
|
198
|
+
EOC
|
199
|
+
|
200
|
+
end
|
201
|
+
it 'should properly generate the layout of a FFI::Struct containing pointer field' do
|
202
|
+
Generator::Structure.new(:node => (@node / 'class')[1]).to_s.should == <<EOC
|
203
|
+
class TestStruct2 < FFI::Struct
|
204
|
+
layout(
|
205
|
+
:ptr, :pointer
|
206
|
+
)
|
207
|
+
end
|
208
|
+
EOC
|
209
|
+
end
|
210
|
+
it 'should properly generate the layout of a FFI::Struct containing array field' do
|
211
|
+
Generator::Structure.new(:node => (@node / 'class')[2]).to_s.should == <<EOC
|
212
|
+
class TestStruct3 < FFI::Struct
|
213
|
+
layout(
|
214
|
+
:c, [:char, 5]
|
215
|
+
)
|
216
|
+
end
|
217
|
+
EOC
|
218
|
+
|
219
|
+
end
|
220
|
+
it 'should properly generate the layout of a FFI::Struct containing array field' do
|
221
|
+
Generator::Structure.new(:node => (@node / 'class')[3]).to_s.should == <<EOC
|
222
|
+
class TestStruct4 < FFI::Struct
|
223
|
+
layout(
|
224
|
+
:s, [TestStruct3, 5]
|
225
|
+
)
|
226
|
+
end
|
227
|
+
EOC
|
228
|
+
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe Generator::Union do
|
233
|
+
it_should_behave_like 'All specs'
|
234
|
+
before :all do
|
235
|
+
@node = generate_xml_wrap_from('unions')
|
236
|
+
end
|
237
|
+
it 'should properly generate the layout of a FFI::Union class' do
|
238
|
+
Generator::Union.new(:node => (@node / 'class')[0]).to_s.should == <<EOC
|
239
|
+
class UnionT < FFI::Union
|
240
|
+
layout(
|
241
|
+
:c, :char,
|
242
|
+
:f, :float
|
243
|
+
)
|
244
|
+
end
|
245
|
+
EOC
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
%module function_testlib
|
2
|
+
|
3
|
+
int func_1(char c, int i);
|
4
|
+
unsigned int func_2(int* p1, int* p2, char** p3);
|
5
|
+
void func_3(char* str);
|
6
|
+
char *func_4(int i);
|
7
|
+
extern void func_5();
|
8
|
+
void func_6(void** ptr);
|
9
|
+
void func_7(enum e e1);
|
10
|
+
enum e { E_1, E_2 };
|
11
|
+
enum e func_8();
|
12
|
+
struct test_struct {
|
13
|
+
char c;
|
14
|
+
};
|
15
|
+
void func_9(struct test_struct s);
|
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
|
+
|
23
|
+
|
24
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
%module test_struct
|
2
|
+
|
3
|
+
struct test_struct_1 {
|
4
|
+
int i;
|
5
|
+
char c;
|
6
|
+
const char* s;
|
7
|
+
const char a[5];
|
8
|
+
};
|
9
|
+
|
10
|
+
struct test_struct_2 {
|
11
|
+
int* ptr;
|
12
|
+
};
|
13
|
+
|
14
|
+
struct test_struct_3 {
|
15
|
+
char c[5];
|
16
|
+
};
|
17
|
+
|
18
|
+
struct test_struct_4 {
|
19
|
+
struct test_struct_3 s[5];
|
20
|
+
};
|
21
|
+
|
22
|
+
struct test_struct_5 {
|
23
|
+
struct test_struct_4 s;
|
24
|
+
};
|
25
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
%module testlib
|
2
|
+
|
3
|
+
%{
|
4
|
+
module TestLib
|
5
|
+
extend FFI::Library
|
6
|
+
%}
|
7
|
+
|
8
|
+
#define CONST_1 0x10
|
9
|
+
#define CONST_2 0x20
|
10
|
+
|
11
|
+
typedef unsigned char byte;
|
12
|
+
typedef enum e_1 {
|
13
|
+
ENUM_1, ENUM_2, ENUM_3
|
14
|
+
} enum_t;
|
15
|
+
|
16
|
+
union union_t {
|
17
|
+
char c;
|
18
|
+
float f;
|
19
|
+
};
|
20
|
+
|
21
|
+
struct test_struct {
|
22
|
+
int i;
|
23
|
+
char c;
|
24
|
+
byte b;
|
25
|
+
};
|
26
|
+
|
27
|
+
typedef struct {
|
28
|
+
char c;
|
29
|
+
} test_struct_3;
|
30
|
+
|
31
|
+
typedef void (*cb)(char*, char*);
|
32
|
+
|
33
|
+
struct test_struct_2 {
|
34
|
+
struct test_struct s;
|
35
|
+
test_struct_3 s_3;
|
36
|
+
enum_t e;
|
37
|
+
cb func;
|
38
|
+
union_t u;
|
39
|
+
};
|
40
|
+
|
41
|
+
int get_int(struct test_struct* s);
|
42
|
+
char get_char(struct test_struct* s);
|
43
|
+
int func_with_enum(enum e_1 e);
|
44
|
+
int func_with_enum_2(enum_t e);
|
45
|
+
byte func_with_typedef();
|
46
|
+
%{
|
47
|
+
end
|
48
|
+
%}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
%module types_test
|
2
|
+
|
3
|
+
char *string;
|
4
|
+
void *ptr;
|
5
|
+
char **ptr_2;
|
6
|
+
|
7
|
+
int array[5];
|
8
|
+
char* ptr_array[5];
|
9
|
+
|
10
|
+
struct test_struct {
|
11
|
+
char c;
|
12
|
+
};
|
13
|
+
|
14
|
+
enum e { E_1, E_2, E_3 };
|
15
|
+
|
16
|
+
struct test_struct ts;
|
17
|
+
struct test_struct a[5];
|
18
|
+
enum e enum_array[5];
|
19
|
+
|
20
|
+
const int ci;
|
21
|
+
const char* cstring;
|
22
|
+
|
23
|
+
char c;
|
24
|
+
double d;
|
25
|
+
float f;
|
26
|
+
int i;
|
27
|
+
long l;
|
28
|
+
long int li;
|
29
|
+
long long ll;
|
30
|
+
long long int lli;
|
31
|
+
long unsigned int lui;
|
32
|
+
short s;
|
33
|
+
signed char sc;
|
34
|
+
signed int si;
|
35
|
+
signed long sl;
|
36
|
+
signed long int sli;
|
37
|
+
signed long long sll;
|
38
|
+
signed long long int slli;
|
39
|
+
signed short ss;
|
40
|
+
signed short int ssi;
|
41
|
+
unsigned char uc;
|
42
|
+
unsigned int ui;
|
43
|
+
unsigned long ul;
|
44
|
+
unsigned long int uli;
|
45
|
+
unsigned long long ull;
|
46
|
+
unsigned long long int ulli;
|
47
|
+
unsigned short us;
|
48
|
+
unsigned short int usi;
|
49
|
+
void v;
|
50
|
+
|
51
|
+
|
52
|
+
|