module FFI::Library
def attach_function(mname, a3, a4, a5=nil)
def attach_function(mname, a3, a4, a5=nil) cname, arg_types, ret_type = a5 ? [ a3, a4, a5 ] : [ mname.to_s, a3, a4 ] # Convert :foo to the native type arg_types.map! { |e| find_type(e) } has_callback = arg_types.any? {|t| t.kind_of?(FFI::CallbackInfo)} options = Hash.new options[:convention] = defined?(@ffi_convention) ? @ffi_convention : :default options[:type_map] = @ffi_typedefs if defined?(@ffi_typedefs) options[:enums] = @ffi_enums if defined?(@ffi_enums) # Try to locate the function in any of the libraries invokers = [] ffi_libraries.each do |lib| begin invokers << FFI.create_invoker(lib, cname.to_s, arg_types, find_type(ret_type), options) rescue LoadError => ex end if invokers.empty? end invoker = invokers.compact.shift raise FFI::NotFoundError.new(cname.to_s, ffi_libraries.map { |lib| lib.name }) unless invoker # Setup the parameter list for the module function as (a1, a2) arity = arg_types.length params = (1..arity).map {|i| "a#{i}" }.join(",") # Always use rest args for functions with callback parameters if has_callback || invoker.kind_of?(FFI::VariadicInvoker) params = "*args, &block" end call = arity <= 3 && !has_callback && !invoker.kind_of?(FFI::VariadicInvoker)? "call#{arity}" : "call" # # Attach the invoker to this module as 'mname'. # if !has_callback && !invoker.kind_of?(FFI::VariadicInvoker) invoker.attach(self, mname.to_s) else self.module_eval <<-code @@#{mname} = invoker def self.#{mname}(#{params}) @@#{mname}.#{call}(#{params}) end def #{mname}(#{params}) @@#{mname}.#{call}(#{params}) end code end invoker end