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

She*_*ter 21 ruby ffi

我想使用Fiddle访问从Rust代码编译的本机库.结构的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);
Run Code Online (Sandbox Code Playgroud)

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

我从Fiddle::Importer文档中借了一个例子.但是,我没有看到如何extern使用结构而不是指向结构的指针正确调用该方法:

require 'fiddle'
require 'fiddle/import'

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

注意

小提琴是一样的FFI宝石.Fiddle是Ruby标准库的一个组件,不作为单独的gem提供.这些相关问题涉及FFI宝石,而不是Fiddle:

小智 11

我已经阅读了Fiddle文档,因为我看到它是不可能的,因为即使在核心函数定义中Fiddle::Function.new它也需要Fiddle::CParser可以处理的args .我做了各种测试并使其工作我必须将你的代码转换成这样的东西:

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;
};
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

我得到的是Fiddle可以使用简单类型操作但需要structunion类型使用引用传递.它还有这个类的包装器.这些包装器也继承Fiddle::Pointer了我们要求我们使用这些数据类型的指针的结论.

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