Class: VirtualBox::COM::XPCOMC::Sig
- Inherits:
-
Object
- Object
- VirtualBox::COM::XPCOMC::Sig
- Defined in:
- lib/virtualbox/com/xpcomc-ffi/sig.rb
Overview
Signatures are a list of type and direction (way: :in, :out) The type supported are simple types which resolved to Symbol or array of simple types
These types need to be “converted” to be interpreted corretly in the contexts of:
- callback
- writing arguments
- reading arguments
Instance Method Summary collapse
-
#initialize(sig) ⇒ Sig
constructor
Store and normalize signatures.
-
#prepare_args(args = []) ⇒ Object
Prepare arguments by converting them to C structures.
-
#read_values(args) ⇒ Object
Takes arguments list and returns the output from a function, properly dereferencing any output pointers.
-
#to_ffi_callback ⇒ Object
Converts a function signature to an FFI function spec.
Constructor Details
#initialize(sig) ⇒ Sig
Store and normalize signatures
16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/virtualbox/com/xpcomc-ffi/sig.rb', line 16 def initialize(sig) @sig = sig.map {|item| if item.is_a?(Array) && item[0] == :out then [ item[1], :out ] else [ item, :in ] end }.freeze.each{|type, way| # Sanity check: only `[type]` or `type` if type.is_a?(Array) && type.length != 1 raise ArgumentError, "only arrays of simple type are supported" end } end |
Instance Method Details
#prepare_args(args = []) ⇒ Object
Prepare arguments by converting them to C structures
47 48 49 50 51 52 53 |
# File 'lib/virtualbox/com/xpcomc-ffi/sig.rb', line 47 def prepare_args(args=[]) args = args.dup results = @sig.inject([]) do |results, item| single_type_to_arg(args, item, results) end end |
#read_values(args) ⇒ Object
Takes arguments list and returns the output from a function, properly dereferencing any output pointers.
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/virtualbox/com/xpcomc-ffi/sig.rb', line 58 def read_values(args) values, i = [], 0 @sig.each do |type, way| # Array of type: [ type ] # Skip 2: size + pointer to array if type.is_a?(Array) if way == :out size, type = args[i].read_uint32, type[0] values << if type == OCTET then read_binary_blob(args[i+1], size) else get_array_by_type(args[i+1], type, size) end end i += 2 # Simple type : type # Skip 1: pointer else if way == :out values << read_by_type(args[i], type) end i += 1 end end case values.size when 0 then nil when 1 then values.first else values end end |
#to_ffi_callback ⇒ Object
Converts a function signature to an FFI function spec. This handles custom types (unicode strings, arrays, and out-parameters) and will return a perfectly valid array ready to be passed into ‘callback`.
36 37 38 39 40 41 42 43 |
# File 'lib/virtualbox/com/xpcomc-ffi/sig.rb', line 36 def to_ffi_callback @sig.map {|type, way| is_array = type.is_a?(Array) case way when :out then is_array ? [:pointer, :pointer] : :pointer when :in then is_array ? [:uint32, :pointer] : mangling(type)[0] end }.unshift(:pointer).flatten # Add `this` element end |