class FFI::Struct
def self.align
def self.align @layout.alignment end
def self.alignment
def self.alignment @layout.alignment end
def self.by_value
def self.by_value ::FFI::StructByValue.new(self) end
def self.in
def self.in :buffer_in end
def self.members
def self.members @layout.members end
def self.offset_of(name)
def self.offset_of(name) @layout.offset_of(name) end
def self.offsets
def self.offsets @layout.offsets end
def self.out
def self.out :buffer_out end
def self.size
def self.size defined?(@layout) ? @layout.size : defined?(@size) ? @size : 0 end
def self.size=(size)
def self.size=(size) raise ArgumentError, "Size already set" if defined?(@size) || defined?(@layout) @size = size end
def alignment
def alignment self.class.alignment end
def array_layout(builder, spec)
def array_layout(builder, spec) mod = enclosing_module i = 0 while i < spec.size name, type = spec[i, 2] i += 2 # If the next param is a Integer, it specifies the offset if spec[i].kind_of?(Integer) offset = spec[i] i += 1 else offset = nil end if type.kind_of?(Class) && type < Struct builder.add_struct(name, type, offset) elsif type.kind_of?(::Array) builder.add_array(name, find_type(type[0], mod), type[1], offset) else builder.add_field(name, find_type(type, mod), offset) end end end
def callback(params, ret)
def callback(params, ret) mod = enclosing_module FFI::CallbackInfo.new(find_type(ret, mod), params.map { |e| find_type(e, mod) }) end
def clear
def clear pointer.clear self end
def enclosing_module
def enclosing_module begin mod = self.name.split("::")[0..-2].inject(Object) { |obj, c| obj.const_get(c) } mod.respond_to?(:find_type) ? mod : nil rescue Exception => ex nil end end
def find_type(type, mod = nil)
def find_type(type, mod = nil) if type.kind_of?(Class) && type < FFI::Struct FFI::Type::Struct.new(type) elsif type.is_a?(::Array) type elsif mod mod.find_type(type) end || FFI.find_type(type) end
def hash_layout(builder, spec)
def hash_layout(builder, spec) raise "Ruby version not supported" if RUBY_VERSION =~ /1.8.*/ mod = enclosing_module spec[0].each do |name,type| if type.kind_of?(Class) && type < Struct builder.add_struct(name, type) elsif type.kind_of?(::Array) builder.add_array(name, find_type(type[0], mod), type[1]) else builder.add_field(name, find_type(type, mod)) end end end
def layout(*spec)
def layout(*spec) return @layout if spec.size == 0 builder = FFI::StructLayoutBuilder.new builder.union = self < Union if spec[0].kind_of?(Hash) hash_layout(builder, spec) else array_layout(builder, spec) end builder.size = @size if defined?(@size) && @size > builder.size cspec = builder.build @layout = cspec unless self == FFI::Struct @size = cspec.size return cspec end
def members
def members self.class.members end
def offset_of(name)
def offset_of(name) self.class.offset_of(name) end
def offsets
def offsets self.class.offsets end
def size
def size self.class.size end
def to_ptr
def to_ptr pointer end
def values
def values members.map { |m| self[m] } end