Dav*_*mar 2 c ruby memory arrays 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;
}
Run Code Online (Sandbox Code Playgroud)
这是我的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
Run Code Online (Sandbox Code Playgroud)
我添加了一些方法来与我的数组,推元素,读取索引处的元素进行交互...但是我的static_array实例不能完全按预期工作...
假设我写:
// creates a static array in memory which can store 4 ints
arr = StaticArray.new(4)
Run Code Online (Sandbox Code Playgroud)
现在让我们在arr中推一个int:
arr.push(20)
Run Code Online (Sandbox Code Playgroud)
arr.print 将输出
20
0
0
0
Run Code Online (Sandbox Code Playgroud)
这是有道理的。现在让我们将另一个int推入arr:
arr.push(16)
Run Code Online (Sandbox Code Playgroud)
并arr.print再次:
4116
16
0
0
Run Code Online (Sandbox Code Playgroud)
20已经被4116取代了。。。我真的不能理解这里发生的事情吗?
如果对https://www.rubydoc.info/github/ffi/ffi/FFI/Pointer有帮助,这是指向FFIPointer类文档的链接
FFI接口不知道指针的类型,因此它只是将其视为字节数组(请参见有关指针类型的初始化)。请注意,当您通过时:int,这是针对特定的write和的read,而不是您在进行索引的位置。因此,您正在以字节偏移量0、1、2、3而不是整数元素0、4、8、12进行写入和打印。
在具有32位,4字节int的little endian系统上,二进制值20是14 00 00 00和16是10 00 00 00。
因此,您分配4 * 4字节,即32个字节,前8个为。
00 00 00 00 00 00 00 00
Run Code Online (Sandbox Code Playgroud)
并在偏移量0处写入20
14 00 00 00 00 00 00 00
Run Code Online (Sandbox Code Playgroud)
然后在偏移量1处写入16
14 10 00 00 00 00 00 00
Run Code Online (Sandbox Code Playgroud)
14 10 00 00是0x00001014或4116,然后在下一个偏移量处打印它10 00 00 00是16。