Class: FFI::ConstGenerator
- Inherits:
-
Object
- Object
- FFI::ConstGenerator
- Defined in:
- lib/ffi/tools/const_generator.rb
Overview
ConstGenerator turns C constants into ruby values.
Defined Under Namespace
Classes: Constant
Instance Attribute Summary collapse
-
#constants ⇒ Object
readonly
Returns the value of attribute constants.
Class Method Summary collapse
Instance Method Summary collapse
- #[](name) ⇒ Object
- #calculate(options = {}) ⇒ Object
-
#const(name, format = nil, cast = '', ruby_name = nil, converter = nil, &converter_proc) ⇒ Object
Request the value for C constant
name
. - #dump_constants(io) ⇒ Object
- #include(i) ⇒ Object
-
#initialize(prefix = nil, options = {}) ⇒ ConstGenerator
constructor
Creates a new constant generator that uses
prefix
as a name, and an options hash. -
#to_ruby ⇒ Object
Outputs values for discovered constants.
Constructor Details
#initialize(prefix = nil, options = {}) ⇒ ConstGenerator
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, #calculate is automatically called at the end of the block, otherwise you must call it yourself.
23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/ffi/tools/const_generator.rb', line 23 def initialize(prefix = nil, = {}) @includes = [] @constants = {} @prefix = prefix @required = [:required] @options = if block_given? then yield self calculate self.class..merge() end end |
Instance Attribute Details
#constants ⇒ Object (readonly)
Returns the value of attribute constants.
11 12 13 |
# File 'lib/ffi/tools/const_generator.rb', line 11 def constants @constants end |
Class Method Details
.options ⇒ Object
39 40 41 |
# File 'lib/ffi/tools/const_generator.rb', line 39 def self. @options end |
.options=(options) ⇒ Object
36 37 38 |
# File 'lib/ffi/tools/const_generator.rb', line 36 def self.() @options = end |
Instance Method Details
#[](name) ⇒ Object
42 43 44 |
# File 'lib/ffi/tools/const_generator.rb', line 42 def [](name) @constants[name].value end |
#calculate(options = {}) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/ffi/tools/const_generator.rb', line 69 def calculate( = {}) binary = File.join Dir.tmpdir, "rb_const_gen_bin_#{Process.pid}" Tempfile.open("#{@prefix}.const_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{" @constants.each_value do |const| f.puts <<-EOF #ifdef #{const.name} printf("#{const.name} #{const.format}\\n", #{const.cast}#{const.name}); #endif EOF end f.puts "\n\treturn 0;\n}" f.flush output = `gcc #{[: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` unless $?.success? then output = output.split("\n").map { |l| "\t#{l}" }.join "\n" raise "Compilation error generating constants #{@prefix}:\n#{output}" end end output = `#{binary}` File.unlink(binary + (FFI::Platform.windows? ? ".exe" : "")) output.each_line do |line| line =~ /^(\S+)\s(.*)$/ const = @constants[$1] const.value = $2 end missing_constants = @constants.select do |name, constant| constant.value.nil? end.map { |name,| name } if @required and not missing_constants.empty? then raise "Missing required constants for #{@prefix}: #{missing_constants.join ', '}" end end |
#const(name, format = nil, cast = '', ruby_name = nil, converter = nil, &converter_proc) ⇒ Object
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 #to_ruby. converter
or converter_proc
allow you to convert the value from a string to the appropriate type for #to_ruby.
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/ffi/tools/const_generator.rb', line 53 def const(name, format = nil, cast = '', ruby_name = nil, converter = nil, &converter_proc) format ||= '%d' cast ||= '' if converter_proc and converter then raise ArgumentError, "Supply only converter or converter block" end converter = converter_proc if converter.nil? const = Constant.new name, format, cast, ruby_name, converter @constants[name.to_s] = const return const end |
#dump_constants(io) ⇒ Object
118 119 120 121 122 123 |
# File 'lib/ffi/tools/const_generator.rb', line 118 def dump_constants(io) @constants.each do |name, constant| name = [@prefix, name].join '.' io.puts "#{name} = #{constant.converted_value}" end end |
#include(i) ⇒ Object
139 140 141 |
# File 'lib/ffi/tools/const_generator.rb', line 139 def include(i) @includes << i end |
#to_ruby ⇒ Object
Outputs values for discovered constants. If the constant’s value was not discovered it is not omitted.
129 130 131 132 133 134 135 136 137 |
# File 'lib/ffi/tools/const_generator.rb', line 129 def to_ruby @constants.sort_by { |name,| name }.map do |name, constant| if constant.value.nil? then "# #{name} not available" else constant.to_ruby end end.join "\n" end |