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

时间:2015-05-18 00:05:36

标签: 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);

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

我从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

注意

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

1 个答案:

答案 0 :(得分: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;
};

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