ghazel-ffi_gen 1.3.9.1 → 1.3.9.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/ffi_gen.rb +71 -12
- data/lib/ffi_gen/clang.rb +1 -1
- data/lib/ffi_gen/java_output.rb +51 -16
- data/lib/ffi_gen/java_static.java +7 -0
- data/lib/ffi_gen/ruby_output.rb +18 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e74a49ab6949c362c786be977bee1502716b0a41
|
4
|
+
data.tar.gz: c17d96a9b1c0b418dd1daece53e5ca39d0626a9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a221f2f05ffb6c4b47286805d7d874e7b67129ffaeecc98402c089ca531b4ed4fb0e2ac3eb50442f16334199d25259de148090ec529ae9d70b46b9b2fa7fb74
|
7
|
+
data.tar.gz: eda187d248897255b28b2769258b9bf3f00d0e2a5805662c2163578d87ea3bcede5b792fe8ac6a7dc31b482764ccc71f0b34512e3dd3e05bf3bd603b84dbd085
|
data/lib/ffi_gen.rb
CHANGED
@@ -204,8 +204,9 @@ class FFIGen
|
|
204
204
|
end
|
205
205
|
|
206
206
|
class PrimitiveType < Type
|
207
|
-
def initialize(clang_type)
|
207
|
+
def initialize(clang_type, full_type)
|
208
208
|
@clang_type = clang_type
|
209
|
+
@full_type = full_type
|
209
210
|
end
|
210
211
|
|
211
212
|
def name
|
@@ -219,7 +220,21 @@ class FFIGen
|
|
219
220
|
end
|
220
221
|
end
|
221
222
|
|
223
|
+
class ByReferenceType < Type
|
224
|
+
attr_accessor :inner_type
|
225
|
+
|
226
|
+
def initialize(inner_type)
|
227
|
+
@inner_type = inner_type
|
228
|
+
end
|
229
|
+
|
230
|
+
def name
|
231
|
+
@inner_type.name
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
222
235
|
class ByValueType < Type
|
236
|
+
attr_accessor :inner_type
|
237
|
+
|
223
238
|
def initialize(inner_type)
|
224
239
|
@inner_type = inner_type
|
225
240
|
end
|
@@ -415,7 +430,8 @@ class FFIGen
|
|
415
430
|
Enum.new self, name, constants, enum_description
|
416
431
|
|
417
432
|
when :struct_decl, :union_decl
|
418
|
-
|
433
|
+
@declarations_by_type[Clang.get_cursor_type(declaration_cursor)] ||= StructOrUnion.new(self, name, (declaration_cursor[:kind] == :union_decl))
|
434
|
+
struct = @declarations_by_type[Clang.get_cursor_type(declaration_cursor)]
|
419
435
|
raise if not struct.fields.empty?
|
420
436
|
struct.description.concat comment
|
421
437
|
|
@@ -514,16 +530,58 @@ class FFIGen
|
|
514
530
|
typedef_children = Clang.get_children declaration_cursor
|
515
531
|
underlying = Clang.get_typedef_decl_underlying_type(declaration_cursor)
|
516
532
|
function_proto = Clang.get_canonical_type(Clang.get_pointee_type(underlying))
|
517
|
-
if function_proto[:kind] == :function_proto
|
533
|
+
if function_proto[:kind] == :function_proto || function_proto[:kind] == :function_no_proto
|
534
|
+
|
535
|
+
function_description = []
|
536
|
+
return_value_description = []
|
537
|
+
parameter_descriptions = {}
|
538
|
+
current_description = function_description
|
539
|
+
comment.each do |line|
|
540
|
+
if line.gsub!(/\\param (.*?) /, '')
|
541
|
+
current_description = []
|
542
|
+
parameter_descriptions[$1] = current_description
|
543
|
+
end
|
544
|
+
current_description = return_value_description if line.gsub! '\\returns ', ''
|
545
|
+
current_description << line
|
546
|
+
end
|
547
|
+
|
518
548
|
return_type = resolve_type Clang.get_result_type(function_proto)
|
519
549
|
parameters = []
|
520
|
-
Clang.
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
550
|
+
Clang.get_children(declaration_cursor).each do |function_child|
|
551
|
+
next if function_child[:kind] != :parm_decl
|
552
|
+
param_name = read_name function_child
|
553
|
+
tokens = Clang.get_tokens translation_unit, Clang.get_cursor_extent(function_child)
|
554
|
+
is_array = tokens.any? { |t| Clang.get_token_spelling(translation_unit, t).to_s_and_dispose == "[" }
|
555
|
+
param_type = resolve_type Clang.get_cursor_type(function_child), is_array
|
556
|
+
param_name ||= param_type.name
|
557
|
+
param_name ||= Name.new []
|
558
|
+
first_parameter_type ||= Clang.get_cursor_type function_child
|
559
|
+
parameters << { name: param_name, type: param_type }
|
525
560
|
end
|
526
|
-
|
561
|
+
|
562
|
+
parameters.each_with_index do |parameter, index|
|
563
|
+
parameter[:description] = parameter[:name] && parameter_descriptions[parameter[:name].raw]
|
564
|
+
parameter[:description] ||= parameter_descriptions.values[index] if parameter_descriptions.size == parameters.size # workaround for wrong names
|
565
|
+
parameter[:description] ||= []
|
566
|
+
end
|
567
|
+
|
568
|
+
function = FunctionOrCallback.new self, name, parameters, return_type, true, false, function_description, return_value_description
|
569
|
+
|
570
|
+
pointee_declaration = first_parameter_type && get_pointee_declaration(first_parameter_type)
|
571
|
+
if pointee_declaration
|
572
|
+
type_prefix = pointee_declaration.name.parts.join.downcase
|
573
|
+
function_name_parts = name.parts.dup
|
574
|
+
while type_prefix.start_with? function_name_parts.first.downcase
|
575
|
+
type_prefix = type_prefix[function_name_parts.first.size..-1]
|
576
|
+
function_name_parts.shift
|
577
|
+
break if function_name_parts.empty?
|
578
|
+
end
|
579
|
+
if type_prefix.empty?
|
580
|
+
pointee_declaration.oo_functions << [Name.new(function_name_parts), function]
|
581
|
+
end
|
582
|
+
end
|
583
|
+
|
584
|
+
function
|
527
585
|
elsif typedef_children.size == 1
|
528
586
|
child_declaration = @declarations_by_type[Clang.get_cursor_type(typedef_children.first)]
|
529
587
|
child_declaration.name = name if child_declaration and child_declaration.name.nil?
|
@@ -653,7 +711,7 @@ class FFIGen
|
|
653
711
|
canonical_type = Clang.get_canonical_type full_type
|
654
712
|
data_array = case canonical_type[:kind]
|
655
713
|
when :void, :bool, :u_char, :u_short, :u_int, :u_long, :u_long_long, :char_s, :s_char, :short, :int, :long, :long_long, :float, :double
|
656
|
-
PrimitiveType.new canonical_type[:kind]
|
714
|
+
PrimitiveType.new canonical_type[:kind], Clang.get_type_spelling(full_type).to_s_and_dispose
|
657
715
|
when :pointer
|
658
716
|
if is_array
|
659
717
|
ArrayType.new resolve_type(Clang.get_pointee_type(canonical_type)), nil
|
@@ -663,8 +721,9 @@ class FFIGen
|
|
663
721
|
when :char_s
|
664
722
|
StringType.new
|
665
723
|
when :record
|
666
|
-
@declarations_by_type[Clang.get_cursor_type(Clang.get_type_declaration(pointee_type))]
|
667
|
-
|
724
|
+
type = @declarations_by_type[Clang.get_cursor_type(Clang.get_type_declaration(pointee_type))]
|
725
|
+
type &&= ByReferenceType.new(type)
|
726
|
+
when :function_proto, :function_no_proto
|
668
727
|
@declarations_by_type[full_type]
|
669
728
|
else
|
670
729
|
nil
|
data/lib/ffi_gen/clang.rb
CHANGED
@@ -4,7 +4,7 @@ require 'ffi'
|
|
4
4
|
|
5
5
|
module FFIGen::Clang
|
6
6
|
extend FFI::Library
|
7
|
-
ffi_lib ["libclang-3.5.so.1", "libclang.so.1", "clang"]
|
7
|
+
ffi_lib ["libclang-3.5.so.1", "libclang.so.1", "clang", '/usr/local/lib/libclang.dylib']
|
8
8
|
|
9
9
|
def self.attach_function(name, *_)
|
10
10
|
begin; super; rescue FFI::NotFoundError => e
|
data/lib/ffi_gen/java_output.rb
CHANGED
@@ -15,7 +15,7 @@ class FFIGen
|
|
15
15
|
end
|
16
16
|
writer.puts ""
|
17
17
|
|
18
|
-
writer.puts "
|
18
|
+
writer.puts "interface #{@module_name}Interface extends Library {"
|
19
19
|
writer.indent do
|
20
20
|
writer.puts "", *IO.readlines(File.join(File.dirname(__FILE__), "java_interface.java")).map(&:rstrip), ""
|
21
21
|
writer.puts "static class JnaInstanceCreator {"
|
@@ -120,22 +120,34 @@ class FFIGen
|
|
120
120
|
writer.puts "public static class #{java_name} extends #{@is_union ? 'Union' : (@fields.empty? ? 'PointerType' : 'Structure')} {"
|
121
121
|
writer.indent do
|
122
122
|
@fields.each do |field|
|
123
|
-
|
123
|
+
if field[:type].is_a? ByReferenceType and not field[:type].inner_type.fields.empty?
|
124
|
+
writer.puts "public volatile #{field[:type].java_jna_type}.ByReference #{field[:name].to_java_downcase};"
|
125
|
+
else
|
126
|
+
writer.puts "public volatile #{field[:type].java_jna_type} #{field[:name].to_java_downcase};"
|
127
|
+
end
|
124
128
|
end
|
125
129
|
writer.puts "// hidden structure" if @fields.empty?
|
126
|
-
|
127
|
-
writer.indent do
|
128
|
-
writer.puts "public static class ByValue extends #{java_name} implements Structure.ByValue {}"
|
130
|
+
|
129
131
|
writer.puts "protected List<String> getFieldOrder() {"
|
130
132
|
writer.indent do
|
131
|
-
fs = @fields.map{|f| '"' + f[:name].
|
133
|
+
fs = @fields.map{|f| '"' + f[:name].to_java_downcase + '"'}.join(", ")
|
132
134
|
writer.puts "return Arrays.asList(new String[] { #{fs} } );"
|
133
135
|
end
|
134
136
|
writer.puts "}"
|
137
|
+
|
138
|
+
if not @fields.empty?
|
139
|
+
writer.puts "public static class ByValue extends #{java_name} implements Structure.ByValue {}"
|
140
|
+
writer.puts "public static class ByReference extends #{java_name} implements Structure.ByReference {"
|
141
|
+
writer.indent do
|
142
|
+
writer.puts "public ByReference() { }"
|
143
|
+
writer.puts "public ByReference(Pointer p) { super(p); read(); }"
|
144
|
+
end
|
145
|
+
writer.puts "}"
|
146
|
+
writer.puts "public #{java_name}() { }"
|
147
|
+
writer.puts "public #{java_name}(Pointer p) { super(p); read(); }"
|
148
|
+
end
|
135
149
|
end
|
136
150
|
writer.puts "}", ""
|
137
|
-
|
138
|
-
@written = true
|
139
151
|
end
|
140
152
|
|
141
153
|
def java_name
|
@@ -143,11 +155,11 @@ class FFIGen
|
|
143
155
|
end
|
144
156
|
|
145
157
|
def java_jna_type
|
146
|
-
|
158
|
+
java_name
|
147
159
|
end
|
148
160
|
|
149
161
|
def java_description
|
150
|
-
|
162
|
+
java_name
|
151
163
|
end
|
152
164
|
end
|
153
165
|
|
@@ -157,14 +169,14 @@ class FFIGen
|
|
157
169
|
writer.puts "public static interface #{java_name.split('.').last} extends Callback {"
|
158
170
|
writer.indent do
|
159
171
|
jna_signature = "#{@parameters.map{ |parameter| "#{parameter[:type].java_jna_type} #{parameter[:name].to_java_downcase}" }.join(', ')}"
|
160
|
-
writer.puts "#{
|
172
|
+
writer.puts "#{java_jna_return_type} invoke(#{jna_signature});"
|
161
173
|
end
|
162
174
|
writer.puts "}", ""
|
163
175
|
return
|
164
176
|
end
|
165
177
|
|
166
178
|
jna_signature = "#{@parameters.map{ |parameter| "#{parameter[:type].java_jna_type} #{parameter[:name].to_java_downcase}" }.join(', ')}"
|
167
|
-
writer.puts "@NativeName(\"#{@name.raw}\")", "#{
|
179
|
+
writer.puts "@NativeName(\"#{@name.raw}\")", "#{java_jna_return_type} #{java_name}(#{jna_signature});", ""
|
168
180
|
end
|
169
181
|
|
170
182
|
def write_static_java(writer)
|
@@ -174,10 +186,10 @@ class FFIGen
|
|
174
186
|
parameters = []
|
175
187
|
lp = nil
|
176
188
|
@parameters.each do |p|
|
177
|
-
if lp
|
189
|
+
if lp and lp[:type].is_a?(PointerType) and lp[:type].pointee_type.respond_to?(:clang_type) and lp[:type].pointee_type.clang_type == :u_char and [:u_long, :u_long_long].include?(p[:type].clang_type)
|
178
190
|
n = lp[:name].to_java_downcase
|
179
191
|
replace[n] = "bytesToPointer(#{n})"
|
180
|
-
replace[p[:name].to_java_downcase] = "
|
192
|
+
replace[p[:name].to_java_downcase] = "#{n}.length";
|
181
193
|
d = lp.dup
|
182
194
|
d[:type] = ArrayType.new(lp[:type].pointee_type, nil)
|
183
195
|
parameters << d
|
@@ -209,7 +221,7 @@ class FFIGen
|
|
209
221
|
replace[n] || n
|
210
222
|
}.join(', ')
|
211
223
|
jna_signature = "#{parameters.map{ |parameter| "#{parameter[:type].java_jna_type} #{parameter[:name].to_java_downcase}" }.join(', ')}"
|
212
|
-
writer.puts "public static #{
|
224
|
+
writer.puts "public static #{java_jna_return_type} #{java_name}(#{jna_signature}) {"
|
213
225
|
writer.indent do
|
214
226
|
call = "INSTANCE.#{java_name}(#{args});"
|
215
227
|
if @return_type.respond_to? :clang_type and @return_type.clang_type == :void
|
@@ -230,6 +242,13 @@ class FFIGen
|
|
230
242
|
java_name
|
231
243
|
end
|
232
244
|
|
245
|
+
def java_jna_return_type
|
246
|
+
if @return_type.is_a? ByReferenceType and not @return_type.inner_type.fields.empty?
|
247
|
+
return "#{@return_type.java_jna_type}.ByReference"
|
248
|
+
end
|
249
|
+
@return_type.java_jna_type
|
250
|
+
end
|
251
|
+
|
233
252
|
def java_description
|
234
253
|
"Proc(_callback_#{java_name}_)"
|
235
254
|
end
|
@@ -260,6 +279,9 @@ class FFIGen
|
|
260
279
|
attr_accessor :clang_type
|
261
280
|
|
262
281
|
def java_name
|
282
|
+
if @full_type == 'boolean'
|
283
|
+
return 'Boolean'
|
284
|
+
end
|
263
285
|
case @clang_type
|
264
286
|
when :void
|
265
287
|
"nil"
|
@@ -273,6 +295,9 @@ class FFIGen
|
|
273
295
|
end
|
274
296
|
|
275
297
|
def java_jna_type
|
298
|
+
if @full_type == 'boolean'
|
299
|
+
return 'boolean'
|
300
|
+
end
|
276
301
|
case @clang_type
|
277
302
|
when :void then "void"
|
278
303
|
when :bool then "boolean"
|
@@ -302,13 +327,23 @@ class FFIGen
|
|
302
327
|
end
|
303
328
|
end
|
304
329
|
|
330
|
+
class ByReferenceType
|
331
|
+
def java_name
|
332
|
+
@inner_type.java_name
|
333
|
+
end
|
334
|
+
|
335
|
+
def java_jna_type
|
336
|
+
@inner_type.java_jna_type
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
305
340
|
class ByValueType
|
306
341
|
def java_name
|
307
342
|
@inner_type.java_name
|
308
343
|
end
|
309
344
|
|
310
345
|
def java_jna_type
|
311
|
-
@inner_type.java_jna_type
|
346
|
+
"#{@inner_type.java_jna_type}.ByValue"
|
312
347
|
end
|
313
348
|
end
|
314
349
|
|
@@ -3,7 +3,14 @@ interface NativeEnum {
|
|
3
3
|
}
|
4
4
|
|
5
5
|
static Pointer bytesToPointer(byte[] b) {
|
6
|
+
if (b.length == 0) {
|
7
|
+
return null;
|
8
|
+
}
|
6
9
|
Pointer p = new Memory(b.length);
|
7
10
|
p.write(0, b, 0, b.length);
|
8
11
|
return p;
|
9
12
|
}
|
13
|
+
|
14
|
+
static byte[] pointerToBytes(Pointer p, long length) {
|
15
|
+
return p.getByteArray(0, (int)length);
|
16
|
+
}
|
data/lib/ffi_gen/ruby_output.rb
CHANGED
@@ -109,7 +109,7 @@ class FFIGen
|
|
109
109
|
end
|
110
110
|
writer.puts "def #{name.to_ruby_downcase}(#{parameter_names.join(', ')})"
|
111
111
|
writer.indent do
|
112
|
-
cast = function.
|
112
|
+
cast = function.ruby_ffi_return_type.is_a?(StructOrUnion) ? "#{function.return_type.ruby_name}.new " : ""
|
113
113
|
writer.puts "#{cast}#{@generator.module_name}.#{function.ruby_name}(#{(["self"] + parameter_names).join(', ')})"
|
114
114
|
end
|
115
115
|
writer.puts "end"
|
@@ -169,6 +169,13 @@ class FFIGen
|
|
169
169
|
@ruby_name ||= @name.to_ruby_downcase
|
170
170
|
end
|
171
171
|
|
172
|
+
def ruby_ffi_return_type
|
173
|
+
if @return_type.is_a? ByReferenceType and not @return_type.inner_type.fields.empty?
|
174
|
+
return @return_type.inner_type
|
175
|
+
end
|
176
|
+
@return_type
|
177
|
+
end
|
178
|
+
|
172
179
|
def ruby_ffi_type
|
173
180
|
":#{ruby_name}"
|
174
181
|
end
|
@@ -247,6 +254,16 @@ class FFIGen
|
|
247
254
|
end
|
248
255
|
end
|
249
256
|
|
257
|
+
class ByReferenceType
|
258
|
+
def ruby_name
|
259
|
+
@inner_type.ruby_name
|
260
|
+
end
|
261
|
+
|
262
|
+
def ruby_ffi_type
|
263
|
+
@inner_type.ruby_ffi_type
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
250
267
|
class ByValueType
|
251
268
|
def ruby_name
|
252
269
|
@inner_type.ruby_name
|