NiceFFI::Library

A module to be used in place of FFI::Library. It acts mostly like FFI::Library, but with some nice extra features and conveniences to make life easier:

Public Class Methods

extend_object( klass ) click to toggle source
# File lib/nice-ffi/library.rb, line 48
def self.extend_object( klass )
  klass.extend FFI::Library

  super

  class << klass
    alias :func :attach_function
    alias :var  :attach_variable
  end
end

Public Instance Methods

attach_function( methname, arg1, arg2, arg3=nil ) click to toggle source
# File lib/nice-ffi/library.rb, line 106
def attach_function( methname, arg1, arg2, arg3=nil )

  # To match the normal attach_function's weird syntax.
  # The arguments can be either:
  # 
  # 1. methname, args, retrn_type  (funcname = methname)
  # 2. methname, funcname, args, retrn_type
  # 
  funcname, args, retrn_type = if arg1.kind_of?(Array)
                                 [methname, arg1, arg2]
                               else
                                 [arg1, arg2, arg3]
                               end

  unless retrn_type.kind_of? NiceFFI::TypedPointer
    # Normal FFI::Library.attach_function behavior.
    super
  else

    # Create the raw FFI binding, which returns a pointer.
    # We call it __methname because it's not meant to be called
    # by users. We also make it private below.
    # 
    super( "__#{methname}".to_sym, funcname, args, :pointer )


    # CAUTION: Metaclass hackery ahead! Handle with care!

    metaklass = class << self; self; end
    metaklass.instance_eval {

      # Create the nice method, which calls __methname and wraps the
      # return value (a pointer) the appropriate class using
      # TypedPointer#wrap. This is the one that users should call,
      # so we don't prepend the name with _'s.
      # 
      define_method( methname ) do |*args|
        retrn_type.wrap( send("__#{methname}".to_sym, *args) )
      end

      # __methname is private.
      private "__#{methname}".to_sym

    }

  end

end
load_library( names, search_paths=NiceFFI::PathSet::DEFAULT ) click to toggle source

Try to find and load a library (e.g. "SDL_ttf") into an FFI wrapper module (e.g. SDL::TTF). This method searches in different locations depending on your OS. See PathSet.

Returns the path to the library that was loaded.

Raises LoadError if it could not find or load the library.

# File lib/nice-ffi/library.rb, line 68
def load_library( names, search_paths=NiceFFI::PathSet::DEFAULT )

  names = [names] unless names.kind_of? Array

  paths = search_paths.find( *names )

  # Try just the plain library name(s), as last resort.
  paths += names

  # Try loading each path until one works.
  loaded = paths.find { |path| 
    begin
      self.module_eval {
        ffi_lib path
      }
    rescue LoadError
      false
    else
      true
    end
  }

  if loaded.nil?
    # Oops, none of them worked.
    pretty_names = if names.size == 1
                     names[0]
                   else
                     names[0..-2].join(", ") + ", or " + names[-1]
                   end

    raise( LoadError, "Could not load #{pretty_names}." )
  else
    # Return the one that did work
    return loaded
  end
end
optfunc( *args ) click to toggle source
Alias for: optional_function
optional( warn_message=nil, &block ) click to toggle source

Calls the given block, but rescues and prints a warning if FFI::NotFoundError is raised. If warn_message is nil, the error message is printed instead.

This is intended to be used around attach_function for cases where the function may not exist (e.g. because the user has an old version of the library) and the library should continue loading anyway (with the function missing).

Example:

module Foo
  extend NiceFFI::Library

  load_library( "libfoo" )

  optional( "Warning: Your libfoo doesn't have opt_func()" ) do
    attach_function :opt_func, [], :int
  end
end
# File lib/nice-ffi/library.rb, line 178
def optional( warn_message=nil, &block )
  raise LocalJumpError, "no block given" unless block_given?
  begin
    block.call()
  rescue FFI::NotFoundError => e
    if warn_message
      puts warn_message
    else
      puts "Warning: #{e.message}"
    end
  end
end
optional_function( *args ) click to toggle source

Like attach_function, but wrapped in optional.

# File lib/nice-ffi/library.rb, line 193
def optional_function( *args )
  optional {  attach_function( *args )  }
end
Also aliased as: optfunc

[Validate]

Generated with the Darkfish Rdoc Generator 2.