Used to construct C classes (CUnion
, CStruct
, etc)
Fiddle::Importer#struct
and Fiddle::Importer#union
wrap this functionality in an easy-to-use manner.
# File tmp/rubies/ruby-3.2.0/ext/fiddle/lib/fiddle/struct.rb, line 215
def create(klass, types, members)
new_class = Class.new(klass){
define_method(:initialize){|addr, func = nil|
if addr.is_a?(self.class.entity_class)
@entity = addr
else
@entity = self.class.entity_class.new(addr, types, func)
end
@entity.assign_names(members)
}
define_method(:[]) { |*args| @entity.send(:[], *args) }
define_method(:[]=) { |*args| @entity.send(:[]=, *args) }
define_method(:to_ptr){ @entity }
define_method(:to_i){ @entity.to_i }
define_singleton_method(:types) { types }
define_singleton_method(:members) { members }
# Return the offset of a struct member given its name.
# For example:
#
# MyStruct = struct [
# "int64_t i",
# "char c",
# ]
#
# MyStruct.offsetof("i") # => 0
# MyStruct.offsetof("c") # => 8
#
define_singleton_method(:offsetof) { |name|
klass.offsetof(name, members, types)
}
members.each{|name|
name = name[0] if name.is_a?(Array) # name is a nested struct
next if method_defined?(name)
define_method(name){ @entity[name] }
define_method(name + "="){|val| @entity[name] = val }
}
entity_class = klass.entity_class
alignment = entity_class.alignment(types)
size = entity_class.size(types)
define_singleton_method(:alignment) { alignment }
define_singleton_method(:size) { size }
define_singleton_method(:malloc) do |func=nil, &block|
if block
entity_class.malloc(types, func, size) do |entity|
block.call(new(entity))
end
else
new(entity_class.malloc(types, func, size))
end
end
}
return new_class
end
Construct a new class given a C:
-
class
klass
(CUnion
,CStruct
, or other that provide an entity_class) -
types
(Fiddle::TYPE_INT, Fiddle::TYPE_SIZE_T, etc., see the C types constants) -
corresponding
members
Fiddle::Importer#struct
and Fiddle::Importer#union
wrap this functionality in an easy-to-use manner.
Examples:
require 'fiddle/struct' require 'fiddle/cparser' include Fiddle::CParser types, members = parse_struct_signature(['int i','char c']) MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members) MyStruct.malloc(Fiddle::RUBY_FREE) do |obj| ... end obj = MyStruct.malloc(Fiddle::RUBY_FREE) begin ... ensure obj.call_free end obj = MyStruct.malloc begin ... ensure Fiddle.free obj.to_ptr end
# File tmp/rubies/ruby-3.2.0/ext/fiddle/lib/fiddle/struct.rb, line 215
def create(klass, types, members)
new_class = Class.new(klass){
define_method(:initialize){|addr, func = nil|
if addr.is_a?(self.class.entity_class)
@entity = addr
else
@entity = self.class.entity_class.new(addr, types, func)
end
@entity.assign_names(members)
}
define_method(:[]) { |*args| @entity.send(:[], *args) }
define_method(:[]=) { |*args| @entity.send(:[]=, *args) }
define_method(:to_ptr){ @entity }
define_method(:to_i){ @entity.to_i }
define_singleton_method(:types) { types }
define_singleton_method(:members) { members }
# Return the offset of a struct member given its name.
# For example:
#
# MyStruct = struct [
# "int64_t i",
# "char c",
# ]
#
# MyStruct.offsetof("i") # => 0
# MyStruct.offsetof("c") # => 8
#
define_singleton_method(:offsetof) { |name|
klass.offsetof(name, members, types)
}
members.each{|name|
name = name[0] if name.is_a?(Array) # name is a nested struct
next if method_defined?(name)
define_method(name){ @entity[name] }
define_method(name + "="){|val| @entity[name] = val }
}
entity_class = klass.entity_class
alignment = entity_class.alignment(types)
size = entity_class.size(types)
define_singleton_method(:alignment) { alignment }
define_singleton_method(:size) { size }
define_singleton_method(:malloc) do |func=nil, &block|
if block
entity_class.malloc(types, func, size) do |entity|
block.call(new(entity))
end
else
new(entity_class.malloc(types, func, size))
end
end
}
return new_class
end
Construct a new class given a C:
-
class
klass
(CUnion
,CStruct
, or other that provide an entity_class) -
types
(Fiddle::TYPE_INT, Fiddle::TYPE_SIZE_T, etc., see the C types constants) -
corresponding
members
Fiddle::Importer#struct
and Fiddle::Importer#union
wrap this functionality in an easy-to-use manner.
Examples:
require 'fiddle/struct' require 'fiddle/cparser' include Fiddle::CParser types, members = parse_struct_signature(['int i','char c']) MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members) MyStruct.malloc(Fiddle::RUBY_FREE) do |obj| ... end obj = MyStruct.malloc(Fiddle::RUBY_FREE) begin ... ensure obj.call_free end obj = MyStruct.malloc begin ... ensure Fiddle.free obj.to_ptr end