是否可以使用Fiddle将结构传递或返回给本机代码? [英] Is it possible to use Fiddle to pass or return a struct to native code?

查看:65
本文介绍了是否可以使用Fiddle将结构传递或返回给本机代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用小提琴来访问从Rust代码编译的本机库. struct的C表示非常简单,它只是一个指针和一个长度:

I would like to use Fiddle to access a native library compiled from Rust code. The C representation of the struct is very simple, it is just a pointer and a length:

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);

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

However, all examples I can find accept or return pointers to structs, and not the structs themselves. I'd like to avoid the double indirection if at all possible.

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

注意

提琴与 FFI宝石 不相同.小提琴是Ruby标准库的组成部分,未作为单独的gem提供.这些相关问题是针对FFI的宝石,而不是Fiddle:

Fiddle is not the same as the FFI gem. Fiddle is a component of the Ruby standard library, and is not provided as a separate gem. These related questions refer to the FFI gem, and not to Fiddle:

  • How to wrap function in Ruby FFI method that takes struct as argument?
  • How do I specify a struct as the return value of a function in RubyFFI?

推荐答案

我浏览了Fiddle文档,并且我看到这是不可能的,因为即使在核心函数定义Fiddle::Function.new中,它也需要Fiddle::CParser可以使用的args处理.我已经进行了各种测试,并且要使其正常工作,我必须将您的代码转换为以下形式:

I've gone through Fiddle documentation and as I can see it is not possible since even in core function definition Fiddle::Function.new it requires args that Fiddle::CParser can handle. I've done various test and to make it work I had to transform your code into something like this:

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继承而来,这使我们得出结论,他们希望我们对这些数据类型使用指针.

What I came to is that Fiddle can operate with simple types but needs struct and union types to be passed using references. Still it has wrappers for this classes. Also these wrappers are inherited from Fiddle::Pointer what kinda leads us to conclusion they want us to use pointers for these data types.

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

If you want more details regarding this or you want to add this functionality you can go through their git repo.

这篇关于是否可以使用Fiddle将结构传递或返回给本机代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆