Method: FFI::Library#attach_function

Defined in:
lib/ffi/library.rb

#attach_function(func, args, returns, options = {}) ⇒ FFI::VariadicInvoker #attach_function(name, func, args, returns, options = {}) ⇒ FFI::VariadicInvoker

Attach C function func to this module.

Overloads:

  • #attach_function(func, args, returns, options = {}) ⇒ FFI::VariadicInvoker

    Examples:

    attach function without an explicit name

    module Foo
      extend FFI::Library
      ffi_lib FFI::Library::LIBC
      attach_function :malloc, [:size_t], :pointer
    end
    # now callable via Foo.malloc
    
  • #attach_function(name, func, args, returns, options = {}) ⇒ FFI::VariadicInvoker

    Examples:

    attach function with an explicit name

    module Bar
      extend FFI::Library
      ffi_lib FFI::Library::LIBC
      attach_function :c_malloc, :malloc, [:size_t], :pointer
    end
    # now callable via Bar.c_malloc
    

Parameters:

  • name (#to_s)

    name of ruby method to attach as

  • func (#to_s)

    name of C function to attach

  • args (Array<Symbol>)

    an array of types

  • returns (Symbol) (defaults to: nil)

    type of return value

  • options (Hash) (defaults to: nil)

    a customizable set of options

Options Hash (options):

  • :blocking (Boolean) — default: @blocking

    set to true if the C function is a blocking call

  • :convention (Symbol) — default: :default

    calling convention (see #ffi_convention)

  • :enums (FFI::Enums)
  • :type_map (Hash)

Returns:

Raises:



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/ffi/library.rb', line 177

def attach_function(name, func, args, returns = nil, options = nil)
  mname, a2, a3, a4, a5 = name, func, args, returns, options
  cname, arg_types, ret_type, opts = (a4 && (a2.is_a?(String) || a2.is_a?(Symbol))) ? [ a2, a3, a4, a5 ] : [ mname.to_s, a2, a3, a4 ]

  # Convert :foo to the native type
  arg_types = arg_types.map { |e| find_type(e) }
  options = {
    :convention => ffi_convention,
    :type_map => defined?(@ffi_typedefs) ? @ffi_typedefs : nil,
    :blocking => defined?(@blocking) && @blocking,
    :enums => defined?(@ffi_enums) ? @ffi_enums : nil,
  }

  @blocking = false
  options.merge!(opts) if opts && opts.is_a?(Hash)

  # Try to locate the function in any of the libraries
  invokers = []
  ffi_libraries.each do |lib|
    if invokers.empty?
      begin
        function = nil
        function_names(cname, arg_types).find do |fname|
          function = lib.find_function(fname)
        end
        raise LoadError unless function

        invokers << if arg_types[-1] == FFI::NativeType::VARARGS
          VariadicInvoker.new(function, arg_types, find_type(ret_type), options)

        else
          Function.new(find_type(ret_type), arg_types, function, options)
        end

      rescue LoadError
      end
    end
  end
  invoker = invokers.compact.shift
  raise FFI::NotFoundError.new(cname.to_s, ffi_libraries.map { |lib| lib.name }) unless invoker

  invoker.attach(self, mname.to_s)
  invoker
end