class FFI::Generators::Structures
Generates an FFI
Struct layout.
Given the @@@ portion in:
module Zlib::ZStream < FFI::Struct @@@ name "struct z_stream_s" include "zlib.h" field :next_in, :pointer field :avail_in, :uint field :total_in, :ulong # ... @@@ end
Structures
will create the layout:
layout :next_in, :pointer, 0, :avail_in, :uint, 4, :total_in, :ulong, 8, # ...
StructGenerator does its best to pad the layout it produces to preserve line numbers. Place the struct definition as close to the top of the file for best results.
Attributes
fields[R]
size[RW]
Public Class Methods
new(name) { |self| ... }
click to toggle source
# File lib/ffi2/generators/structures.rb, line 68 def initialize(name) @name = name @struct_name = nil @includes = [] @include_dirs = [] @fields = [] @found = false @size = nil @platform = Platform.new if block_given? then yield self calculate end end
Public Instance Methods
calculate()
click to toggle source
# File lib/ffi2/generators/structures.rb, line 122 def calculate raise "struct name not set" if @struct_name.nil? output = BodyGuard.new(self, @struct_name, @platform).perform.split "\n" sizeof = output.shift unless @size m = /\s*sizeof\([^)]+\) (\d+)/.match sizeof @size = m[1] end line_no = 0 output.each do |line| md = line.match(/.+ (\d+) (\d+)/) @fields[line_no].offset = md[1].to_i @fields[line_no].size = md[2].to_i line_no += 1 end @found = true end
field(name, type=nil)
click to toggle source
# File lib/ffi2/generators/structures.rb, line 145 def field(name, type=nil) field = Field.new(name, type) @fields << field return field end
found?()
click to toggle source
# File lib/ffi2/generators/structures.rb, line 151 def found? @found end
generate_layout()
click to toggle source
# File lib/ffi2/generators/structures.rb, line 161 def generate_layout buf = "" @fields.each_with_index do |field, i| if buf.empty? buf << "layout :#{field.name}, :#{field.type}, #{field.offset}" else buf << " :#{field.name}, :#{field.type}, #{field.offset}" end if i < @fields.length - 1 buf << ",\n" end end buf end
get_field(name)
click to toggle source
# File lib/ffi2/generators/structures.rb, line 179 def get_field(name) @fields.find { |f| name == f.name } end
include(i)
click to toggle source
# File lib/ffi2/generators/structures.rb, line 183 def include(i) @includes << i end
include_dir(i)
click to toggle source
# File lib/ffi2/generators/structures.rb, line 187 def include_dir(i) @include_dirs << i end
name(n)
click to toggle source
# File lib/ffi2/generators/structures.rb, line 191 def name(n) @struct_name = n end
prepare(name, target)
click to toggle source
# File lib/ffi2/generators/structures.rb, line 106 def prepare(name, target) @platform.compile(@include_dirs, name, target) end
prepare_failed()
click to toggle source
# File lib/ffi2/generators/structures.rb, line 110 def prepare_failed "Compilation error generating struct #{@name} (#{@struct_name})" end
process(target)
click to toggle source
# File lib/ffi2/generators/structures.rb, line 114 def process(target) target end
process_failed()
click to toggle source
# File lib/ffi2/generators/structures.rb, line 118 def process_failed "Error generating struct #{@name} (#{@struct_name})" end
source(io)
click to toggle source
# File lib/ffi2/generators/structures.rb, line 84 def source(io) io.puts "#include <stdio.h>" @includes.each do |inc| io.puts "#include <#{inc}>" end io.puts "#include <stddef.h>\n\n" io.puts "int main(int argc, char **argv)\n{" io.puts " #{@struct_name} s;" io.puts %[ printf("sizeof(#{@struct_name}) %u\\n", (unsigned int) sizeof(#{@struct_name}));] @fields.each do |field| io.puts <<-EOF printf("#{field.name} %u %u\\n", (unsigned int) offsetof(#{@struct_name}, #{field.name}), (unsigned int) sizeof(s.#{field.name})); EOF end io.puts "\n return 0;\n}" end
write_config(io)
click to toggle source
# File lib/ffi2/generators/structures.rb, line 155 def write_config(io) io.puts "rbx.platform.#{@name}.sizeof = #{@size}" @fields.each { |field| io.puts field.to_config(@name) } end