在 Ruby FFI 中声明 char 数组

问题描述 投票:0回答:2

我有以下 C 代码:

typedef void (*mycallback) (char buf[128]);
void take_callback(mycallback cb)
{
}

我编写了等效的 Ruby FFI 声明,如下所示(遵循 FFI wiki 上的结构建议):

  callback :mycallback, [[:char, 128]], :void
  attach_function :take_callback, [:mycallback], :void

当我运行它时,出现以下错误:

`find_type': unable to resolve type '[:char, 128]' (TypeError)

看来我没有正确声明回调中的 char 数组。从数组在 C 中函数参数中的工作方式来看,我认为我应该使用

:pointer
而不是
[:char, 128]
。但我不确定 FFI 的特殊性。这里真正正确的语法是什么?

c ruby callback ruby-ffi
2个回答
2
投票

在 C 中数组不是按值传递的——它们作为指向第一个元素的指针传递,因此

:pointer
(或通常用于
char *
的任何内容)应该是正确的。


0
投票

使用

:pointer
是此类参数的正确方法,不仅对于回调,而且对于一般情况也是如此。例如,这也是不可能的:
typedef [:char, 128], :buffer_128
。唯一的例外是允许这些类型的
FFI::Struct
布局。

这有点令人沮丧,特别是因为 FFI 如此无缝地支持空终止字符串(通过

:string
)。幸运的是,使用
:pointer
参数仍然相对容易。

我在我的一些项目中使用这个助手:

def with_buffer(size, clear: true, &)
  FFI::MemoryPointer.new(:char, size, clear) do |buffer|
    yield buffer
    return buffer.read_string
  end
end

使用示例:(来自我正在开发的 CEC Ruby 库,为了清晰起见,进行了删除)

name = with_buffer(13) { |buffer| libcec_get_device_osd_name(*, buffer) }

或者当被调用的函数想要知道缓冲区大小并且您不想重复该信息时:

cec_version = 
  with_buffer(50) do |buffer| 
    libcec_cec_version_to_string(*, buffer, buffer.size) # buffer.size == 50
  end

也许这对某人有用......

© www.soinside.com 2019 - 2024. All rights reserved.