Class: RubyBindgen::Generators::Rice::SignatureBuilder
- Inherits:
-
Object
- Object
- RubyBindgen::Generators::Rice::SignatureBuilder
- Defined in:
- lib/ruby-bindgen/generators/rice/signature_builder.rb
Overview
Builds callable signatures and argument metadata for generated Rice bindings, including default-value handling and buffer detection.
Constant Summary collapse
- STRING_POINTER_TYPES =
[ :type_char_u, :type_char_s, :type_wchar ].freeze
Instance Method Summary collapse
- #arguments(cursor) ⇒ Object
-
#buffer_type?(type) ⇒ Boolean
Check if a type should use ArgBuffer (for parameters) or ReturnBuffer (for return types).
- #constructor_signature(cursor) ⇒ Object
-
#initialize(type_speller:, reference_qualifier:, cursor_literals:, fundamental_types:) ⇒ SignatureBuilder
constructor
A new instance of SignatureBuilder.
- #method_signature(cursor) ⇒ Object
Constructor Details
#initialize(type_speller:, reference_qualifier:, cursor_literals:, fundamental_types:) ⇒ SignatureBuilder
Returns a new instance of SignatureBuilder.
13 14 15 16 17 18 |
# File 'lib/ruby-bindgen/generators/rice/signature_builder.rb', line 13 def initialize(type_speller:, reference_qualifier:, cursor_literals:, fundamental_types:) @type_speller = type_speller @reference_qualifier = reference_qualifier @cursor_literals = cursor_literals @fundamental_types = fundamental_types end |
Instance Method Details
#arguments(cursor) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/ruby-bindgen/generators/rice/signature_builder.rb', line 69 def arguments(cursor) (0...cursor.num_arguments).map do |index| param = cursor.argument(index) param_name = param.spelling.empty? ? "arg_#{index}" : param.spelling.underscore type = param.type if type.kind == :type_pointer && type.pointee.kind == :type_unexposed type_param = type.pointee.spelling arg_class = "std::conditional_t<std::is_fundamental_v<#{type_param}>, ArgBuffer, Arg>" else arg_class = buffer_type?(type) ? "ArgBuffer" : "Arg" end result = "#{arg_class}(\"#{param_name}\")" default_value = find_default_value(param) if default_value && param.type.copyable? qualified_type = @type_speller.type_spelling(param.type) if param.semantic_parent&.semantic_parent&.kind == :cursor_class_template qualified_type = @type_speller.qualify_class_template_typedefs(qualified_type, param.semantic_parent.semantic_parent) end decl = param.type.declaration is_array_alias = (decl.kind == :cursor_type_alias_decl || decl.kind == :cursor_typedef_decl) && [:type_constant_array, :type_incomplete_array].include?(decl..canonical.kind) if is_array_alias result << " = #{default_value}" elsif default_value == '{}' # Strip cv-qualifiers and reference via libclang so T{} is # well-formed regardless of whether the parameter is `T &`, # `T &&`, or `const T &`. base_type = @type_speller.type_spelling(param.type.non_reference_type.unqualified_type) if param.semantic_parent&.semantic_parent&.kind == :cursor_class_template base_type = @type_speller.qualify_class_template_typedefs(base_type, param.semantic_parent.semantic_parent) end result << " = static_cast<#{qualified_type}>(#{base_type}{})" else result << " = static_cast<#{qualified_type}>(#{default_value})" end end result end end |
#buffer_type?(type) ⇒ Boolean
Check if a type should use ArgBuffer (for parameters) or ReturnBuffer (for return types). Returns true if the type is:
- A pointer to a fundamental type (int*, double*, char*, etc.)
- A double pointer (T**) - pointer to any pointer type
Types that look like pointers to fundamentals but are actually strings char* and wchar_t* are C strings, not buffers
26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/ruby-bindgen/generators/rice/signature_builder.rb', line 26 def buffer_type?(type) return false unless type.kind == :type_pointer pointee = type.pointee pointee_kind = pointee.canonical.kind return false if STRING_POINTER_TYPES.include?(pointee_kind) return true if @fundamental_types.include?(pointee_kind) return true if pointee_kind == :type_pointer false end |
#constructor_signature(cursor) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/ruby-bindgen/generators/rice/signature_builder.rb', line 39 def constructor_signature(cursor) signature = Array.new case cursor.kind when :cursor_constructor parent = cursor.semantic_parent class_name = @type_speller.qualified_display_name(parent) signature << class_name params = constructor_type_spellings(cursor) if cursor.semantic_parent&.kind == :cursor_class_template params = params.map { |pt| @type_speller.qualify_class_template_typedefs(pt, cursor.semantic_parent) } end if parent params = params.map { |pt| @type_speller.qualify_class_static_members(pt, parent) } end if parent&.kind == :cursor_class_template params = params.map { |pt| @type_speller.preserve_template_parameter_names(pt, parent) } end signature += params when :cursor_class_decl, :cursor_struct signature << @type_speller.qualified_display_name(cursor) else raise("Unsupported cursor kind: #{cursor.kind}") end result = signature.compact.join(", ") result.match(/std::initializer_list/) ? nil : result end |
#method_signature(cursor) ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/ruby-bindgen/generators/rice/signature_builder.rb', line 112 def method_signature(cursor) param_types = @type_speller.type_spellings(cursor) result_type = @type_speller.type_spelling(cursor.type.result_type) if cursor.semantic_parent&.kind == :cursor_class_template result_type = @type_speller.qualify_class_template_typedefs(result_type, cursor.semantic_parent) param_types = param_types.map { |pt| @type_speller.qualify_class_template_typedefs(pt, cursor.semantic_parent) } end parent = cursor.semantic_parent if parent result_type = @type_speller.qualify_class_static_members(result_type, parent) param_types = param_types.map { |pt| @type_speller.qualify_class_static_members(pt, parent) } if same_self_type?(cursor.type.result_type, parent) result_type = self_type_spelling(cursor.type.result_type, @type_speller.qualified_display_name(parent)) end end if parent&.kind == :cursor_class_template result_type = @type_speller.preserve_template_parameter_names(result_type, parent) param_types = param_types.map { |pt| @type_speller.preserve_template_parameter_names(pt, parent) } end signature = Array.new if cursor.kind == :cursor_function || cursor.static? signature << "#{result_type}(*)(#{param_types.join(', ')})" else signature << "#{result_type}(#{@type_speller.qualified_display_name(cursor.semantic_parent)}::*)(#{param_types.join(', ')})" end signature << "const" if cursor.const? signature << "noexcept" if cursor.type.exception_specification == :basic_noexcept result = "<#{signature.join(' ')}>" result.match(/std::initializer_list/) ? nil : result end |