def attach_function(mname, a3, a4, a5=nil)
cname, arg_types, ret_type = a5 ? [ a3, a4, a5 ] : [ mname.to_s, a3, a4 ]
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)
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
arity = arg_types.length
params = (1..arity).map {|i| "a#{i}" }.join(",")
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"
if !has_callback && !invoker.kind_of?(FFI::VariadicInvoker)
invoker.attach(self, mname.to_s)
else
self.module_eval "@@\#{mname} = invoker\ndef self.\#{mname}(\#{params})\n@@\#{mname}.\#{call}(\#{params})\nend\ndef \#{mname}(\#{params})\n@@\#{mname}.\#{call}(\#{params})\nend\n"
end
invoker
end