module FFI
def self.add_typedef(current, add)
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