# # Copyright (C) 2008-2010 Wayne Meissner # Copyright (c) 2007, 2008 Evan Phoenix # # This file is part of ruby-ffi. # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # * Neither the name of the Ruby FFI project nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # see {file:README} module FFI # @param [Type, DataConverter, Symbol] old type definition used by {FFI.find_type} # @param [Symbol] add new type definition's name to add # @return [Type] # Add a definition type to type definitions. def self.typedef(old, add) TypeDefs[add] = self.find_type(old) end # (see FFI.typedef) def self.add_typedef(old, add) typedef old, add end # @param [Type, DataConverter, Symbol] name # @param [Hash] type_map if nil, {FFI::TypeDefs} is used # @return [Type] # Find a type in +type_map+ ({FFI::TypeDefs}, by default) from # a type objet, a type name (symbol). If +name+ is a {DataConverter}, # a new {Type::Mapped} is created. def self.find_type(name, type_map = nil) if name.is_a?(Type) name elsif type_map && type_map.has_key?(name) type_map[name] elsif TypeDefs.has_key?(name) TypeDefs[name] elsif name.is_a?(DataConverter) (type_map || TypeDefs)[name] = Type::Mapped.new(name) else raise TypeError, "unable to resolve type '#{name}'" end end # List of type definitions TypeDefs.merge!({ # The C void type; only useful for function return types :void => Type::VOID, # C boolean type :bool => Type::BOOL, # C nul-terminated string :string => Type::STRING, # C signed char :char => Type::CHAR, # C unsigned char :uchar => Type::UCHAR, # C signed short :short => Type::SHORT, # C unsigned short :ushort => Type::USHORT, # C signed int :int => Type::INT, # C unsigned int :uint => Type::UINT, # C signed long :long => Type::LONG, # C unsigned long :ulong => Type::ULONG, # C signed long long integer :long_long => Type::LONG_LONG, # C unsigned long long integer :ulong_long => Type::ULONG_LONG, # C single precision float :float => Type::FLOAT, # C double precision float :double => Type::DOUBLE, # C long double :long_double => Type::LONGDOUBLE, # Native memory address :pointer => Type::POINTER, # 8 bit signed integer :int8 => Type::INT8, # 8 bit unsigned integer :uint8 => Type::UINT8, # 16 bit signed integer :int16 => Type::INT16, # 16 bit unsigned integer :uint16 => Type::UINT16, # 32 bit signed integer :int32 => Type::INT32, # 32 bit unsigned integer :uint32 => Type::UINT32, # 64 bit signed integer :int64 => Type::INT64, # 64 bit unsigned integer :uint64 => Type::UINT64, :buffer_in => Type::BUFFER_IN, :buffer_out => Type::BUFFER_OUT, :buffer_inout => Type::BUFFER_INOUT, # Used in function prototypes to indicate the arguments are variadic :varargs => Type::VARARGS, }) class StrPtrConverter extend DataConverter native_type Type::POINTER # @param [Pointer] val # @param [] ctx # @return [Array(String, Pointer)] # Returns a [ String, Pointer ] tuple so the C memory for the string can be freed def self.from_native(val, ctx) [ val.null? ? nil : val.get_string(0), val ] end end typedef(StrPtrConverter, :strptr) # @param type +type+ is an instance of class accepted by {FFI.find_type} # @return [Numeric] # Get +type+ size, in bytes. def self.type_size(type) find_type(type).size end # Load all the platform dependent types begin File.open(File.join(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*/) typedef(orig_type.to_sym, new_type.to_sym) end } end typedef :pointer, :caddr_t rescue Errno::ENOENT end end