gpt4 book ai didi

使用 FFI 和 C 函数在 ruby​​ 中创建动态数组类

转载 作者:数据小太阳 更新时间:2023-10-29 06:59:00 27 4
gpt4 key购买 nike

我想在 ruby​​ 中创建我自己的动态数组类(作为培训)。这个想法是有一个 DynamicArray 类,它有一个容量(在给定时刻它可以容纳的元素数量),一个大小(在给定时刻实际被插入数组的元素数量)和一个 static_array 是固定大小的静态整数数组。每当这个 static_array 已满时,我们将创建一个容量是原始 static_array 两倍的新静态数组,并将每个元素复制到新的 static_array 中。由于 ruby​​ 中没有静态数组,我的想法是使用 FFI https://github.com/ffi/ffi .在 c 中创建一个函数,该函数创建一个大小为 n 的静态 int 数组,然后能够在我的 ruby​​ 程序中使用它。我对 C 知之甚少,很难理解 FFI 的文档到目前为止,这是一个 create_array.c 文件,它定义了我的 c 函数来创建一个数组。

#include<stdio.h>
int * createArray ( int size )
{
int array[size];
return 0;

}

一个 create_array.h 文件(根据我对 FFI 的理解,你需要将你的 c 函数放在一个 c 库中。):

int * createArray ( int size )

这是我的 dynamic_array.rb 文件,它将按照以下方式执行某些操作:

require 'ffi'
class DynamicArray
extend FFI::Library
ffi_lib "./create_array.h"
attach_function :create_array, [:int], :int
def initialize
@size = 0
@capacity = 1
@current_index = 0
@static_array = create_array(@capacity)
end

def add(element)
@size += 1
resize_array if @size > @capacity
@static_array[@current_index] = element
@current_index += 1
end

private

def resize_array
@capacity = @capacity*2
new_arr = create_array(@capacity)
@static_array.each_with_index do |val, index|
new_arr[index] = val
end
@static_array = new_arr
end
end

以下是添加和调整大小的一些测试:

  def test_add
dynamic_arr = DynamicArray.new
dynamic_arr.add(1)
dynamic_arr.add(2)
assert_equal(1, dynamic_arr.static_array[0])
assert_equal(2, dynamic_arr.static_array[1])
end

def test_resize_array
dynamic_arr = DynamicArray.new
dynamic_arr.add(1)
dynamic_arr.add(2)
assert_equal(2, dynamic_arr.capacity)
dynamic_arr.resize_array
assert_equal(4, dynamic_arr.capacity)
assert_equal
end

你能解释一下我应该怎么做才能完成这项工作吗?

最佳答案

看来您没有正确使用 C 代码。

create_array C函数:

  • 您没有返回数组,因此 ruby​​ 代码无法处理新创建的数组,您需要返回它
  • 如果你想返回一个数组你实际上需要返回它的指针
  • 在 C 中,为了创建一个数组并且在编译前不知道大小,您需要使用 malloc 分配它的内存。 (或 alloc 家族中的一些其他函数)

把它们放在一起,这就是你的 create_array.c文件看起来像:

#include <stdlib.h> /* in order to use malloc */

int * create_array (int size){
int *a = malloc(size * sizeof(int));
return a; /* returning the pointer to the array a*/
}

和你的头文件create_array.h :

int * create_array(int);

为了包装所有内容,您仍然需要在 ruby​​ 接触它之前对其进行编译:

gcc -shared -o create_array.so -fPIC create_array.c

此命令使用 gcc 将您的 C 代码编译到名为 create_array.so 的共享库中来自 create_array.c源文件。需要安装 gcc 才能工作。

最后,您可以在 ruby​​ 中使用 C 函数,并在您的 dynamic_array.rb 中进行一些修改。 :

require 'ffi'
class DynamicArray
extend FFI::Library
ffi_lib "./create_array.so" # using the shared lib
attach_function :create_array, [:int], :pointer # receiving a pointer to the array
# rest of your code

现在,这应该可以工作了!但是您的 ruby​​ 代码仍然存在一些问题:

  • 当你做 @static_array = create_array(@capacity)您收到的是指向已分配数组的 C 指针,而不是数组本身,至少在 ruby​​ 中不是。
  • 写作@static_array[@current_index] = element不会工作 NoMethodError: undefined method '[]=' for #<FFI::Pointer address=0x000055d50e798600>
  • 如果要向数组中添加一个元素,必须用 C 代码来完成。像这样的东西:
void add_to_array (int * array, int index, int number){
array[index] = number;
}
attach_function :add_to_array, [:pointer, :int, :int], :void
add_to_array(@static_array, @current_index, element)
  • 同样适用于 @static_array.each_with_index你需要用 C 编写代码。

关于使用 FFI 和 C 函数在 ruby​​ 中创建动态数组类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55440686/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com