2015-05-18 45 views
21

我想使用Fiddle來訪問從Rust代碼編譯的本地庫。該結構的C表現是非常簡單的,它只是一個指針和長度:是否可以使用Fiddle將結構傳遞給本機代碼?

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的寶石,而不是擺弄:

+0

有趣的問題,但我懷疑它可能作爲FFI(其中小提琴是一個包裝)似乎不支持直接傳遞結構,請參閱[本文檔]的「函數參數和返回值」部分(http:// fistfvck .sakura.ne.jp/ruby​​/rurima-2.1.0/library/fiddle.html)(日語,我正在閱讀谷歌的翻譯),如果你期望提高性能,你將不太可能得到任何有意義的東西 - ruby​​的變量是指向結構與數據('RBasic'和子類),甚至是從那裏到堆中實際數據的另一個指針。 –

+0

此外,函數簽名中支持的類型列表可以從['parse_ctype']中獲取(https://github.com/ruby/ruby/blob/c8b3f1b470e343e7408ab5883f046b1056d94ccc/ext/fiddle/lib/fiddle/cparser.rb#L120 )功能。 –

回答

11

我已經通過小提琴的文檔和我可以看到它消失是不可能的,因爲即使在覈心函數定義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

相關問題