Module: FFI::Accessors::ClassMethods

Included in:
FFI::Accessors, StructWrapper
Defined in:
lib/ffi/accessors.rb

Overview

Class methods for defining struct member accessors

Accessor Definition collapse

Accessor Information collapse

Instance Method Summary collapse

Instance Method Details

#attr_accessor(*args) ⇒ Object

Override instance variable based accessor to build our enhanced readers and writers



155
156
157
# File 'lib/ffi/accessors.rb', line 155

def attr_accessor(*args)
  attr_reader(*args) + attr_writer(*args)
end

#attr_reader(*args) ⇒ Array<Symbol]

Standard instance variable based reader with support for boolean and integration with to_h, inspect etc..

The member registered for each attribute will be its instance variable symbol (ie with a leading '@')

Returns:

  • (Array<Symbol])

    Array<Symbol]



141
142
143
144
# File 'lib/ffi/accessors.rb', line 141

def attr_reader(*args)
  super(*args.map { |a| a[-1] == '?' ? a[0..-2] : a })
  ffi_attr_reader_method(**args.to_h { |a| [a, :"@#{a[-1] == '?' ? a[0..-2] : a}"] })
end

#attr_writer(*args) ⇒ Object

Standard instance variable based writer with support for booleans and integration with fill etc..

The member registered for each attribute will be its instance variable symbol (ie with a leading '@')



149
150
151
152
# File 'lib/ffi/accessors.rb', line 149

def attr_writer(*args)
  super(*args.map { |a| a[-1] == '?' ? a[0..-2] : a })
  ffi_attr_writer_method(**args.to_h { |a| [a, :"@#{a[-1] == '?' ? a[0..-2] : a}"] })
end

#ffi_attr_accessor(*attrs, **attrs_map) ⇒ Array<Symbol] list of methods defined

Define both reader and writer

Returns:

  • (Array<Symbol] list of methods defined)

    Array<Symbol] list of methods defined



163
164
165
# File 'lib/ffi/accessors.rb', line 163

def ffi_attr_accessor(*attrs, **attrs_map)
  ffi_attr_reader(*attrs, **attrs_map) + ffi_attr_writer(*attrs, **attrs_map)
end

#ffi_attr_reader(*attrs, **attrs_map, &block) ⇒ Array<Symbol>

Define reader methods for the given attributes

Parameters:

  • attrs (Array<Symbol>)

    List of struct field members to treat as attributes

    a trailing '?' in an attribute name indicates a boolean reader. eg. :debug? will define the reader method :debug and an alias method :debug? => :debug,

    String values are converted to Symbol

  • attrs_map (Hash<Symbol,Symbol>)

    Map of attribute name to struct field name - where field names don't fit natural ruby methods etc...

    A Hash value in attrs is also treated as an attrs_map. String keys/values are transformed to Symbol.

  • block (Proc)

    An optional block taking a single argument (the struct field value) to convert into something more useful.

    This block is evaluated within the method using :instance_exec

Returns:

  • (Array<Symbol>)

    list of methods defined



187
188
189
190
191
192
193
# File 'lib/ffi/accessors.rb', line 187

def ffi_attr_reader(*attrs, **attrs_map, &block)
  ffi_attr_reader_method(*attrs, **attrs_map) do
    _attr, member = ffi_attr_reader_member(__method__)
    val = self[member]
    block ? instance_exec(val, &block) : val
  end
end

#ffi_attr_reader_method(*attrs, **attrs_map, &block) ⇒ Array<Symbol>

Define reader methods directly from a block

Examples:

Related struct members

# uid/gid are only meaningful if corresponding set_ field is true
layout(set_uid: :bool, uid: :uint, set_gid: :bool, gid: :uint)

# @!attribute [r] uid
#   @return [Integer] the user id
#   @return [nil] if uid has not been explicitly set

# @!attribute [r] gid
#   @return [Integer] the group id
#   @return [nil] if gid has not been explicitly set

ffi_attr_reader_method(:uid, :gid) do
  attr, member = ffi_attr_reader_member(__method__)
  setter = :"set_#{attr}"
  self[setter] ? self[:attr] : nil
end # => [:uid :gid]

Parameters:

  • attrs (Array<Symbol>)
  • attrs_map (Hash<Symbol,Symbol>)
  • block (Proc)

    must allow zero arity, but can have additional optional arguments or keyword arguments.

    the block is evaluated using :instance_exec

    within block the attribute name is always the method name (__method__) and the associated struct field member name is from any attribute maps supplied; ie attrs_map or Hash value in attrs. They can be retrieved using FFI::Accessors#ffi_attr_reader_member

    attr, member = ffi_attr_reader_member(__method__)

    if not supplied a reader will still be registered for each attribute and a boolean alias created if required

Returns:

  • (Array<Symbol>)

    list of methods defined



229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/ffi/accessors.rb', line 229

def ffi_attr_reader_method(*attrs, **attrs_map, &block)
  attr_methods = map_attributes(attrs, attrs_map).flat_map do |attr, member, bool|
    ffi_attr_readers_map[attr] = member
    define_method(attr, &block) if block
    next attr unless bool

    bool_alias = :"#{attr}?"
    alias_method(bool_alias, attr)
    [attr, bool_alias]
  end
  send(default_visibility, *attr_methods)
  attr_methods
end

#ffi_attr_readersArray<Symbol>

Returns list of accessor reader methods defined. (excludes boolean aliases).

Returns:

  • (Array<Symbol>)

    list of accessor reader methods defined. (excludes boolean aliases)



327
328
329
# File 'lib/ffi/accessors.rb', line 327

def ffi_attr_readers
  ffi_attr_readers_map.keys
end

#ffi_attr_writer(*attrs, **attrs_map, &block) ⇒ Array<Symbol>

Define struct attribute writers for the given attributes

Parameters:

  • attrs (Array<Symbol>)
  • attrs_map (Hash<Symbol,Symbol>)
  • block (Proc<Object>)

    An optional block taking a single argument to convert input value into a value to be placed in the underlying struct field

    This block is evaluated within the method using :instance_exec

Returns:

  • (Array<Symbol>)

    list of methods defined



252
253
254
255
256
257
# File 'lib/ffi/accessors.rb', line 252

def ffi_attr_writer(*attrs, **attrs_map, &block)
  ffi_attr_writer_method(*attrs, **attrs_map) do |val|
    _attr, member = ffi_attr_writer_member(__method__)
    self[member] = block ? instance_exec(val, &block) : val
  end
end

#ffi_attr_writer_method(*attrs, **attrs_map, &block) ⇒ Array<Symbol>

Define writer methods directly from a block

Parameters:

  • attrs (Array<Symbol>)
  • attrs_map (Hash<Symbol,Symbol>)
  • block (Proc)

    must allow arity = 1, but can have additional optional arguments or keyword arguments.

    the block is evaluated using :instance_exec

    within block the attribute name is always the method name stripped of its trailing '=' (:"#{__method__[0..-2]}") and the associated struct field member name is from any attribute maps supplied. ie attrs_map or Hash value in attrs. They can be retrieved using FFI::Accessors#ffi_attr_writer_member

    attr, member = ffi_attr_writer_member(__method__)

    if not supplied a writer method is still registered for each attribute name

Returns:

  • (Array<Symbol>)

    list of methods defined



275
276
277
278
279
280
281
282
# File 'lib/ffi/accessors.rb', line 275

def ffi_attr_writer_method(*attrs, **attrs_map, &block)
  writer_methods = map_attributes(attrs, attrs_map) do |attr, member, _bool|
    ffi_attr_writers_map[attr] = member
    block ? define_method("#{attr}=", &block) : attr
  end
  send(default_visibility, *writer_methods)
  writer_methods
end

#ffi_attr_writersArray<Symbol>

Returns list of accessor writer methods (ie ending in '=').

Returns:

  • (Array<Symbol>)

    list of accessor writer methods (ie ending in '=')



333
334
335
# File 'lib/ffi/accessors.rb', line 333

def ffi_attr_writers
  ffi_attr_writers_map.keys.map { |a| :"#{a}=" }
end

#ffi_bitflag_accessor(member, *flags) ⇒ Array<Symbol>

Define individual flag accessors over a bitmask field

Returns:

  • (Array<Symbol>)

    list of methods defined



286
287
288
289
# File 'lib/ffi/accessors.rb', line 286

def ffi_bitflag_accessor(member, *flags)
  ffi_bitflag_reader(member, *flags)
  ffi_bitflag_writer(member, *flags)
end

#ffi_bitflag_reader(member, *flags) ⇒ Array<Symbol>

Define individual flag readers over a bitmask field

Parameters:

  • member (Symbol)

    the bitmask member

  • flags (Array<Symbol>)

    list of flags to define methods for. Each flag also gets a :flag? boolean alias

Returns:

  • (Array<Symbol>)

    list of methods defined



295
296
297
298
299
300
301
# File 'lib/ffi/accessors.rb', line 295

def ffi_bitflag_reader(member, *flags)
  bool_attrs = flags.to_h { |f| [:"#{f}?", member] }
  ffi_attr_reader_method(**bool_attrs) do
    flag_attr, member = ffi_attr_reader_member(__method__)
    self[member].include?(flag_attr)
  end
end

#ffi_bitflag_writer(member, *flags) ⇒ Array<Symbol>

Define individual flag writers over a bitmask field

Parameters:

  • member (Symbol)

    the bitmask member

  • flags (Array<Symbol>)

    list of flag attributes

Returns:

  • (Array<Symbol>)

    list of methods defined



307
308
309
310
311
312
313
314
# File 'lib/ffi/accessors.rb', line 307

def ffi_bitflag_writer(member, *flags)
  writers = flags.to_h { |f| [f, member] }
  ffi_attr_writer_method(**writers) do |v|
    flag_attr, member = ffi_attr_writer_member(__method__)
    v ? self[member] += [flag_attr] : self[member] -= flag
    v
  end
end

#ffi_public_attr_readersArray<Symbol>

Returns list of public attr accessor reader methods.

Returns:

  • (Array<Symbol>)

    list of public attr accessor reader methods



321
322
323
# File 'lib/ffi/accessors.rb', line 321

def ffi_public_attr_readers
  ffi_attr_readers & public_instance_methods
end

#ffi_public_attr_writersArray<Symbol>

Returns list of public accessor writer methods (ie ending in '=').

Returns:

  • (Array<Symbol>)

    list of public accessor writer methods (ie ending in '=')



339
340
341
# File 'lib/ffi/accessors.rb', line 339

def ffi_public_attr_writers
  ffi_attr_writers & public_instance_methods
end