是否可以使用 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:
- 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
可以处理的参数。我做了各种测试,为了让它工作,我不得不将你的代码转换成这样的东西:
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
可以使用简单类型进行操作,但需要使用引用传递 struct
和 union
类型。它仍然有这个 类 的包装器。此外,这些包装器继承自 Fiddle::Pointer
是什么让我们得出结论,他们希望我们对这些数据类型使用指针。
如果您想了解有关此的更多详细信息或想要添加此功能,您可以通过 their git repo。
我想使用 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:
- 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
可以处理的参数。我做了各种测试,为了让它工作,我不得不将你的代码转换成这样的东西:
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
可以使用简单类型进行操作,但需要使用引用传递 struct
和 union
类型。它仍然有这个 类 的包装器。此外,这些包装器继承自 Fiddle::Pointer
是什么让我们得出结论,他们希望我们对这些数据类型使用指针。
如果您想了解有关此的更多详细信息或想要添加此功能,您可以通过 their git repo。