ffi_gen 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,6 +8,7 @@ module FFIGen::Clang
8
8
 
9
9
  # A single translation unit, which resides in an index.
10
10
  class TranslationUnitImpl < FFI::Struct
11
+ layout :dummy, :char
11
12
  end
12
13
 
13
14
  # Provides the contents of a file that has not yet been saved to disk.
@@ -316,7 +317,7 @@ module FFIGen::Clang
316
317
  # @method get_presumed_location(location, filename, line, column)
317
318
  # @param [SourceLocation] location the location within a source file that will be decomposed
318
319
  # into its parts.
319
- # @param [FFI::Pointer(*String)] filename (out) if non-NULL, will be set to the filename of the
320
+ # @param [String] filename (out) if non-NULL, will be set to the filename of the
320
321
  # source location. Note that filenames returned will be for "virtual" files,
321
322
  # which don't necessarily exist on the machine running clang - e.g. when
322
323
  # parsing preprocessed output obtained from a different environment. If
@@ -329,7 +330,7 @@ module FFIGen::Clang
329
330
  # source location. For an invalid source location, zero is returned.
330
331
  # @return [nil]
331
332
  # @scope class
332
- attach_function :get_presumed_location, :clang_getPresumedLocation, [SourceLocation.by_value, :pointer, :pointer, :pointer], :void
333
+ attach_function :get_presumed_location, :clang_getPresumedLocation, [SourceLocation.by_value, String, :pointer, :pointer], :void
333
334
 
334
335
  # Legacy API to retrieve the file, line, column, and offset represented
335
336
  # by the given source location.
@@ -565,12 +566,12 @@ module FFIGen::Clang
565
566
  #
566
567
  # @method get_diagnostic_option(diag, disable)
567
568
  # @param [FFI::Pointer(Diagnostic)] diag The diagnostic to be queried.
568
- # @param [FFI::Pointer(*String)] disable If non-NULL, will be set to the option that disables this
569
+ # @param [String] disable If non-NULL, will be set to the option that disables this
569
570
  # diagnostic (if any).
570
571
  # @return [String] A string that contains the command-line option used to enable this
571
572
  # warning, such as "-Wconversion" or "-pedantic".
572
573
  # @scope class
573
- attach_function :get_diagnostic_option, :clang_getDiagnosticOption, [:pointer, :pointer], String.by_value
574
+ attach_function :get_diagnostic_option, :clang_getDiagnosticOption, [:pointer, String], String.by_value
574
575
 
575
576
  # Retrieve the category number for this diagnostic.
576
577
  #
@@ -640,14 +641,14 @@ module FFIGen::Clang
640
641
  # @method get_diagnostic_fix_it(diagnostic, fix_it, replacement_range)
641
642
  # @param [FFI::Pointer(Diagnostic)] diagnostic The diagnostic whose fix-its are being queried.
642
643
  # @param [Integer] fix_it The zero-based index of the fix-it.
643
- # @param [FFI::Pointer(*SourceRange)] replacement_range The source range whose contents will be
644
+ # @param [SourceRange] replacement_range The source range whose contents will be
644
645
  # replaced with the returned replacement string. Note that source
645
646
  # ranges are half-open ranges (a, b), so the source code should be
646
647
  # replaced from a and up to (but not including) b.
647
648
  # @return [String] A string containing text that should be replace the source
648
649
  # code indicated by the \c ReplacementRange.
649
650
  # @scope class
650
- attach_function :get_diagnostic_fix_it, :clang_getDiagnosticFixIt, [:pointer, :uint, :pointer], String.by_value
651
+ attach_function :get_diagnostic_fix_it, :clang_getDiagnosticFixIt, [:pointer, :uint, SourceRange], String.by_value
651
652
 
652
653
  # Get the original translation unit source file name.
653
654
  #
@@ -1961,6 +1962,7 @@ module FFIGen::Clang
1961
1962
 
1962
1963
  # A fast container representing a set of CXCursors.
1963
1964
  class CursorSetImpl < FFI::Struct
1965
+ layout :dummy, :char
1964
1966
  end
1965
1967
 
1966
1968
  # Creates an empty CXCursorSet.
@@ -2120,10 +2122,10 @@ module FFIGen::Clang
2120
2122
  # clang_getOverriddenCursors().
2121
2123
  #
2122
2124
  # @method dispose_overridden_cursors(overridden)
2123
- # @param [FFI::Pointer(*Cursor)] overridden
2125
+ # @param [Cursor] overridden
2124
2126
  # @return [nil]
2125
2127
  # @scope class
2126
- attach_function :dispose_overridden_cursors, :clang_disposeOverriddenCursors, [:pointer], :void
2128
+ attach_function :dispose_overridden_cursors, :clang_disposeOverriddenCursors, [Cursor], :void
2127
2129
 
2128
2130
  # Retrieve the file that is included by the given inclusion directive
2129
2131
  # cursor.
@@ -3025,23 +3027,23 @@ module FFIGen::Clang
3025
3027
  #
3026
3028
  # @method annotate_tokens(tu, tokens, num_tokens, cursors)
3027
3029
  # @param [TranslationUnitImpl] tu the translation unit that owns the given tokens.
3028
- # @param [FFI::Pointer(*Token)] tokens the set of tokens to annotate.
3030
+ # @param [Token] tokens the set of tokens to annotate.
3029
3031
  # @param [Integer] num_tokens the number of tokens in \p Tokens.
3030
- # @param [FFI::Pointer(*Cursor)] cursors an array of \p NumTokens cursors, whose contents will be
3032
+ # @param [Cursor] cursors an array of \p NumTokens cursors, whose contents will be
3031
3033
  # replaced with the cursors corresponding to each token.
3032
3034
  # @return [nil]
3033
3035
  # @scope class
3034
- attach_function :annotate_tokens, :clang_annotateTokens, [TranslationUnitImpl, :pointer, :uint, :pointer], :void
3036
+ attach_function :annotate_tokens, :clang_annotateTokens, [TranslationUnitImpl, Token, :uint, Cursor], :void
3035
3037
 
3036
3038
  # Free the given set of tokens.
3037
3039
  #
3038
3040
  # @method dispose_tokens(tu, tokens, num_tokens)
3039
3041
  # @param [TranslationUnitImpl] tu
3040
- # @param [FFI::Pointer(*Token)] tokens
3042
+ # @param [Token] tokens
3041
3043
  # @param [Integer] num_tokens
3042
3044
  # @return [nil]
3043
3045
  # @scope class
3044
- attach_function :dispose_tokens, :clang_disposeTokens, [TranslationUnitImpl, :pointer, :uint], :void
3046
+ attach_function :dispose_tokens, :clang_disposeTokens, [TranslationUnitImpl, Token, :uint], :void
3045
3047
 
3046
3048
  # for debug/testing
3047
3049
  #
@@ -3357,12 +3359,12 @@ module FFIGen::Clang
3357
3359
  #
3358
3360
  # = Fields:
3359
3361
  # :results ::
3360
- # (FFI::Pointer(*CompletionResult)) The code-completion results.
3362
+ # (CompletionResult) The code-completion results.
3361
3363
  # :num_results ::
3362
3364
  # (Integer) The number of code-completion results stored in the
3363
3365
  # \c Results array.
3364
3366
  class CodeCompleteResults < FFI::Struct
3365
- layout :results, :pointer,
3367
+ layout :results, CompletionResult,
3366
3368
  :num_results, :uint
3367
3369
  end
3368
3370
 
@@ -3473,39 +3475,39 @@ module FFIGen::Clang
3473
3475
  # CXCodeComplete_Flags enumeration. The
3474
3476
  # \c clang_defaultCodeCompleteOptions() function returns a default set
3475
3477
  # of code-completion options.
3476
- # @return [FFI::Pointer(*CodeCompleteResults)] If successful, a new \c CXCodeCompleteResults structure
3478
+ # @return [CodeCompleteResults] If successful, a new \c CXCodeCompleteResults structure
3477
3479
  # containing code-completion results, which should eventually be
3478
3480
  # freed with \c clang_disposeCodeCompleteResults(). If code
3479
3481
  # completion fails, returns NULL.
3480
3482
  # @scope class
3481
- attach_function :code_complete_at, :clang_codeCompleteAt, [TranslationUnitImpl, :string, :uint, :uint, UnsavedFile, :uint, :uint], :pointer
3483
+ attach_function :code_complete_at, :clang_codeCompleteAt, [TranslationUnitImpl, :string, :uint, :uint, UnsavedFile, :uint, :uint], CodeCompleteResults
3482
3484
 
3483
3485
  # Sort the code-completion results in case-insensitive alphabetical
3484
3486
  # order.
3485
3487
  #
3486
3488
  # @method sort_code_completion_results(results, num_results)
3487
- # @param [FFI::Pointer(*CompletionResult)] results The set of results to sort.
3489
+ # @param [CompletionResult] results The set of results to sort.
3488
3490
  # @param [Integer] num_results The number of results in \p Results.
3489
3491
  # @return [nil]
3490
3492
  # @scope class
3491
- attach_function :sort_code_completion_results, :clang_sortCodeCompletionResults, [:pointer, :uint], :void
3493
+ attach_function :sort_code_completion_results, :clang_sortCodeCompletionResults, [CompletionResult, :uint], :void
3492
3494
 
3493
3495
  # Free the given set of code-completion results.
3494
3496
  #
3495
3497
  # @method dispose_code_complete_results(results)
3496
- # @param [FFI::Pointer(*CodeCompleteResults)] results
3498
+ # @param [CodeCompleteResults] results
3497
3499
  # @return [nil]
3498
3500
  # @scope class
3499
- attach_function :dispose_code_complete_results, :clang_disposeCodeCompleteResults, [:pointer], :void
3501
+ attach_function :dispose_code_complete_results, :clang_disposeCodeCompleteResults, [CodeCompleteResults], :void
3500
3502
 
3501
3503
  # Determine the number of diagnostics produced prior to the
3502
3504
  # location where code completion was performed.
3503
3505
  #
3504
3506
  # @method code_complete_get_num_diagnostics(results)
3505
- # @param [FFI::Pointer(*CodeCompleteResults)] results
3507
+ # @param [CodeCompleteResults] results
3506
3508
  # @return [Integer]
3507
3509
  # @scope class
3508
- attach_function :code_complete_get_num_diagnostics, :clang_codeCompleteGetNumDiagnostics, [:pointer], :uint
3510
+ attach_function :code_complete_get_num_diagnostics, :clang_codeCompleteGetNumDiagnostics, [CodeCompleteResults], :uint
3509
3511
 
3510
3512
  # Retrieve a diagnostic associated with the given code completion.
3511
3513
  #
@@ -3513,22 +3515,22 @@ module FFIGen::Clang
3513
3515
  # the code completion results to query.
3514
3516
  #
3515
3517
  # @method code_complete_get_diagnostic(results, index)
3516
- # @param [FFI::Pointer(*CodeCompleteResults)] results
3518
+ # @param [CodeCompleteResults] results
3517
3519
  # @param [Integer] index the zero-based diagnostic number to retrieve.
3518
3520
  # @return [FFI::Pointer(Diagnostic)] the requested diagnostic. This diagnostic must be freed
3519
3521
  # via a call to \c clang_disposeDiagnostic().
3520
3522
  # @scope class
3521
- attach_function :code_complete_get_diagnostic, :clang_codeCompleteGetDiagnostic, [:pointer, :uint], :pointer
3523
+ attach_function :code_complete_get_diagnostic, :clang_codeCompleteGetDiagnostic, [CodeCompleteResults, :uint], :pointer
3522
3524
 
3523
3525
  # Determines what compeltions are appropriate for the context
3524
3526
  # the given code completion.
3525
3527
  #
3526
3528
  # @method code_complete_get_contexts(results)
3527
- # @param [FFI::Pointer(*CodeCompleteResults)] results the code completion results to query
3529
+ # @param [CodeCompleteResults] results the code completion results to query
3528
3530
  # @return [Integer] the kinds of completions that are appropriate for use
3529
3531
  # along with the given code completion results.
3530
3532
  # @scope class
3531
- attach_function :code_complete_get_contexts, :clang_codeCompleteGetContexts, [:pointer], :ulong_long
3533
+ attach_function :code_complete_get_contexts, :clang_codeCompleteGetContexts, [CodeCompleteResults], :ulong_long
3532
3534
 
3533
3535
  # Returns the cursor kind for the container for the current code
3534
3536
  # completion context. The container is only guaranteed to be set for
@@ -3537,24 +3539,24 @@ module FFIGen::Clang
3537
3539
  # CXCursor_InvalidCode.
3538
3540
  #
3539
3541
  # @method code_complete_get_container_kind(results, is_incomplete)
3540
- # @param [FFI::Pointer(*CodeCompleteResults)] results the code completion results to query
3542
+ # @param [CodeCompleteResults] results the code completion results to query
3541
3543
  # @param [FFI::Pointer(*UInt)] is_incomplete on return, this value will be false if Clang has complete
3542
3544
  # information about the container. If Clang does not have complete
3543
3545
  # information, this value will be true.
3544
3546
  # @return [Symbol from _enum_cursor_kind_] the container kind, or CXCursor_InvalidCode if there is not a
3545
3547
  # container
3546
3548
  # @scope class
3547
- attach_function :code_complete_get_container_kind, :clang_codeCompleteGetContainerKind, [:pointer, :pointer], :cursor_kind
3549
+ attach_function :code_complete_get_container_kind, :clang_codeCompleteGetContainerKind, [CodeCompleteResults, :pointer], :cursor_kind
3548
3550
 
3549
3551
  # Returns the USR for the container for the current code completion
3550
3552
  # context. If there is not a container for the current context, this
3551
3553
  # function will return the empty string.
3552
3554
  #
3553
3555
  # @method code_complete_get_container_usr(results)
3554
- # @param [FFI::Pointer(*CodeCompleteResults)] results the code completion results to query
3556
+ # @param [CodeCompleteResults] results the code completion results to query
3555
3557
  # @return [String] the USR for the container
3556
3558
  # @scope class
3557
- attach_function :code_complete_get_container_usr, :clang_codeCompleteGetContainerUSR, [:pointer], String.by_value
3559
+ attach_function :code_complete_get_container_usr, :clang_codeCompleteGetContainerUSR, [CodeCompleteResults], String.by_value
3558
3560
 
3559
3561
  # Returns the currently-entered selector for an Objective-C message
3560
3562
  # send, formatted like "initWithFoo:bar:". Only guaranteed to return a
@@ -3562,11 +3564,11 @@ module FFIGen::Clang
3562
3564
  # CXCompletionContext_ObjCClassMessage.
3563
3565
  #
3564
3566
  # @method code_complete_get_obj_c_selector(results)
3565
- # @param [FFI::Pointer(*CodeCompleteResults)] results the code completion results to query
3567
+ # @param [CodeCompleteResults] results the code completion results to query
3566
3568
  # @return [String] the selector (or partial selector) that has been entered thus far
3567
3569
  # for an Objective-C message send.
3568
3570
  # @scope class
3569
- attach_function :code_complete_get_obj_c_selector, :clang_codeCompleteGetObjCSelector, [:pointer], String.by_value
3571
+ attach_function :code_complete_get_obj_c_selector, :clang_codeCompleteGetObjCSelector, [CodeCompleteResults], String.by_value
3570
3572
 
3571
3573
  # Return a version string, suitable for showing to a user, but not
3572
3574
  # intended to be parsed (the format is not guaranteed to be stable).
@@ -3601,12 +3603,12 @@ module FFIGen::Clang
3601
3603
  # <em>This entry is only for documentation and no real method.</em>
3602
3604
  #
3603
3605
  # @method _callback_inclusion_visitor_(inclusion_stack, include_len, client_data)
3604
- # @param [FFI::Pointer(*SourceLocation)] inclusion_stack
3606
+ # @param [SourceLocation] inclusion_stack
3605
3607
  # @param [Integer] include_len
3606
3608
  # @param [FFI::Pointer(ClientData)] client_data
3607
3609
  # @return [FFI::Pointer(File)]
3608
3610
  # @scope class
3609
- callback :inclusion_visitor, [:pointer, :uint, :pointer], :pointer
3611
+ callback :inclusion_visitor, [SourceLocation, :uint, :pointer], :pointer
3610
3612
 
3611
3613
  # Visit the set of preprocessor inclusions in a translation unit.
3612
3614
  # The visitor function is called with the provided data for every included
@@ -3643,12 +3645,12 @@ module FFIGen::Clang
3643
3645
  # @method remap_get_filenames(remapping, index, original, transformed)
3644
3646
  # @param [FFI::Pointer(Remapping)] remapping
3645
3647
  # @param [Integer] index
3646
- # @param [FFI::Pointer(*String)] original If non-NULL, will be set to the original filename.
3647
- # @param [FFI::Pointer(*String)] transformed If non-NULL, will be set to the filename that the original
3648
+ # @param [String] original If non-NULL, will be set to the original filename.
3649
+ # @param [String] transformed If non-NULL, will be set to the filename that the original
3648
3650
  # is associated with.
3649
3651
  # @return [nil]
3650
3652
  # @scope class
3651
- attach_function :remap_get_filenames, :clang_remap_getFilenames, [:pointer, :uint, :pointer, :pointer], :void
3653
+ attach_function :remap_get_filenames, :clang_remap_getFilenames, [:pointer, :uint, String, String], :void
3652
3654
 
3653
3655
  # Dispose the remapping.
3654
3656
  #
@@ -0,0 +1,242 @@
1
+ class FFIGen
2
+ def generate_java
3
+ writer = Writer.new " ", " * ", "/**", " */"
4
+ writer.puts "// Generated by ffi_gen. Please do not change this file by hand.", "import java.util.*;", "import com.sun.jna.*;", "import java.lang.annotation.*;", "import java.lang.reflect.Method;", "", "public interface #{@module_name} extends Library {"
5
+ writer.indent do
6
+ writer.puts "", *IO.readlines(File.join(File.dirname(__FILE__), "java_pre.java")).map(&:rstrip)
7
+ writer.puts "", "public static #{@module_name} INSTANCE = JnaInstanceCreator.createInstance();", ""
8
+ writer.puts "static class JnaInstanceCreator {"
9
+ writer.indent do
10
+ writer.puts "private static #{@module_name} createInstance() {"
11
+ writer.indent do
12
+ writer.puts "DefaultTypeMapper typeMapper = new DefaultTypeMapper();", "typeMapper.addFromNativeConverter(NativeEnum.class, new EnumConverter());", "typeMapper.addToNativeConverter(NativeEnum.class, new EnumConverter());", ""
13
+ writer.puts "Map<String, Object> options = new HashMap<String, Object>();", "options.put(Library.OPTION_FUNCTION_MAPPER, new NativeNameAnnotationFunctionMapper());", "options.put(Library.OPTION_TYPE_MAPPER, typeMapper);", ""
14
+ writer.puts "return (#{@module_name}) Native.loadLibrary(\"#{@ffi_lib}\", #{@module_name}.class, options);"
15
+ end
16
+ writer.puts "}"
17
+ end
18
+ writer.puts "}", ""
19
+ declarations.values.compact.uniq.each do |declaration|
20
+ declaration.write_java writer
21
+ end
22
+ end
23
+ writer.puts "}"
24
+ writer.output
25
+ end
26
+
27
+ def to_java_type(full_type, is_array = false)
28
+ canonical_type = Clang.get_canonical_type full_type
29
+ data_array = case canonical_type[:kind]
30
+ when :void then ["void", "nil"]
31
+ when :bool then ["boolean", "Boolean"]
32
+ when :u_char then ["byte", "Integer"]
33
+ when :u_short then ["short", "Integer"]
34
+ when :u_int then ["int", "Integer"]
35
+ when :u_long then ["NativeLong", "Integer"]
36
+ when :u_long_long then ["long", "Integer"]
37
+ when :char_s, :s_char then ["byte", "Integer"]
38
+ when :short then ["short", "Integer"]
39
+ when :int then ["int", "Integer"]
40
+ when :long then ["NativeLong", "Integer"]
41
+ when :long_long then ["long", "Integer"]
42
+ when :float then ["float", "Float"]
43
+ when :double then ["double", "Float"]
44
+ when :pointer
45
+ if is_array
46
+ element_type = to_java_type Clang.get_pointee_type(canonical_type)
47
+ return { jna_type: "#{element_type[:jna_type]}[]", description: "Array of #{element_type[:description]}", parameter_name: element_type[:parameter_name] }
48
+ end
49
+
50
+ pointee_type = Clang.get_pointee_type canonical_type
51
+ result = nil
52
+ case pointee_type[:kind]
53
+ when :char_s
54
+ result = ["String", "String"]
55
+ when :record
56
+ pointee_declaration = @declarations[Clang.get_cursor_type(Clang.get_type_declaration(pointee_type))]
57
+ result = [pointee_declaration.java_name, pointee_declaration.java_name] if pointee_declaration and pointee_declaration.written
58
+ when :function_proto
59
+ declaration = @declarations[full_type]
60
+ result = [":#{declaration.java_name}", "Proc(_callback_#{declaration.java_name}_)"] if declaration
61
+ end
62
+
63
+ if result.nil?
64
+ pointer_depth = 0
65
+ pointer_target_name = ""
66
+ current_type = full_type
67
+ loop do
68
+ declaration = Clang.get_type_declaration current_type
69
+ pointer_target_name = Name.new self, Clang.get_cursor_spelling(declaration).to_s_and_dispose
70
+ break if not pointer_target_name.empty?
71
+
72
+ case current_type[:kind]
73
+ when :pointer
74
+ pointer_depth += 1
75
+ current_type = Clang.get_pointee_type current_type
76
+ when :unexposed
77
+ break
78
+ else
79
+ pointer_target_name = Name.new self, Clang.get_type_kind_spelling(current_type[:kind]).to_s_and_dispose
80
+ break
81
+ end
82
+ end
83
+ result = ["Pointer", "FFI::Pointer(#{'*' * pointer_depth}#{pointer_target_name.to_java_classname})", pointer_target_name]
84
+ end
85
+
86
+ result
87
+ when :record
88
+ declaration = @declarations[canonical_type]
89
+ declaration ? ["#{declaration.java_name}.by_value", declaration.java_name] : ["byte", "unknown"] # TODO
90
+ when :enum
91
+ declaration = @declarations[canonical_type]
92
+ declaration ? [declaration.java_name, "Symbol from _enum_#{declaration.java_name}_", declaration.name] : ["byte", "unknown"] # TODO
93
+ when :constant_array
94
+ element_type_data = to_java_type Clang.get_array_element_type(canonical_type)
95
+ size = Clang.get_array_size canonical_type
96
+ ["[#{element_type_data[:jna_type]}, #{size}]", "Array<#{element_type_data[:description]}>"]
97
+ else
98
+ raise NotImplementedError, "No translation for values of type #{canonical_type[:kind]}"
99
+ end
100
+
101
+ { jna_type: data_array[0], description: data_array[1], parameter_name: (data_array[2] || Name.new(self, data_array[1])).to_java_downcase }
102
+ end
103
+
104
+ class Name
105
+ JAVA_KEYWORDS = %w{abstract assert boolean break byte case catch char class const continue default do double else enum extends final finally float for goto if implements import instanceof int interface long native new package private protected public return short static strictfp super switch synchronized this throw throws transient try void volatile while}
106
+
107
+ def to_java_downcase
108
+ format :camelcase, :initial_downcase, JAVA_KEYWORDS
109
+ end
110
+
111
+ def to_java_classname
112
+ format :camelcase, JAVA_KEYWORDS
113
+ end
114
+
115
+ def to_java_constant
116
+ format :upcase, :underscores, JAVA_KEYWORDS
117
+ end
118
+ end
119
+
120
+ class Enum
121
+ def write_java(writer)
122
+ shorten_names
123
+
124
+ @constants.each do |constant|
125
+ constant[:symbol] = ":#{constant[:name].to_ruby_downcase}"
126
+ end
127
+
128
+ writer.comment do
129
+ writer.write_description @comment
130
+ # TODO constant comments
131
+ end
132
+
133
+ writer.puts "public enum #{java_name} implements NativeEnum {"
134
+ writer.indent do
135
+ writer.write_array @constants, "," do |constant|
136
+ "#{constant[:name].to_java_constant}(#{constant[:value]})"
137
+ end
138
+ writer.puts ";"
139
+
140
+ writer.puts "", "private int nativeInt;", "", "private #{java_name}(int nativeInt) {", " this.nativeInt = nativeInt;", "}", "", "@Override", "public int toNativeInt() {", " return nativeInt;", "}"
141
+ end
142
+ writer.puts "}", ""
143
+ end
144
+
145
+ def java_name
146
+ @java_name ||= @name.to_java_classname
147
+ end
148
+ end
149
+
150
+ class StructOrUnion
151
+ def write_java(writer)
152
+ @fields.each do |field|
153
+ field[:symbol] = field[:name].to_java_downcase
154
+ field[:type_data] = @generator.to_java_type field[:type]
155
+ end
156
+
157
+ writer.comment do
158
+ writer.write_description @comment
159
+ unless @fields.empty?
160
+ writer.puts "", "= Fields:"
161
+ @fields.each do |field|
162
+ writer.puts "#{field[:symbol]} ::"
163
+ writer.write_description field[:comment], false, " (#{field[:type_data][:description]}) ", " "
164
+ end
165
+ end
166
+ end
167
+
168
+ writer.puts "public static class #{java_name} extends #{@is_union ? 'Union' : (@fields.empty? ? 'PointerType' : 'Structure')} {"
169
+ writer.indent do
170
+ @fields.each do |field|
171
+ writer.puts "public #{field[:type_data][:jna_type]} #{field[:symbol]};"
172
+ end
173
+ writer.puts "// hidden structure" if @fields.empty?
174
+ end
175
+ writer.puts "}", ""
176
+
177
+ @written = true
178
+ end
179
+
180
+ def java_name
181
+ @java_name ||= @name.to_java_classname
182
+ end
183
+ end
184
+
185
+ class FunctionOrCallback
186
+ def write_java(writer)
187
+ return if @is_callback # not yet supported
188
+
189
+ @parameters.each do |parameter|
190
+ parameter[:type_data] = @generator.to_java_type parameter[:type], parameter[:is_array]
191
+ parameter[:java_name] = !parameter[:name].empty? ? parameter[:name].to_java_downcase : parameter[:type_data][:parameter_name]
192
+ parameter[:description] = []
193
+ end
194
+ return_type_data = @generator.to_java_type @return_type
195
+
196
+ function_description = []
197
+ return_value_description = []
198
+ current_description = function_description
199
+ @comment.split("\n").map do |line|
200
+ line = writer.prepare_comment_line line
201
+ if line.gsub!(/\\param (.*?) /, '')
202
+ parameter = @parameters.find { |p| p[:name].raw == $1 }
203
+ if parameter
204
+ current_description = parameter[:description]
205
+ else
206
+ current_description << "#{$1}: "
207
+ end
208
+ end
209
+ current_description = return_value_description if line.gsub! '\\returns ', ''
210
+ current_description << line
211
+ end
212
+
213
+ writer.comment do
214
+ writer.write_description function_description
215
+ writer.puts "", "<em>This entry is only for documentation and no real method.</em>" if @is_callback
216
+ writer.puts "", "@method #{@is_callback ? "_callback_#{java_name}_" : java_name}(#{@parameters.map{ |parameter| parameter[:java_name] }.join(', ')})"
217
+ @parameters.each do |parameter|
218
+ writer.write_description parameter[:description], false, "@param [#{parameter[:type_data][:description]}] #{parameter[:java_name]} ", " "
219
+ end
220
+ writer.write_description return_value_description, false, "@return [#{return_type_data[:description]}] ", " "
221
+ writer.puts "@scope class"
222
+ end
223
+
224
+ jna_signature = "#{@parameters.map{ |parameter| "#{parameter[:type_data][:jna_type]} #{parameter[:java_name]}" }.join(', ')}"
225
+ if @is_callback
226
+ writer.puts "callback :#{java_name}, #{jna_signature}", ""
227
+ else
228
+ writer.puts "@NativeName(\"#{@name.raw}\")", "#{return_type_data[:jna_type]} #{java_name}(#{jna_signature});", ""
229
+ end
230
+ end
231
+
232
+ def java_name
233
+ @java_name ||= @name.to_java_downcase
234
+ end
235
+ end
236
+
237
+ class Constant
238
+ def write_java(writer)
239
+ writer.puts "public static int #{@name.to_java_constant} = #{@value};", ""
240
+ end
241
+ end
242
+ end