Module: Fiddle::Importer

Included in:
LibUI::FFI
Defined in:
lib/libui/ffi.rb

Instance Method Summary collapse

Instance Method Details

#extern(signature, *opts) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/libui/ffi.rb', line 51

def extern(signature, *opts)
  symname, ctype, argtype, inner_funcs = parse_signature(signature, type_alias)
  opt = parse_bind_options(opts)
  f = import_function(symname, ctype, argtype, opt[:call_type])

  f.inner_functions = inner_funcs # Added
  f.argtype         = argtype     # Added

  name = symname.gsub(/@.+/, '')
  @func_map[name] = f
  # define_method(name){|*args,&block| f.call(*args,&block)}
  begin
    /^(.+?):(\d+)/ =~ caller.first
    file = Regexp.last_match(1)
    line = Regexp.last_match(2).to_i
  rescue StandardError
    file, line = __FILE__, __LINE__ + 3
  end
  module_eval("    def \#{name}(*args, &block)\n      @func_map['\#{name}'].call(*args,&block)\n    end\n  EOS\n  module_function(name)\n  f\nend\n", file, line)

#parse_signature(signature, tymap = nil) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/libui/ffi.rb', line 13

def parse_signature(signature, tymap = nil)
  tymap ||= {}
  ret, func, args = split_signature(signature)
  symname = func
  ctype   = parse_ctype(ret, tymap)
  inner_funcs = []                                                    # Added
  argtype = split_arguments(args).collect.with_index do |arg, idx|    # Added with_index
    # Check if it is a function pointer or not
    if arg =~ /\(\*.*\)\(.*\)/ # Added
      # From the arguments, create a notation that looks like a function declaration
      # int(*f)(int *, void *) -> int f(int *, void *)
      func_arg = arg.sub('(*', ' ').sub(')', '') # Added
      # Use Fiddle's parse_signature method again.
      inner_funcs[idx] = parse_signature(func_arg)                    # Added
    end                                                               # Added
    parse_ctype(arg, tymap)
  end
  # Added inner_funcs. Original method return only 3 values.
  [symname, ctype, argtype, inner_funcs]
end

#split_signature(signature) ⇒ Object

refactored



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/libui/ffi.rb', line 35

def split_signature(signature)
  case compact(signature)
  when /^(?:[\w*\s]+)\(\*(\w+)\((.*?)\)\)(?:\[\w*\]|\(.*?\));?$/
    ret  = TYPE_VOIDP
    func = Regexp.last_match(1)
    args = Regexp.last_match(2)
  when /^([\w*\s]+[*\s])(\w+)\((.*?)\);?$/
    ret  = Regexp.last_match(1).strip
    func = Regexp.last_match(2)
    args = Regexp.last_match(3)
  else
    raise("can't parse the function prototype: #{signature}")
  end
  [ret, func, args]
end