module FFI

def self.add_typedef(current, add)

TypeDefs = Hash.new
def self.add_typedef(current, add)
  if current.kind_of?(FFI::Type)
    code = current
  else
    code = TypeDefs[current]
    raise TypeError, "Unable to resolve type '#{current}'" unless code
  end
  TypeDefs[add] = code
end

def self.create_invoker(lib, name, args, ret_type, options = { :convention => :default })

def self.create_invoker(lib, name, args, ret_type, options = { :convention => :default })
  # Current artificial limitation based on JRuby::FFI limit
  raise SignatureError, 'FFI functions may take max 32 arguments!' if args.size > 32
  # Open the library if needed
  library = if lib.kind_of?(DynamicLibrary)
    lib
  elsif lib.kind_of?(String)
    # Allow FFI.create_invoker to be  called with a library name
    DynamicLibrary.open(FFI.map_library_name(lib), DynamicLibrary::RTLD_LAZY)
  elsif lib.nil?
    FFI::Library::DEFAULT
  else
    raise LoadError, "Invalid library '#{lib}'"
  end
  function = library.find_function(name)
  raise NotFoundError.new(name, library.name) unless function
  args = args.map {|e| find_type(e) }
  invoker = if args.length > 0 && args[args.length - 1] == FFI::NativeType::VARARGS
    FFI::VariadicInvoker.new(function, args, find_type(ret_type), options)
  else
    FFI::Function.new(find_type(ret_type), args, function, options)
  end
  raise NotFoundError.new(name, library.name) unless invoker
  return invoker
end

def self.errno

def self.errno
  FFI::LastError.error
end

def self.errno=(error)

def self.errno=(error)
  FFI::LastError.error = error
end

def self.find_type(name, type_map = nil)

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?(FFI::Type)
  raise TypeError, "Unable to resolve type '#{name}'" unless code
  return code
end

def self.map_library_name(lib)

def self.map_library_name(lib)
  # Mangle the library name to reflect the native library naming conventions
  lib = Platform::LIBC if Platform::IS_LINUX && lib == 'c'
  if lib && File.basename(lib) == lib
    ext = ".#{Platform::LIBSUFFIX}"
    lib = Platform::LIBPREFIX + lib unless lib =~ /^#{Platform::LIBPREFIX}/
    lib += ext unless lib =~ /#{ext}/
  end
  lib
end

def self.size_to_type(size)

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)

def self.type_size(type)
  if sz = SizeTypes[find_type(type)]
    return sz
  end
  raise ArgumentError, "Unknown native type"
end