ghazel-ffi_gen 1.3.9.1 → 1.3.9.2
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.
- 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
|