使用ruby FFI在ruby中创建静态数组类

时间:2019-04-08 10:17:43

标签: c arrays ruby memory ffi

我想在ruby中实现我自己的静态数组类。这将是一个具有固定容量的数组,并且该数组中的所有元素都是单一类型。 为了直接访问内存,我使用了FFI gem https://github.com/ffi/ffi,它可以创建您自己的C函数并将其用于ruby程序。 我创建了一个非常简单的C函数,该函数为整数数组分配内存并返回指向内存空间的指针:

int * create_static_array(int size) {
  int *arr = malloc(size * sizeof(int));
  return arr;
}

这是我的ruby static_array类,它使用create_static_array:

require 'ffi'
class StaticArray
  attr_accessor :pointer, :capacity, :next_index
  extend FFI::Library

  ffi_lib './create_array/create_array.so'
  attach_function :create_static_array, [:int], :pointer

  def initialize(capacity)
    @capacity = capacity
    @pointer = create_static_array(capacity)
    @next_index = 0
  end
 # adds value to the next_index in array
  def push(val)
    @pointer[@next_index].write(:int, val)
    @next_index += 1
  end
 # reads value at index
  def [](index)
    raise IndexOutOfBoundException if index >= @capacity
    self.pointer[index].read(:int)
  end
 # print every value in index
  def print
    i = 0
    while (i <   @capacity)
      puts @pointer[i].read(:int)
      i += 1
    end
  end
end

我添加了一些方法来与数组交互,推送元素,读取索引处的元素... 但是我的static_array实例不能完全按预期工作...

让我说:

// creates a static array in memory which can store 4 ints
arr = StaticArray.new(4)

现在让我们在arr中推送一个整数:

arr.push(20)

arr.print将输出

20
0
0
0

这很有意义。现在让我们将另一个int推入arr:

arr.push(16)

arr.print

4116
16
0
0

20已被4116取代...我真的无法理解这里发生的事情吗?

Here's the link to the FFIPointer class doc if that helps https://www.rubydoc.info/github/ffi/ffi/FFI/Pointer

1 个答案:

答案 0 :(得分:5)

FFI接口不知道指针的类型,因此它只是将其视为字节数组(请参见有关指针类型的初始化)。请注意,虽然您确实传递了:int,但这是针对特定的writeread的,而不是您进行索引的位置。因此,您正在以字节偏移量0、1、2、3而不是整数元素0、4、8、12进行写入和打印。

在具有32位,4字节int的小端系统中,二进制值为20的是14 00 00 00,而二进制值为16的是10 00 00 00

因此,您分配4 * 4字节,即32个字节,前8个为。

00 00 00 00 00 00 00 00

然后在偏移量0处写入20

14 00 00 00 00 00 00 00

然后在偏移量1处写入16

14 10 00 00 00 00 00 00

14 10 00 000x00001014或4116,然后在下一个偏移量处打印的是10 00 00 00,即16。