2015-05-18 8 views
21

Rust kodundan derlenen bir yerel kitaplığa erişmek için Fiddle kullanmak istiyorum.Bir yapının yerel koda geçirilmesi veya geri gönderilmesi için Fiddle kullanmak mümkün mü?

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

Ancak, tüm örnekler kabul ederim veya yapılar için işaretçi göndermektedir bulabilir ve değil yapılar kendilerini: yapının C gösterimi sadece bir işaretçi ve bir uzunluk, çok basittir. Mümkünse çift indirmeden kaçınmak istiyorum.

Fiddle::Importer documentation'dan bir örnek ödünç aldım. Ancak, ben düzgün bir yapıya bir işaretçi yerine bir yapıyla extern yöntemini çağırmak nasıl görmüyorum:

Fiddle değilFFI gem aynıdır

require 'fiddle' 
require 'fiddle/import' 

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

Not. Fiddle, Ruby standart kütüphanesinin bir bileşenidir ve ayrı bir mücevher olarak sağlanmamıştır. Bunlar ilgili sorular FFI taş bakın ve keman: Ben Keman belgelerine yoluyla ve bunu gördüğünüz gibi gittin

+0

İlginç bir soru, ancak FFI (bunun için Fiddle bir sarıcıdır) doğrudan yapıları desteklemiyor gibi göründüğünden şüphe duyuyorum, [bu dokümanın] "İşlev argümanları ve dönüş değerleri" bölümüne bakın (http: // fistfvck .sakura.ne.jp/ruby ​​/ rurima-2.1.0/library/fiddle.html) (japonca, google'ın çevirisini okuyordum) ve eğer bazı performans artışlarını beklerseniz, çok da önemli olmayan bir şey elde edersiniz - Ruby değişkenleri Bir veri ('RBasic' ve alt sınıflar) ile yapı, ya da oradan fiili veriler için başka bir işaretçi. –

+0

Ayrıca, işlev imzalarındaki desteklenen türlerin listesi de ['parse_ctype'] 'den alınabilir (https://github.com/ruby/ruby/blob/c8b3f1b470e343e7408ab5883f046b1056d94ccc/ext/fiddle/lib/fiddle/cparser.rb#L120) işlevi. –

cevap

11

mümkün olmasa bile zira çekirdek işlev tanımı Fiddle::Function.new, Fiddle::CParser'un işleyebileceği hatalar gerektirir. Çeşitli testi yaptık ve böyle bir şey haline kodunuzu dönüştürmek zorunda çalışması için: olmasıdır için geldim ne

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, basit türlerle çalışabilir, ancak başvurular kullanılarak geçirilecek struct ve union türlerine gereksinim duyar. Yine de bu sınıflar için sarmalayıcılar var. Ayrıca, bu sarmalayıcılar, Fiddle::Pointer'dan miras kalmıştır, bu da bizi bu veri türleri için işaretçiler kullanmamızı istedikleri sonuca götürür.

Bununla ilgili daha fazla bilgi almak isterseniz veya bu işlevselliği eklemek istiyorsanız, their git repo'u kullanabilirsiniz.