Class: GirFFI::Callback

Inherits:
Proc
  • Object
show all
Defined in:
lib/gir_ffi/callback.rb

Overview

Specialized kind of Proc to be used for callback arguments. TODO: Create superclass for all actual callback types that does the wrapping for this.

Class Method Summary collapse

Class Method Details

.from(namespace, name, prc) ⇒ Object

Create Callback from a Proc. Makes sure arguments are properly wrapped, and the callback is stored to prevent garbage collection.



7
8
9
10
11
# File 'lib/gir_ffi/callback.rb', line 7

def self.from namespace, name, prc
  wrap_in_callback_args_mapper(namespace, name, prc).tap do |cb|
    CallbackHelper.store_callback cb
  end
end

.map_callback_args(args, info) ⇒ Object



24
25
26
27
# File 'lib/gir_ffi/callback.rb', line 24

def self.map_callback_args args, info
  args.zip(info.args).map { |arg, inf|
    map_single_callback_arg arg, inf.argument_type }
end

.map_interface_callback_arg(arg, type) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/gir_ffi/callback.rb', line 50

def self.map_interface_callback_arg arg, type
  iface = type.interface
  case iface.info_type
  when :object, :interface
    arg.to_object
  when :struct
    klass = GirFFI::Builder.build_class iface
    klass.wrap arg
  else
    arg
  end
end

.map_single_callback_arg(arg, type) ⇒ Object

TODO: Use GirFFI::ReturnValue classes for mapping.



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/gir_ffi/callback.rb', line 30

def self.map_single_callback_arg arg, type
  case type.tag
  when :interface
    map_interface_callback_arg arg, type
  when :utf8
    ArgHelper.ptr_to_utf8 arg
  when :void
    map_void_callback_arg arg
  when :array
    subtype = type.param_type(0)
    if subtype.tag == :interface and arg.is_a?(FFI::Pointer)
      map_interface_callback_arg arg, subtype
    else
      raise NotImplementedError
    end
  else
    arg
  end
end

.map_void_callback_arg(arg) ⇒ Object



63
64
65
66
67
68
69
# File 'lib/gir_ffi/callback.rb', line 63

def self.map_void_callback_arg arg
  if arg.null?
    nil
  else
    GirFFI::ArgHelper::OBJECT_STORE[arg.address]
  end
end

.wrap_in_callback_args_mapper(namespace, name, prc) ⇒ Object

TODO: Create actual callback class from the callback info, so no lookup is needed. This class can then also perform the argument mapping.



15
16
17
18
19
20
21
22
# File 'lib/gir_ffi/callback.rb', line 15

def self.wrap_in_callback_args_mapper namespace, name, prc
  return prc if FFI::Function === prc
  return nil if prc.nil?
  info = GObjectIntrospection::IRepository.default.find_by_name namespace, name
  return self.new do |*args|
    prc.call(*map_callback_args(args, info))
  end
end