gir_ffi 0.10.2 → 0.11.0
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/Changelog.md +13 -0
- data/Gemfile +9 -4
- data/README.md +3 -2
- data/Rakefile +2 -1
- data/lib/ffi-glib/byte_array.rb +1 -1
- data/lib/ffi-glib/main_loop.rb +2 -1
- data/lib/ffi-glib/strv.rb +5 -2
- data/lib/ffi-glib/variant.rb +3 -5
- data/lib/ffi-glib.rb +4 -0
- data/lib/ffi-gobject/closure.rb +8 -10
- data/lib/ffi-gobject/object.rb +9 -6
- data/lib/ffi-gobject/param_spec.rb +4 -0
- data/lib/ffi-gobject/value.rb +13 -16
- data/lib/ffi-gobject_introspection/gobject_type_init.rb +18 -0
- data/lib/ffi-gobject_introspection/i_callable_info.rb +1 -5
- data/lib/ffi-gobject_introspection/i_constant_info.rb +3 -3
- data/lib/ffi-gobject_introspection/i_repository.rb +3 -47
- data/lib/ffi-gobject_introspection/i_vfunc_info.rb +3 -11
- data/lib/ffi-gobject_introspection/lib.rb +8 -31
- data/lib/{gir_ffi-base/glib → ffi-gobject_introspection}/strv.rb +9 -13
- data/lib/ffi-gobject_introspection.rb +47 -2
- data/lib/gir_ffi/allocation_helper.rb +1 -19
- data/lib/gir_ffi/arg_helper.rb +36 -26
- data/lib/{gir_ffi-base/glib → gir_ffi}/boolean.rb +7 -5
- data/lib/gir_ffi/boxed_base.rb +5 -23
- data/lib/gir_ffi/builder.rb +3 -3
- data/lib/gir_ffi/builders/argument_builder.rb +7 -8
- data/lib/gir_ffi/builders/base_argument_builder.rb +0 -1
- data/lib/gir_ffi/builders/callback_argument_builder.rb +2 -2
- data/lib/gir_ffi/builders/callback_return_value_builder.rb +21 -13
- data/lib/gir_ffi/builders/field_builder.rb +4 -10
- data/lib/gir_ffi/builders/module_builder.rb +6 -4
- data/lib/gir_ffi/builders/object_builder.rb +16 -16
- data/lib/gir_ffi/builders/struct_builder.rb +4 -6
- data/lib/gir_ffi/builders/struct_like.rb +1 -1
- data/lib/gir_ffi/builders/user_defined_builder.rb +83 -23
- data/lib/gir_ffi/builders/vfunc_argument_builder.rb +12 -17
- data/lib/gir_ffi/class_base.rb +0 -4
- data/lib/gir_ffi/core.rb +16 -13
- data/lib/gir_ffi/enum_base.rb +2 -41
- data/lib/gir_ffi/enum_like_base.rb +48 -0
- data/lib/gir_ffi/ffi_ext/pointer.rb +1 -1
- data/lib/gir_ffi/flags_base.rb +2 -41
- data/lib/gir_ffi/in_out_pointer.rb +1 -1
- data/lib/gir_ffi/in_pointer.rb +4 -4
- data/lib/gir_ffi/info_ext/i_type_info.rb +14 -5
- data/lib/gir_ffi/info_ext/i_vfunc_info.rb +8 -0
- data/lib/gir_ffi/module_base.rb +4 -0
- data/lib/gir_ffi/receiver_argument_info.rb +1 -1
- data/lib/gir_ffi/sized_array.rb +6 -6
- data/lib/gir_ffi/struct_base.rb +1 -6
- data/lib/gir_ffi/struct_like_base.rb +54 -45
- data/lib/gir_ffi/type_map.rb +6 -7
- data/lib/gir_ffi/union_base.rb +1 -1
- data/lib/gir_ffi/{user_defined_type_info.rb → user_defined_object_info.rb} +1 -2
- data/lib/gir_ffi/user_defined_property_info.rb +80 -2
- data/lib/gir_ffi/version.rb +1 -1
- data/lib/gir_ffi-base/gobject/lib.rb +0 -1
- data/lib/gir_ffi-base/gobject.rb +3 -5
- data/lib/gir_ffi-base.rb +3 -8
- data/tasks/test.rake +17 -3
- data/test/base_test_helper.rb +39 -23
- data/test/ffi-glib/closure_test.rb +37 -0
- data/test/ffi-glib/main_loop_test.rb +24 -0
- data/test/ffi-glib/ruby_closure_test.rb +0 -5
- data/test/ffi-gobject/object_test.rb +6 -10
- data/test/ffi-gobject/param_spec_test.rb +17 -5
- data/test/ffi-gobject/value_test.rb +15 -6
- data/test/ffi-gobject_introspection/gobject_type_init_test.rb +25 -0
- data/test/ffi-gobject_introspection/i_base_info_test.rb +1 -1
- data/test/ffi-gobject_introspection/i_repository_test.rb +18 -0
- data/test/ffi-gobject_introspection/i_vfunc_info_test.rb +40 -0
- data/test/{gir_ffi-base/glib → ffi-gobject_introspection}/strv_test.rb +8 -8
- data/test/gir_ffi/allocation_helper_test.rb +35 -0
- data/test/gir_ffi/arg_helper_test.rb +102 -7
- data/test/gir_ffi/boolean_test.rb +34 -0
- data/test/gir_ffi/boxed_base_test.rb +46 -6
- data/test/gir_ffi/builder_test.rb +88 -29
- data/test/gir_ffi/builders/argument_builder_test.rb +19 -0
- data/test/gir_ffi/builders/callback_argument_builder_test.rb +17 -0
- data/test/gir_ffi/builders/callback_return_value_builder_test.rb +1 -1
- data/test/gir_ffi/builders/field_builder_test.rb +2 -1
- data/test/gir_ffi/builders/struct_builder_test.rb +42 -25
- data/test/gir_ffi/builders/user_defined_builder_test.rb +365 -17
- data/test/gir_ffi/builders/vfunc_argument_builder_test.rb +100 -0
- data/test/gir_ffi/builders/vfunc_builder_test.rb +5 -3
- data/test/{gir_ffi_test.rb → gir_ffi/core_test.rb} +8 -6
- data/test/gir_ffi/in_out_pointer_test.rb +1 -1
- data/test/gir_ffi/receiver_argument_info_test.rb +32 -0
- data/test/gir_ffi/sized_array_test.rb +34 -0
- data/test/gir_ffi/struct_base_test.rb +4 -32
- data/test/gir_ffi/struct_like_base_test.rb +164 -0
- data/test/gir_ffi/union_base_test.rb +4 -20
- data/test/gir_ffi/{user_defined_type_info_test.rb → user_defined_object_info_test.rb} +10 -10
- data/test/gir_ffi/user_defined_property_info_test.rb +22 -5
- data/test/gir_ffi/version_test.rb +1 -1
- data/test/integration/callback_exceptions_test.rb +2 -0
- data/test/integration/derived_classes_test.rb +2 -0
- data/test/integration/generated_everything_test.rb +22 -0
- data/test/integration/generated_gimarshallingtests_test.rb +23 -21
- data/test/integration/generated_gio_test.rb +2 -0
- data/test/integration/generated_glib_test.rb +2 -0
- data/test/integration/generated_gst_test.rb +2 -0
- data/test/integration/generated_gtop_test.rb +2 -0
- data/test/integration/generated_regress_test.rb +113 -29
- data/test/integration/generated_secret_test.rb +2 -0
- data/test/integration/generated_warnlib_test.rb +2 -0
- data/test/integration/method_lookup_test.rb +2 -0
- data/test/introspection_test_helper.rb +15 -0
- metadata +21 -27
- data/lib/gir_ffi-base/glib.rb +0 -8
- data/test/gir_ffi-base/glib/boolean_test.rb +0 -34
    
        data/lib/gir_ffi/arg_helper.rb
    CHANGED
    
    | @@ -10,45 +10,28 @@ module GirFFI | |
| 10 10 | 
             
              module ArgHelper
         | 
| 11 11 | 
             
                OBJECT_STORE = ObjectStore.new
         | 
| 12 12 |  | 
| 13 | 
            -
                def self.ptr_to_utf8_length(ptr, len)
         | 
| 14 | 
            -
                  ptr.null? ? nil : ptr.read_string(len)
         | 
| 15 | 
            -
                end
         | 
| 16 | 
            -
             | 
| 17 13 | 
             
                def self.check_error(errpp)
         | 
| 18 14 | 
             
                  err = GLib::Error.wrap(errpp.read_pointer)
         | 
| 19 15 | 
             
                  raise GLibError, err if err
         | 
| 20 16 | 
             
                end
         | 
| 21 17 |  | 
| 22 18 | 
             
                def self.check_fixed_array_size(size, arr, name)
         | 
| 23 | 
            -
                  unless arr.size  | 
| 19 | 
            +
                  unless arr.size.equal? size
         | 
| 24 20 | 
             
                    raise ArgumentError, "#{name} should have size #{size}"
         | 
| 25 21 | 
             
                  end
         | 
| 26 22 | 
             
                end
         | 
| 27 23 |  | 
| 28 | 
            -
                 | 
| 24 | 
            +
                # NOTE: Only used in List, SList and HashTable classes.
         | 
| 25 | 
            +
                # TODO: Stop using basic types and instead cast type to an ITypeInfo
         | 
| 26 | 
            +
                # look-alike.
         | 
| 27 | 
            +
                def self.cast_from_pointer(type, ptr)
         | 
| 29 28 | 
             
                  case type
         | 
| 30 | 
            -
                  when  | 
| 31 | 
            -
                     | 
| 32 | 
            -
                  when :gint32, :gint8
         | 
| 33 | 
            -
                    cast_pointer_to_int32 it
         | 
| 29 | 
            +
                  when Symbol
         | 
| 30 | 
            +
                    cast_from_simple_type_pointer(type, ptr)
         | 
| 34 31 | 
             
                  when Class
         | 
| 35 | 
            -
                    type.wrap  | 
| 36 | 
            -
                  when :guint32
         | 
| 37 | 
            -
                    it.address
         | 
| 32 | 
            +
                    type.wrap ptr
         | 
| 38 33 | 
             
                  when Array
         | 
| 39 | 
            -
                     | 
| 40 | 
            -
                    raise "Unexpected main type #{main_type}" if main_type != :pointer
         | 
| 41 | 
            -
                    case subtype
         | 
| 42 | 
            -
                    when Array
         | 
| 43 | 
            -
                      container_type, *element_type = *subtype
         | 
| 44 | 
            -
                      raise "Unexpected container type #{container_type}" if container_type != :ghash
         | 
| 45 | 
            -
                      GLib::HashTable.wrap(element_type, it)
         | 
| 46 | 
            -
                    else
         | 
| 47 | 
            -
                      raise "Unexpected subtype #{subtype}"
         | 
| 48 | 
            -
                    end
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                  else
         | 
| 51 | 
            -
                    raise "Don't know how to cast #{type}"
         | 
| 34 | 
            +
                    cast_from_complex_type_pointer(type, ptr)
         | 
| 52 35 | 
             
                  end
         | 
| 53 36 | 
             
                end
         | 
| 54 37 |  | 
| @@ -67,5 +50,32 @@ module GirFFI | |
| 67 50 | 
             
                def self.store(obj)
         | 
| 68 51 | 
             
                  OBJECT_STORE.store(obj)
         | 
| 69 52 | 
             
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                def self.cast_from_simple_type_pointer(type, ptr)
         | 
| 55 | 
            +
                  case type
         | 
| 56 | 
            +
                  when :utf8, :filename
         | 
| 57 | 
            +
                    ptr.to_utf8
         | 
| 58 | 
            +
                  when :gint32, :gint8
         | 
| 59 | 
            +
                    cast_pointer_to_int32 ptr
         | 
| 60 | 
            +
                  when :guint32
         | 
| 61 | 
            +
                    ptr.address
         | 
| 62 | 
            +
                  else
         | 
| 63 | 
            +
                    raise "Don't know how to cast #{type}"
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                def self.cast_from_complex_type_pointer(type, ptr)
         | 
| 68 | 
            +
                  main_type, (container_type, *element_type) = *type
         | 
| 69 | 
            +
                  case main_type
         | 
| 70 | 
            +
                  when :pointer
         | 
| 71 | 
            +
                    case container_type
         | 
| 72 | 
            +
                    when :ghash
         | 
| 73 | 
            +
                      return GLib::HashTable.wrap(element_type, ptr)
         | 
| 74 | 
            +
                    end
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
                  raise "Don't know how to cast #{type}"
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                private_class_method :cast_from_complex_type_pointer, :cast_from_simple_type_pointer
         | 
| 70 80 | 
             
              end
         | 
| 71 81 | 
             
            end
         | 
| @@ -1,19 +1,21 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 | 
             
            require 'ffi'
         | 
| 3 | 
            -
            require 'gir_ffi-base/glib'
         | 
| 4 3 |  | 
| 5 | 
            -
            module  | 
| 6 | 
            -
              #  | 
| 4 | 
            +
            module GirFFI
         | 
| 5 | 
            +
              # Class representing a boolean (natively, an int).
         | 
| 7 6 | 
             
              class Boolean
         | 
| 8 7 | 
             
                extend FFI::DataConverter
         | 
| 9 8 | 
             
                native_type FFI::Type::INT
         | 
| 10 9 |  | 
| 10 | 
            +
                FROM_NATIVE = { 0 => false, 1 => true }.freeze
         | 
| 11 | 
            +
                TO_NATIVE = FROM_NATIVE.invert
         | 
| 12 | 
            +
             | 
| 11 13 | 
             
                def self.from_native(value, _context)
         | 
| 12 | 
            -
                  value | 
| 14 | 
            +
                  FROM_NATIVE.fetch(value)
         | 
| 13 15 | 
             
                end
         | 
| 14 16 |  | 
| 15 17 | 
             
                def self.to_native(value, _context)
         | 
| 16 | 
            -
                  value | 
| 18 | 
            +
                  TO_NATIVE.fetch(value)
         | 
| 17 19 | 
             
                end
         | 
| 18 20 |  | 
| 19 21 | 
             
                def self.size
         | 
    
        data/lib/gir_ffi/boxed_base.rb
    CHANGED
    
    | @@ -5,50 +5,32 @@ module GirFFI | |
| 5 5 | 
             
              # Base class for generated classes representing boxed types.
         | 
| 6 6 | 
             
              class BoxedBase < StructBase
         | 
| 7 7 | 
             
                def initialize
         | 
| 8 | 
            -
                  store_pointer( | 
| 8 | 
            +
                  store_pointer(nil)
         | 
| 9 9 | 
             
                end
         | 
| 10 10 |  | 
| 11 | 
            -
                def self.make_finalizer(struct | 
| 11 | 
            +
                def self.make_finalizer(struct)
         | 
| 12 12 | 
             
                  proc do
         | 
| 13 13 | 
             
                    if struct.owned?
         | 
| 14 | 
            -
                      struct.owned =  | 
| 14 | 
            +
                      struct.owned = nil
         | 
| 15 15 | 
             
                      GObject.boxed_free gtype, struct.to_ptr
         | 
| 16 16 | 
             
                    end
         | 
| 17 17 | 
             
                  end
         | 
| 18 18 | 
             
                end
         | 
| 19 19 |  | 
| 20 | 
            -
                # Wrap value and take ownership of it
         | 
| 21 | 
            -
                def self.wrap_own(val)
         | 
| 22 | 
            -
                  wrap(val).tap { |it| it && it.struct.owned = true }
         | 
| 23 | 
            -
                end
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                # Create an unowned copy of the struct represented by val
         | 
| 26 | 
            -
                def self.copy_from(val)
         | 
| 27 | 
            -
                  copy from(val)
         | 
| 28 | 
            -
                end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                # Wrap an owned copy of the struct represented by val
         | 
| 31 | 
            -
                def self.wrap_copy(val)
         | 
| 32 | 
            -
                  # TODO: Is this needed? We may get away with just copying on transfer away from us.
         | 
| 33 | 
            -
                  copy(wrap(val)).tap { |it| it && it.struct.owned = true }
         | 
| 34 | 
            -
                end
         | 
| 35 | 
            -
             | 
| 36 20 | 
             
                def self.copy(val)
         | 
| 37 | 
            -
                  return unless val
         | 
| 38 21 | 
             
                  ptr = GObject.boxed_copy(gtype, val)
         | 
| 39 22 | 
             
                  wrap(ptr)
         | 
| 40 23 | 
             
                end
         | 
| 41 24 |  | 
| 42 25 | 
             
                private
         | 
| 43 26 |  | 
| 44 | 
            -
                def store_pointer( | 
| 27 | 
            +
                def store_pointer(*)
         | 
| 45 28 | 
             
                  super
         | 
| 46 29 | 
             
                  make_finalizer
         | 
| 47 30 | 
             
                end
         | 
| 48 31 |  | 
| 49 32 | 
             
                def make_finalizer
         | 
| 50 | 
            -
                   | 
| 51 | 
            -
                  ObjectSpace.define_finalizer self, self.class.make_finalizer(@struct, gtype)
         | 
| 33 | 
            +
                  ObjectSpace.define_finalizer self, self.class.make_finalizer(struct)
         | 
| 52 34 | 
             
                end
         | 
| 53 35 | 
             
              end
         | 
| 54 36 | 
             
            end
         | 
    
        data/lib/gir_ffi/builder.rb
    CHANGED
    
    | @@ -29,9 +29,9 @@ module GirFFI | |
| 29 29 | 
             
                end
         | 
| 30 30 |  | 
| 31 31 | 
             
                def self.build_module(namespace, version = nil)
         | 
| 32 | 
            -
                  module_name = namespace. | 
| 33 | 
            -
                  if  | 
| 34 | 
            -
                    modul =  | 
| 32 | 
            +
                  module_name = namespace.sub(/\A./, &:upcase)
         | 
| 33 | 
            +
                  if const_defined? module_name
         | 
| 34 | 
            +
                    modul = const_get module_name
         | 
| 35 35 | 
             
                    unless modul.const_defined? :GIR_FFI_BUILDER
         | 
| 36 36 | 
             
                      raise "The module #{module_name} was already defined elsewhere"
         | 
| 37 37 | 
             
                    end
         | 
| @@ -14,7 +14,6 @@ module GirFFI | |
| 14 14 | 
             
                    name if has_input_value? && !helper_argument?
         | 
| 15 15 | 
             
                  end
         | 
| 16 16 |  | 
| 17 | 
            -
                  # TODO: Improve this so each method can only have one block argument.
         | 
| 18 17 | 
             
                  def block_argument?
         | 
| 19 18 | 
             
                    specialized_type_tag == :callback
         | 
| 20 19 | 
             
                  end
         | 
| @@ -90,7 +89,7 @@ module GirFFI | |
| 90 89 | 
             
                    base = pointer_to_value_method_call call_argument_name, type_spec
         | 
| 91 90 | 
             
                    if needs_out_conversion?
         | 
| 92 91 | 
             
                      outgoing_convertor(base).conversion
         | 
| 93 | 
            -
                    elsif allocated_by_them?
         | 
| 92 | 
            +
                    elsif allocated_by_them? && specialized_type_tag != :void
         | 
| 94 93 | 
             
                      pointer_to_value_method_call base, sub_type_spec
         | 
| 95 94 | 
             
                    else
         | 
| 96 95 | 
             
                      base
         | 
| @@ -98,7 +97,7 @@ module GirFFI | |
| 98 97 | 
             
                  end
         | 
| 99 98 |  | 
| 100 99 | 
             
                  def outgoing_convertor(base)
         | 
| 101 | 
            -
                    FullCToRubyConvertor.new( | 
| 100 | 
            +
                    FullCToRubyConvertor.new(type_info, base, length_argument_name,
         | 
| 102 101 | 
             
                                             ownership_transfer: @arginfo.ownership_transfer)
         | 
| 103 102 | 
             
                  end
         | 
| 104 103 |  | 
| @@ -111,11 +110,11 @@ module GirFFI | |
| 111 110 | 
             
                  end
         | 
| 112 111 |  | 
| 113 112 | 
             
                  def needs_out_conversion?
         | 
| 114 | 
            -
                     | 
| 113 | 
            +
                    type_info.needs_c_to_ruby_conversion_for_functions?
         | 
| 115 114 | 
             
                  end
         | 
| 116 115 |  | 
| 117 116 | 
             
                  def gvalue?
         | 
| 118 | 
            -
                     | 
| 117 | 
            +
                    type_info.gvalue?
         | 
| 119 118 | 
             
                  end
         | 
| 120 119 |  | 
| 121 120 | 
             
                  # Check if an out argument needs to be allocated by them, the callee. Since
         | 
| @@ -123,7 +122,7 @@ module GirFFI | |
| 123 122 | 
             
                  # is a pointer. For example, an out parameter of type gint8* will always
         | 
| 124 123 | 
             
                  # be allocated by the caller (that's us).
         | 
| 125 124 | 
             
                  def allocated_by_them?
         | 
| 126 | 
            -
                    !@arginfo.caller_allocates? &&  | 
| 125 | 
            +
                    !@arginfo.caller_allocates? && type_info.pointer?
         | 
| 127 126 | 
             
                  end
         | 
| 128 127 |  | 
| 129 128 | 
             
                  def length_argument_name
         | 
| @@ -197,8 +196,8 @@ module GirFFI | |
| 197 196 | 
             
                      NullConvertor.new(DESTROY_NOTIFIER)
         | 
| 198 197 | 
             
                    elsif closure?
         | 
| 199 198 | 
             
                      ClosureToPointerConvertor.new(pre_convertor_argument, @is_closure)
         | 
| 200 | 
            -
                    elsif  | 
| 201 | 
            -
                      RubyToCConvertor.new( | 
| 199 | 
            +
                    elsif type_info.needs_ruby_to_c_conversion_for_functions?
         | 
| 200 | 
            +
                      RubyToCConvertor.new(type_info, pre_convertor_argument,
         | 
| 202 201 | 
             
                                           ownership_transfer: ownership_transfer)
         | 
| 203 202 | 
             
                    else
         | 
| 204 203 | 
             
                      NullConvertor.new(pre_convertor_argument)
         | 
| @@ -144,8 +144,8 @@ module GirFFI | |
| 144 144 |  | 
| 145 145 | 
             
                  def out_parameter_preparation
         | 
| 146 146 | 
             
                    value = if allocated_by_us?
         | 
| 147 | 
            -
                              ffi_type = TypeMap.type_specification_to_ffi_type type_spec | 
| 148 | 
            -
                              " | 
| 147 | 
            +
                              ffi_type = TypeMap.type_specification_to_ffi_type type_spec.last
         | 
| 148 | 
            +
                              "FFI::MemoryPointer.new(#{ffi_type.inspect})" \
         | 
| 149 149 | 
             
                                ".tap { |ptr| #{method_argument_name}.put_pointer 0, ptr }"
         | 
| 150 150 | 
             
                            else
         | 
| 151 151 | 
             
                              method_argument_name
         | 
| @@ -9,16 +9,14 @@ module GirFFI | |
| 9 9 | 
             
                class CallbackReturnValueBuilder < BaseReturnValueBuilder
         | 
| 10 10 | 
             
                  def post_conversion
         | 
| 11 11 | 
             
                    if has_post_conversion?
         | 
| 12 | 
            -
                       | 
| 13 | 
            -
                        ["#{post_converted_name} = #{post_convertor.conversion}.to_ptr"]
         | 
| 14 | 
            -
                      else
         | 
| 15 | 
            -
                        ["#{post_converted_name} = #{post_convertor.conversion}"]
         | 
| 16 | 
            -
                      end
         | 
| 12 | 
            +
                      optional_outgoing_ref + base_post_conversion
         | 
| 17 13 | 
             
                    else
         | 
| 18 14 | 
             
                      []
         | 
| 19 15 | 
             
                    end
         | 
| 20 16 | 
             
                  end
         | 
| 21 17 |  | 
| 18 | 
            +
                  private
         | 
| 19 | 
            +
             | 
| 22 20 | 
             
                  def has_post_conversion?
         | 
| 23 21 | 
             
                    relevant? && needs_ruby_to_c_conversion?
         | 
| 24 22 | 
             
                  end
         | 
| @@ -27,19 +25,29 @@ module GirFFI | |
| 27 25 | 
             
                    type_info.needs_ruby_to_c_conversion_for_callbacks?
         | 
| 28 26 | 
             
                  end
         | 
| 29 27 |  | 
| 30 | 
            -
                   | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
                     | 
| 28 | 
            +
                  def optional_outgoing_ref
         | 
| 29 | 
            +
                    if outgoing_ref_needed?
         | 
| 30 | 
            +
                      ["#{capture_variable_name}.ref"]
         | 
| 31 | 
            +
                    else
         | 
| 32 | 
            +
                      []
         | 
| 33 | 
            +
                    end
         | 
| 34 34 | 
             
                  end
         | 
| 35 35 |  | 
| 36 | 
            -
                  def  | 
| 37 | 
            -
                    if  | 
| 38 | 
            -
                      "#{ | 
| 36 | 
            +
                  def base_post_conversion
         | 
| 37 | 
            +
                    if specialized_type_tag == :object
         | 
| 38 | 
            +
                      ["#{post_converted_name} = #{post_convertor.conversion}.to_ptr"]
         | 
| 39 39 | 
             
                    else
         | 
| 40 | 
            -
                       | 
| 40 | 
            +
                      ["#{post_converted_name} = #{post_convertor.conversion}"]
         | 
| 41 41 | 
             
                    end
         | 
| 42 42 | 
             
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  def post_convertor
         | 
| 45 | 
            +
                    @post_convertor ||= RubyToCConvertor.new(type_info, capture_variable_name)
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  def outgoing_ref_needed?
         | 
| 49 | 
            +
                    ownership_transfer == :everything && specialized_type_tag == :object
         | 
| 50 | 
            +
                  end
         | 
| 43 51 | 
             
                end
         | 
| 44 52 | 
             
              end
         | 
| 45 53 | 
             
            end
         | 
| @@ -229,8 +229,9 @@ module GirFFI | |
| 229 229 |  | 
| 230 230 | 
             
                  attr_reader :info
         | 
| 231 231 |  | 
| 232 | 
            -
                  def initialize(field_info)
         | 
| 232 | 
            +
                  def initialize(field_info, container_class)
         | 
| 233 233 | 
             
                    @info = field_info
         | 
| 234 | 
            +
                    @container_class = container_class
         | 
| 234 235 | 
             
                  end
         | 
| 235 236 |  | 
| 236 237 | 
             
                  def build
         | 
| @@ -285,13 +286,7 @@ module GirFFI | |
| 285 286 | 
             
                    @field_type_tag ||= field_type.tag_or_class
         | 
| 286 287 | 
             
                  end
         | 
| 287 288 |  | 
| 288 | 
            -
                   | 
| 289 | 
            -
                    @container_class ||= container_module.const_get(container_info.safe_name)
         | 
| 290 | 
            -
                  end
         | 
| 291 | 
            -
             | 
| 292 | 
            -
                  def container_module
         | 
| 293 | 
            -
                    @container_module ||= Object.const_get(container_info.safe_namespace)
         | 
| 294 | 
            -
                  end
         | 
| 289 | 
            +
                  attr_reader :container_class
         | 
| 295 290 |  | 
| 296 291 | 
             
                  def container_info
         | 
| 297 292 | 
             
                    @container_info ||= info.container
         | 
| @@ -310,9 +305,8 @@ module GirFFI | |
| 310 305 | 
             
                                                            field_argument_info)
         | 
| 311 306 | 
             
                  end
         | 
| 312 307 |  | 
| 313 | 
            -
                  # rubocop:disable Style/ZeroLengthPredicate
         | 
| 314 308 | 
             
                  def hidden_struct_type?
         | 
| 315 | 
            -
                    field_type. | 
| 309 | 
            +
                    field_type.hidden_struct_type?
         | 
| 316 310 | 
             
                  end
         | 
| 317 311 | 
             
                end
         | 
| 318 312 | 
             
              end
         | 
| @@ -32,6 +32,10 @@ module GirFFI | |
| 32 32 | 
             
                    true
         | 
| 33 33 | 
             
                  end
         | 
| 34 34 |  | 
| 35 | 
            +
                  def method_available?(method)
         | 
| 36 | 
            +
                    function_introspection_data(method.to_s) and true
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
             | 
| 35 39 | 
             
                  def build_namespaced_class(classname)
         | 
| 36 40 | 
             
                    info = find_namespaced_class_info(classname)
         | 
| 37 41 | 
             
                    Builder.build_class info
         | 
| @@ -109,11 +113,9 @@ module GirFFI | |
| 109 113 | 
             
                  end
         | 
| 110 114 |  | 
| 111 115 | 
             
                  def gir
         | 
| 112 | 
            -
                     | 
| 113 | 
            -
                      @ | 
| 114 | 
            -
                      @gir.require @namespace, @version
         | 
| 116 | 
            +
                    @gir ||= GObjectIntrospection::IRepository.default.tap do |it|
         | 
| 117 | 
            +
                      it.require @namespace, @version
         | 
| 115 118 | 
             
                    end
         | 
| 116 | 
            -
                    @gir
         | 
| 117 119 | 
             
                  end
         | 
| 118 120 | 
             
                end
         | 
| 119 121 | 
             
              end
         | 
| @@ -79,12 +79,7 @@ module GirFFI | |
| 79 79 | 
             
                  end
         | 
| 80 80 |  | 
| 81 81 | 
             
                  def parent_info
         | 
| 82 | 
            -
                     | 
| 83 | 
            -
                      @parent_info = if (parent = info.parent) && parent != info
         | 
| 84 | 
            -
                                       parent
         | 
| 85 | 
            -
                                     end
         | 
| 86 | 
            -
                    end
         | 
| 87 | 
            -
                    @parent_info
         | 
| 82 | 
            +
                    info.parent
         | 
| 88 83 | 
             
                  end
         | 
| 89 84 |  | 
| 90 85 | 
             
                  def superclass
         | 
| @@ -105,7 +100,7 @@ module GirFFI | |
| 105 100 |  | 
| 106 101 | 
             
                  def setup_field_accessors
         | 
| 107 102 | 
             
                    eligible_fields.each do |finfo|
         | 
| 108 | 
            -
                      FieldBuilder.new(finfo).build
         | 
| 103 | 
            +
                      FieldBuilder.new(finfo, klass).build
         | 
| 109 104 | 
             
                    end
         | 
| 110 105 | 
             
                  end
         | 
| 111 106 |  | 
| @@ -119,9 +114,7 @@ module GirFFI | |
| 119 114 | 
             
                  # TODO: Create object responsible for creating these invokers
         | 
| 120 115 | 
             
                  def setup_vfunc_invokers
         | 
| 121 116 | 
             
                    info.vfuncs.each do |vfinfo|
         | 
| 122 | 
            -
                       | 
| 123 | 
            -
                        define_vfunc_invoker vfinfo.name, invoker.name
         | 
| 124 | 
            -
                      end
         | 
| 117 | 
            +
                      define_vfunc_invoker vfinfo.name, vfinfo.invoker_name if vfinfo.has_invoker?
         | 
| 125 118 | 
             
                    end
         | 
| 126 119 | 
             
                  end
         | 
| 127 120 |  | 
| @@ -137,12 +130,19 @@ module GirFFI | |
| 137 130 | 
             
                  def provide_initializer
         | 
| 138 131 | 
             
                    return if info.find_method 'new'
         | 
| 139 132 |  | 
| 140 | 
            -
                     | 
| 141 | 
            -
             | 
| 142 | 
            -
             | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 133 | 
            +
                    if info.abstract?
         | 
| 134 | 
            +
                      klass.class_eval <<-END
         | 
| 135 | 
            +
                        def initialize(*)
         | 
| 136 | 
            +
                          raise NoMethodError
         | 
| 137 | 
            +
                        end
         | 
| 138 | 
            +
                      END
         | 
| 139 | 
            +
                    else
         | 
| 140 | 
            +
                      klass.class_eval <<-END
         | 
| 141 | 
            +
                        def initialize(properties = {})
         | 
| 142 | 
            +
                          base_initialize(properties)
         | 
| 143 | 
            +
                        end
         | 
| 144 | 
            +
                      END
         | 
| 145 | 
            +
                    end
         | 
| 146 146 | 
             
                  end
         | 
| 147 147 |  | 
| 148 148 | 
             
                  def setup_interfaces
         | 
| @@ -16,12 +16,10 @@ module GirFFI | |
| 16 16 | 
             
                  def superclass
         | 
| 17 17 | 
             
                    if info.gtype_struct?
         | 
| 18 18 | 
             
                      # HACK: Inheritance chain is not expressed in GObject's code correctly.
         | 
| 19 | 
            -
                       | 
| 20 | 
            -
             | 
| 21 | 
            -
                       | 
| 22 | 
            -
             | 
| 23 | 
            -
                        return type.tag_or_class if type.tag == :interface
         | 
| 24 | 
            -
                      end
         | 
| 19 | 
            +
                      type_name = info.full_type_name
         | 
| 20 | 
            +
                      return GObject::ObjectClass if type_name == 'GObject::InitiallyUnownedClass'
         | 
| 21 | 
            +
                      type = fields.first.field_type
         | 
| 22 | 
            +
                      return type.tag_or_class if type.tag == :interface
         | 
| 25 23 | 
             
                    end
         | 
| 26 24 |  | 
| 27 25 | 
             
                    if GObject.type_fundamental(info.gtype) == GObject::TYPE_BOXED
         | 
| @@ -11,8 +11,8 @@ module GirFFI | |
| 11 11 | 
             
                  end
         | 
| 12 12 |  | 
| 13 13 | 
             
                  def setup_class
         | 
| 14 | 
            -
                    register_type
         | 
| 15 14 | 
             
                    setup_layout
         | 
| 15 | 
            +
                    register_type
         | 
| 16 16 | 
             
                    setup_constants
         | 
| 17 17 | 
             
                    setup_property_accessors
         | 
| 18 18 | 
             
                    setup_constructor
         | 
| @@ -86,8 +86,10 @@ module GirFFI | |
| 86 86 |  | 
| 87 87 | 
             
                  def instance_size
         | 
| 88 88 | 
             
                    size = parent_gtype.instance_size
         | 
| 89 | 
            -
                     | 
| 90 | 
            -
             | 
| 89 | 
            +
                    alignment = struct_class.alignment
         | 
| 90 | 
            +
                    properties.each do |prop|
         | 
| 91 | 
            +
                      type_size = FFI.type_size(prop.ffi_type)
         | 
| 92 | 
            +
                      size += [type_size, alignment].max
         | 
| 91 93 | 
             
                    end
         | 
| 92 94 | 
             
                    size
         | 
| 93 95 | 
             
                  end
         | 
| @@ -109,13 +111,13 @@ module GirFFI | |
| 109 111 |  | 
| 110 112 | 
             
                  def property_getter
         | 
| 111 113 | 
             
                    proc do |object, _property_id, value, pspec|
         | 
| 112 | 
            -
                      value.set_value object.send(pspec. | 
| 114 | 
            +
                      value.set_value object.send(pspec.accessor_name)
         | 
| 113 115 | 
             
                    end
         | 
| 114 116 | 
             
                  end
         | 
| 115 117 |  | 
| 116 118 | 
             
                  def property_setter
         | 
| 117 119 | 
             
                    proc do |object, _property_id, value, pspec|
         | 
| 118 | 
            -
                      object.send("#{pspec. | 
| 120 | 
            +
                      object.send("#{pspec.accessor_name}=", value.get_value)
         | 
| 119 121 | 
             
                    end
         | 
| 120 122 | 
             
                  end
         | 
| 121 123 |  | 
| @@ -167,34 +169,92 @@ module GirFFI | |
| 167 169 | 
             
                  end
         | 
| 168 170 |  | 
| 169 171 | 
             
                  def layout_specification
         | 
| 170 | 
            -
                    parent_spec = [:parent, superclass::Struct | 
| 171 | 
            -
                    offset =  | 
| 172 | 
            -
             | 
| 173 | 
            -
             | 
| 174 | 
            -
             | 
| 172 | 
            +
                    parent_spec = [:parent, superclass::Struct]
         | 
| 173 | 
            +
                    offset = parent_gtype.instance_size
         | 
| 174 | 
            +
             | 
| 175 | 
            +
                    alignment = superclass::Struct.alignment
         | 
| 176 | 
            +
                    fields_spec = properties.flat_map do |param_info|
         | 
| 177 | 
            +
                      field_name = param_info.accessor_name
         | 
| 178 | 
            +
                      ffi_type = param_info.ffi_type
         | 
| 179 | 
            +
                      type_size = FFI.type_size(ffi_type)
         | 
| 180 | 
            +
                      spec = [field_name, ffi_type, offset]
         | 
| 181 | 
            +
                      offset += [type_size, alignment].max
         | 
| 175 182 | 
             
                      spec
         | 
| 176 183 | 
             
                    end
         | 
| 177 184 | 
             
                    parent_spec + fields_spec
         | 
| 178 185 | 
             
                  end
         | 
| 179 186 |  | 
| 180 | 
            -
                   | 
| 181 | 
            -
             | 
| 182 | 
            -
             | 
| 187 | 
            +
                  # TODO: Move this to its own file.
         | 
| 188 | 
            +
                  # TODO: See if this or FieldTypeInfo can be merged with with
         | 
| 189 | 
            +
                  # UserDefinedPropertyInfo.
         | 
| 190 | 
            +
                  class UserDefinedPropertyFieldInfo
         | 
| 191 | 
            +
                    # Field info for user-defined property
         | 
| 192 | 
            +
                    class FieldTypeInfo
         | 
| 193 | 
            +
                      include InfoExt::ITypeInfo
         | 
| 194 | 
            +
             | 
| 195 | 
            +
                      def initialize(property_info)
         | 
| 196 | 
            +
                        @property_info = property_info
         | 
| 197 | 
            +
                      end
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                      def tag
         | 
| 200 | 
            +
                        @property_info.type_tag
         | 
| 201 | 
            +
                      end
         | 
| 202 | 
            +
             | 
| 203 | 
            +
                      def pointer?
         | 
| 204 | 
            +
                        @property_info.pointer_type?
         | 
| 205 | 
            +
                      end
         | 
| 206 | 
            +
             | 
| 207 | 
            +
                      def interface_type
         | 
| 208 | 
            +
                        @property_info.interface_type_tag if tag == :interface
         | 
| 209 | 
            +
                      end
         | 
| 210 | 
            +
             | 
| 211 | 
            +
                      def hidden_struct_type?
         | 
| 212 | 
            +
                        false
         | 
| 213 | 
            +
                      end
         | 
| 214 | 
            +
             | 
| 215 | 
            +
                      def interface_class
         | 
| 216 | 
            +
                        Builder.build_by_gtype @property_info.value_type if tag == :interface
         | 
| 217 | 
            +
                      end
         | 
| 218 | 
            +
             | 
| 219 | 
            +
                      def interface_class_name
         | 
| 220 | 
            +
                        interface_class.name if tag == :interface
         | 
| 221 | 
            +
                      end
         | 
| 183 222 | 
             
                    end
         | 
| 184 | 
            -
                  end
         | 
| 185 223 |  | 
| 186 | 
            -
             | 
| 187 | 
            -
             | 
| 188 | 
            -
             | 
| 189 | 
            -
             | 
| 190 | 
            -
                      @struct[:#{field_name}]
         | 
| 224 | 
            +
                    def initialize(property_info, container, offset)
         | 
| 225 | 
            +
                      @property_info = property_info
         | 
| 226 | 
            +
                      @container = container
         | 
| 227 | 
            +
                      @offset = offset
         | 
| 191 228 | 
             
                    end
         | 
| 192 | 
            -
             | 
| 193 | 
            -
             | 
| 229 | 
            +
             | 
| 230 | 
            +
                    attr_reader :container, :offset
         | 
| 231 | 
            +
             | 
| 232 | 
            +
                    def name
         | 
| 233 | 
            +
                      @property_info.accessor_name
         | 
| 194 234 | 
             
                    end
         | 
| 195 | 
            -
                    CODE
         | 
| 196 235 |  | 
| 197 | 
            -
                     | 
| 236 | 
            +
                    def field_type
         | 
| 237 | 
            +
                      @field_type ||= FieldTypeInfo.new @property_info
         | 
| 238 | 
            +
                    end
         | 
| 239 | 
            +
             | 
| 240 | 
            +
                    def related_array_length_field
         | 
| 241 | 
            +
                      nil
         | 
| 242 | 
            +
                    end
         | 
| 243 | 
            +
             | 
| 244 | 
            +
                    def writable?
         | 
| 245 | 
            +
                      @property_info.writable?
         | 
| 246 | 
            +
                    end
         | 
| 247 | 
            +
                  end
         | 
| 248 | 
            +
             | 
| 249 | 
            +
                  def setup_property_accessors
         | 
| 250 | 
            +
                    offset = parent_gtype.instance_size
         | 
| 251 | 
            +
                    alignment = struct_class.alignment
         | 
| 252 | 
            +
                    properties.each do |param_info|
         | 
| 253 | 
            +
                      field_info = UserDefinedPropertyFieldInfo.new(param_info, info, offset)
         | 
| 254 | 
            +
                      type_size = FFI.type_size(param_info.ffi_type)
         | 
| 255 | 
            +
                      offset += [type_size, alignment].max
         | 
| 256 | 
            +
                      FieldBuilder.new(field_info, klass).build
         | 
| 257 | 
            +
                    end
         | 
| 198 258 | 
             
                  end
         | 
| 199 259 |  | 
| 200 260 | 
             
                  def method_introspection_data(_method)
         | 
| @@ -7,8 +7,16 @@ module GirFFI | |
| 7 7 | 
             
                # argument mapper for vfuncs.
         | 
| 8 8 | 
             
                class VFuncArgumentBuilder < CallbackArgumentBuilder
         | 
| 9 9 | 
             
                  def pre_conversion
         | 
| 10 | 
            -
                    if ingoing_ref_needed
         | 
| 11 | 
            -
                      super + [ | 
| 10 | 
            +
                    if ingoing_ref_needed?
         | 
| 11 | 
            +
                      super + ["#{pre_converted_name}.ref"]
         | 
| 12 | 
            +
                    else
         | 
| 13 | 
            +
                      super
         | 
| 14 | 
            +
                    end
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def post_conversion
         | 
| 18 | 
            +
                    if outgoing_ref_needed?
         | 
| 19 | 
            +
                      ["#{result_name}.ref"] + super
         | 
| 12 20 | 
             
                    else
         | 
| 13 21 | 
             
                      super
         | 
| 14 22 | 
             
                    end
         | 
| @@ -16,26 +24,13 @@ module GirFFI | |
| 16 24 |  | 
| 17 25 | 
             
                  private
         | 
| 18 26 |  | 
| 19 | 
            -
                  def ingoing_ref_needed
         | 
| 27 | 
            +
                  def ingoing_ref_needed?
         | 
| 20 28 | 
             
                    direction == :in &&
         | 
| 21 29 | 
             
                      ownership_transfer == :nothing &&
         | 
| 22 30 | 
             
                      specialized_type_tag == :object
         | 
| 23 31 | 
             
                  end
         | 
| 24 32 |  | 
| 25 | 
            -
                  def  | 
| 26 | 
            -
                    "#{pre_converted_name}.ref"
         | 
| 27 | 
            -
                  end
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                  # SMELL: Override private method
         | 
| 30 | 
            -
                  def post_convertor_argument
         | 
| 31 | 
            -
                    if outgoing_ref_needed
         | 
| 32 | 
            -
                      "#{super}.ref"
         | 
| 33 | 
            -
                    else
         | 
| 34 | 
            -
                      super
         | 
| 35 | 
            -
                    end
         | 
| 36 | 
            -
                  end
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                  def outgoing_ref_needed
         | 
| 33 | 
            +
                  def outgoing_ref_needed?
         | 
| 39 34 | 
             
                    direction == :out &&
         | 
| 40 35 | 
             
                      ownership_transfer == :everything &&
         | 
| 41 36 | 
             
                      specialized_type_tag == :object
         | 
    
        data/lib/gir_ffi/class_base.rb
    CHANGED
    
    | @@ -31,10 +31,6 @@ module GirFFI | |
| 31 31 | 
             
                  other.class == self.class && to_ptr.address == other.to_ptr.address
         | 
| 32 32 | 
             
                end
         | 
| 33 33 |  | 
| 34 | 
            -
                def initialize
         | 
| 35 | 
            -
                  raise NoMethodError
         | 
| 36 | 
            -
                end
         | 
| 37 | 
            -
             | 
| 38 34 | 
             
                def self.setup_and_call(method, arguments, &block)
         | 
| 39 35 | 
             
                  method_name = try_in_ancestors(:setup_method, method.to_s)
         | 
| 40 36 |  |