Subject:
Re: [ruby-ffi] struct questions
From:
Wayne Meissner
Date:
12/19/09 5:54 PM
To:
ruby-ffi@googlegroups.com

2009/12/19 rogerdpack <rogerpack2005@gmail.com>:

> With char arrays, it seems "difficult" to insert a string
>
> (rdb:1) ss[:title] = "abc"
> ArgumentError Exception: put not supported for
> FFI::StructLayout::Array
>
> is there an easier way than ss[:title][0] = 33; ss[:title][1] = 34; //
> one at a time?


Assuming you mean an array like this:
class S < FFI::Struct
  layout :title, [ :char, 20 ]
end

Then currently the only easy way to fill it is:

s[:title].to_ptr.put_string(0, "foo")

Thats kinda ugly, so we should have an easier syntax.

I have patches that make the following work for :char/:uchar arrays:

s[:title] = "foo"
s[:title] = [ 'f'.ord, 'o'.ord, 'o'.ord ]
s[:title] = [ 1, 2, 3]

The second form also works for all other array element types.

The inverse also works for :char/:uchar arrays:

s[:title].to_s # => "foo"


There are a couple of corner cases that need to be figured out though.
1) What to do when a string + nul byte is larger than the array size
  a) raise an error
  b) do not terminate the string with a nul byte
  c) truncate the string and terminate with a nul byte

Currently (a) is the preferred way (makes it consistent with put_string()

e.g.
class S < FFI::Struct
  layout :title, [ :char, 4 ]
end

s = S.new
s[:title] = "abc"  # works
s[:title] = "test" # raises IndexError



2) Should array assignments be zero padded?
i.e.
class S < FFI::Struct
  layout :i, [ :int, 100 ]
end

s = S.new
s[:i] = [ 1, 2, 3]

Currently it zero pads the array if the source is smaller than the
array field size.

3) Should over-sized array assignments raise an error or truncate?
class S < FFI::Struct
  layout :i, [ :int, 2 ]
end
s = S.new
s[:i] = [ 1, 2, 3]

This currently raises an IndexError