/usr/lib/ruby/vendor_ruby/gir_ffi/builders/user_defined_builder.rb is in ruby-gir-ffi 0.9.0-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 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 68 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 111 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 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | require 'gir_ffi/builders/object_builder'
require 'gir_ffi/g_type'
module GirFFI
module Builders
# Implements the creation of GObject subclasses from Ruby.
class UserDefinedBuilder < ObjectBuilder
def initialize(info)
@info = info
end
def setup_class
register_type
setup_layout
setup_constants
setup_property_accessors
setup_constructor
TypeBuilder::CACHE[@gtype] = klass
end
def target_gtype
@gtype ||= klass.gtype
end
private
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
def parent_info
@info.parent
end
def parent_gtype
@info.parent_gtype
end
def interface_gtypes
included_interfaces.map { |interface| GType.new(interface.gtype) }
end
def included_interfaces
klass.included_modules - Object.included_modules
end
def klass
@klass ||= @info.described_class
end
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
def gobject_interface_info(interface)
GObject::InterfaceInfo.new.tap do |interface_info|
interface_info.interface_init = interface_init_proc(interface)
end
end
def class_init_proc
proc do |object_class_ptr, _data|
setup_properties object_class_ptr
setup_vfuncs object_class_ptr
end
end
def interface_init_proc(interface)
proc do |interface_ptr, _data|
setup_interface_vfuncs interface, interface_ptr
end
end
def instance_size
size = parent_gtype.instance_size
properties.each do
size += FFI.type_size(:int32)
end
size
end
def class_size
parent_gtype.class_size + interface_gtypes.map(&:class_size).inject(0, :+)
end
def setup_properties(object_class_ptr)
object_class = GObject::ObjectClass.wrap object_class_ptr
object_class.get_property = property_getter
object_class.set_property = property_setter
properties.each_with_index do |property, index|
object_class.install_property index + 1, property.param_spec
end
end
def property_getter
proc do |object, _property_id, value, pspec|
value.set_value object.send(pspec.get_name)
end
end
def property_setter
proc do |object, _property_id, value, pspec|
object.send("#{pspec.get_name}=", value.get_value)
end
end
def setup_vfuncs(object_class_ptr)
super_class_struct =
superclass.gir_ffi_builder.object_class_struct::Struct.new(object_class_ptr)
info.vfunc_implementations.each do |impl|
setup_vfunc super_class_struct, impl
end
end
def setup_interface_vfuncs(interface, interface_ptr)
interface_builder = interface.gir_ffi_builder
interface_struct = interface_builder.interface_struct::Struct.new(interface_ptr)
interface_info = interface_builder.info
info.vfunc_implementations.each do |impl|
setup_interface_vfunc interface_info, interface_struct, impl
end
end
def setup_vfunc(super_class_struct, impl)
vfunc_name = impl.name
vfunc_info = parent_info.find_vfunc vfunc_name.to_s
if vfunc_info
install_vfunc super_class_struct, vfunc_name, vfunc_info, impl.implementation
end
end
def setup_interface_vfunc(interface_info, interface_struct, impl)
vfunc_name = impl.name
vfunc_info = interface_info.find_vfunc vfunc_name.to_s
if vfunc_info
install_vfunc interface_struct, vfunc_name, vfunc_info, impl.implementation
end
end
def install_vfunc(container_struct, vfunc_name, vfunc_info, implementation)
vfunc = VFuncBuilder.new(vfunc_info).build_class
container_struct[vfunc_name] = vfunc.from implementation
end
def properties
info.properties
end
def layout_specification
parent_spec = [:parent, superclass::Struct, 0]
offset = superclass::Struct.size
fields_spec = properties.flat_map do |pinfo|
spec = [pinfo.name.to_sym, :int32, offset]
offset += FFI.type_size(:int32)
spec
end
parent_spec + fields_spec
end
def setup_property_accessors
properties.each do |pinfo|
setup_accessors_for_param_info pinfo
end
end
def setup_accessors_for_param_info(pinfo)
field_name = pinfo.name
code = <<-CODE
def #{field_name}
@struct[:#{field_name}]
end
def #{field_name}= val
@struct[:#{field_name}] = val
end
CODE
klass.class_eval code
end
def method_introspection_data(_method)
nil
end
def setup_constructor
code = <<-CODE
def initialize
ptr = GObject::Lib.g_object_newv #{@gtype}, 0, nil
store_pointer(ptr)
end
CODE
klass.class_eval code
end
end
end
end
|