是否可以使用 Fiddle 将结构传递或 return 到本机代码?

Is it possible to use Fiddle to pass or return a struct to native code?

我想使用 Fiddle 访问从 Rust 代码编译的本机库。 struct的C表示很简单,就是一个指针和一个长度:

typedef struct {
    char *data;
    size_t len;
} my_thing_t;

// Example function that somehow accepts a struct
void accepts_a_struct(my_thing_t thing);

// Example function that somehow returns a struct
my_thing_t returns_a_struct(void);

但是,我能找到的所有示例都接受或 return 指向结构的指针,而不是结构本身。如果可能的话,我想避免双重间接寻址。

我借用了 Fiddle::Importer documentation 的例子。但是,我看不到如何使用结构而不是指向结构的指针正确调用 extern 方法:

require 'fiddle'
require 'fiddle/import'

module LibSum
  extend Fiddle::Importer
  dlload './libsum.so'
  extern 'double sum(double*, int)'
  extern 'double split(double)'
end

备注

Fiddle 与 FFI gem 不同 。 Fiddle 是 Ruby 标准库的一个组件,不作为单独的 gem 提供。这些相关问题指的是 FFI gem,而不是 Fiddle:

我已经阅读了 Fiddle 文档,正如我所见,这是不可能的,因为即使在核心函数定义 Fiddle::Function.new 中,它也需要 Fiddle::CParser 可以处理的参数。我做了各种测试,为了让它工作,我不得不将你的代码转换成这样的东西:

test2.c

#include <stdio.h>
#include <stdlib.h>

typedef struct {
  char *data;
  char *more_data;
  size_t len;
} my_thing_t;

my_thing_t *returns_a_struct(void){
  my_thing_t *structure = malloc(sizeof(my_thing_t));
  structure->data = "test2";
  structure->more_data = "I am more data";
  structure->len = 5;
  return structure;
};

IRB

require 'fiddle'
require 'fiddle/import'
module Testmd
  extend Fiddle::Importer
  dlload './test2.dll'
  RetStruct = struct ['char *data','char *more_data','size_t len']
  extern 'RetStruct* returns_a_struct(void)'
end
include Testmd
2.2.1 :013 >   res = Testmd::returns_a_struct(nil)
 => #<Fiddle::Pointer:0x00000000b12a10 ptr=0x00000000e066b0 size=0 free=0x00000000000000> 
2.2.1 :014 > s = RetStruct.new(res)
 => #<Testmd::RetStruct:0x00000000c3e9e8 @entity=#<Fiddle::CStructEntity:0x000000007f0ad0 ptr=0x00000000e066b0 size=24 free=0x00000000000000>> 
2.2.1 :015 > s.data.to_s
 => "test2" 
2.2.1 :016 > s.more_data.to_s
 => "I am more data" 
2.2.1 :017 > s.len
 => 5

我得出的结论是 Fiddle 可以使用简单类型进行操作,但需要使用引用传递 structunion 类型。它仍然有这个 类 的包装器。此外,这些包装器继承自 Fiddle::Pointer 是什么让我们得出结论,他们希望我们对这些数据类型使用指针。

如果您想了解有关此的更多详细信息或想要添加此功能,您可以通过 their git repo