# File lib/ffi/tools/struct_generator.rb, line 58
    def calculate(options = {})
      binary = File.join Dir.tmpdir, "rb_struct_gen_bin_#{Process.pid}"

      raise "struct name not set" if @struct_name.nil?

      Tempfile.open("#{@name}.struct_generator") do |f|
        f.puts "#include <stdio.h>"

        @includes.each do |inc|
          f.puts "#include <#{inc}>"
        end

        f.puts "#include <stddef.h>\n\n"
        f.puts "int main(int argc, char **argv)\n{"
        f.puts "  #{@struct_name} s;"
        f.puts %[  printf("sizeof(#{@struct_name}) %u\\n", (unsigned int) sizeof(#{@struct_name}));]

        @fields.each do |field|
          f.puts "printf(\"\#{field.name} %u %u\\\\n\", (unsigned int) offsetof(\#{@struct_name}, \#{field.name}),\n(unsigned int) sizeof(s.\#{field.name}));\n"
        end

        f.puts "\n  return 0;\n}"
        f.flush

        output = `gcc #{options[:cppflags]} #{options[:cflags]} -D_DARWIN_USE_64_BIT_INODE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -x c -Wall -Werror #{f.path} -o #{binary} 2>&1`

        unless $?.success? then
          @found = false
          output = output.split("\n").map { |l| "\t#{l}" }.join "\n"
          raise "Compilation error generating struct #{@name} (#{@struct_name}):\n#{output}"
        end
      end
      
      output = `#{binary}`.split "\n"
      File.unlink(binary + (FFI::Platform.windows? ? ".exe" : ""))
      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