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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8a0d67dc3a56cc1b5a4d73a74f89316005b61f70
4
- data.tar.gz: c5b89dbc227b3bc2c6bb597368419e301aee368d
3
+ metadata.gz: e74a49ab6949c362c786be977bee1502716b0a41
4
+ data.tar.gz: c17d96a9b1c0b418dd1daece53e5ca39d0626a9c
5
5
  SHA512:
6
- metadata.gz: ac7353f0a2543473fb4e299c2291614cd0e8b62e01961295ea3a9c7e4281e75a8712b51430231115dddb8ee270e952d25b391d2940f596aa6e504a561aa6bbc2
7
- data.tar.gz: 8745ddb1d5b14852e96d91b361098ed4ab1321104121df97d0770c19875a9d04a9fb1a80f8a4ddea300ab655f56912888f535a13d8463e302ab9717581c7b77c
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
- struct = @declarations_by_type[Clang.get_cursor_type(declaration_cursor)] || StructOrUnion.new(self, name, (declaration_cursor[:kind] == :union_decl))
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.get_num_arg_types(function_proto).times do |i|
521
- param_type = resolve_type Clang.get_arg_type(function_proto, i)
522
- # XXX: TODO: get arg name, somehow
523
- param_name = Name.new ['arg', i.to_s]
524
- parameters << { name:param_name, type: param_type, description: [] }
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
- FunctionOrCallback.new self, name, parameters, return_type, true, false, comment, []
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
- when :function_proto
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
@@ -15,7 +15,7 @@ class FFIGen
15
15
  end
16
16
  writer.puts ""
17
17
 
18
- writer.puts "private interface #{@module_name}Interface extends Library {"
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
- writer.puts "public #{field[:type].java_jna_type} #{field[:name].raw};"
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
- end
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].raw + '"'}.join(", ")
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
- @written ? java_name : "Pointer"
158
+ java_name
147
159
  end
148
160
 
149
161
  def java_description
150
- @written ? java_name : "FFI::Pointer(*#{java_name})"
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 "#{@return_type.java_jna_type} invoke(#{jna_signature});"
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}\")", "#{@return_type.java_jna_type} #{java_name}(#{jna_signature});", ""
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 && lp[:type].is_a?(PointerType) && lp[:type].pointee_type.respond_to?(:clang_type) && lp[:type].pointee_type.clang_type == :u_char && p[:type].clang_type == :u_long
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] = "new NativeLong(#{n}.length)";
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 #{@return_type.java_jna_type} #{java_name}(#{jna_signature}) {"
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
+ }
@@ -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.return_type.is_a?(StructOrUnion) ? "#{function.return_type.ruby_name}.new " : ""
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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ghazel-ffi_gen
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.9.1
4
+ version: 1.3.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Musiol