module FFI TypeDefs = Hash.new def self.add_typedef(current, add) if current.kind_of? Integer code = current else code = TypeDefs[current] raise TypeError, "Unable to resolve type '#{current}'" unless code end TypeDefs[add] = code end def self.find_type(name, type_map = nil) type_map = TypeDefs if type_map.nil? code = type_map[name] code = name if !code && name.kind_of?(Integer) code = name if !code && name.kind_of?(FFI::CallbackInfo) raise TypeError, "Unable to resolve type '#{name}'" unless code return code end # Converts a char add_typedef(NativeType::INT8, :char) # Converts an unsigned char add_typedef(NativeType::UINT8, :uchar) # Converts an 8 bit int add_typedef(NativeType::INT8, :int8) # Converts an unsigned char add_typedef(NativeType::UINT8, :uint8) # Converts a short add_typedef(NativeType::INT16, :short) # Converts an unsigned short add_typedef(NativeType::UINT16, :ushort) # Converts a 16bit int add_typedef(NativeType::INT16, :int16) # Converts an unsigned 16 bit int add_typedef(NativeType::UINT16, :uint16) # Converts an int add_typedef(NativeType::INT32, :int) # Converts an unsigned int add_typedef(NativeType::UINT32, :uint) # Converts a 32 bit int add_typedef(NativeType::INT32, :int32) # Converts an unsigned 16 bit int add_typedef(NativeType::UINT32, :uint32) # Converts a long add_typedef(NativeType::LONG, :long) # Converts an unsigned long add_typedef(NativeType::ULONG, :ulong) # Converts a 64 bit int add_typedef(NativeType::INT64, :int64) # Converts an unsigned 64 bit int add_typedef(NativeType::UINT64, :uint64) # Converts a long long add_typedef(NativeType::INT64, :long_long) # Converts an unsigned long long add_typedef(NativeType::UINT64, :ulong_long) # Converts a float add_typedef(NativeType::FLOAT32, :float) # Converts a double add_typedef(NativeType::FLOAT64, :double) # Converts a pointer to opaque data add_typedef(NativeType::POINTER, :pointer) # For when a function has no return value add_typedef(NativeType::VOID, :void) # Converts NUL-terminated C strings add_typedef(NativeType::STRING, :string) # Converts FFI::Buffer objects add_typedef(NativeType::BUFFER_IN, :buffer_in) add_typedef(NativeType::BUFFER_OUT, :buffer_out) add_typedef(NativeType::BUFFER_INOUT, :buffer_inout) add_typedef(NativeType::VARARGS, :varargs) # Use for a C struct with a char [] embedded inside. add_typedef(NativeType::CHAR_ARRAY, :char_array) TypeSizes = { 1 => :char, 2 => :short, 4 => :int, 8 => :long_long, } SizeTypes = { NativeType::INT8 => 1, NativeType::UINT8 => 1, NativeType::INT16 => 2, NativeType::UINT16 => 2, NativeType::INT32 => 4, NativeType::UINT32 => 4, NativeType::INT64 => 8, NativeType::UINT64 => 8, NativeType::FLOAT32 => 4, NativeType::FLOAT64 => 8, NativeType::LONG => FFI::Platform::LONG_SIZE / 8, NativeType::ULONG => FFI::Platform::LONG_SIZE / 8, NativeType::POINTER => FFI::Platform::ADDRESS_SIZE / 8, } def self.size_to_type(size) if sz = TypeSizes[size] return sz end # Be like C, use int as the default type size. return :int end def self.type_size(type) if sz = SizeTypes[find_type(type)] return sz end raise ArgumentError, "Unknown native type" end # Load all the platform dependent types begin File.open(File.join(FFI::Platform::CONF_DIR, 'types.conf'), "r") do |f| prefix = "rbx.platform.typedef." f.each_line { |line| if line.index(prefix) == 0 new_type, orig_type = line.chomp.slice(prefix.length..-1).split(/\s*=\s*/) add_typedef(orig_type.to_sym, new_type.to_sym) end } end rescue Errno::ENOENT end end