ConstGenerator turns C constants into ruby values.
Creates a new constant generator that uses prefix as a name, and an options hash.
The only option is :required, which if set to true raises an error if a constant you have requested was not found.
When passed a block, # is automatically called at the end of the block, otherwise you must call it yourself.
# File lib/ffi/tools/const_generator.rb, line 23 23: def initialize(prefix = nil, options = {}) 24: @includes = [] 25: @constants = {} 26: @prefix = prefix 27: 28: @required = options[:required] 29: @options = options 30: 31: if block_given? then 32: yield self 33: calculate self.class.options.merge(options) 34: end 35: end
# File lib/ffi/tools/const_generator.rb, line 42 42: def [](name) 43: @constants[name].value 44: end
# File lib/ffi/tools/const_generator.rb, line 69 69: def calculate(options = {}) 70: binary = File.join Dir.tmpdir, "rb_const_gen_bin_#{Process.pid}" 71: 72: Tempfile.open("#{@prefix}.const_generator") do |f| 73: f.puts "#include <stdio.h>" 74: 75: @includes.each do |inc| 76: f.puts "#include <#{inc}>" 77: end 78: 79: f.puts "#include <stddef.h>\n\n" 80: f.puts "int main(int argc, char **argv)\n{" 81: 82: @constants.each_value do |const| 83: f.puts #ifdef #{const.name} printf("#{const.name} #{const.format}\\n", #{const.cast}#{const.name}); #endif 84: end 85: 86: f.puts "\n\treturn 0;\n}" 87: f.flush 88: 89: output = `gcc #{options[:cppflags]} -D_DARWIN_USE_64_BIT_INODE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -x c -Wall -Werror #{f.path} -o #{binary} 2>&1` 90: 91: unless $?.success? then 92: output = output.split("\n").map { |l| "\t#{l}" }.join "\n" 93: raise "Compilation error generating constants #{@prefix}:\n#{output}" 94: end 95: end 96: 97: output = `#{binary}` 98: File.unlink(binary + (FFI::Platform.windows? ? ".exe" : "")) 99: output.each_line do |line| 100: line =~ /^(\S+)\s(.*)$/ 101: const = @constants[$1] 102: const.value = $2 103: end 104: 105: missing_constants = @constants.select do |name, constant| 106: constant.value.nil? 107: end.map { |name,| name } 108: 109: if @required and not missing_constants.empty? then 110: raise "Missing required constants for #{@prefix}: #{missing_constants.join ', '}" 111: end 112: end
Request the value for C constant name. format is a printf format string to print the value out, and cast is a C cast for the value. ruby_name allows you to give the constant an alternate ruby name for #. converter or converter_proc allow you to convert the value from a string to the appropriate type for #.
# File lib/ffi/tools/const_generator.rb, line 53 53: def const(name, format = nil, cast = '', ruby_name = nil, converter = nil, 54: &converter_proc) 55: format ||= '%d' 56: cast ||= '' 57: 58: if converter_proc and converter then 59: raise ArgumentError, "Supply only converter or converter block" 60: end 61: 62: converter = converter_proc if converter.nil? 63: 64: const = Constant.new name, format, cast, ruby_name, converter 65: @constants[name.to_s] = const 66: return const 67: end
# File lib/ffi/tools/const_generator.rb, line 118 118: def dump_constants(io) 119: @constants.each do |name, constant| 120: name = [@prefix, name].join '.' 121: io.puts "#{name} = #{constant.converted_value}" 122: end 123: end
# File lib/ffi/tools/const_generator.rb, line 139 139: def include(i) 140: @includes << i 141: end
Outputs values for discovered constants. If the constant’s value was not discovered it is not omitted.
# File lib/ffi/tools/const_generator.rb, line 129 129: def to_ruby 130: @constants.sort_by { |name,| name }.map do |name, constant| 131: if constant.value.nil? then 132: "# #{name} not available" 133: else 134: constant.to_ruby 135: end 136: end.join "\n" 137: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.