Module: Fiddle::CStructBuilder
Relationships & Source Files | |
Defined in: | ext/fiddle/lib/fiddle/struct.rb |
Overview
Used to construct C classes (CUnion, CStruct
, etc)
Importer#struct and Importer#union wrap this functionality in an easy-to-use manner.
Class Method Summary
-
.create(klass, types, members)
mod_func
Construct a new class given a C: * class
klass
(CUnion,CStruct
, or other that provide an.
Class Method Details
.create(klass, types, members) (mod_func)
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
Importer#struct and 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 '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