class FFI::TypesGenerator
@private
def self.generate(options = {})
def self.generate(options = {}) typedefs = nil Tempfile.open 'ffi_types_generator' do |io| io.puts <<-C lude <stdint.h> lude <stddef.h> lude <sys/types.h> !(defined(WIN32)) lude <sys/socket.h> lude <netinet/in.h> lude <sys/resource.h> if C io.close cc = ENV['CC'] || 'gcc' cmd = "#{cc} -E -x c #{options[:cppflags]} -D_DARWIN_USE_64_BIT_INODE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -c" if options[:input] typedefs = File.read(options[:input]) elsif options[:remote] typedefs = `ssh #{options[:remote]} #{cmd} - < #{io.path}` else typedefs = `#{cmd} #{io.path}` end end code = [] typedefs.each_line do |type| # We only care about single line typedef next unless type =~ /typedef/ # Ignore unions or structs next if type =~ /union|struct/ # strip off the starting typedef and ending ; type.gsub!(/^(.*typedef\s*)/, "") type.gsub!(/\s*;\s*$/, "") parts = type.split(/\s+/) def_type = parts.join(" ") # GCC does mapping with __attribute__ stuf, also see # http://hal.cs.berkeley.edu/cil/cil016.html section 16.2.7. Problem # with this is that the __attribute__ stuff can either occur before or # after the new type that is defined... if type =~ /__attribute__/ if parts.last =~ /__QI__|__HI__|__SI__|__DI__|__word__/ # In this case, the new type is BEFORE __attribute__ we need to # find the final_type as the type before the part that starts with # __attribute__ final_type = "" parts.each do |p| break if p =~ /__attribute__/ final_type = p end else final_type = parts.pop end def_type = case type when /__QI__/ then "char" when /__HI__/ then "short" when /__SI__/ then "int" when /__DI__/ then "long long" when /__word__/ then "long" else "int" end def_type = "unsigned #{def_type}" if type =~ /unsigned/ else final_type = parts.pop def_type = parts.join(" ") end if type = TYPE_MAP[def_type] code << "rbx.platform.typedef.#{final_type} = #{type}" TYPE_MAP[final_type] = TYPE_MAP[def_type] else # Fallback to an ordinary pointer if we don't know the type if def_type =~ /\*/ code << "rbx.platform.typedef.#{final_type} = pointer" TYPE_MAP[final_type] = :pointer end end end code.sort.join("\n") end