class GirFFI::Builders::UserDefinedBuilder

Implements the creation of GObject subclasses from Ruby.

Public Class Methods

new(info) click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 10
def initialize(info)
  @info = info
end

Public Instance Methods

setup_class() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 14
def setup_class
  check_ancestry
  setup_layout
  register_type
  setup_constants
  setup_property_accessors
  setup_initializer
  TypeBuilder::CACHE[@gtype] = klass
end
target_gtype() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 24
def target_gtype
  @gtype ||= klass.gtype
end

Private Instance Methods

check_ancestry() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 30
def check_ancestry
  unless klass < GirFFI::ObjectBase
    raise ArgumentError, "#{klass} is not a GObject class"
  end
end
class_init_proc() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 80
def class_init_proc
  proc do |type_class, _data|
    class_struct_ptr = type_class.to_ptr
    setup_properties class_struct_ptr
    setup_vfuncs class_struct_ptr
  end
end
class_size() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 107
def class_size
  parent_gtype.class_size + interface_gtypes.sum(&:class_size)
end
field_alignment() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 179
def field_alignment
  @field_alignment ||= superclass::Struct.alignment
end
gobject_interface_info(interface) click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 74
def gobject_interface_info(interface)
  GObject::InterfaceInfo.new.tap do |interface_info|
    interface_info.interface_init = interface_init_proc(interface)
  end
end
gobject_type_info() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 66
def gobject_type_info
  GObject::TypeInfo.new.tap do |type_info|
    type_info.class_size = class_size
    type_info.instance_size = instance_size
    type_info.class_init = class_init_proc
  end
end
included_interfaces() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 58
def included_interfaces
  klass.included_interfaces
end
instance_size() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 95
def instance_size
  if property_fields.any?
    last_property = property_fields.last
    size = last_property.offset
    type_size = FFI.type_size(last_property.ffi_type)
    size += [type_size, field_alignment].max
  else
    size = parent_gtype.instance_size
  end
  size
end
interface_gtypes() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 54
def interface_gtypes
  included_interfaces.map { |interface| GType.new(interface.gtype) }
end
interface_init_proc(interface) click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 88
def interface_init_proc(interface)
  proc do |type_interface, _data|
    interface_struct_ptr = type_interface.to_ptr
    setup_interface_vfuncs interface, interface_struct_ptr
  end
end
klass() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 62
def klass
  @klass ||= @info.described_class
end
layout_specification() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 169
def layout_specification
  parent_spec = [:parent, superclass::Struct]

  fields_spec = property_fields.flat_map do |property_info|
    [property_info.field_symbol, property_info.ffi_type, property_info.offset]
  end

  parent_spec + fields_spec
end
method_introspection_data(_method) click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 202
def method_introspection_data(_method)
  nil
end
parent_gtype() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 50
def parent_gtype
  @info.parent_gtype
end
parent_info() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 46
def parent_info
  @info.parent
end
properties() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 165
def properties
  @properties ||= info.properties
end
property_fields() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 189
def property_fields
  @property_fields ||=
    begin
      offset = parent_gtype.instance_size
      properties.map do |param_spec|
        field_info = UserDefinedPropertyInfo.new(param_spec, info, offset)
        type_size = FFI.type_size(field_info.ffi_type)
        offset += [type_size, field_alignment].max
        field_info
      end
    end
end
property_getter_func() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 122
def property_getter_func
  getter = proc do |object, _property_id, value, pspec|
    value.set_value object.send(pspec.accessor_name)
  end
  GObject::ObjectGetPropertyFunc.from getter
end
property_setter_func() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 129
def property_setter_func
  setter = proc do |object, _property_id, value, pspec|
    object.send("#{pspec.accessor_name}=", value.get_value)
  end
  GObject::ObjectSetPropertyFunc.from setter
end
register_type() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 36
def register_type
  @gtype = GObject.type_register_static(parent_gtype.to_i,
                                        info.g_name,
                                        gobject_type_info, 0)
  included_interfaces.each do |interface|
    ifinfo = gobject_interface_info interface
    GObject.type_add_interface_static @gtype, interface.gtype, ifinfo
  end
end
setup_interface_vfuncs(interface, interface_struct_ptr) click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 145
def setup_interface_vfuncs(interface, interface_struct_ptr)
  interface_builder = interface.gir_ffi_builder

  interface_struct = interface_builder.interface_struct.wrap(interface_struct_ptr)
  interface_info = interface_builder.info

  info.vfunc_implementations.each do |impl|
    setup_vfunc interface_info, interface_struct, impl
  end
end
setup_properties(class_struct_ptr) click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 111
def setup_properties(class_struct_ptr)
  class_struct = GObject::ObjectClass.wrap class_struct_ptr

  class_struct.struct[:get_property] = property_getter_func
  class_struct.struct[:set_property] = property_setter_func

  property_fields.each_with_index do |property, index|
    class_struct.install_property index + 1, property.param_spec
  end
end
setup_property_accessors() click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 183
def setup_property_accessors
  property_fields.each do |field_info|
    FieldBuilder.new(field_info, klass).build
  end
end
setup_vfunc(ancestor_info, ancestor_struct, impl) click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 156
def setup_vfunc(ancestor_info, ancestor_struct, impl)
  vfunc_name = impl.name
  vfunc_info = ancestor_info.find_vfunc vfunc_name.to_s
  return unless vfunc_info

  vfunc_class = VFuncBuilder.new(vfunc_info).build_class
  ancestor_struct.struct[vfunc_name] = vfunc_class.from(impl.implementation)
end
setup_vfuncs(class_struct_ptr) click to toggle source
# File lib/gir_ffi/builders/user_defined_builder.rb, line 136
def setup_vfuncs(class_struct_ptr)
  super_class_struct =
    superclass.gir_ffi_builder.class_struct_class.wrap(class_struct_ptr)

  info.vfunc_implementations.each do |impl|
    setup_vfunc parent_info, super_class_struct, impl
  end
end