2015-06-24 13 views
9

Sto provando a passare una stringa in Ruby a un eseguibile ruggine, a manipolarlo e a passare la stringa manipolata indietro.Stringa di rubino per arrugginire e tornare indietro

Finora riesco a passare la stringa e restituirla, ma non riesco a capire come convertirla in una stringa di ruggine, manipolarla e poi restituirla a ruby. Ecco quello che ho finora:

// lib.rs 
use std::ffi::CStr; 

#[no_mangle] 
pub extern fn return_string(test_str: &CStr) -> &CStr { 
    // working funciton 
    test_str 
} 

#[no_mangle] 
pub extern fn manipulate_and_return_string(mystr: &CStr) -> &CStr { 
    // mystr type == &std::ffi::c_str::CStr 
    // println!("{:?}", mystr); => std::ffi::c_str::CStr` cannot be formatted using `:?` 
    let cstr = mystr.to_bytes_with_nul(); 
    // println!("{:?}", mystr); => [] 
    // cstr type == &[u8] 
    let ptr = cstr.as_ptr(); 
    // ptr type == *const u8 
    // println!("{:?}", mystr); => 0x7fd898edb520 
    let str_slice: &str = std::str::from_utf8(cstr).unwrap(); 
    // str type == &str 
    // println!("{:?}", mystr); => "" 
    let str_buf: String = str_slice.to_owned(); 
    // str_bug == collections::string::String 
    // println!("{:?}", mystr); => "" 
} 
# rust.rb 
require 'ffi' 

module Rust 
    extend FFI::Library 
    ffi_lib './bin/libembed.dylib' 

    attach_function :return_string, [:string], :string 
    attach_function :manipulate_and_return_string, [:string], :string 
end 
+7

commento rapida: ci sono due problemi immediati con questo. Innanzitutto, 'CStr' ** non è un tipo FFI-safe ** e non dovrebbe essere usato in questo modo. Dovresti usare '* const libc :: c_char'. In secondo luogo, la risposta dipende interamente da chi, esattamente, possiede la stringa risultante. Ruby lo gestisce? Se é cosi, come? Su quale heap deve essere assegnato? Rust lo possiede ancora? In tal caso, come si fornisce una funzione di pulizia? Tutto quello che posso raccomandare è di scoprire come farlo in C, quindi fallo in questo modo in Rust. –

+2

Guarda anche http://stackoverflow.com/q/30510764/155423, poiché copre tutte le parti importanti. Adattarlo a Ruby è facile a quel punto. – Shepmaster

+1

http://clalance.blogspot.ca/2011/01/writing-ruby-extensions-in-c-part-8.html sarà utile, così come sarà https://github.com/ruby/ruby/blob /trunk/doc/extension.rdoc –

risposta

4

Grazie a un orientamento da Steve Klabnik, shepmaster e DK ho capito come scrivere una funzione di stringa concat esterna di Rust e usarlo in Ruby.

// lib.rs 
#![feature(libc)] 
#![feature(cstr_to_str)] 
#![feature(cstr_memory)] 
extern crate libc; 
use std::ffi::{CStr,CString}; 

#[no_mangle] 
pub extern fn concat(s1: *const libc::c_char, s2: *const libc::c_char) -> *const libc::c_char { 
    let s1_cstr = unsafe { CStr::from_ptr(s1) }; // &std::ffi::c_str::CStr 
    let s2_cstr = unsafe { CStr::from_ptr(s2) }; // &std::ffi::c_str::CStr 
    let s1_and_str = s1_cstr.to_str().unwrap(); // &str 
    let s2_and_str = s2_cstr.to_str().unwrap(); // &str 

    let mut s1_string = s1_and_str.to_string(); // collections::string::String 

    s1_string.push_str(s2_and_str); 
    // s1_string + s2_and_str); // same thing 

    let concated_string = CString::new(s1_string).unwrap(); // std::ffi::c_str::CString 

    concated_string.into_ptr() // const i8 
} 
# rust.rb 
require 'ffi' 

module Rust 
    extend FFI::Library 
    ffi_lib './bin/libembed.dylib' 

    attach_function :concat, [:string, :string], :string 
end 
#calling the function in Ruby 

Rust.concat('This is a ', 'cohesive sentence') # => 'This is a cohesive sentence' 
Problemi correlati